Ospf6d merge from Zebra repository with added privs stuff and merged
zclient changes.
diff --git a/ospf6d/.cvsignore b/ospf6d/.cvsignore
index 5e76e4d..cec4061 100644
--- a/ospf6d/.cvsignore
+++ b/ospf6d/.cvsignore
@@ -1,5 +1,4 @@
Makefile
-Makefile.in
*.o
*.patch
ospf6d
diff --git a/ospf6d/ChangeLog b/ospf6d/ChangeLog
index 0e9d7fc..b74dead 100644
--- a/ospf6d/ChangeLog
+++ b/ospf6d/ChangeLog
@@ -1,20 +1,17 @@
-2004-05-08 Paul Jakma <paul@dishone.st>
+2004-05-18 Hasso Tepper <hasso@estpak.ee>
- * ospf6_zebra.c: Sync to zclient changes
-
+ * *.*: Merge rewritten ospf6d from Zebra repository.
+ * ospf6_network.c, ospf6_main.c: Merged privs stuff back in.
+ * ospf6_zebra.c: Sync back to zclient changes.
+
+2003-08-18 Yasuhiro Ohara <yasu@sfc.wide.ad.jp>
+
+ * *.[ch]: rewrite all source code from scratch
+ * ospf6d.h: version 0.9.7
+
2003-08-11 Taisuke Sasaki <sasaki@soft.net.fujitsu.co.jp>
- * ospf6_ism.c: DR Election bug fix.
-
-2003-05-18 Hasso Tepper <hasso@estpak.ee>
-
- * ospf6_{dump,interface,zebra}.c,ospf6d.c: show router and interface
- nodes from ospf6d when using vtysh, and don't show defaults in
- interface node (from ^WIND patch).
-
-2003-04-23 Hasso Tepper <hasso@estpak.ee>
-
- * {ospf6_damp,ospf6d}.c: fix "router xxx" node commands in vtysh
+ * ospf6_ism.c: DR Election bug fix.
2003-04-25 Yasuhiro Ohara <yasu@sfc.wide.ad.jp>
@@ -22,11 +19,6 @@
prefix of the obsolete LSA. It was wrong so fixed.
* version: 0.9.6p
-2003-04-19 Hasso Tepper <hasso@estpak.ee>
-
- * rip_routemap.c: sync daemon's route-map commands to have same
- syntax
-
2002-11-09 Vincent Jardin <jardin@6wind.com>
* ospf6_interface.c: update link-local address on interface creation.
diff --git a/ospf6d/Makefile.am b/ospf6d/Makefile.am
index 14b87af..de18391 100644
--- a/ospf6d/Makefile.am
+++ b/ospf6d/Makefile.am
@@ -8,22 +8,16 @@
sbin_PROGRAMS = ospf6d
libospf6_a_SOURCES = \
- ospf6_dump.c ospf6d.c ospf6_interface.c ospf6_network.c \
- ospf6_neighbor.c ospf6_message.c ospf6_lsa.c ospf6_spf.c \
- ospf6_route.c ospf6_zebra.c ospf6_ism.c ospf6_dbex.c \
- ospf6_lsdb.c ospf6_prefix.c ospf6_top.c ospf6_area.c ospf6_nsm.c \
- ospf6_routemap.c ospf6_proto.c \
- ospf6_hook.c ospf6_asbr.c ospf6_bintree.c ospf6_linklist.c \
- ospf6_abr.c ospf6_intra.c ospf6_damp.c
+ ospf6_network.c ospf6_message.c ospf6_lsa.c ospf6_lsdb.c \
+ ospf6_top.c ospf6_area.c ospf6_interface.c ospf6_neighbor.c \
+ ospf6_flood.c ospf6_route.c ospf6_intra.c ospf6_zebra.c \
+ ospf6_spf.c ospf6_proto.c ospf6_asbr.c ospf6d.c
noinst_HEADERS = \
- ospf6_area.h ospf6_dump.h ospf6_interface.h ospf6_lsa.h \
- ospf6_message.h ospf6_neighbor.h ospf6_network.h ospf6_proto.h \
- ospf6_spf.h ospf6_route.h ospf6_types.h ospf6_zebra.h ospf6d.h \
- ospf6_ism.h ospf6_dbex.h ospf6_lsdb.h ospf6_prefix.h \
- ospf6_top.h ospf6_nsm.h ospf6_routemap.h \
- ospf6_hook.h ospf6_asbr.h ospf6_bintree.h ospf6_linklist.h \
- ospf6_abr.h ospf6_intra.h ospf6_damp.h
+ ospf6_network.h ospf6_message.h ospf6_lsa.h ospf6_lsdb.h \
+ ospf6_top.h ospf6_area.h ospf6_interface.h ospf6_neighbor.h \
+ ospf6_flood.h ospf6_route.h ospf6_intra.h ospf6_zebra.h \
+ ospf6_spf.h ospf6_proto.h ospf6_asbr.h ospf6d.h
ospf6d_SOURCES = \
ospf6_main.c $(libospf6_a_SOURCES)
diff --git a/ospf6d/README b/ospf6d/README
index b3b4d16..883486f 100644
--- a/ospf6d/README
+++ b/ospf6d/README
@@ -1,6 +1,14 @@
Zebra OSPF daemon for IPv6 network
+ 2003/08/18
+
+README for newer code is not yet. General usage should remain
+the same. For further usage, see command helps by typing '?'
+in vty, and then imagin ! ;p) Previous README contents follows.
+
+ Zebra OSPF daemon for IPv6 network
+
2001/12/20
Zebra OSPF6d is OSPF version 3 daemon which is specified by
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
deleted file mode 100644
index 864e0c2..0000000
--- a/ospf6d/ospf6_abr.c
+++ /dev/null
@@ -1,655 +0,0 @@
-/*
- * Copyright (C) 2001 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 "ospf6d.h"
-
-#include "ospf6_dump.h"
-#include "ospf6_abr.h"
-
-static int abr_index;
-#define IS_OSPF6_DUMP_ABR (ospf6_dump_is_on (abr_index))
-
-#define ADD 0
-#define CHANGE 1
-#define REMOVE 2
-
-/* Inter-Area-Prefix-LSA Calculation */
-
-static struct ospf6_route_req *
-ospf6_abr_entry_lookup (struct ospf6_route_req *abr_entry,
- u_int32_t router_id, struct ospf6_area *area)
-{
- struct prefix_ls abr_id;
- char router_string[32];
-
- inet_ntop (AF_INET, &router_id, router_string, sizeof (router_string));
-
- //zlog_info ("ABR: Finding router %s in area %s", router_string, area->str);
-
- memset (&abr_id, 0, sizeof (abr_id));
- abr_id.family = AF_UNSPEC;
- abr_id.prefixlen = 64; /* xxx */
- abr_id.id.s_addr = htonl (0);
- abr_id.adv_router.s_addr = router_id;
-
- ospf6_route_lookup (abr_entry, (struct prefix *) &abr_id,
- area->table_topology);
-
- if (ospf6_route_end (abr_entry))
- {
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: Router %s not found in area %s",
- router_string, area->str);
- return NULL;
- }
-
- if (abr_entry->path.area_id != area->area_id)
- {
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: ABR area id mismatch");
- return NULL;
- }
-
- if (! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_B))
- {
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: ABR entry's B bit off");
- return NULL;
- }
-
- return abr_entry;
-}
-
-static int
-ospf6_abr_prefix_lsa_to_route (struct ospf6_lsa *lsa,
- struct ospf6_route_req *request)
-{
- struct ospf6_inter_area_prefix_lsa *iep;
- struct ospf6_route_req abr_entry;
-
- if (lsa->header->type != htons (OSPF6_LSA_TYPE_INTER_PREFIX))
- {
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: LSA type mismatch");
- return -1;
- }
-
- if (IS_LSA_MAXAGE (lsa))
- {
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: LSA MaxAge");
- return -1;
- }
-
- if (! ospf6_abr_entry_lookup (&abr_entry, lsa->header->adv_router,
- (struct ospf6_area *) lsa->scope))
- {
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: ABR check failed");
- return -1;
- }
-
- iep = OSPF6_LSA_HEADER_END (lsa->header);
-
- memset (request, 0, sizeof (struct ospf6_route_req));
- request->route.type = OSPF6_DEST_TYPE_NETWORK;
- request->route.prefix.family = AF_INET6;
- request->route.prefix.prefixlen = iep->prefix.prefix_length;
- ospf6_prefix_in6_addr (&iep->prefix, &request->route.prefix.u.prefix6);
-
- request->path.cost = abr_entry.path.cost +
- (ntohl (iep->metric) & ntohl (0x000fffff));
- request->path.type = OSPF6_PATH_TYPE_INTER;
- request->path.origin.type = lsa->header->type;
- request->path.origin.id = lsa->header->id;
- request->path.origin.adv_router = lsa->header->adv_router;
- memcpy (&request->nexthop.address, &abr_entry.nexthop.address,
- sizeof (request->nexthop.address));
- request->nexthop.ifindex = abr_entry.nexthop.ifindex;
-
- return 0;
-}
-
-void
-ospf6_abr_prefix_lsa_add (struct ospf6_lsa *lsa)
-{
- struct ospf6_route_req request;
- int ret;
-
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: Calculate %s", lsa->str);
-
- ret = ospf6_abr_prefix_lsa_to_route (lsa, &request);
- if (ret < 0)
- return;
-
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: Inter Area Route add for %s", lsa->str);
-
- ospf6_route_add (&request, ospf6->route_table);
-}
-
-void
-ospf6_abr_prefix_lsa_remove (struct ospf6_lsa *lsa)
-{
- struct ospf6_inter_area_prefix_lsa *iep;
- struct prefix_ipv6 prefix6;
- struct ospf6_route_req request;
-
- iep = OSPF6_LSA_HEADER_END (lsa->header);
-
- prefix6.family = AF_INET6;
- prefix6.prefixlen = iep->prefix.prefix_length;
- ospf6_prefix_in6_addr (&iep->prefix, &prefix6.prefix);
-
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: Inter Area Route remove for %s", lsa->str);
-
- for (ospf6_route_lookup (&request, (struct prefix *) &prefix6,
- ospf6->route_table);
- ! ospf6_route_end (&request);
- ospf6_route_next (&request))
- {
- if (memcmp (&prefix6, &request.route.prefix, sizeof (prefix6)))
- break;
- if (request.path.origin.type != htons (OSPF6_LSA_TYPE_INTER_PREFIX) ||
- request.path.origin.adv_router != lsa->header->adv_router ||
- request.path.origin.id != lsa->header->id)
- continue;
-
- ospf6_route_remove (&request, ospf6->route_table);
- }
-}
-
-static int
-ospf6_abr_router_lsa_to_route (struct ospf6_lsa *lsa,
- struct ospf6_route_req *request)
-{
- struct ospf6_inter_area_router_lsa *ier;
- struct ospf6_route_req abr_entry;
-
- if (lsa->header->type != htons (OSPF6_LSA_TYPE_INTER_ROUTER))
- {
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: LSA type mismatch");
- return -1;
- }
-
- if (IS_LSA_MAXAGE (lsa))
- {
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: LSA MaxAge");
- return -1;
- }
-
- if (! ospf6_abr_entry_lookup (&abr_entry, lsa->header->adv_router,
- (struct ospf6_area *) lsa->scope))
- {
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: Advertising router check failed");
- return -1;
- }
-
- ier = OSPF6_LSA_HEADER_END (lsa->header);
-
- memset (request, 0, sizeof (struct ospf6_route_req));
- request->route.type = OSPF6_DEST_TYPE_ROUTER;
- request->route.prefix.family = AF_UNSPEC;
- request->route.prefix.prefixlen = 64; /* XXX */
- ((struct prefix_ls *) &request->route.prefix)->adv_router.s_addr
- = ier->router_id;
-
- request->path.cost = abr_entry.path.cost +
- (ntohl (ier->metric & htonl (0x000fffff)));
- request->path.type = OSPF6_PATH_TYPE_INTER;
- request->path.origin.type = lsa->header->type;
- request->path.origin.id = lsa->header->id;
- request->path.origin.adv_router = lsa->header->adv_router;
- SET_FLAG (request->path.router_bits, OSPF6_ROUTER_LSA_BIT_E);
- request->path.capability[0] = ier->options[0];
- request->path.capability[1] = ier->options[1];
- request->path.capability[2] = ier->options[2];
-
- memcpy (&request->nexthop.address, &abr_entry.nexthop.address,
- sizeof (request->nexthop.address));
- request->nexthop.ifindex = abr_entry.nexthop.ifindex;
-
- return 0;
-}
-
-void
-ospf6_abr_router_lsa_add (struct ospf6_lsa *lsa)
-{
- struct ospf6_route_req request;
- int ret;
-
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: Calculate %s", lsa->str);
-
- ret = ospf6_abr_router_lsa_to_route (lsa, &request);
- if (ret < 0)
- return;
-
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: Inter Area Router add for %s", lsa->str);
-
- ospf6_route_add (&request, ospf6->topology_table);
-}
-
-void
-ospf6_abr_router_lsa_remove (struct ospf6_lsa *lsa)
-{
- struct ospf6_inter_area_router_lsa *ier;
- struct prefix_ls prefix_ls;
- struct ospf6_route_req request;
-
- ier = OSPF6_LSA_HEADER_END (lsa->header);
-
- memset (&prefix_ls, 0, sizeof (prefix_ls));
- prefix_ls.family = AF_INET6;
- prefix_ls.prefixlen = 64; /* XXX */
- prefix_ls.adv_router.s_addr = ier->router_id;
-
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: Inter Area Route remove for %s", lsa->str);
-
- for (ospf6_route_lookup (&request, (struct prefix *) &prefix_ls,
- ospf6->route_table);
- ! ospf6_route_end (&request);
- ospf6_route_next (&request))
- {
- if (memcmp (&prefix_ls, &request.route.prefix, sizeof (prefix_ls)))
- break;
- if (request.path.origin.type != htons (OSPF6_LSA_TYPE_INTER_ROUTER) ||
- request.path.origin.adv_router != lsa->header->adv_router ||
- request.path.origin.id != lsa->header->id)
- continue;
-
- ospf6_route_remove (&request, ospf6->route_table);
- }
-}
-
-
-void
-ospf6_abr_abr_entry_add (struct ospf6_route_req *abr_entry)
-{
- struct ospf6_lsdb_node node;
- struct prefix_ls *abr_id;
- struct ospf6_route_req request;
- struct ospf6_area *area;
-
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: New Area Border Router found");
-
- area = ospf6_area_lookup (abr_entry->path.area_id, ospf6);
- if (! area)
- {
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: Can't find associated area");
- return;
- }
-
- abr_id = (struct prefix_ls *) &abr_entry->route.prefix;
- if (! ospf6_abr_entry_lookup (&request, abr_id->adv_router.s_addr, area))
- {
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: back check failed");
- return;
- }
-
- /* for each inter-prefix LSA this ABR originated */
- for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_INTER_PREFIX),
- abr_id->adv_router.s_addr, area->lsdb);
- ! ospf6_lsdb_is_end (&node);
- ospf6_lsdb_next (&node))
- ospf6_abr_prefix_lsa_add (node.lsa);
-
- /* for each inter-router LSA this ABR originated */
- for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_INTER_ROUTER),
- abr_id->adv_router.s_addr, area->lsdb);
- ! ospf6_lsdb_is_end (&node);
- ospf6_lsdb_next (&node))
- ospf6_abr_router_lsa_add (node.lsa);
-}
-
-void
-ospf6_abr_abr_entry_remove (struct ospf6_route_req *abr_entry)
-{
- struct ospf6_lsdb_node node;
- struct prefix_ls *abr_id;
- struct ospf6_area *area;
-
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: Area Border Router removed");
-
- abr_id = (struct prefix_ls *) &abr_entry->route.prefix;
-
- area = ospf6_area_lookup (abr_entry->path.area_id, ospf6);
- if (! area)
- {
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: Can't find associated area");
- return;
- }
-
- /* for each inter-prefix LSA this ABR originated */
- for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_INTER_PREFIX),
- abr_id->adv_router.s_addr, area->lsdb);
- ! ospf6_lsdb_is_end (&node);
- ospf6_lsdb_next (&node))
- ospf6_abr_prefix_lsa_remove (node.lsa);
-
- /* for each inter-router LSA this ABR originated */
- for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_INTER_ROUTER),
- abr_id->adv_router.s_addr, area->lsdb);
- ! ospf6_lsdb_is_end (&node);
- ospf6_lsdb_next (&node))
- ospf6_abr_router_lsa_remove (node.lsa);
-}
-
-/* Inter-Area-Prefix-LSA Origination */
-
-static void
-ospf6_abr_prefix_lsa_update_add (struct ospf6_route_req *request,
- struct ospf6_area *area)
-{
- char buffer [MAXLSASIZE];
- u_int16_t size;
- struct ospf6_inter_area_prefix_lsa *iep;
- char *p;
-
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("Update Inter-Prefix for %s: ID: %lu",
- area->str, (u_long) ntohl (request->route_id));
-
- /* prepare buffer */
- memset (buffer, 0, sizeof (buffer));
- size = sizeof (struct ospf6_inter_area_prefix_lsa);
- iep = (struct ospf6_inter_area_prefix_lsa *) buffer;
- p = (char *) (iep + 1);
-
- /* prefixlen */
- iep->prefix.prefix_length = request->route.prefix.prefixlen;
-
- /* PrefixOptions */
- iep->prefix.prefix_options = request->path.prefix_options;
-
- /* set Prefix */
- memcpy (p, &request->route.prefix.u.prefix6,
- OSPF6_PREFIX_SPACE (request->route.prefix.prefixlen));
- ospf6_prefix_apply_mask (&iep->prefix);
- size += OSPF6_PREFIX_SPACE (request->route.prefix.prefixlen);
-
- ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_INTER_PREFIX),
- htonl (request->route_id), ospf6->router_id,
- (char *) iep, size, area);
-}
-
-static void
-ospf6_abr_prefix_lsa_update_remove (struct ospf6_route_req *request,
- struct ospf6_area *area)
-{
- struct ospf6_lsa *lsa;
- lsa = ospf6_lsdb_lookup_lsdb (htons (OSPF6_LSA_TYPE_INTER_PREFIX),
- htonl (request->route_id),
- ospf6->router_id, area->lsdb);
- if (lsa)
- ospf6_lsa_premature_aging (lsa);
-}
-
-static void
-ospf6_abr_prefix_lsa_update (int type, struct ospf6_route_req *request)
-{
- struct ospf6_route_req route, target;
- listnode node;
- struct ospf6_area *area;
- struct ospf6_interface *o6i;
-
- if (request->route.type != OSPF6_DEST_TYPE_NETWORK)
- return;
-
- /* assert this is best path; if not, return */
- ospf6_route_lookup (&route, &request->route.prefix, request->table);
- if (memcmp (&route.path, &request->path, sizeof (route.path)))
- return;
-
- if (target.path.cost >= LS_INFINITY ||
- target.path.cost_e2 >= LS_INFINITY)
- {
- if (IS_OSPF6_DUMP_ABR)
- zlog_info ("ABR: Exceeds LS Infinity, ignore");
- return;
- }
-
- ospf6_route_lookup (&target, &request->route.prefix, request->table);
- if (type == REMOVE)
- {
- ospf6_route_next (&route);
- if (! memcmp (&route.route, &request->route, sizeof (route.route)))
- {
- type = ADD;
- ospf6_route_next (&target);
- }
- }
-
- for (node = listhead (ospf6->area_list); node; nextnode (node))
- {
- area = getdata (node);
-
- if (target.path.area_id == area->area_id)
- continue;
-
- o6i = ospf6_interface_lookup_by_index (target.nexthop.ifindex);
- if (o6i && o6i->area && o6i->area->area_id == area->area_id)
- {
- zlog_info ("ABR: Logical equivalent of split horizon, skip for %s",
- area->str);
- continue;
- }
-
- if (area->area_id == ntohs (0) && /* Backbone */
- target.path.type != OSPF6_PATH_TYPE_INTRA)
- continue;
-
- /* XXX, stub area check */
-
- /* XXX, aggregate */
- /* if either the area of the route or the area trying to
- advertise is backbone, do not aggregate */
-
- if (type == ADD)
- ospf6_abr_prefix_lsa_update_add (&target, area);
- else
- ospf6_abr_prefix_lsa_update_remove (&target, area);
- }
-}
-
-void
-ospf6_abr_route_add (struct ospf6_route_req *request)
-{
- ospf6_abr_prefix_lsa_update (ADD, request);
-}
-
-void
-ospf6_abr_route_remove (struct ospf6_route_req *request)
-{
- ospf6_abr_prefix_lsa_update (REMOVE, request);
-}
-
-int
-ospf6_abr_prefix_lsa_refresh (void *data)
-{
- struct ospf6_lsa *lsa = data;
- struct ospf6_inter_area_prefix_lsa *ier;
- struct prefix_ipv6 prefix6;
- struct ospf6_route_req route;
-
- ier = OSPF6_LSA_HEADER_END (lsa->header);
- memset (&prefix6, 0, sizeof (prefix6));
- prefix6.family = AF_INET6;
- prefix6.prefixlen = ier->prefix.prefix_length;
- ospf6_prefix_in6_addr (&ier->prefix, &prefix6.prefix);
-
- ospf6_route_lookup (&route, (struct prefix *) &prefix6,
- ospf6->route_table);
- assert (! ospf6_route_end (&route));
-
- ospf6_abr_prefix_lsa_update (ADD, &route);
- return 0;
-}
-
-int
-ospf6_abr_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
-{
- struct ospf6_inter_area_prefix_lsa *ier;
- char prefix[128];
-
- assert (lsa->header);
- ier = OSPF6_LSA_HEADER_END (lsa->header);
-
- ospf6_prefix_string (&ier->prefix, prefix, sizeof (prefix));
-
- vty_out (vty, " Metric: %d%s",
- ntohl (ier->metric & htonl (0x000fffff)), VTY_NEWLINE);
- vty_out (vty, " Prefix: %s%s", prefix, VTY_NEWLINE);
-
- return 0;
-}
-
-int
-ospf6_abr_prefix_lsa_hook_add (void *data)
-{
- struct ospf6_lsa *lsa = data;
- ospf6_abr_prefix_lsa_add (lsa);
- return 0;
-}
-
-int
-ospf6_abr_prefix_lsa_hook_remove (void *data)
-{
- struct ospf6_lsa *lsa = data;
- ospf6_abr_prefix_lsa_remove (lsa);
- return 0;
-}
-
-void
-ospf6_abr_database_hook_inter_prefix (struct ospf6_lsa *old,
- struct ospf6_lsa *new)
-{
- if (old)
- ospf6_abr_prefix_lsa_hook_remove (old);
- if (new && ! IS_LSA_MAXAGE (new))
- ospf6_abr_prefix_lsa_hook_add (new);
-}
-
-void
-ospf6_abr_register_inter_prefix ()
-{
- struct ospf6_lsa_slot slot;
-
- memset (&slot, 0, sizeof (slot));
- slot.type = htons (OSPF6_LSA_TYPE_INTER_PREFIX);
- slot.name = "Inter-Prefix";
- slot.func_show = ospf6_abr_prefix_lsa_show;
- slot.func_refresh = ospf6_abr_prefix_lsa_refresh;
- ospf6_lsa_slot_register (&slot);
-
- ospf6_lsdb_hook[OSPF6_LSA_TYPE_INTER_PREFIX & OSPF6_LSTYPE_CODE_MASK].hook =
- ospf6_abr_database_hook_inter_prefix;
-}
-
-int
-ospf6_abr_router_lsa_hook_add (void *data)
-{
- struct ospf6_lsa *lsa = data;
- ospf6_abr_router_lsa_add (lsa);
- return 0;
-}
-
-int
-ospf6_abr_router_lsa_hook_remove (void *data)
-{
- struct ospf6_lsa *lsa = data;
- ospf6_abr_router_lsa_remove (lsa);
- return 0;
-}
-
-int
-ospf6_abr_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
-{
- return 0;
-}
-
-int
-ospf6_abr_router_lsa_refresh (void *data)
-{
- return 0;
-}
-
-void
-ospf6_abr_database_hook_inter_router (struct ospf6_lsa *old,
- struct ospf6_lsa *new)
-{
- if (old)
- ospf6_abr_router_lsa_hook_remove (old);
- if (new && ! IS_LSA_MAXAGE (new))
- ospf6_abr_router_lsa_hook_add (new);
-}
-
-void
-ospf6_abr_register_inter_router ()
-{
- struct ospf6_lsa_slot slot;
-
- memset (&slot, 0, sizeof (slot));
- slot.type = htons (OSPF6_LSA_TYPE_INTER_ROUTER);
- slot.name = "Inter-Router";
- slot.func_show = ospf6_abr_router_lsa_show;
- slot.func_refresh = ospf6_abr_router_lsa_refresh;
- ospf6_lsa_slot_register (&slot);
-
- ospf6_lsdb_hook[OSPF6_LSA_TYPE_INTER_ROUTER & OSPF6_LSTYPE_CODE_MASK].hook =
- ospf6_abr_database_hook_inter_router;
-}
-
-void
-ospf6_abr_inter_route_calculation (struct ospf6_area *area)
-{
- struct ospf6_lsdb_node node;
-
- /* for each inter-prefix LSA */
- for (ospf6_lsdb_type (&node, htons (OSPF6_LSA_TYPE_INTER_PREFIX),
- area->lsdb);
- ! ospf6_lsdb_is_end (&node);
- ospf6_lsdb_next (&node))
- ospf6_abr_prefix_lsa_add (node.lsa);
-}
-
-void
-ospf6_abr_init ()
-{
- abr_index = ospf6_dump_install ("abr", "Area Border Router Function\n");
-
- ospf6_abr_register_inter_prefix ();
- ospf6_abr_register_inter_router ();
-}
-
-
diff --git a/ospf6d/ospf6_abr.h b/ospf6d/ospf6_abr.h
deleted file mode 100644
index 510532e..0000000
--- a/ospf6d/ospf6_abr.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2001 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.
- */
-
-#ifndef OSPF6_ABR_H
-#define OSPF6_ABR_H
-
-/* Inter-Area-Prefix-LSA */
-struct ospf6_inter_area_prefix_lsa
-{
- u_int32_t metric; /* 12bits reserved, 20bits metric */
- struct ospf6_prefix prefix; /* followed by one address prefix */
-};
-
-/* Inter-Area-Router-LSA */
-struct ospf6_inter_area_router_lsa
-{
- u_char reserved;
- u_char options[3]; /* Optional Capability */
- u_int32_t metric; /* 12bits reserved, 20bits metric */
- u_int32_t router_id; /* Destination Router ID */
-};
-
-void ospf6_abr_prefix_lsa_add (struct ospf6_lsa *);
-void ospf6_abr_prefix_lsa_remove (struct ospf6_lsa *);
-void ospf6_abr_prefix_lsa_change (struct ospf6_lsa *, struct ospf6_lsa *);
-
-void ospf6_abr_abr_entry_add (struct ospf6_route_req *);
-void ospf6_abr_abr_entry_remove (struct ospf6_route_req *);
-
-void ospf6_abr_route_add (struct ospf6_route_req *);
-void ospf6_abr_route_remove (struct ospf6_route_req *);
-
-void ospf6_abr_inter_route_calculation (struct ospf6_area *);
-
-void ospf6_abr_init ();
-
-#endif /* OSPF6_ABR_H */
-
diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c
index 51af508..ef283cd 100644
--- a/ospf6d/ospf6_area.c
+++ b/ospf6d/ospf6_area.c
@@ -1,6 +1,5 @@
/*
- * OSPF6 Area Data Structure
- * Copyright (C) 1999-2002 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -20,67 +19,35 @@
* Boston, MA 02111-1307, USA.
*/
+#include <zebra.h>
+
+#include "log.h"
+#include "memory.h"
+#include "linklist.h"
+#include "thread.h"
+#include "vty.h"
+#include "command.h"
+#include "if.h"
+#include "prefix.h"
+#include "table.h"
+
#include "ospf6d.h"
+#include "ospf6_proto.h"
+#include "ospf6_lsa.h"
+#include "ospf6_lsdb.h"
+#include "ospf6_route.h"
+#include "ospf6_spf.h"
+#include "ospf6_top.h"
+#include "ospf6_area.h"
+#include "ospf6_interface.h"
+#include "ospf6_intra.h"
-static int area_index;
-#define IS_OSPF6_DUMP_AREA (ospf6_dump_is_on (area_index))
-
-static void
-ospf6_area_foreach_interface (struct ospf6_area *o6a, void *arg, int val,
- void (*func) (void *, int, void *))
+int
+ospf6_area_cmp (void *va, void *vb)
{
- listnode node;
- struct ospf6_interface *o6i;
-
- for (node = listhead (o6a->if_list); node; nextnode (node))
- {
- o6i = (struct ospf6_interface *) getdata (node);
- (*func) (arg, val, o6i);
- }
-}
-
-static void
-ospf6_area_foreach_neighbor (struct ospf6_area *o6a, void *arg, int val,
- void (*func) (void *, int, void *))
-{
- listnode node;
- struct ospf6_interface *o6i;
-
- for (node = listhead (o6a->if_list); node; nextnode (node))
- {
- o6i = (struct ospf6_interface *) getdata (node);
- (*o6i->foreach_nei) (o6i, arg, val, func);
- }
-}
-
-static int
-ospf6_area_maxage_remover (struct thread *t)
-{
- int count;
- struct ospf6_area *o6a = (struct ospf6_area *) THREAD_ARG (t);
-
- o6a->maxage_remover = (struct thread *) NULL;
-
- count = 0;
- o6a->foreach_nei (o6a, &count, NBS_EXCHANGE, ospf6_count_state);
- o6a->foreach_nei (o6a, &count, NBS_LOADING, ospf6_count_state);
- if (count != 0)
- return 0;
-
- ospf6_lsdb_remove_maxage (o6a->lsdb);
- return 0;
-}
-
-void
-ospf6_area_schedule_maxage_remover (void *arg, int val, void *obj)
-{
- struct ospf6_area *o6a = (struct ospf6_area *) obj;
-
- if (o6a->maxage_remover != NULL)
- return;
-
- o6a->maxage_remover =
- thread_add_event (master, ospf6_area_maxage_remover, o6a, 0);
+ struct ospf6_area *oa = (struct ospf6_area *) va;
+ struct ospf6_area *ob = (struct ospf6_area *) vb;
+ return (ntohl (oa->area_id) - ntohl (ob->area_id));
}
int
@@ -91,242 +58,811 @@
return 1;
}
-int
-ospf6_area_is_transit (struct ospf6_area *o6a)
-{
- return 0;
-}
-
-
-
+/* schedule routing table recalculation */
void
-ospf6_area_route_add (void *data)
+ospf6_area_lsdb_hook_add (struct ospf6_lsa *lsa)
{
- struct ospf6_route_req *route = data;
- struct in6_addr local;
+ struct ospf6_area *oa;
- inet_pton (AF_INET6, "::1", &local);
- if (! memcmp (&route->nexthop.address, &local, sizeof (struct in6_addr)))
+ oa = (struct ospf6_area *) lsa->scope;
+ switch (ntohs (lsa->header->type))
{
- if (IS_OSPF6_DUMP_AREA)
- zlog_info ("AREA: Self-originated route add, ignore");
- return;
- }
+ case OSPF6_LSTYPE_ROUTER:
+ case OSPF6_LSTYPE_NETWORK:
+ ospf6_spf_schedule (oa);
+ break;
- ospf6_route_add (route, ospf6->route_table);
+ case OSPF6_LSTYPE_INTRA_PREFIX:
+ ospf6_intra_prefix_lsa_add (lsa);
+ break;
+
+ case OSPF6_LSTYPE_INTER_PREFIX:
+ case OSPF6_LSTYPE_INTER_ROUTER:
+ break;
+
+ default:
+ if (IS_OSPF6_DEBUG_LSA (RECV))
+ zlog_info ("Unknown LSA in Area %s's lsdb", oa->name);
+ break;
+ }
}
void
-ospf6_area_route_remove (void *data)
+ospf6_area_lsdb_hook_remove (struct ospf6_lsa *lsa)
{
- struct ospf6_route_req *route = data;
- struct in6_addr local;
+ struct ospf6_area *oa;
- inet_pton (AF_INET6, "::1", &local);
- if (! memcmp (&route->nexthop.address, &local, sizeof (struct in6_addr)))
+ oa = (struct ospf6_area *) lsa->scope;
+ switch (ntohs (lsa->header->type))
{
- if (IS_OSPF6_DUMP_AREA)
- zlog_info ("AREA: Self-originated route remove, ignore");
- return;
- }
+ case OSPF6_LSTYPE_ROUTER:
+ case OSPF6_LSTYPE_NETWORK:
+ ospf6_spf_schedule (oa);
+ break;
- ospf6_route_remove (route, ospf6->route_table);
+ case OSPF6_LSTYPE_INTRA_PREFIX:
+ ospf6_intra_prefix_lsa_remove (lsa);
+ break;
+
+ case OSPF6_LSTYPE_INTER_PREFIX:
+ case OSPF6_LSTYPE_INTER_ROUTER:
+ break;
+
+ default:
+ if (IS_OSPF6_DEBUG_LSA (RECV))
+ zlog_info ("Unknown LSA in Area %s's lsdb", oa->name);
+ break;
+ }
+}
+
+void
+ospf6_area_route_hook_add (struct ospf6_route *route)
+{
+ struct ospf6_route *copy = ospf6_route_copy (route);
+ ospf6_route_add (copy, ospf6->route_table);
+}
+
+void
+ospf6_area_route_hook_remove (struct ospf6_route *route)
+{
+ struct ospf6_route *copy;
+
+ copy = ospf6_route_lookup_identical (route, ospf6->route_table);
+ if (copy)
+ ospf6_route_remove (copy, ospf6->route_table);
}
/* Make new area structure */
struct ospf6_area *
-ospf6_area_create (u_int32_t area_id)
+ospf6_area_create (u_int32_t area_id, struct ospf6 *o)
{
- struct ospf6_area *o6a;
- char namebuf[64];
+ struct ospf6_area *oa;
- /* allocate memory */
- o6a = XCALLOC (MTYPE_OSPF6_AREA, sizeof (struct ospf6_area));
+ oa = XCALLOC (MTYPE_OSPF6_AREA, sizeof (struct ospf6_area));
- /* initialize */
- inet_ntop (AF_INET, &area_id, o6a->str, sizeof (o6a->str));
- o6a->area_id = area_id;
- o6a->if_list = list_new ();
+ inet_ntop (AF_INET, &area_id, oa->name, sizeof (oa->name));
+ oa->area_id = area_id;
+ oa->if_list = list_new ();
- o6a->lsdb = ospf6_lsdb_create ();
- o6a->spf_tree = ospf6_spftree_create ();
+ oa->lsdb = ospf6_lsdb_create ();
+ oa->lsdb->hook_add = ospf6_area_lsdb_hook_add;
+ oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove;
- snprintf (namebuf, sizeof (namebuf), "Area %s's route table", o6a->str);
- o6a->route_table = ospf6_route_table_create (namebuf);
- o6a->route_table->hook_add = ospf6_area_route_add;
- o6a->route_table->hook_change = ospf6_area_route_add;
- o6a->route_table->hook_remove = ospf6_area_route_remove;
+ oa->spf_table = ospf6_route_table_create ();
+ oa->route_table = ospf6_route_table_create ();
+ oa->route_table->hook_add = ospf6_area_route_hook_add;
+ oa->route_table->hook_remove = ospf6_area_route_hook_remove;
- snprintf (namebuf, sizeof (namebuf), "Area %s's topology table", o6a->str);
- o6a->table_topology = ospf6_route_table_create (namebuf);
- o6a->table_topology->hook_add = ospf6_intra_topology_add;
- o6a->table_topology->hook_change = ospf6_intra_topology_add;
- o6a->table_topology->hook_remove = ospf6_intra_topology_remove;
+ /* set default options */
+ OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
+ OSPF6_OPT_SET (oa->options, OSPF6_OPT_E);
+ OSPF6_OPT_SET (oa->options, OSPF6_OPT_R);
- /* xxx, set options */
- OSPF6_OPT_SET (o6a->options, OSPF6_OPT_V6);
- OSPF6_OPT_SET (o6a->options, OSPF6_OPT_E);
- OSPF6_OPT_SET (o6a->options, OSPF6_OPT_R);
+ oa->ospf6 = o;
+ listnode_add_sort (o->area_list, oa);
- o6a->foreach_if = ospf6_area_foreach_interface;
- o6a->foreach_nei = ospf6_area_foreach_neighbor;
-
- return o6a;
+ return oa;
}
void
-ospf6_area_bind_top (struct ospf6_area *o6a, struct ospf6 *o6)
-{
- o6a->ospf6 = o6;
- CALL_CHANGE_HOOK (&area_hook, o6a);
- return;
-}
-
-void
-ospf6_area_delete (struct ospf6_area *o6a)
+ospf6_area_delete (struct ospf6_area *oa)
{
listnode n;
- struct ospf6_interface *o6i;
-
- CALL_REMOVE_HOOK (&area_hook, o6a);
+ struct ospf6_interface *oi;
/* ospf6 interface list */
- for (n = listhead (o6a->if_list); n; nextnode (n))
+ for (n = listhead (oa->if_list); n; nextnode (n))
{
- o6i = (struct ospf6_interface *) getdata (n);
- /* ospf6_interface_delete (o6i); */
+ oi = (struct ospf6_interface *) getdata (n);
+ ospf6_interface_delete (oi);
}
- list_delete (o6a->if_list);
+ list_delete (oa->if_list);
- /* terminate LSDB */
- ospf6_lsdb_remove_all (o6a->lsdb);
+ ospf6_lsdb_delete (oa->lsdb);
+ ospf6_route_table_delete (oa->spf_table);
+ ospf6_route_table_delete (oa->route_table);
- /* spf tree terminate */
- /* xxx */
+#if 0
+ ospf6_spftree_delete (oa->spf_tree);
+ ospf6_route_table_delete (oa->topology_table);
+#endif /*0*/
- /* threads */
- if (o6a->spf_calc)
- thread_cancel (o6a->spf_calc);
- o6a->spf_calc = (struct thread *) NULL;
- if (o6a->route_calc)
- thread_cancel (o6a->route_calc);
- o6a->route_calc = (struct thread *) NULL;
+ THREAD_OFF (oa->thread_spf_calculation);
+ THREAD_OFF (oa->thread_route_calculation);
- /* new */
- ospf6_route_table_delete (o6a->route_table);
-
- ospf6_spftree_delete (o6a->spf_tree);
- ospf6_route_table_delete (o6a->table_topology);
+ listnode_delete (oa->ospf6->area_list, oa);
+ oa->ospf6 = NULL;
/* free area */
- XFREE (MTYPE_OSPF6_AREA, o6a);
+ XFREE (MTYPE_OSPF6_AREA, oa);
}
struct ospf6_area *
-ospf6_area_lookup (u_int32_t area_id, struct ospf6 *o6)
+ospf6_area_lookup (u_int32_t area_id, struct ospf6 *ospf6)
{
- struct ospf6_area *o6a;
+ struct ospf6_area *oa;
listnode n;
- for (n = listhead (o6->area_list); n; nextnode (n))
+ for (n = listhead (ospf6->area_list); n; nextnode (n))
{
- o6a = (struct ospf6_area *) getdata (n);
- if (o6a->area_id == area_id)
- return o6a;
+ oa = (struct ospf6_area *) getdata (n);
+ if (oa->area_id == area_id)
+ return oa;
}
return (struct ospf6_area *) NULL;
}
void
-ospf6_area_show (struct vty *vty, struct ospf6_area *o6a)
+ospf6_area_enable (struct ospf6_area *oa)
{
listnode i;
- struct ospf6_interface *o6i;
+ struct ospf6_interface *oi;
- vty_out (vty, " Area %s%s", o6a->str, VTY_NEWLINE);
- vty_out (vty, " Number of Area scoped LSAs is %u%s",
- o6a->lsdb->count, VTY_NEWLINE);
+ UNSET_FLAG (oa->flag, OSPF6_AREA_DISABLE);
- ospf6_spf_statistics_show (vty, o6a->spf_tree);
-
- vty_out (vty, " Interface attached to this area:");
- for (i = listhead (o6a->if_list); i; nextnode (i))
+ for (i = listhead (oa->if_list); i; nextnode (i))
{
- o6i = (struct ospf6_interface *) getdata (i);
- vty_out (vty, " %s", o6i->interface->name);
- }
- vty_out (vty, "%s", VTY_NEWLINE);
-
- for (i = listhead (o6a->if_list); i; nextnode (i))
- {
- o6i = (struct ospf6_interface *) getdata (i);
- if (listcount (o6i->neighbor_list) != 0)
- ospf6_interface_statistics_show (vty, o6i);
+ oi = (struct ospf6_interface *) getdata (i);
+ ospf6_interface_enable (oi);
}
}
void
-ospf6_area_statistics_show (struct vty *vty, struct ospf6_area *o6a)
+ospf6_area_disable (struct ospf6_area *oa)
{
-#if 0
- listnode node;
- struct ospf6_interface *o6i;
+ listnode i;
+ struct ospf6_interface *oi;
- vty_out (vty, " Statistics of Area %s%s", o6a->str, VTY_NEWLINE);
-#endif
+ SET_FLAG (oa->flag, OSPF6_AREA_DISABLE);
+
+ for (i = listhead (oa->if_list); i; nextnode (i))
+ {
+ oi = (struct ospf6_interface *) getdata (i);
+ ospf6_interface_disable (oi);
+ }
}
-DEFUN (show_ipv6_ospf6_area_route,
- show_ipv6_ospf6_area_route_cmd,
- "show ipv6 ospf6 area A.B.C.D route",
+
+void
+ospf6_area_show (struct vty *vty, struct ospf6_area *oa)
+{
+ listnode i;
+ struct ospf6_interface *oi;
+
+ vty_out (vty, " Area %s%s", oa->name, VTY_NEWLINE);
+ vty_out (vty, " Number of Area scoped LSAs is %u%s",
+ oa->lsdb->count, VTY_NEWLINE);
+
+ vty_out (vty, " Interface attached to this area:");
+ for (i = listhead (oa->if_list); i; nextnode (i))
+ {
+ oi = (struct ospf6_interface *) getdata (i);
+ vty_out (vty, " %s", oi->interface->name);
+ }
+ vty_out (vty, "%s", VTY_NEWLINE);
+}
+
+
+#define OSPF6_CMD_AREA_LOOKUP(str, oa) \
+{ \
+ u_int32_t area_id = 0; \
+ if (inet_pton (AF_INET, str, &area_id) != 1) \
+ { \
+ vty_out (vty, "Malformed Area-ID: %s%s", str, VTY_NEWLINE); \
+ return CMD_SUCCESS; \
+ } \
+ oa = ospf6_area_lookup (area_id, ospf6); \
+ if (oa == NULL) \
+ { \
+ vty_out (vty, "No such Area: %s%s", str, VTY_NEWLINE); \
+ return CMD_SUCCESS; \
+ } \
+}
+
+DEFUN (show_ipv6_ospf6_area_route_intra,
+ show_ipv6_ospf6_area_route_intra_cmd,
+ "show ipv6 ospf6 area A.B.C.D route intra-area",
SHOW_STR
IP6_STR
OSPF6_STR
OSPF6_AREA_STR
OSPF6_AREA_ID_STR
ROUTE_STR
+ "Display Intra-Area routes\n"
)
{
- struct ospf6_area *o6a;
- u_int32_t area_id;
-
- OSPF6_CMD_CHECK_RUNNING ();
-
- inet_pton (AF_INET, argv[0], &area_id);
- o6a = ospf6_area_lookup (area_id, ospf6);
-
- if (! o6a)
- return CMD_SUCCESS;
-
- argc -= 1;
- argv += 1;
-
- return ospf6_route_table_show (vty, argc, argv, o6a->route_table);
+ struct ospf6_area *oa;
+ OSPF6_CMD_AREA_LOOKUP (argv[0], oa);
+ argc--;
+ argv++;
+ return ospf6_route_table_show (vty, argc, argv, oa->route_table);
}
-ALIAS (show_ipv6_ospf6_area_route,
- show_ipv6_ospf6_area_route_prefix_cmd,
- "show ipv6 ospf6 area A.B.C.D route (X::X|detail)",
+ALIAS (show_ipv6_ospf6_area_route_intra,
+ show_ipv6_ospf6_area_route_intra_detail_cmd,
+ "show ipv6 ospf6 area A.B.C.D route intra-area (X::X|X::X/M|detail)",
SHOW_STR
IP6_STR
OSPF6_STR
OSPF6_AREA_STR
OSPF6_AREA_ID_STR
ROUTE_STR
+ "Display Intra-Area routes\n"
"Specify IPv6 address\n"
+ "Specify IPv6 prefix\n"
+ "Detailed information\n"
+ );
+
+DEFUN (show_ipv6_ospf6_area_route_intra_match,
+ show_ipv6_ospf6_area_route_intra_match_cmd,
+ "show ipv6 ospf6 area A.B.C.D route intra-area X::X/M match",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ ROUTE_STR
+ "Display Intra-Area routes\n"
+ OSPF6_AREA_STR
+ OSPF6_AREA_ID_STR
+ "Specify IPv6 prefix\n"
+ "Display routes which match the specified route\n"
+ )
+{
+ char *sargv[CMD_ARGC_MAX];
+ int i, sargc;
+ struct ospf6_area *oa;
+
+ OSPF6_CMD_AREA_LOOKUP (argv[0], oa);
+ argc--;
+ argv++;
+
+ /* copy argv to sargv and then append "match" */
+ for (i = 0; i < argc; i++)
+ sargv[i] = argv[i];
+ sargc = argc;
+ sargv[sargc++] = "match";
+ sargv[sargc] = NULL;
+
+ return ospf6_route_table_show (vty, sargc, sargv, oa->route_table);
+}
+
+DEFUN (show_ipv6_ospf6_area_route_intra_match_detail,
+ show_ipv6_ospf6_area_route_intra_match_detail_cmd,
+ "show ipv6 ospf6 area A.B.C.D route intra-area X::X/M match detail",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ OSPF6_AREA_STR
+ OSPF6_AREA_ID_STR
+ ROUTE_STR
+ "Display Intra-Area routes\n"
+ "Specify IPv6 prefix\n"
+ "Display routes which match the specified route\n"
"Detailed information\n"
)
+{
+ char *sargv[CMD_ARGC_MAX];
+ int i, sargc;
+ struct ospf6_area *oa;
+
+ OSPF6_CMD_AREA_LOOKUP (argv[0], oa);
+ argc--;
+ argv++;
+
+ /* copy argv to sargv and then append "match" and "detail" */
+ for (i = 0; i < argc; i++)
+ sargv[i] = argv[i];
+ sargc = argc;
+ sargv[sargc++] = "match";
+ sargv[sargc++] = "detail";
+ sargv[sargc] = NULL;
+
+ return ospf6_route_table_show (vty, sargc, sargv, oa->route_table);
+}
+
+DEFUN (show_ipv6_ospf6_route_intra,
+ show_ipv6_ospf6_route_intra_cmd,
+ "show ipv6 ospf6 route intra-area",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ ROUTE_STR
+ "Display Intra-Area routes\n"
+ )
+{
+ listnode node;
+ struct ospf6_area *oa;
+
+ for (node = listhead (ospf6->area_list); node; nextnode (node))
+ {
+ oa = (struct ospf6_area *) getdata (node);
+ vty_out (vty, "Area %s%s", oa->name, VTY_NEWLINE);
+ ospf6_route_table_show (vty, argc, argv, oa->route_table);
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_route_intra,
+ show_ipv6_ospf6_route_intra_detail_cmd,
+ "show ipv6 ospf6 route intra-area (X::X|X::X/M|detail|summary)",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ ROUTE_STR
+ "Display Intra-Area routes\n"
+ "Specify IPv6 address\n"
+ "Specify IPv6 prefix\n"
+ "Detailed information\n"
+ "Summary of route table\n"
+ );
+
+DEFUN (show_ipv6_ospf6_route_intra_match,
+ show_ipv6_ospf6_route_intra_match_cmd,
+ "show ipv6 ospf6 route intra-area X::X/M match",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ ROUTE_STR
+ "Display Intra-Area routes\n"
+ "Specify IPv6 prefix\n"
+ "Display routes which match the specified route\n"
+ )
+{
+ char *sargv[CMD_ARGC_MAX];
+ int i, sargc;
+ listnode node;
+ struct ospf6_area *oa;
+
+ /* copy argv to sargv and then append "match" */
+ for (i = 0; i < argc; i++)
+ sargv[i] = argv[i];
+ sargc = argc;
+ sargv[sargc++] = "match";
+ sargv[sargc] = NULL;
+
+ for (node = listhead (ospf6->area_list); node; nextnode (node))
+ {
+ oa = (struct ospf6_area *) getdata (node);
+ ospf6_route_table_show (vty, sargc, sargv, oa->route_table);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ipv6_ospf6_route_intra_match_detail,
+ show_ipv6_ospf6_route_intra_match_detail_cmd,
+ "show ipv6 ospf6 route intra-area X::X/M match detail",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ ROUTE_STR
+ "Display Intra-Area routes\n"
+ "Specify IPv6 prefix\n"
+ "Display routes which match the specified route\n"
+ "Detailed information\n"
+ )
+{
+ char *sargv[CMD_ARGC_MAX];
+ int i, sargc;
+ listnode node;
+ struct ospf6_area *oa;
+
+ /* copy argv to sargv and then append "match" and "detail" */
+ for (i = 0; i < argc; i++)
+ sargv[i] = argv[i];
+ sargc = argc;
+ sargv[sargc++] = "match";
+ sargv[sargc++] = "detail";
+ sargv[sargc] = NULL;
+
+ for (node = listhead (ospf6->area_list); node; nextnode (node))
+ {
+ oa = (struct ospf6_area *) getdata (node);
+ ospf6_route_table_show (vty, sargc, sargv, oa->route_table);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ipv6_ospf6_spf_tree,
+ show_ipv6_ospf6_spf_tree_cmd,
+ "show ipv6 ospf6 spf tree",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ "Shortest Path First caculation\n"
+ "Show SPF tree\n")
+{
+ listnode node;
+ struct ospf6_area *oa;
+ struct ospf6_vertex *root;
+ struct ospf6_route *route;
+ struct prefix prefix;
+
+ ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix);
+ for (node = listhead (ospf6->area_list); node; nextnode (node))
+ {
+ oa = (struct ospf6_area *) getdata (node);
+ route = ospf6_route_lookup (&prefix, oa->spf_table);
+ if (route == NULL)
+ {
+ vty_out (vty, "LS entry for root not found in area %s%s",
+ oa->name, VTY_NEWLINE);
+ continue;
+ }
+ root = (struct ospf6_vertex *) route->route_option;
+ ospf6_spf_display_subtree (vty, "", 0, root);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ipv6_ospf6_area_spf_tree,
+ show_ipv6_ospf6_area_spf_tree_cmd,
+ "show ipv6 ospf6 area A.B.C.D spf tree",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ OSPF6_AREA_STR
+ OSPF6_AREA_ID_STR
+ "Shortest Path First caculation\n"
+ "Show SPF tree\n")
+{
+ u_int32_t area_id;
+ struct ospf6_area *oa;
+ struct ospf6_vertex *root;
+ struct ospf6_route *route;
+ struct prefix prefix;
+
+ ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix);
+
+ if (inet_pton (AF_INET, argv[0], &area_id) != 1)
+ {
+ vty_out (vty, "Malformed Area-ID: %s%s", argv[0], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+ oa = ospf6_area_lookup (area_id, ospf6);
+ if (oa == NULL)
+ {
+ vty_out (vty, "No such Area: %s%s", argv[0], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ route = ospf6_route_lookup (&prefix, oa->spf_table);
+ if (route == NULL)
+ {
+ vty_out (vty, "LS entry for root not found in area %s%s",
+ oa->name, VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+ root = (struct ospf6_vertex *) route->route_option;
+ ospf6_spf_display_subtree (vty, "", 0, root);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ipv6_ospf6_area_spf_table,
+ show_ipv6_ospf6_area_spf_table_cmd,
+ "show ipv6 ospf6 area A.B.C.D spf table",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ OSPF6_AREA_STR
+ OSPF6_AREA_ID_STR
+ "Shortest Path First caculation\n"
+ "Show table contains SPF result\n"
+ )
+{
+ u_int32_t area_id;
+ struct ospf6_area *oa;
+
+ if (inet_pton (AF_INET, argv[0], &area_id) != 1)
+ {
+ vty_out (vty, "Malformed Area-ID: %s%s", argv[0], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+ oa = ospf6_area_lookup (area_id, ospf6);
+ if (oa == NULL)
+ {
+ vty_out (vty, "No such Area: %s%s", argv[0], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ argc--;
+ argv++;
+
+ ospf6_lsentry_table_show (vty, argc, argv, oa->spf_table);
+ return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_area_spf_table,
+ show_ipv6_ospf6_area_spf_table_1_cmd,
+ "show ipv6 ospf6 area A.B.C.D spf table (A.B.C.D|A.B.C.D/M|detail)",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ OSPF6_AREA_STR
+ OSPF6_AREA_ID_STR
+ "Shortest Path First caculation\n"
+ "Show table contains SPF result\n"
+ "Specify Router-ID\n"
+ "Display multiple entry by specifying match-prefix of Router-ID\n"
+ "Display Detail\n"
+ );
+
+ALIAS (show_ipv6_ospf6_area_spf_table,
+ show_ipv6_ospf6_area_spf_table_2_cmd,
+ "show ipv6 ospf6 area A.B.C.D spf table (A.B.C.D|*) (A.B.C.D|A.B.C.D/M|detail)",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ OSPF6_AREA_STR
+ OSPF6_AREA_ID_STR
+ "Shortest Path First caculation\n"
+ "Show table contains SPF result\n"
+ "Specify Router-ID\n"
+ "Wildcard Router-ID\n"
+ "Specify Link State ID\n"
+ "Display multiple entry by specifying match-prefix of Link State ID\n"
+ "Display Detail\n"
+ );
+
+DEFUN (show_ipv6_ospf6_area_spf_table_3,
+ show_ipv6_ospf6_area_spf_table_3_cmd,
+ "show ipv6 ospf6 area A.B.C.D spf table (A.B.C.D|*) A.B.C.D/M detail",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ OSPF6_AREA_STR
+ OSPF6_AREA_ID_STR
+ "Shortest Path First caculation\n"
+ "Show table contains SPF result\n"
+ "Specify Router-ID\n"
+ "Wildcard Router-ID\n"
+ "Display multiple entry by specifying match-prefix of Link State ID\n"
+ "Display Detail\n"
+ )
+{
+ u_int32_t area_id;
+ struct ospf6_area *oa;
+ char *sargv[CMD_ARGC_MAX];
+ int i, sargc;
+
+ if (inet_pton (AF_INET, argv[0], &area_id) != 1)
+ {
+ vty_out (vty, "Malformed Area-ID: %s%s", argv[0], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+ oa = ospf6_area_lookup (area_id, ospf6);
+ if (oa == NULL)
+ {
+ vty_out (vty, "No such Area: %s%s", argv[0], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ argc--;
+ argv++;
+
+ /* copy argv to sargv and then append "detail" */
+ for (i = 0; i < argc; i++)
+ sargv[i] = argv[i];
+ sargc = argc;
+ sargv[sargc++] = "detail";
+ sargv[sargc] = NULL;
+
+ ospf6_lsentry_table_show (vty, sargc, sargv, oa->spf_table);
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ipv6_ospf6_spf_table,
+ show_ipv6_ospf6_spf_table_cmd,
+ "show ipv6 ospf6 spf table",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ "Shortest Path First caculation\n"
+ "Show table contains SPF result\n"
+ )
+{
+ listnode node;
+ struct ospf6_area *oa;
+
+ for (node = listhead (ospf6->area_list); node; nextnode (node))
+ {
+ oa = (struct ospf6_area *) getdata (node);
+ ospf6_lsentry_table_show (vty, argc, argv, oa->spf_table);
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_spf_table,
+ show_ipv6_ospf6_spf_table_1_cmd,
+ "show ipv6 ospf6 spf table (A.B.C.D|A.B.C.D/M|detail)",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ "Shortest Path First caculation\n"
+ "Show table contains SPF result\n"
+ "Specify Router-ID\n"
+ "Display multiple entry by specifying match-prefix of Router-ID\n"
+ "Display Detail\n"
+ );
+
+ALIAS (show_ipv6_ospf6_spf_table,
+ show_ipv6_ospf6_spf_table_2_cmd,
+ "show ipv6 ospf6 spf table (A.B.C.D|A.B.C.D/M|*) (A.B.C.D|A.B.C.D/M|detail)",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ "Shortest Path First caculation\n"
+ "Show table contains SPF result\n"
+ "Specify Router-ID\n"
+ "Display multiple entry by specifying match-prefix of Router-ID\n"
+ "Wildcard Router-ID\n"
+ "Specify Link State ID\n"
+ "Display multiple entry by specifying match-prefix of Link State ID\n"
+ "Display Detail\n"
+ );
+
+DEFUN (show_ipv6_ospf6_spf_table_3,
+ show_ipv6_ospf6_spf_table_3_cmd,
+ "show ipv6 ospf6 spf table (A.B.C.D|*) A.B.C.D/M detail",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ "Shortest Path First caculation\n"
+ "Show table contains SPF result\n"
+ "Specify Router-ID\n"
+ "Wildcard Router-ID\n"
+ "Display multiple entry by specifying match-prefix of Link State ID\n"
+ "Display Detail\n"
+ )
+{
+ listnode node;
+ struct ospf6_area *oa;
+ char *sargv[CMD_ARGC_MAX];
+ int i, sargc;
+
+ /* copy argv to sargv and then append "detail" */
+ for (i = 0; i < argc; i++)
+ sargv[i] = argv[i];
+ sargc = argc;
+ sargv[sargc++] = "detail";
+ sargv[sargc] = NULL;
+
+ for (node = listhead (ospf6->area_list); node; nextnode (node))
+ {
+ oa = (struct ospf6_area *) getdata (node);
+ ospf6_lsentry_table_show (vty, sargc, sargv, oa->spf_table);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (show_ipv6_ospf6_simulate_spf_tree_root,
+ show_ipv6_ospf6_simulate_spf_tree_root_cmd,
+ "show ipv6 ospf6 simulate spf-tree A.B.C.D area A.B.C.D",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ "Shortest Path First caculation\n"
+ "Show SPF tree\n"
+ "Specify root's router-id to calculate another router's SPF tree\n")
+{
+ u_int32_t area_id;
+ struct ospf6_area *oa;
+ struct ospf6_vertex *root;
+ struct ospf6_route *route;
+ struct prefix prefix;
+ u_int32_t router_id;
+ struct ospf6_route_table *spf_table;
+ unsigned char tmp_debug_ospf6_spf = 0;
+
+ inet_pton (AF_INET, argv[0], &router_id);
+ ospf6_linkstate_prefix (router_id, htonl (0), &prefix);
+
+ if (inet_pton (AF_INET, argv[1], &area_id) != 1)
+ {
+ vty_out (vty, "Malformed Area-ID: %s%s", argv[1], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+ oa = ospf6_area_lookup (area_id, ospf6);
+ if (oa == NULL)
+ {
+ vty_out (vty, "No such Area: %s%s", argv[1], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ tmp_debug_ospf6_spf = conf_debug_ospf6_spf;
+ conf_debug_ospf6_spf = 0;
+
+ spf_table = ospf6_route_table_create ();
+ ospf6_spf_calculation (router_id, spf_table, oa);
+
+ conf_debug_ospf6_spf = tmp_debug_ospf6_spf;
+
+ route = ospf6_route_lookup (&prefix, spf_table);
+ if (route == NULL)
+ {
+ ospf6_spf_table_finish (spf_table);
+ ospf6_route_table_delete (spf_table);
+ return CMD_SUCCESS;
+ }
+ root = (struct ospf6_vertex *) route->route_option;
+ ospf6_spf_display_subtree (vty, "", 0, root);
+
+ ospf6_spf_table_finish (spf_table);
+ ospf6_route_table_delete (spf_table);
+
+ return CMD_SUCCESS;
+}
void
ospf6_area_init ()
{
- area_index = ospf6_dump_install ("area", "Area information\n");
+ install_element (VIEW_NODE, &show_ipv6_ospf6_spf_tree_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_spf_table_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_spf_table_1_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_spf_table_2_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_spf_table_3_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_area_spf_table_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_area_spf_table_1_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_area_spf_table_2_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_area_spf_table_3_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_area_route_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_area_route_prefix_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_area_route_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_area_route_prefix_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_route_intra_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_route_intra_detail_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_route_intra_match_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_route_intra_match_detail_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_area_route_intra_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_area_route_intra_detail_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_area_route_intra_match_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_area_route_intra_match_detail_cmd);
+
+ install_element (VIEW_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
+
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_spf_tree_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_spf_table_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_spf_table_1_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_spf_table_2_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_spf_table_3_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_area_spf_table_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_area_spf_table_1_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_area_spf_table_2_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_area_spf_table_3_cmd);
+
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_route_intra_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_route_intra_detail_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_route_intra_match_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_route_intra_match_detail_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_area_route_intra_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_area_route_intra_detail_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_area_route_intra_match_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_area_route_intra_match_detail_cmd);
+
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_simulate_spf_tree_root_cmd);
}
-
-
diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h
index 0684464..14d3eb9 100644
--- a/ospf6d/ospf6_area.h
+++ b/ospf6d/ospf6_area.h
@@ -1,6 +1,5 @@
/*
- * OSPF6 Area Data Structure
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -23,67 +22,54 @@
#ifndef OSPF_AREA_H
#define OSPF_AREA_H
-/* This file defines area parameters and data structures. */
-
-#define OSPF6_AREA_RANGE_ADVERTISE 0
-#define OSPF6_AREA_RANGE_NOT_ADVERTISE 1
-
-#include "ospf6_spf.h"
#include "ospf6_top.h"
struct ospf6_area
{
- char str[16];
+ /* Reference to Top data structure */
+ struct ospf6 *ospf6;
- struct ospf6 *ospf6; /* back pointer */
- u_int32_t area_id;
- u_char options[3]; /* OSPF Option including ExternalCapability */
+ /* Area-ID */
+ u_int32_t area_id;
- list if_list; /* OSPF interface to this area */
+ /* Area-ID string */
+ char name[16];
- struct ospf6_lsdb *lsdb;
+ /* flag */
+ u_char flag;
- struct thread *spf_calc;
- struct thread *route_calc;
- int stat_spf_execed;
- int stat_route_execed;
+ /* OSPF Option */
+ u_char options[3];
- struct route_table *table; /* new route table */
+ /* OSPF interface list */
+ list if_list;
- struct prefix_ipv6 area_range;
- struct ospf6_spftree *spf_tree;
-
+ struct ospf6_lsdb *lsdb;
+ struct ospf6_route_table *spf_table;
struct ospf6_route_table *route_table;
- struct ospf6_route_table *table_topology;
- void (*foreach_if) (struct ospf6_area *, void *, int,
- void (*func) (void *, int, void *));
- void (*foreach_nei) (struct ospf6_area *, void *, int,
- void (*func) (void *, int, void *));
-
- struct thread *maxage_remover;
+ struct thread *thread_spf_calculation;
+ struct thread *thread_route_calculation;
struct thread *thread_router_lsa;
+ struct thread *thread_intra_prefix_lsa;
+ u_int32_t router_lsa_size_limit;
};
+#define OSPF6_AREA_DISABLE 0x01
+#define OSPF6_AREA_STUB 0x02
/* prototypes */
-
-int
-ospf6_area_count_neighbor_in_state (u_char state, struct ospf6_area *o6a);
-
-void
-ospf6_area_schedule_maxage_remover (void *arg, int val, void *obj);
-
+int ospf6_area_cmp (void *va, void *vb);
int ospf6_area_is_stub (struct ospf6_area *o6a);
-int ospf6_area_is_transit (struct ospf6_area *o6a);
-struct ospf6_area *ospf6_area_lookup (u_int32_t, struct ospf6 *);
-struct ospf6_area *ospf6_area_create (u_int32_t);
+struct ospf6_area *ospf6_area_create (u_int32_t, struct ospf6 *);
void ospf6_area_delete (struct ospf6_area *);
-void ospf6_area_show (struct vty *, struct ospf6_area *);
-void
-ospf6_area_statistics_show (struct vty *vty, struct ospf6_area *o6a);
+struct ospf6_area *ospf6_area_lookup (u_int32_t, struct ospf6 *);
+void ospf6_area_enable (struct ospf6_area *);
+void ospf6_area_disable (struct ospf6_area *);
+
+void ospf6_area_show (struct vty *, struct ospf6_area *);
void ospf6_area_init ();
#endif /* OSPF_AREA_H */
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 5846ab8..81edb60 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2001-2002 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -30,78 +30,644 @@
#include "table.h"
#include "plist.h"
#include "thread.h"
+#include "linklist.h"
-#include "ospf6_prefix.h" /* xxx for ospf6_asbr.h */
-#include "ospf6_lsa.h" /* xxx for ospf6_asbr.h */
-#include "ospf6_route.h" /* xxx for ospf6_asbr.h, ospf6_zebra.h */
-#include "ospf6_zebra.h"
-#include "ospf6_asbr.h"
-#include "ospf6_damp.h"
-#include "ospf6_top.h"
-#include "ospf6_lsdb.h"
+#include "ospf6d.h"
#include "ospf6_proto.h"
+#include "ospf6_lsa.h"
+#include "ospf6_lsdb.h"
+#include "ospf6_route.h"
+#include "ospf6_zebra.h"
+#include "ospf6_top.h"
+#include "ospf6_area.h"
+#include "ospf6_asbr.h"
+#include "ospf6_intra.h"
-extern struct thread_master *master;
+unsigned char conf_debug_ospf6_asbr = 0;
-struct route_table *external_table;
-struct
+char *zroute_name[] =
+{ "system", "kernel", "connected", "static",
+ "rip", "ripng", "ospf", "ospf6", "bgp", "unknown" };
+
+char *zroute_abname[] =
+{ "X", "K", "C", "S", "R", "R", "O", "O", "B", "?" };
+
+#define ZROUTE_NAME(x) \
+ (0 < (x) && (x) < ZEBRA_ROUTE_MAX ? zroute_name[(x)] : \
+ zroute_name[ZEBRA_ROUTE_MAX])
+#define ZROUTE_ABNAME(x) \
+ (0 < (x) && (x) < ZEBRA_ROUTE_MAX ? zroute_abname[(x)] : \
+ zroute_abname[ZEBRA_ROUTE_MAX])
+
+/* AS External LSA origination */
+void
+ospf6_as_external_lsa_originate_sub (struct ospf6_route *route, int force)
{
- char *name;
- struct route_map *map;
-} rmap [ZEBRA_ROUTE_MAX];
+ char buffer[OSPF6_MAX_LSASIZE];
+ struct ospf6_lsa_header *lsa_header;
+ struct ospf6_lsa *old, *lsa;
-static u_int32_t link_state_id = 0;
+ struct ospf6_external_info *info = route->route_option;
+ struct ospf6_as_external_lsa *as_external_lsa;
+ char buf[64];
+ caddr_t p;
-char *
-zroute_name[] =
-{
- "system", "kernel", "connected", "static",
- "rip", "ripng", "ospf", "ospf6", "isis", "bgp", "unknown"
-};
-char *
-zroute_abname[] =
+ /* find previous LSA */
+ old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
+ htonl (info->id), ospf6->router_id,
+ ospf6->lsdb);
+
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ {
+ prefix2str (&route->prefix, buf, sizeof (buf));
+ zlog_info ("Originate AS-External-LSA for %s", buf);
+ }
+
+ /* prepare buffer */
+ memset (buffer, 0, sizeof (buffer));
+ lsa_header = (struct ospf6_lsa_header *) buffer;
+ as_external_lsa = (struct ospf6_as_external_lsa *)
+ ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
+ p = (caddr_t)
+ ((caddr_t) as_external_lsa + sizeof (struct ospf6_as_external_lsa));
+
+ /* Fill AS-External-LSA */
+ /* Metric type */
+ if (route->path.metric_type == 2)
+ SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
+ else
+ UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
+
+ /* forwarding address */
+ if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
+ SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
+ else
+ UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
+
+ /* external route tag */
+ UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);
+
+ /* Set metric */
+ OSPF6_ASBR_METRIC_SET (as_external_lsa, route->path.cost);
+
+ /* prefixlen */
+ as_external_lsa->prefix.prefix_length = route->prefix.prefixlen;
+
+ /* PrefixOptions */
+ as_external_lsa->prefix.prefix_options = route->path.prefix_options;
+
+ /* don't use refer LS-type */
+ as_external_lsa->prefix.prefix_refer_lstype = htons (0);
+
+ /* set Prefix */
+ memcpy (p, &route->prefix.u.prefix6,
+ OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
+ ospf6_prefix_apply_mask (&as_external_lsa->prefix);
+ p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);
+
+ /* Forwarding address */
+ if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
+ {
+ memcpy (p, &info->forwarding, sizeof (struct in6_addr));
+ p += sizeof (struct in6_addr);
+ }
+
+ /* External Route Tag */
+ if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
+ {
+ /* xxx */
+ }
+
+ /* Fill LSA Header */
+ lsa_header->age = 0;
+ lsa_header->type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
+ lsa_header->id = htonl (info->id);
+ lsa_header->adv_router = ospf6->router_id;
+ lsa_header->seqnum =
+ ospf6_lsa_new_seqnum (lsa_header->type, lsa_header->id,
+ lsa_header->adv_router, ospf6);
+ lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header);
+
+ /* LSA checksum */
+ ospf6_lsa_checksum (lsa_header);
+
+ /* create LSA */
+ lsa = ospf6_lsa_create (lsa_header);
+ lsa->scope = ospf6;
+ if (force)
+ SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
+
+ /* Originate */
+ ospf6_lsa_originate (lsa);
+}
+
+int
+ospf6_as_external_lsa_reoriginate (struct ospf6_lsa *lsa)
{
- "X", "K", "C", "S", "R", "R", "O", "O", "I", "B", "?"
-};
+ struct prefix prefix_id;
+ struct route_node *node;
+ struct ospf6_route *route;
-#define ZROUTE_NAME(x) \
- (0 < (x) && (x) < ZEBRA_ROUTE_MAX ? \
- zroute_name[(x)] : zroute_name[ZEBRA_ROUTE_MAX])
+ /* create/update binding in external_id_table */
+ prefix_id.family = AF_INET;
+ prefix_id.prefixlen = 32;
+ prefix_id.u.prefix4.s_addr = lsa->header->id;
+ node = route_node_get (ospf6->external_id_table, &prefix_id);
+ route = node->info;
-#define ZROUTE_ABNAME(x) \
- (0 < (x) && (x) < ZEBRA_ROUTE_MAX ? \
- zroute_abname[(x)] : zroute_abname[ZEBRA_ROUTE_MAX])
+ if (route)
+ ospf6_as_external_lsa_originate_sub (route, 1);
+ else
+ ospf6_lsa_premature_aging (lsa);
+ return 0;
+}
+
+
+
+void
+ospf6_asbr_lsa_add (struct ospf6_lsa *lsa)
+{
+ struct ospf6_as_external_lsa *external;
+ struct prefix asbr_id;
+ struct ospf6_route *asbr_entry, *route;
+ char buf[64];
+ int i;
+
+ external = (struct ospf6_as_external_lsa *)
+ OSPF6_LSA_HEADER_END (lsa->header);
+
+ if (IS_OSPF6_DEBUG_ASBR)
+ zlog_info ("Calculate AS-External route for %s", lsa->name);
+
+ if (lsa->header->adv_router == ospf6->router_id)
+ {
+ if (IS_OSPF6_DEBUG_ASBR)
+ zlog_info ("Ignore self-originated AS-External-LSA");
+ return;
+ }
+
+ if (OSPF6_ASBR_METRIC (external) == LS_INFINITY)
+ {
+ if (IS_OSPF6_DEBUG_ASBR)
+ zlog_info ("Ignore LSA with LSInfinity Metric");
+ return;
+ }
+
+ asbr_id.family = AF_INET;
+ asbr_id.prefixlen = 32;
+ asbr_id.u.prefix4.s_addr = lsa->header->adv_router;
+ asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->asbr_table);
+
+ if (asbr_entry == NULL)
+ {
+ if (IS_OSPF6_DEBUG_ASBR)
+ {
+ prefix2str (&asbr_id, buf, sizeof (buf));
+ zlog_info ("ASBR entry not found: %s", buf);
+ }
+ return;
+ }
+
+ route = ospf6_route_create ();
+ route->type = OSPF6_DEST_TYPE_NETWORK;
+ route->prefix.family = AF_INET6;
+ route->prefix.prefixlen = external->prefix.prefix_length;
+ ospf6_prefix_in6_addr (&route->prefix.u.prefix6, &external->prefix);
+
+ route->path.area_id = asbr_entry->path.area_id;
+ route->path.origin.type = lsa->header->type;
+ route->path.origin.id = lsa->header->id;
+ route->path.origin.adv_router = lsa->header->adv_router;
+
+ route->path.prefix_options = external->prefix.prefix_options;
+ if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E))
+ {
+ route->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
+ route->path.metric_type = 2;
+ route->path.cost = asbr_entry->path.cost;
+ route->path.cost_e2 = OSPF6_ASBR_METRIC (external);
+ }
+ else
+ {
+ route->path.type = OSPF6_PATH_TYPE_EXTERNAL1;
+ route->path.metric_type = 1;
+ route->path.cost = asbr_entry->path.cost + OSPF6_ASBR_METRIC (external);
+ route->path.cost_e2 = 0;
+ }
+
+ for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
+ ospf6_nexthop_copy (&route->nexthop[i], &asbr_entry->nexthop[i]);
+
+ if (IS_OSPF6_DEBUG_ASBR)
+ {
+ prefix2str (&route->prefix, buf, sizeof (buf));
+ zlog_info ("AS-External route add: %s", buf);
+ }
+
+ ospf6_route_add (route, ospf6->route_table);
+}
+
+void
+ospf6_asbr_lsa_remove (struct ospf6_lsa *lsa)
+{
+ struct ospf6_as_external_lsa *external;
+ struct prefix prefix;
+ struct ospf6_route *route;
+ char buf[64];
+
+ external = (struct ospf6_as_external_lsa *)
+ OSPF6_LSA_HEADER_END (lsa->header);
+
+ if (IS_OSPF6_DEBUG_ASBR)
+ zlog_info ("Withdraw AS-External route for %s", lsa->name);
+
+ if (lsa->header->adv_router == ospf6->router_id)
+ {
+ if (IS_OSPF6_DEBUG_ASBR)
+ zlog_info ("Ignore self-originated AS-External-LSA");
+ return;
+ }
+
+ memset (&prefix, 0, sizeof (struct prefix));
+ prefix.family = AF_INET6;
+ prefix.prefixlen = external->prefix.prefix_length;
+ ospf6_prefix_in6_addr (&prefix.u.prefix6, &external->prefix);
+
+ route = ospf6_route_lookup (&prefix, ospf6->route_table);
+ if (route == NULL)
+ {
+ if (IS_OSPF6_DEBUG_ASBR)
+ {
+ prefix2str (&prefix, buf, sizeof (buf));
+ zlog_info ("AS-External route %s not found", buf);
+ }
+ return;
+ }
+
+ for (ospf6_route_lock (route);
+ route && ospf6_route_is_prefix (&prefix, route);
+ route = ospf6_route_next (route))
+ {
+ if (route->type != OSPF6_DEST_TYPE_NETWORK)
+ continue;
+ if (route->path.origin.type != lsa->header->type)
+ continue;
+ if (route->path.origin.id != lsa->header->id)
+ continue;
+ if (route->path.origin.adv_router != lsa->header->adv_router)
+ continue;
+
+ if (IS_OSPF6_DEBUG_ASBR)
+ {
+ prefix2str (&route->prefix, buf, sizeof (buf));
+ zlog_info ("AS-External route remove: %s", buf);
+ }
+ ospf6_route_remove (route, ospf6->route_table);
+ }
+}
+
+void
+ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry)
+{
+ char buf[64];
+ struct ospf6_lsa *lsa;
+ u_int16_t type;
+ u_int32_t router;
+
+ if (IS_OSPF6_DEBUG_ASBR)
+ {
+ ospf6_linkstate_prefix2str (&asbr_entry->prefix, buf, sizeof (buf));
+ zlog_info ("New ASBR %s found", buf);
+ }
+
+ type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
+ router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
+ for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb);
+ lsa; lsa = ospf6_lsdb_type_router_next (type, router, lsa))
+ {
+ if (! OSPF6_LSA_IS_MAXAGE (lsa))
+ ospf6_asbr_lsa_add (lsa);
+ }
+
+ if (IS_OSPF6_DEBUG_ASBR)
+ {
+ ospf6_linkstate_prefix2str (&asbr_entry->prefix, buf, sizeof (buf));
+ zlog_info ("Calculation for new ASBR %s done", buf);
+ }
+}
+
+void
+ospf6_asbr_lsentry_remove (struct ospf6_route *asbr_entry)
+{
+ char buf[64];
+ struct ospf6_lsa *lsa;
+ u_int16_t type;
+ u_int32_t router;
+
+ if (IS_OSPF6_DEBUG_ASBR)
+ {
+ ospf6_linkstate_prefix2str (&asbr_entry->prefix, buf, sizeof (buf));
+ zlog_info ("ASBR %s disappeared", buf);
+ }
+
+ type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
+ router = ospf6_linkstate_prefix_adv_router (&asbr_entry->prefix);
+ for (lsa = ospf6_lsdb_type_router_head (type, router, ospf6->lsdb);
+ lsa; lsa = ospf6_lsdb_type_router_next (type, router, lsa))
+ ospf6_asbr_lsa_remove (lsa);
+
+ if (IS_OSPF6_DEBUG_ASBR)
+ {
+ ospf6_linkstate_prefix2str (&asbr_entry->prefix, buf, sizeof (buf));
+ zlog_info ("Calculation for old ASBR %s done", buf);
+ }
+}
+
+
+
/* redistribute function */
+
void
ospf6_asbr_routemap_set (int type, char *mapname)
{
- if (rmap[type].name)
- free (rmap[type].name);
-
- rmap[type].name = strdup (mapname);
- rmap[type].map = route_map_lookup_by_name (mapname);
+ if (ospf6->rmap[type].name)
+ free (ospf6->rmap[type].name);
+ ospf6->rmap[type].name = strdup (mapname);
+ ospf6->rmap[type].map = route_map_lookup_by_name (mapname);
}
void
ospf6_asbr_routemap_unset (int type)
{
- if (rmap[type].name)
- free (rmap[type].name);
- rmap[type].name = NULL;
- rmap[type].map = NULL;
+ if (ospf6->rmap[type].name)
+ free (ospf6->rmap[type].name);
+ ospf6->rmap[type].name = NULL;
+ ospf6->rmap[type].map = NULL;
}
void
ospf6_asbr_routemap_update ()
{
- int i;
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ int type;
+
+ if (ospf6 == NULL)
+ return;
+
+ for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
{
- if (rmap[i].name)
- rmap[i].map = route_map_lookup_by_name (rmap[i].name);
+ if (ospf6->rmap[type].name)
+ ospf6->rmap[type].map =
+ route_map_lookup_by_name (ospf6->rmap[type].name);
else
- rmap[i].map = NULL;
+ ospf6->rmap[type].map = NULL;
+ }
+}
+
+int
+ospf6_asbr_is_asbr (struct ospf6 *o)
+{
+ return o->external_table->count;
+}
+
+void
+ospf6_asbr_redistribute_set (int type)
+{
+ ospf6_zebra_redistribute (type);
+}
+
+void
+ospf6_asbr_redistribute_unset (int type)
+{
+ struct ospf6_route *route;
+ struct ospf6_external_info *info;
+
+ ospf6_zebra_no_redistribute (type);
+
+ for (route = ospf6_route_head (ospf6->external_table); route;
+ route = ospf6_route_next (route))
+ {
+ info = route->route_option;
+ if (info->type != type)
+ continue;
+
+ ospf6_asbr_redistribute_remove (info->type, route->nexthop[0].ifindex,
+ &route->prefix);
+ }
+}
+
+void
+ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix,
+ u_int nexthop_num, struct in6_addr *nexthop)
+{
+ int ret;
+ struct ospf6_route troute;
+ struct ospf6_external_info tinfo;
+ struct ospf6_route *route, *match;
+ struct ospf6_external_info *info;
+ struct prefix prefix_id;
+ struct route_node *node;
+ char pbuf[64], ibuf[16];
+ listnode lnode;
+ struct ospf6_area *oa;
+
+ if (! ospf6_zebra_is_redistribute (type))
+ return;
+
+ if (IS_OSPF6_DEBUG_ASBR)
+ {
+ prefix2str (prefix, pbuf, sizeof (pbuf));
+ zlog_info ("Redistribute %s (%s)", pbuf, ZROUTE_NAME (type));
+ }
+
+ /* if route-map was specified but not found, do not advertise */
+ if (ospf6->rmap[type].name)
+ {
+ if (ospf6->rmap[type].map == NULL)
+ ospf6_asbr_routemap_update ();
+ if (ospf6->rmap[type].map == NULL)
+ {
+ zlog_warn ("route-map \"%s\" not found, suppress redistributing",
+ ospf6->rmap[type].name);
+ return;
+ }
+ }
+
+ /* apply route-map */
+ if (ospf6->rmap[type].map)
+ {
+ memset (&troute, 0, sizeof (troute));
+ memset (&tinfo, 0, sizeof (tinfo));
+ troute.route_option = &tinfo;
+
+ ret = route_map_apply (ospf6->rmap[type].map, prefix,
+ RMAP_OSPF6, &troute);
+ if (ret != RMAP_MATCH)
+ {
+ if (IS_OSPF6_DEBUG_ASBR)
+ zlog_info ("Denied by route-map \"%s\"", ospf6->rmap[type].name);
+ return;
+ }
+ }
+
+ match = ospf6_route_lookup (prefix, ospf6->external_table);
+ if (match)
+ {
+ info = match->route_option;
+
+ /* copy result of route-map */
+ if (ospf6->rmap[type].map)
+ {
+ if (troute.path.metric_type)
+ match->path.metric_type = troute.path.metric_type;
+ if (troute.path.cost)
+ match->path.cost = troute.path.cost;
+ if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
+ memcpy (&info->forwarding, &tinfo.forwarding,
+ sizeof (struct in6_addr));
+ }
+
+ info->type = type;
+ match->nexthop[0].ifindex = ifindex;
+ if (nexthop_num && nexthop)
+ memcpy (&match->nexthop[0].address, nexthop, sizeof (struct in6_addr));
+
+ /* create/update binding in external_id_table */
+ prefix_id.family = AF_INET;
+ prefix_id.prefixlen = 32;
+ prefix_id.u.prefix4.s_addr = htonl (info->id);
+ node = route_node_get (ospf6->external_id_table, &prefix_id);
+ node->info = match;
+
+ if (IS_OSPF6_DEBUG_ASBR)
+ {
+ inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
+ zlog_info ("Advertise as AS-External Id:%s", ibuf);
+ }
+
+ ospf6_as_external_lsa_originate_sub (match, 0);
+ return;
+ }
+
+ /* create new entry */
+ route = ospf6_route_create ();
+ route->type = OSPF6_DEST_TYPE_NETWORK;
+ memcpy (&route->prefix, prefix, sizeof (struct prefix));
+
+ info = (struct ospf6_external_info *)
+ XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO, sizeof (struct ospf6_external_info));
+ memset (info, 0, sizeof (struct ospf6_external_info));
+ route->route_option = info;
+ info->id = ospf6->external_id++;
+
+ /* copy result of route-map */
+ if (ospf6->rmap[type].map)
+ {
+ if (troute.path.metric_type)
+ route->path.metric_type = troute.path.metric_type;
+ if (troute.path.cost)
+ route->path.cost = troute.path.cost;
+ if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
+ memcpy (&info->forwarding, &tinfo.forwarding,
+ sizeof (struct in6_addr));
+ }
+
+ info->type = type;
+ route->nexthop[0].ifindex = ifindex;
+ if (nexthop_num && nexthop)
+ memcpy (&route->nexthop[0].address, nexthop, sizeof (struct in6_addr));
+
+ /* create/update binding in external_id_table */
+ prefix_id.family = AF_INET;
+ prefix_id.prefixlen = 32;
+ prefix_id.u.prefix4.s_addr = htonl (info->id);
+ node = route_node_get (ospf6->external_id_table, &prefix_id);
+ node->info = route;
+
+ route = ospf6_route_add (route, ospf6->external_table);
+ route->route_option = info;
+
+ if (IS_OSPF6_DEBUG_ASBR)
+ {
+ inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
+ zlog_info ("Advertise as AS-External Id:%s", ibuf);
+ }
+
+ ospf6_as_external_lsa_originate_sub (route, 0);
+
+ /* Router-Bit (ASBR Flag) may have to be updated */
+ for (lnode = listhead (ospf6->area_list); lnode; nextnode (lnode))
+ {
+ oa = (struct ospf6_area *) getdata (lnode);
+ OSPF6_ROUTER_LSA_SCHEDULE (oa);
+ }
+}
+
+void
+ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix)
+{
+ struct ospf6_route *match;
+ struct ospf6_external_info *info = NULL;
+ struct route_node *node;
+ struct ospf6_lsa *lsa;
+ struct prefix prefix_id;
+ char pbuf[64], ibuf[16];
+ listnode lnode;
+ struct ospf6_area *oa;
+
+ match = ospf6_route_lookup (prefix, ospf6->external_table);
+ if (match == NULL)
+ {
+ if (IS_OSPF6_DEBUG_ASBR)
+ {
+ prefix2str (prefix, pbuf, sizeof (pbuf));
+ zlog_info ("No such route %s to withdraw", pbuf);
+ }
+ return;
+ }
+
+ info = match->route_option;
+ assert (info);
+
+ if (info->type != type)
+ {
+ if (IS_OSPF6_DEBUG_ASBR)
+ {
+ prefix2str (prefix, pbuf, sizeof (pbuf));
+ zlog_info ("Original protocol mismatch: %s", pbuf);
+ }
+ return;
+ }
+
+ if (IS_OSPF6_DEBUG_ASBR)
+ {
+ prefix2str (prefix, pbuf, sizeof (pbuf));
+ inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
+ zlog_info ("Withdraw %s (AS-External Id:%s)", pbuf, ibuf);
+ }
+
+ lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
+ htonl (info->id), ospf6->router_id, ospf6->lsdb);
+ if (lsa)
+ ospf6_lsa_premature_aging (lsa);
+
+ /* remove binding in external_id_table */
+ prefix_id.family = AF_INET;
+ prefix_id.prefixlen = 32;
+ prefix_id.u.prefix4.s_addr = htonl (info->id);
+ node = route_node_lookup (ospf6->external_id_table, &prefix_id);
+ assert (node);
+ node->info = NULL;
+ route_unlock_node (node);
+
+ ospf6_route_remove (match, ospf6->external_table);
+ XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info);
+
+ /* Router-Bit (ASBR Flag) may have to be updated */
+ for (lnode = listhead (ospf6->area_list); lnode; nextnode (lnode))
+ {
+ oa = (struct ospf6_area *) getdata (lnode);
+ OSPF6_ROUTER_LSA_SCHEDULE (oa);
}
}
@@ -129,9 +695,9 @@
else if (strncmp (argv[0], "bgp", 3) == 0)
type = ZEBRA_ROUTE_BGP;
- ospf6_zebra_no_redistribute (type);
+ ospf6_asbr_redistribute_unset (type);
ospf6_asbr_routemap_unset (type);
- ospf6_zebra_redistribute (type);
+ ospf6_asbr_redistribute_set (type);
return CMD_SUCCESS;
}
@@ -161,9 +727,9 @@
else if (strncmp (argv[0], "bgp", 3) == 0)
type = ZEBRA_ROUTE_BGP;
- ospf6_zebra_no_redistribute (type);
+ ospf6_asbr_redistribute_unset (type);
ospf6_asbr_routemap_set (type, argv[1]);
- ospf6_zebra_redistribute (type);
+ ospf6_asbr_redistribute_set (type);
return CMD_SUCCESS;
}
@@ -180,9 +746,6 @@
)
{
int type = 0;
- struct route_node *node;
- struct ospf6_external_route *route;
- struct ospf6_external_info *info, *info_next = NULL;
if (strncmp (argv[0], "sta", 3) == 0)
type = ZEBRA_ROUTE_STATIC;
@@ -195,48 +758,30 @@
else if (strncmp (argv[0], "bgp", 3) == 0)
type = ZEBRA_ROUTE_BGP;
- ospf6_zebra_no_redistribute (type);
+ ospf6_asbr_redistribute_unset (type);
ospf6_asbr_routemap_unset (type);
- /* remove redistributed route */
- for (node = route_top (external_table); node; node = route_next (node))
- {
- route = node->info;
- if (! route)
- continue;
- for (info = route->info_head; info; info = info_next)
- {
- info_next = info->next;
- if (info->type != type)
- continue;
- ospf6_asbr_route_remove (info->type, info->ifindex,
- &route->prefix);
- }
- }
-
return CMD_SUCCESS;
}
-
int
ospf6_redistribute_config_write (struct vty *vty)
{
- int i;
+ int type;
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+ for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
{
- if (i == ZEBRA_ROUTE_OSPF6)
+ if (type == ZEBRA_ROUTE_OSPF6)
+ continue;
+ if (! ospf6_zebra_is_redistribute (type))
continue;
- if (! ospf6_zebra_is_redistribute (i))
- continue;
-
- if (rmap[i].map)
+ if (ospf6->rmap[type].name)
vty_out (vty, " redistribute %s route-map %s%s",
- ZROUTE_NAME(i), rmap[i].name, VTY_NEWLINE);
+ ZROUTE_NAME (type), ospf6->rmap[type].name, VTY_NEWLINE);
else
vty_out (vty, " redistribute %s%s",
- ZROUTE_NAME(i), VTY_NEWLINE);
+ ZROUTE_NAME (type), VTY_NEWLINE);
}
return 0;
@@ -245,748 +790,420 @@
void
ospf6_redistribute_show_config (struct vty *vty)
{
- int i;
-
- if (! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_SYSTEM) &&
- ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_KERNEL) &&
- ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_STATIC) &&
- ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_RIPNG) &&
- ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_BGP))
- return;
-
- vty_out (vty, " Redistributing External Routes from,%s", VTY_NEWLINE);
- for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
- {
- if (i == ZEBRA_ROUTE_OSPF6)
- continue;
- if (! ospf6_zebra_is_redistribute (i))
- continue;
-
- if (rmap[i].map)
- vty_out (vty, " %s with route-map %s%s",
- ZROUTE_NAME(i), rmap[i].name, VTY_NEWLINE);
- else
- vty_out (vty, " %s%s", ZROUTE_NAME(i), VTY_NEWLINE);
- }
-}
-
-/* AS External LSA origination */
-int
-ospf6_asbr_external_lsa_originate (struct thread *thread)
-{
+ int type;
+ int nroute[ZEBRA_ROUTE_MAX];
+ int total;
+ struct ospf6_route *route;
struct ospf6_external_info *info;
- char buffer [MAXLSASIZE];
- struct ospf6_lsa_as_external *e;
- char *p;
- info = THREAD_ARG (thread);
-
- /* clear thread */
- info->thread_originate = NULL;
-
- if (info->is_removed)
+ total = 0;
+ for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
+ nroute[type] = 0;
+ for (route = ospf6_route_head (ospf6->external_table); route;
+ route = ospf6_route_next (route))
{
- if (IS_OSPF6_DUMP_ASBR)
- {
- char pbuf[64];
- prefix2str (&info->route->prefix, pbuf, sizeof (pbuf));
- zlog_info ("ASBR: quit redistribution %s: state is down",
- pbuf);
- }
- return 0;
+ info = route->route_option;
+ nroute[info->type]++;
+ total++;
}
- /* prepare buffer */
- memset (buffer, 0, sizeof (buffer));
- e = (struct ospf6_lsa_as_external *) buffer;
- p = (char *) (e + 1);
-
- if (info->metric_type == 2)
- SET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_E); /* type2 */
- else
- UNSET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_E); /* type1, default */
-
- /* forwarding address */
- if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
- SET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_F);
- else
- UNSET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_F);
-
- /* external route tag */
- UNSET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_T);
-
- /* set metric. note: related to E bit */
- OSPF6_ASBR_METRIC_SET (e, info->metric);
-
- /* prefixlen */
- e->prefix.prefix_length = info->route->prefix.prefixlen;
-
- /* PrefixOptions */
- e->prefix.prefix_options = info->prefix_options;
-
- /* don't use refer LS-type */
- e->prefix.prefix_refer_lstype = htons (0);
-
- /* set Prefix */
- memcpy (p, &info->route->prefix.u.prefix6,
- OSPF6_PREFIX_SPACE (info->route->prefix.prefixlen));
- ospf6_prefix_apply_mask (&e->prefix);
- p += OSPF6_PREFIX_SPACE (info->route->prefix.prefixlen);
-
- /* Forwarding address */
- if (CHECK_FLAG (e->bits_metric, OSPF6_ASBR_BIT_F))
+ vty_out (vty, "Redistributing External Routes from:%s", VTY_NEWLINE);
+ for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
{
- memcpy (p, &info->forwarding, sizeof (struct in6_addr));
- p += sizeof (struct in6_addr);
- }
-
- /* External Route Tag */
- if (CHECK_FLAG (e->bits_metric, OSPF6_ASBR_BIT_T))
- {
- /* xxx */
- }
-
- ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_AS_EXTERNAL),
- htonl (info->id), ospf6->router_id,
- (char *) buffer, p - buffer, ospf6);
- return 0;
-}
-
-int
-ospf6_asbr_schedule_external (void *data)
-{
- struct ospf6_external_info *info = data;
- u_long elasped_time, time = 0;
-
- if (info->thread_originate)
- {
- if (IS_OSPF6_DUMP_ASBR)
- {
- char pbuf[64];
- prefix2str (&info->route->prefix, pbuf, sizeof (pbuf));
- zlog_info ("ASBR: schedule redistribution %s: another thread",
- pbuf);
- }
- return 0;
- }
-
- elasped_time =
- ospf6_lsa_has_elasped (htons (OSPF6_LSA_TYPE_AS_EXTERNAL),
- htonl (info->id), ospf6->router_id, ospf6);
- if (elasped_time < OSPF6_MIN_LS_INTERVAL)
- time = OSPF6_MIN_LS_INTERVAL - elasped_time;
- else
- time = 0;
-
- //if (IS_OSPF6_DUMP_ASBR)
- {
- char pbuf[64];
- prefix2str (&info->route->prefix, pbuf, sizeof (pbuf));
- zlog_info ("ASBR: schedule redistribution %s as LS-ID %ld after %lu sec",
- pbuf, (u_long) info->id, time);
- }
-
- if (time)
- info->thread_originate =
- thread_add_timer (master, ospf6_asbr_external_lsa_originate, info, time);
- else
- info->thread_originate =
- thread_add_timer (master, ospf6_asbr_external_lsa_originate, info, 0);
-
- return 0;
-}
-
-int
-ospf6_asbr_external_lsa_flush (void *data)
-{
- struct ospf6_lsa *lsa = data;
- if (lsa)
- ospf6_lsa_premature_aging (lsa);
- return 0;
-}
-
-int
-ospf6_asbr_external_lsa_refresh (void *data)
-{
- struct ospf6_lsa *lsa = data;
- struct ospf6_lsa_as_external *e;
- struct prefix prefix;
- struct route_node *node;
- struct ospf6_external_route *route = NULL;
- struct ospf6_external_info *info = NULL;
- struct ospf6_external_info *match = NULL;
-
- if (IS_OSPF6_DUMP_ASBR)
- zlog_info ("ASBR: refresh %s", lsa->str);
-
- e = (struct ospf6_lsa_as_external *) (lsa->header + 1);
- ospf6_prefix_in6_addr (&e->prefix, &prefix.u.prefix6);
- prefix.prefixlen = e->prefix.prefix_length;
- prefix.family = AF_INET6;
- apply_mask_ipv6 ((struct prefix_ipv6 *) &prefix);
-
- for (node = route_top (external_table); node; node = route_next (node))
- {
- route = node->info;
- if (route == NULL)
+ if (type == ZEBRA_ROUTE_OSPF6)
+ continue;
+ if (! ospf6_zebra_is_redistribute (type))
continue;
- for (info = route->info_head; info; info = info->next)
- {
- if (lsa->header->id == htonl (info->id))
- match = info;
- }
- }
-
- if (match == NULL)
- {
- ospf6_lsa_premature_aging (lsa);
- return 0;
- }
-
- ospf6_asbr_schedule_external (match);
- return 0;
-
-#if 0
- node = route_node_lookup (external_table, &prefix);
- if (! node || ! node->info)
- {
- char pname[64];
-
- prefix2str (&prefix, pname, sizeof (pname));
- if (IS_OSPF6_DUMP_ASBR)
- zlog_info ("ASBR: could not find %s: premature age", pname);
- ospf6_lsa_premature_aging (lsa);
- return 0;
- }
-
- /* find external_info */
- route = node->info;
- for (info = route->info_head; info; info = info->next)
- {
- if (lsa->header->id == htonl (info->id))
- break;
- }
-
- if (info)
- ospf6_asbr_schedule_external (info);
- else
- ospf6_lsa_premature_aging (lsa);
-
- return 0;
-#endif
-}
-
-void
-ospf6_asbr_route_add (int type, int ifindex, struct prefix *prefix,
- u_int nexthop_num, struct in6_addr *nexthop)
-{
- int ret;
- struct route_node *node;
- struct ospf6_external_route *route;
- struct ospf6_external_info *info, tinfo;
-
-#if defined (MUSICA) || defined (LINUX)
- /* XXX As long as the OSPFv3 redistribution is applied to all the connected
- * routes, one needs to filter the ::/96 prefixes.
- * However it could be a wanted case, it will be removed soon.
- */
- struct prefix_ipv6 *p = (prefix_ipv6 *)prefix;
-
- if ((IN6_IS_ADDR_V4COMPAT(&p->prefix)) ||
- (IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && (p->prefixlen == 96)))
- return;
-#endif /* MUSICA or LINUX */
-
- if (! ospf6_zebra_is_redistribute (type))
- return;
-
- /* apply route-map */
- memset (&tinfo, 0, sizeof (struct ospf6_external_info));
- if (rmap[type].map)
- {
- ret = route_map_apply (rmap[type].map, prefix, RMAP_OSPF6, &tinfo);
- if (ret == RMAP_DENYMATCH)
- {
- if (IS_OSPF6_DUMP_ASBR)
- zlog_info ("ASBR: denied by route-map %s", rmap[type].name);
- return;
- }
- }
-
- node = route_node_get (external_table, prefix);
- route = node->info;
-
- if (! route)
- {
- route = XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO,
- sizeof (struct ospf6_external_route));
- memset (route, 0, sizeof (struct ospf6_external_route));
-
- memcpy (&route->prefix, prefix, sizeof (struct prefix));
-
- node->info = route;
- route->node = node;
- }
-
- for (info = route->info_head; info; info = info->next)
- {
- if (info->type == type && info->ifindex == ifindex)
- break;
- }
-
- if (! info)
- {
- info = XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO,
- sizeof (struct ospf6_external_info));
- memset (info, 0, sizeof (struct ospf6_external_info));
-
- info->route = route;
- /* add tail */
- info->prev = route->info_tail;
- if (route->info_tail)
- route->info_tail->next = info;
+ if (ospf6->rmap[type].name)
+ vty_out (vty, " %d: %s with route-map \"%s\"%s%s", nroute[type],
+ ZROUTE_NAME (type), ospf6->rmap[type].name,
+ (ospf6->rmap[type].map ? "" : " (not found !)"),
+ VTY_NEWLINE);
else
- route->info_head = info;
- route->info_tail = info;
-
- info->id = link_state_id++;
+ vty_out (vty, " %d: %s%s", nroute[type],
+ ZROUTE_NAME (type), VTY_NEWLINE);
}
+ vty_out (vty, "Total %d routes%s", total, VTY_NEWLINE);
+}
- /* copy result of route-map */
- info->metric_type = tinfo.metric_type;
- info->metric = tinfo.metric;
- memcpy (&info->forwarding, &tinfo.forwarding,
- sizeof (struct in6_addr));
- info->type = type;
- info->ifindex = ifindex;
+
+/* Routemap Functions */
+route_map_result_t
+ospf6_routemap_rule_match_address_prefixlist (void *rule,
+ struct prefix *prefix,
+ route_map_object_t type,
+ void *object)
+{
+ struct prefix_list *plist;
- if (nexthop_num && nexthop)
- {
- info->nexthop_num = nexthop_num;
+ if (type != RMAP_OSPF6)
+ return RMAP_NOMATCH;
- if (info->nexthop)
- XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info->nexthop);
+ plist = prefix_list_lookup (AFI_IP6, (char *) rule);
+ if (plist == NULL)
+ return RMAP_NOMATCH;
- info->nexthop = (struct in6_addr *)
- XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO,
- nexthop_num * sizeof (struct in6_addr));
- memcpy (info->nexthop, nexthop,
- nexthop_num * sizeof (struct in6_addr));
- }
+ return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
+ RMAP_NOMATCH : RMAP_MATCH);
+}
- info->is_removed = 0;
-
- //if (IS_OSPF6_DUMP_ASBR)
- {
- char pbuf[64];
- struct timeval now;
- prefix2str (&info->route->prefix, pbuf, sizeof (pbuf));
- gettimeofday (&now, NULL);
- zlog_info ("ASBR: start redistributing %s as LS-ID %ld: %ld.%06ld",
- pbuf, (u_long) info->id, now.tv_sec, now.tv_usec);
- }
-
-#ifdef HAVE_OSPF6_DAMP
- ospf6_damp_event_up (OSPF6_DAMP_TYPE_ROUTE, prefix,
- ospf6_asbr_schedule_external, info);
-#else /*HAVE_OSPF6_DAMP*/
- ospf6_asbr_schedule_external (info);
-#endif /*HAVE_OSPF6_DAMP*/
+void *
+ospf6_routemap_rule_match_address_prefixlist_compile (char *arg)
+{
+ return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
}
void
-ospf6_asbr_route_remove (int type, int ifindex, struct prefix *prefix)
+ospf6_routemap_rule_match_address_prefixlist_free (void *rule)
{
- struct route_node *node;
- struct ospf6_external_route *route;
- struct ospf6_external_info *info;
- struct ospf6_lsa *lsa;
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
-#if defined (MUSICA) || defined (LINUX)
- /* XXX As long as the OSPFv3 redistribution is applied to all the connected
- * routes, one needs to filter the ::/96 prefixes.
- * However it could be a wanted case, it will be removed soon.
- */
- struct prefix_ipv6 *p = (prefix_ipv6 *)prefix;
+struct route_map_rule_cmd
+ospf6_routemap_rule_match_address_prefixlist_cmd =
+{
+ "ipv6 address prefix-list",
+ ospf6_routemap_rule_match_address_prefixlist,
+ ospf6_routemap_rule_match_address_prefixlist_compile,
+ ospf6_routemap_rule_match_address_prefixlist_free,
+};
- if ((IN6_IS_ADDR_V4COMPAT(&p->prefix)) ||
- (IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && (p->prefixlen == 96)))
- return;
-#endif /* MUSICA or LINUX */
+route_map_result_t
+ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ char *metric_type = rule;
+ struct ospf6_route *route = object;
- node = route_node_get (external_table, prefix);
- route = node->info;
+ if (type != RMAP_OSPF6)
+ return RMAP_OKAY;
- if (! route)
- return;
-
- for (info = route->info_head; info; info = info->next)
- {
- if (info->type == type && info->ifindex == ifindex)
- break;
- }
-
- if (! info)
- return;
-
- //if (IS_OSPF6_DUMP_ASBR)
- {
- char pbuf[64];
- struct timeval now;
- prefix2str (&info->route->prefix, pbuf, sizeof (pbuf));
- gettimeofday (&now, NULL);
- zlog_info ("ASBR: quit redistributing %s as LS-ID %ld: %ld.%06ld",
- pbuf, (u_long) info->id, now.tv_sec, now.tv_usec);
- }
-
- if (info->thread_originate)
- thread_cancel (info->thread_originate);
- info->thread_originate = NULL;
-
- lsa = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_AS_EXTERNAL),
- htonl (info->id), ospf6->router_id, ospf6);
-#ifdef HAVE_OSPF6_DAMP
- ospf6_damp_event_down (OSPF6_DAMP_TYPE_ROUTE, &info->route->prefix,
- ospf6_asbr_external_lsa_flush, lsa);
-#else /*HAVE_OSPF6_DAMP*/
- ospf6_asbr_external_lsa_flush (lsa);
-#endif /*HAVE_OSPF6_DAMP*/
-
-#if 1
- info->is_removed = 1;
-#else
- /* remove from route */
- if (info->prev)
- info->prev->next = info->next;
+ if (strcmp (metric_type, "type-2") == 0)
+ route->path.metric_type = 2;
else
- info->route->info_head = info->next;
- if (info->next)
- info->next->prev = info->prev;
- else
- info->route->info_tail = info->prev;
+ route->path.metric_type = 1;
- /* if no info, free route */
- if (! info->route->info_head && ! info->route->info_tail)
- {
- info->route->node->info = NULL;
- free (info->route);
- }
+ return RMAP_OKAY;
+}
- if (info->nexthop)
- free (info->nexthop);
- free (info);
-#endif /*0*/
+void *
+ospf6_routemap_rule_set_metric_type_compile (char *arg)
+{
+ if (strcmp (arg, "type-2") && strcmp (arg, "type-1"))
+ return NULL;
+ return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
}
void
-ospf6_asbr_external_lsa_add (struct ospf6_lsa *lsa)
+ospf6_routemap_rule_set_metric_type_free (void *rule)
{
- struct ospf6_lsa_as_external *external;
- struct prefix_ls asbr_id;
- struct ospf6_route_req asbr_entry;
- struct ospf6_route_req request;
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
- external = OSPF6_LSA_HEADER_END (lsa->header);
+struct route_map_rule_cmd
+ospf6_routemap_rule_set_metric_type_cmd =
+{
+ "metric-type",
+ ospf6_routemap_rule_set_metric_type,
+ ospf6_routemap_rule_set_metric_type_compile,
+ ospf6_routemap_rule_set_metric_type_free,
+};
- if (IS_LSA_MAXAGE (lsa))
- {
- if (IS_OSPF6_DUMP_ASBR)
- zlog_info ("ASBR: maxage external lsa: %s seq: %lx",
- lsa->str, (u_long)ntohl (lsa->header->seqnum));
- ospf6_asbr_external_lsa_remove (lsa);
- return;
- }
+route_map_result_t
+ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ char *metric = rule;
+ struct ospf6_route *route = object;
- if (IS_OSPF6_DUMP_ASBR)
- zlog_info ("ASBR: new external lsa: %s seq: %lx",
- lsa->str, (u_long)ntohl (lsa->header->seqnum));
+ if (type != RMAP_OSPF6)
+ return RMAP_OKAY;
- if (lsa->header->adv_router == ospf6->router_id)
- {
- if (IS_OSPF6_DUMP_ASBR)
- zlog_info ("ASBR: my external LSA, ignore");
- return;
- }
+ route->path.cost = atoi (metric);
+ return RMAP_OKAY;
+}
- if (OSPF6_ASBR_METRIC (external) == LS_INFINITY)
- {
- if (IS_OSPF6_DUMP_ASBR)
- zlog_info ("ASBR: metric is infinity, ignore");
- return;
- }
-
- memset (&asbr_id, 0, sizeof (asbr_id));
- asbr_id.family = AF_UNSPEC;
- asbr_id.prefixlen = 64; /* xxx */
- asbr_id.adv_router.s_addr = lsa->header->adv_router;
-
- ospf6_route_lookup (&asbr_entry, (struct prefix *) &asbr_id,
- ospf6->topology_table);
-
- if (ospf6_route_end (&asbr_entry))
- {
- if (IS_OSPF6_DUMP_ASBR)
- {
- char buf[64];
- inet_ntop (AF_INET, &asbr_id.adv_router, buf, sizeof (buf));
- zlog_info ("ASBR: router %s not found, ignore", buf);
- }
- return;
- }
-
- memset (&request, 0, sizeof (request));
- request.route.type = OSPF6_DEST_TYPE_NETWORK;
- request.route.prefix.family = AF_INET6;
- request.route.prefix.prefixlen = external->prefix.prefix_length;
- memcpy (&request.route.prefix.u.prefix6, (char *)(external + 1),
- OSPF6_PREFIX_SPACE (request.route.prefix.prefixlen));
-
- request.path.area_id = asbr_entry.path.area_id;
- request.path.origin.type = htons (OSPF6_LSA_TYPE_AS_EXTERNAL);
- request.path.origin.id = lsa->header->id;
- request.path.origin.adv_router = lsa->header->adv_router;
- if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E))
- {
- request.path.type = OSPF6_PATH_TYPE_EXTERNAL2;
- request.path.metric_type = 2;
- request.path.cost = asbr_entry.path.cost;
- request.path.cost_e2 = OSPF6_ASBR_METRIC (external);
- }
- else
- {
- request.path.type = OSPF6_PATH_TYPE_EXTERNAL1;
- request.path.metric_type = 1;
- request.path.cost = asbr_entry.path.cost
- + OSPF6_ASBR_METRIC (external);
- request.path.cost_e2 = 0;
- }
- request.path.prefix_options = external->prefix.prefix_options;
-
- while (((struct prefix_ls *)&asbr_entry.route.prefix)->adv_router.s_addr ==
- asbr_id.adv_router.s_addr &&
- asbr_entry.route.type == OSPF6_DEST_TYPE_ROUTER)
- {
- memcpy (&request.nexthop, &asbr_entry.nexthop,
- sizeof (struct ospf6_nexthop));
- if (IS_OSPF6_DUMP_ASBR)
- {
- char buf[64], nhop[64], ifname[IFNAMSIZ];
- prefix2str (&request.route.prefix, buf, sizeof (buf));
- inet_ntop (AF_INET6, &request.nexthop.address, nhop, sizeof (nhop));
- if_indextoname (request.nexthop.ifindex, ifname);
- zlog_info ("ASBR: add route: %s %s%%%s", buf, nhop, ifname);
- }
- ospf6_route_add (&request, ospf6->route_table);
- ospf6_route_next (&asbr_entry);
- }
+void *
+ospf6_routemap_rule_set_metric_compile (char *arg)
+{
+ u_int32_t metric;
+ char *endp;
+ metric = strtoul (arg, &endp, 0);
+ if (metric > LS_INFINITY || *endp != '\0')
+ return NULL;
+ return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
}
void
-ospf6_asbr_external_lsa_remove (struct ospf6_lsa *lsa)
+ospf6_routemap_rule_set_metric_free (void *rule)
{
- struct ospf6_lsa_as_external *external;
- struct prefix dest;
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd
+ospf6_routemap_rule_set_metric_cmd =
+{
+ "metric",
+ ospf6_routemap_rule_set_metric,
+ ospf6_routemap_rule_set_metric_compile,
+ ospf6_routemap_rule_set_metric_free,
+};
+
+route_map_result_t
+ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ char *forwarding = rule;
+ struct ospf6_route *route = object;
+ struct ospf6_external_info *info = route->route_option;
+
+ if (type != RMAP_OSPF6)
+ return RMAP_OKAY;
+
+ if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1)
+ {
+ memset (&info->forwarding, 0, sizeof (struct in6_addr));
+ return RMAP_ERROR;
+ }
+
+ return RMAP_OKAY;
+}
+
+void *
+ospf6_routemap_rule_set_forwarding_compile (char *arg)
+{
+ struct in6_addr a;
+ if (inet_pton (AF_INET6, arg, &a) != 1)
+ return NULL;
+ return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
+}
+
+void
+ospf6_routemap_rule_set_forwarding_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+struct route_map_rule_cmd
+ospf6_routemap_rule_set_forwarding_cmd =
+{
+ "forwarding-address",
+ ospf6_routemap_rule_set_forwarding,
+ ospf6_routemap_rule_set_forwarding_compile,
+ ospf6_routemap_rule_set_forwarding_free,
+};
+
+int
+route_map_command_status (struct vty *vty, int ret)
+{
+ if (! ret)
+ return CMD_SUCCESS;
+
+ switch (ret)
+ {
+ case RMAP_RULE_MISSING:
+ vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
+ break;
+ case RMAP_COMPILE_ERROR:
+ vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
+ break;
+ default:
+ vty_out (vty, "route-map add set failed.%s", VTY_NEWLINE);
+ break;
+ }
+ return CMD_WARNING;
+}
+
+/* add "match address" */
+DEFUN (ospf6_routemap_match_address_prefixlist,
+ ospf6_routemap_match_address_prefixlist_cmd,
+ "match ipv6 address prefix-list WORD",
+ "Match values\n"
+ IPV6_STR
+ "Match address of route\n"
+ "Match entries of prefix-lists\n"
+ "IPv6 prefix-list name\n")
+{
+ int ret = route_map_add_match ((struct route_map_index *) vty->index,
+ "ipv6 address prefix-list", argv[0]);
+ return route_map_command_status (vty, ret);
+}
+
+/* delete "match address" */
+DEFUN (ospf6_routemap_no_match_address_prefixlist,
+ ospf6_routemap_no_match_address_prefixlist_cmd,
+ "no match ipv6 address prefix-list WORD",
+ NO_STR
+ "Match values\n"
+ IPV6_STR
+ "Match address of route\n"
+ "Match entries of prefix-lists\n"
+ "IPv6 prefix-list name\n")
+{
+ int ret = route_map_delete_match ((struct route_map_index *) vty->index,
+ "ipv6 address prefix-list", argv[0]);
+ return route_map_command_status (vty, ret);
+}
+
+/* add "set metric-type" */
+DEFUN (ospf6_routemap_set_metric_type,
+ ospf6_routemap_set_metric_type_cmd,
+ "set metric-type (type-1|type-2)",
+ "Set value\n"
+ "Type of metric\n"
+ "OSPF6 external type 1 metric\n"
+ "OSPF6 external type 2 metric\n")
+{
+ int ret = route_map_add_set ((struct route_map_index *) vty->index,
+ "metric-type", argv[0]);
+ return route_map_command_status (vty, ret);
+}
+
+/* delete "set metric-type" */
+DEFUN (ospf6_routemap_no_set_metric_type,
+ ospf6_routemap_no_set_metric_type_cmd,
+ "no set metric-type (type-1|type-2)",
+ NO_STR
+ "Set value\n"
+ "Type of metric\n"
+ "OSPF6 external type 1 metric\n"
+ "OSPF6 external type 2 metric\n")
+{
+ int ret = route_map_delete_set ((struct route_map_index *) vty->index,
+ "metric-type", argv[0]);
+ return route_map_command_status (vty, ret);
+}
+
+/* add "set metric" */
+DEFUN (set_metric,
+ set_metric_cmd,
+ "set metric <0-4294967295>",
+ "Set value\n"
+ "Metric value\n"
+ "Metric value\n")
+{
+ int ret = route_map_add_set ((struct route_map_index *) vty->index,
+ "metric", argv[0]);
+ return route_map_command_status (vty, ret);
+}
+
+/* delete "set metric" */
+DEFUN (no_set_metric,
+ no_set_metric_cmd,
+ "no set metric <0-4294967295>",
+ NO_STR
+ "Set value\n"
+ "Metric\n"
+ "METRIC value\n")
+{
+ int ret = route_map_delete_set ((struct route_map_index *) vty->index,
+ "metric", argv[0]);
+ return route_map_command_status (vty, ret);
+}
+
+/* add "set forwarding-address" */
+DEFUN (ospf6_routemap_set_forwarding,
+ ospf6_routemap_set_forwarding_cmd,
+ "set forwarding-address X:X::X:X",
+ "Set value\n"
+ "Forwarding Address\n"
+ "IPv6 Address\n")
+{
+ int ret = route_map_add_set ((struct route_map_index *) vty->index,
+ "forwarding-address", argv[0]);
+ return route_map_command_status (vty, ret);
+}
+
+/* delete "set forwarding-address" */
+DEFUN (ospf6_routemap_no_set_forwarding,
+ ospf6_routemap_no_set_forwarding_cmd,
+ "no set forwarding-address X:X::X:X",
+ NO_STR
+ "Set value\n"
+ "Forwarding Address\n"
+ "IPv6 Address\n")
+{
+ int ret = route_map_delete_set ((struct route_map_index *) vty->index,
+ "forwarding-address", argv[0]);
+ return route_map_command_status (vty, ret);
+}
+
+void
+ospf6_routemap_init ()
+{
+ route_map_init ();
+ route_map_init_vty ();
+ route_map_add_hook (ospf6_asbr_routemap_update);
+ route_map_delete_hook (ospf6_asbr_routemap_update);
+
+ route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
+ route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
+ route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
+ route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
+
+ /* Match address prefix-list */
+ install_element (RMAP_NODE, &ospf6_routemap_match_address_prefixlist_cmd);
+ install_element (RMAP_NODE, &ospf6_routemap_no_match_address_prefixlist_cmd);
+
+ /* ASE Metric Type (e.g. Type-1/Type-2) */
+ install_element (RMAP_NODE, &ospf6_routemap_set_metric_type_cmd);
+ install_element (RMAP_NODE, &ospf6_routemap_no_set_metric_type_cmd);
+
+ /* ASE Metric */
+ install_element (RMAP_NODE, &set_metric_cmd);
+ install_element (RMAP_NODE, &no_set_metric_cmd);
+
+ /* ASE Metric */
+ install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
+ install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
+}
+
+
+/* Display functions */
+int
+ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
+{
+ struct ospf6_as_external_lsa *external;
char buf[64];
- struct ospf6_route_req request;
-
- if (IS_OSPF6_DUMP_ASBR)
- zlog_info ("ASBR: withdraw external lsa: %s seq: %lx",
- lsa->str, (u_long)ntohl (lsa->header->seqnum));
-
- if (lsa->header->adv_router == ospf6->router_id)
- {
- if (IS_OSPF6_DUMP_ASBR)
- zlog_info ("ASBR: my external LSA, ignore");
- return;
- }
-
- external = OSPF6_LSA_HEADER_END (lsa->header);
- memset (&dest, 0, sizeof (dest));
- dest.family = AF_INET6;
- dest.prefixlen = external->prefix.prefix_length;
- memcpy (&dest.u.prefix6, (char *)(external + 1),
- OSPF6_PREFIX_SPACE (dest.prefixlen));
-
- ospf6_route_lookup (&request, &dest, ospf6->route_table);
- if (ospf6_route_end (&request))
- {
- if (IS_OSPF6_DUMP_ASBR)
- {
- prefix2str (&dest, buf, sizeof (buf));
- zlog_info ("ASBR: %s not found", buf);
- }
- return;
- }
-
- while (request.path.origin.id != lsa->header->id ||
- request.path.origin.adv_router != lsa->header->adv_router)
- {
- if (prefix_same (&request.route.prefix, &dest) != 1)
- {
- if (IS_OSPF6_DUMP_ASBR)
- zlog_info ("ASBR: Can't find the entry matches the origin");
- return;
- }
- ospf6_route_next (&request);
- }
- assert (request.path.origin.id == lsa->header->id);
- assert (request.path.origin.adv_router == request.path.origin.adv_router);
-
- while (request.path.origin.id == lsa->header->id &&
- request.path.origin.adv_router == lsa->header->adv_router &&
- prefix_same (&request.route.prefix, &dest) == 1)
- {
- if (IS_OSPF6_DUMP_ASBR)
- {
- char nhop[64], ifname[IFNAMSIZ];
- prefix2str (&dest, buf, sizeof (buf));
- inet_ntop (AF_INET6, &request.nexthop.address, nhop, sizeof (nhop));
- if_indextoname (request.nexthop.ifindex, ifname);
- zlog_info ("ASBR: remove route: %s %s%%%s", buf, nhop, ifname);
- }
-
- ospf6_route_remove (&request, ospf6->route_table);
- ospf6_route_next (&request);
- }
-}
-
-void
-ospf6_asbr_external_lsa_change (struct ospf6_lsa *old, struct ospf6_lsa *new)
-{
- assert (old || new);
-
- if (old == NULL)
- ospf6_asbr_external_lsa_add (new);
- else if (new == NULL)
- ospf6_asbr_external_lsa_remove (old);
- else
- {
- ospf6_route_table_freeze (ospf6->route_table);
- ospf6_asbr_external_lsa_remove (old);
- ospf6_asbr_external_lsa_add (new);
- ospf6_route_table_thaw (ospf6->route_table);
- }
-}
-
-void
-ospf6_asbr_asbr_entry_add (struct ospf6_route_req *topo_entry)
-{
- struct ospf6_lsdb_node node;
-
- struct prefix_ls *inter_router;
- u_int32_t id, adv_router;
-
- inter_router = (struct prefix_ls *) &topo_entry->route.prefix;
- id = inter_router->id.s_addr;
- adv_router = inter_router->adv_router.s_addr;
-
- if (IS_OSPF6_DUMP_ASBR)
- {
- char buf[64];
- inet_ntop (AF_INET, &inter_router->adv_router, buf, sizeof (buf));
- zlog_info ("ASBR: new router found: %s", buf);
- }
-
- if (ntohl (id) != 0 ||
- ! OSPF6_OPT_ISSET (topo_entry->path.capability, OSPF6_OPT_E))
- {
- zlog_warn ("ASBR: Inter topology table malformed");
- return;
- }
-
- for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_AS_EXTERNAL),
- adv_router, ospf6->lsdb);
- ! ospf6_lsdb_is_end (&node);
- ospf6_lsdb_next (&node))
- ospf6_asbr_external_lsa_add (node.lsa);
-}
-
-void
-ospf6_asbr_asbr_entry_remove (struct ospf6_route_req *topo_entry)
-{
- struct prefix_ls *inter_router;
- u_int32_t id, adv_router;
- struct ospf6_route_req request;
-
- inter_router = (struct prefix_ls *) &topo_entry->route.prefix;
- id = inter_router->id.s_addr;
- adv_router = inter_router->adv_router.s_addr;
-
- if (IS_OSPF6_DUMP_ASBR)
- {
- char buf[64];
- inet_ntop (AF_INET, &inter_router->adv_router, buf, sizeof (buf));
- zlog_info ("ASBR: router disappearing: %s", buf);
- }
-
- if (ntohl (id) != 0 ||
- ! OSPF6_OPT_ISSET (topo_entry->path.capability, OSPF6_OPT_E))
- {
- zlog_warn ("ASBR: Inter topology table malformed");
- }
-
- for (ospf6_route_head (&request, ospf6->route_table);
- ! ospf6_route_end (&request);
- ospf6_route_next (&request))
- {
- if (request.path.type != OSPF6_PATH_TYPE_EXTERNAL1 &&
- request.path.type != OSPF6_PATH_TYPE_EXTERNAL2)
- continue;
- if (request.path.area_id != topo_entry->path.area_id)
- continue;
- if (request.path.origin.adv_router != topo_entry->path.origin.adv_router)
- continue;
- if (memcmp (&topo_entry->nexthop, &request.nexthop,
- sizeof (struct ospf6_nexthop)))
- continue;
-
- ospf6_route_remove (&request, ospf6->route_table);
- }
-}
-
-int
-ospf6_asbr_external_show (struct vty *vty, struct ospf6_lsa *lsa)
-{
- struct ospf6_lsa_as_external *external;
- char buf[128], *ptr;
- struct in6_addr in6;
+ struct in6_addr in6, *forwarding;
assert (lsa->header);
- external = (struct ospf6_lsa_as_external *)(lsa->header + 1);
+ external = (struct ospf6_as_external_lsa *)
+ OSPF6_LSA_HEADER_END (lsa->header);
/* bits */
- snprintf (buf, sizeof (buf), "%s%s%s",
- (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E) ?
- "E" : "-"),
- (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F) ?
- "F" : "-"),
- (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T) ?
- "T" : "-"));
+ snprintf (buf, sizeof (buf), "%c%c%c",
+ (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E) ? 'E' : '-'),
+ (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F) ? 'F' : '-'),
+ (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T) ? 'T' : '-'));
vty_out (vty, " Bits: %s%s", buf, VTY_NEWLINE);
- vty_out (vty, " Metric: %5lu%s", (u_long)OSPF6_ASBR_METRIC (external),
+ vty_out (vty, " Metric: %5lu%s", (u_long) OSPF6_ASBR_METRIC (external),
VTY_NEWLINE);
- ospf6_prefix_options_str (external->prefix.prefix_options,
- buf, sizeof (buf));
- vty_out (vty, " Prefix Options: %s%s", buf, VTY_NEWLINE);
+ ospf6_prefix_options_printbuf (external->prefix.prefix_options,
+ buf, sizeof (buf));
+ vty_out (vty, " Prefix Options: %s%s", buf,
+ VTY_NEWLINE);
vty_out (vty, " Referenced LSType: %d%s",
- ntohs (external->prefix.prefix_refer_lstype), VTY_NEWLINE);
+ ntohs (external->prefix.prefix_refer_lstype),
+ VTY_NEWLINE);
- ospf6_prefix_in6_addr (&external->prefix, &in6);
+ ospf6_prefix_in6_addr (&in6, &external->prefix);
inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
- vty_out (vty, " Prefix: %s/%d%s",
- buf, external->prefix.prefix_length, VTY_NEWLINE);
+ vty_out (vty, " Prefix: %s/%d%s", buf,
+ external->prefix.prefix_length, VTY_NEWLINE);
/* Forwarding-Address */
if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
{
- ptr = ((char *)(external + 1))
- + OSPF6_PREFIX_SPACE (external->prefix.prefix_length);
- inet_ntop (AF_INET6, (struct in6_addr *) ptr, buf, sizeof (buf));
+ forwarding = (struct in6_addr *)
+ ((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
+ OSPF6_PREFIX_SPACE (external->prefix.prefix_length));
+ inet_ntop (AF_INET6, forwarding, buf, sizeof (buf));
vty_out (vty, " Forwarding-Address: %s%s", buf, VTY_NEWLINE);
}
@@ -994,96 +1211,184 @@
}
void
-ospf6_asbr_database_hook (struct ospf6_lsa *old, struct ospf6_lsa *new)
+ospf6_asbr_external_route_show (struct vty *vty, struct ospf6_route *route)
{
- if (old)
- ospf6_asbr_external_lsa_remove (old);
- if (new && ! IS_LSA_MAXAGE (new))
- ospf6_asbr_external_lsa_add (new);
+ struct ospf6_external_info *info = route->route_option;
+ char prefix[64], id[16], forwarding[64];
+ u_int32_t tmp_id;
+
+ prefix2str (&route->prefix, prefix, sizeof (prefix));
+ tmp_id = ntohl (info->id);
+ inet_ntop (AF_INET, &tmp_id, id, sizeof (id));
+ if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
+ inet_ntop (AF_INET6, &info->forwarding, forwarding, sizeof (forwarding));
+ else
+ snprintf (forwarding, sizeof (forwarding), ":: (ifindex %d)",
+ route->nexthop[0].ifindex);
+
+ vty_out (vty, "%s %-32s %-15s type-%d %5lu %s%s",
+ ZROUTE_ABNAME (info->type),
+ prefix, id, route->path.metric_type,
+ (u_long) (route->path.metric_type == 2 ?
+ route->path.cost_e2 : route->path.cost),
+ forwarding, VTY_NEWLINE);
}
-void
-ospf6_asbr_register_as_external ()
-{
- struct ospf6_lsa_slot slot;
-
- memset (&slot, 0, sizeof (slot));
- slot.type = htons (OSPF6_LSA_TYPE_AS_EXTERNAL);
- slot.name = "AS-External";
- slot.func_show = ospf6_asbr_external_show;
- slot.func_refresh = ospf6_asbr_external_lsa_refresh;
- ospf6_lsa_slot_register (&slot);
-
- ospf6_lsdb_hook[OSPF6_LSA_TYPE_AS_EXTERNAL & OSPF6_LSTYPE_CODE_MASK].hook =
- ospf6_asbr_database_hook;
-}
-
-void
-ospf6_asbr_external_info_show (struct vty *vty,
- struct ospf6_external_info *info)
-{
- char prefix_buf[64], id_buf[16];
- struct in_addr id;
-
- if (info->is_removed)
- return;
-
- id.s_addr = ntohl (info->id);
- inet_ntop (AF_INET, &id, id_buf, sizeof (id_buf));
- prefix2str (&info->route->prefix, prefix_buf, sizeof (prefix_buf));
- vty_out (vty, "%s %-32s %3d %-15s %3d %lu(type-%d)%s",
- ZROUTE_ABNAME(info->type), prefix_buf, info->ifindex, id_buf,
- info->nexthop_num, (u_long) info->metric, info->metric_type,
- VTY_NEWLINE);
-}
-
-void
-ospf6_asbr_external_route_show (struct vty *vty,
- struct ospf6_external_route *route)
-{
- struct ospf6_external_info *info;
- for (info = route->info_head; info; info = info->next)
- ospf6_asbr_external_info_show (vty, info);
-}
-
-DEFUN (show_ipv6_route_ospf6_external,
- show_ipv6_route_ospf6_external_cmd,
- "show ipv6 ospf6 route redistribute",
+DEFUN (show_ipv6_ospf6_redistribute,
+ show_ipv6_ospf6_redistribute_cmd,
+ "show ipv6 ospf6 redistribute",
SHOW_STR
IP6_STR
- ROUTE_STR
OSPF6_STR
"redistributing External information\n"
)
{
- struct route_node *node;
- struct ospf6_external_route *route;
+ struct ospf6_route *route;
- vty_out (vty, "%s %-32s %3s %-15s %3s %s%s",
- " ", "Prefix", "I/F", "LS-Id", "#NH", "Metric",
- VTY_NEWLINE);
- for (node = route_top (external_table); node; node = route_next (node))
- {
- route = node->info;
- if (route)
- ospf6_asbr_external_route_show (vty, route);
- }
+ ospf6_redistribute_show_config (vty);
+
+ for (route = ospf6_route_head (ospf6->external_table); route;
+ route = ospf6_route_next (route))
+ ospf6_asbr_external_route_show (vty, route);
+
return CMD_SUCCESS;
}
+DEFUN (show_ipv6_ospf6_asbr,
+ show_ipv6_ospf6_asbr_cmd,
+ "show ipv6 ospf6 asbr",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ "Show AS Boundary Router table\n"
+ )
+{
+ ospf6_lsentry_table_show (vty, argc, argv, ospf6->asbr_table);
+ return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_asbr,
+ show_ipv6_ospf6_asbr_1_cmd,
+ "show ipv6 ospf6 asbr (A.B.C.D|A.B.C.D/M|detail)",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ "Show AS Boundary Router table\n"
+ "Specify Router-ID\n"
+ "Display multiple entry by specifying match-prefix of Router-ID\n"
+ "Display Detail\n"
+ );
+
+ALIAS (show_ipv6_ospf6_asbr,
+ show_ipv6_ospf6_asbr_2_cmd,
+ "show ipv6 ospf6 asbr (A.B.C.D|A.B.C.D/M|*) (A.B.C.D|A.B.C.D/M|detail)",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ "Show AS Boundary Router table\n"
+ "Specify Router-ID\n"
+ "Display multiple entry by specifying match-prefix of Router-ID\n"
+ "Wildcard Router-ID\n"
+ "Specify Link State ID\n"
+ "Display multiple entry by specifying match-prefix of Link State ID\n"
+ "Display Detail\n"
+ );
+
+DEFUN (show_ipv6_ospf6_asbr_3,
+ show_ipv6_ospf6_asbr_3_cmd,
+ "show ipv6 ospf6 asbr (A.B.C.D|*) A.B.C.D/M detail",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ "Show AS Boundary Router table\n"
+ "Specify Router-ID\n"
+ "Wildcard Router-ID\n"
+ "Display multiple entry by specifying match-prefix of Link State ID\n"
+ "Display Detail\n"
+ )
+{
+ char *sargv[CMD_ARGC_MAX];
+ int i, sargc;
+
+ /* copy argv to sargv and then append "detail" */
+ for (i = 0; i < argc; i++)
+ sargv[i] = argv[i];
+ sargc = argc;
+ sargv[sargc++] = "detail";
+ sargv[sargc] = NULL;
+
+ ospf6_lsentry_table_show (vty, sargc, sargv, ospf6->asbr_table);
+ return CMD_SUCCESS;
+}
+
+
void
ospf6_asbr_init ()
{
- external_table = route_table_init ();
- link_state_id = 0;
+ ospf6_routemap_init ();
- ospf6_asbr_register_as_external ();
+ ospf6_lstype[5].name = "AS-External";
+ ospf6_lstype[5].reoriginate = ospf6_as_external_lsa_reoriginate;
+ ospf6_lstype[5].show = ospf6_as_external_lsa_show;
- install_element (VIEW_NODE, &show_ipv6_route_ospf6_external_cmd);
- install_element (ENABLE_NODE, &show_ipv6_route_ospf6_external_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_redistribute_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_redistribute_cmd);
+
+ install_element (VIEW_NODE, &show_ipv6_ospf6_asbr_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_asbr_1_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_asbr_2_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_asbr_3_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_asbr_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_asbr_1_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_asbr_2_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_asbr_3_cmd);
+
install_element (OSPF6_NODE, &ospf6_redistribute_cmd);
install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd);
install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd);
}
+DEFUN (debug_ospf6_asbr,
+ debug_ospf6_asbr_cmd,
+ "debug ospf6 asbr",
+ DEBUG_STR
+ OSPF6_STR
+ "Debug OSPFv3 ASBR function\n"
+ )
+{
+ OSPF6_DEBUG_ASBR_ON ();
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_ospf6_asbr,
+ no_debug_ospf6_asbr_cmd,
+ "no debug ospf6 asbr",
+ NO_STR
+ DEBUG_STR
+ OSPF6_STR
+ "Debug OSPFv3 ASBR function\n"
+ )
+{
+ OSPF6_DEBUG_ASBR_OFF ();
+ return CMD_SUCCESS;
+}
+
+int
+config_write_ospf6_debug_asbr (struct vty *vty)
+{
+ if (IS_OSPF6_DEBUG_ASBR)
+ vty_out (vty, "debug ospf6 asbr%s", VTY_NEWLINE);
+ return 0;
+}
+
+void
+install_element_ospf6_debug_asbr ()
+{
+ install_element (ENABLE_NODE, &debug_ospf6_asbr_cmd);
+ install_element (ENABLE_NODE, &no_debug_ospf6_asbr_cmd);
+ install_element (CONFIG_NODE, &debug_ospf6_asbr_cmd);
+ install_element (CONFIG_NODE, &no_debug_ospf6_asbr_cmd);
+}
+
+
diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h
index 153ed21..f3aabc8 100644
--- a/ospf6d/ospf6_asbr.h
+++ b/ospf6d/ospf6_asbr.h
@@ -22,53 +22,29 @@
#ifndef OSPF6_ASBR_H
#define OSPF6_ASBR_H
-#include "thread.h"
+/* Debug option */
+extern unsigned char conf_debug_ospf6_asbr;
+#define OSPF6_DEBUG_ASBR_ON() \
+ (conf_debug_ospf6_asbr = 1)
+#define OSPF6_DEBUG_ASBR_OFF() \
+ (conf_debug_ospf6_asbr = 0)
+#define IS_OSPF6_DEBUG_ASBR \
+ (conf_debug_ospf6_asbr)
struct ospf6_external_info
{
- int is_removed;
- struct thread *thread_originate;
-
- struct ospf6_external_route *route;
-
- struct ospf6_external_info *prev;
- struct ospf6_external_info *next;
-
- /* external route type */
+ /* External route type */
int type;
- /* external route ifindex */
- int ifindex;
-
- /* LS-ID */
+ /* Originating Link State ID */
u_int32_t id;
- /* nexthops */
- u_int nexthop_num;
- struct in6_addr *nexthop;
-
- u_int8_t prefix_options;
-
- u_int8_t metric_type;
- u_int32_t metric;
struct in6_addr forwarding;
/* u_int32_t tag; */
};
-struct ospf6_external_route
-{
- struct route_node *node;
-
- /* prefix */
- struct prefix prefix;
-
- /* external information */
- struct ospf6_external_info *info_head;
- struct ospf6_external_info *info_tail;
-};
-
/* AS-External-LSA */
-struct ospf6_lsa_as_external
+struct ospf6_as_external_lsa
{
u_int32_t bits_metric;
@@ -87,26 +63,24 @@
{ (E)->bits_metric &= htonl (0xff000000); \
(E)->bits_metric |= htonl (0x00ffffff) & htonl (C); }
-void ospf6_asbr_routemap_update ();
+void ospf6_asbr_lsa_add (struct ospf6_lsa *lsa);
+void ospf6_asbr_lsa_remove (struct ospf6_lsa *lsa);
+void ospf6_asbr_lsentry_add (struct ospf6_route *asbr_entry);
+void ospf6_asbr_lsentry_remove (struct ospf6_route *asbr_entry);
+
+int ospf6_asbr_is_asbr (struct ospf6 *o);
+void
+ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix,
+ u_int nexthop_num, struct in6_addr *nexthop);
+void
+ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix);
int ospf6_redistribute_config_write (struct vty *vty);
-void ospf6_redistribute_show_config (struct vty *vty);
-
-void
-ospf6_asbr_route_add (int type, int ifindex, struct prefix *prefix,
- u_int nexthop_num, struct in6_addr *nexthop);
-void
-ospf6_asbr_route_remove (int type, int ifindex, struct prefix *prefix);
-
-void ospf6_asbr_external_lsa_add (struct ospf6_lsa *lsa);
-void ospf6_asbr_external_lsa_remove (struct ospf6_lsa *lsa);
-void ospf6_asbr_external_lsa_change (struct ospf6_lsa *old,
- struct ospf6_lsa *new);
-
-void ospf6_asbr_asbr_entry_add (struct ospf6_route_req *topo_entry);
-void ospf6_asbr_asbr_entry_remove (struct ospf6_route_req *topo_entry);
void ospf6_asbr_init ();
+int config_write_ospf6_debug_asbr (struct vty *vty);
+void install_element_ospf6_debug_asbr ();
+
#endif /* OSPF6_ASBR_H */
diff --git a/ospf6d/ospf6_bintree.c b/ospf6d/ospf6_bintree.c
deleted file mode 100644
index c1e9e55..0000000
--- a/ospf6d/ospf6_bintree.c
+++ /dev/null
@@ -1,436 +0,0 @@
-
-#include <zebra.h>
-#include "ospf6_bintree.h"
-
-static struct bintree_node *
-bintree_lookup_node_min (struct bintree_node *subroot)
-{
- struct bintree_node *node;
-
- if (subroot == NULL)
- return NULL;
-
- node = subroot;
- while (node->bl_left)
- node = node->bl_left;
- return node;
-}
-
-static struct bintree_node *
-bintree_lookup_node_max (struct bintree_node *subroot)
-{
- struct bintree_node *node;
-
- assert (subroot != NULL);
- node = subroot;
- while (node->bl_right)
- node = node->bl_right;
- return node;
-}
-
-void *
-bintree_lookup (void *data, struct bintree *tree)
-{
- int cmp;
- struct bintree_node *node;
-
- node = tree->root;
-
- while (node)
- {
- if (tree->cmp)
- cmp = (*tree->cmp) (node->data, data);
- else
- cmp = (node->data - data);
-
- if (cmp == 0)
- break;
-
- if (cmp > 0)
- node = node->bl_left;
- else /* if (cmp < 0) */
- node = node->bl_right;
- }
-
- if (node)
- return node->data;
-
- return NULL;
-}
-
-void *
-bintree_lookup_min (struct bintree *tree)
-{
- struct bintree_node *node;
- node = bintree_lookup_node_min (tree->root);
- if (node == NULL)
- return NULL;
- return node->data;
-}
-
-void *
-bintree_lookup_max (struct bintree *tree)
-{
- struct bintree_node *node;
- node = bintree_lookup_node_max (tree->root);
- if (node == NULL)
- return NULL;
- return node->data;
-}
-
-int
-bintree_add (void *data, struct bintree *tree)
-{
- int cmp = 0;
- struct bintree_node *node, *parent;
-
- node = tree->root;
- parent = NULL;
-
- while (node)
- {
- if (tree->cmp)
- cmp = (*tree->cmp) (node->data, data);
- else
- cmp = (node->data - data);
-
- if (cmp == 0)
- break;
-
- parent = node;
- if (cmp > 0)
- node = node->bl_left;
- else /* if (cmp < 0) */
- node = node->bl_right;
- }
-
- if (node)
- return -1;
-
- node = malloc (sizeof (struct bintree_node));
- memset (node, 0, sizeof (struct bintree_node));
- node->tree = tree;
- node->data = data;
-
- if (parent)
- {
- node->parent = parent;
-
- assert (cmp != 0);
- if (cmp > 0)
- {
- node->parent_link = BL_LEFT;
- parent->bl_left = node;
- }
- else /* if (cmp < 0) */
- {
- node->parent_link = BL_RIGHT;
- parent->bl_right = node;
- }
- }
- else
- tree->root = node;
-
- tree->count++;
- return 0;
-}
-
-static void
-bintree_remove_nochild (struct bintree_node *node)
-{
- assert (node->bl_left == NULL && node->bl_right == NULL);
-
- if (node->parent == NULL)
- node->tree->root = NULL;
- else
- node->parent->link[node->parent_link] = NULL;
-}
-
-static void
-bintree_remove_onechild (struct bintree_node *node)
-{
- assert ((node->bl_left == NULL && node->bl_right != NULL) ||
- (node->bl_left != NULL && node->bl_right == NULL));
-
- if (node->bl_left)
- {
- if (node->parent == NULL)
- {
- node->tree->root = node->bl_left;
- node->bl_left->parent = NULL;
- }
- else
- {
- node->parent->link[node->parent_link] = node->bl_left;
- node->bl_left->parent = node->parent;
- node->bl_left->parent_link = node->parent_link;
- }
- }
- else if (node->bl_right)
- {
- if (node->parent == NULL)
- {
- node->tree->root = node->bl_right;
- node->bl_right->parent = NULL;
- }
- else
- {
- node->parent->link[node->parent_link] = node->bl_right;
- node->bl_right->parent = node->parent;
- node->bl_right->parent_link = node->parent_link;
- }
- }
- else
- assert (0);
-}
-
-int
-bintree_remove (void *data, struct bintree *tree)
-{
- int cmp;
- struct bintree_node *node;
-
- node = tree->root;
-
- while (node)
- {
- if (tree->cmp)
- cmp = (*tree->cmp) (node->data, data);
- else
- cmp = (node->data - data);
-
- if (cmp == 0)
- break;
-
- if (cmp > 0)
- node = node->bl_left;
- else /* if (cmp < 0) */
- node = node->bl_right;
- }
-
- if (node == NULL)
- return -1;
-
- if (node->bl_left == NULL && node->bl_right == NULL)
- {
- bintree_remove_nochild (node);
- free (node);
- tree->count--;
- return 0;
- }
-
- if ((node->bl_left == NULL && node->bl_right != NULL) ||
- (node->bl_left != NULL && node->bl_right == NULL))
- {
- bintree_remove_onechild (node);
- free (node);
- tree->count--;
- return 0;
- }
-
- if (node->bl_left != NULL && node->bl_right != NULL)
- {
- struct bintree_node *successor;
-
- /* find successor of the removing node */
- successor = bintree_lookup_node_min (node->bl_right);
-
- /* remove successor from tree */
- if (successor->bl_right)
- bintree_remove_onechild (successor);
- else
- bintree_remove_nochild (successor);
-
- /* swap removing node with successor */
- successor->parent = node->parent;
- successor->parent_link = node->parent_link;
- successor->bl_left = node->bl_left;
- successor->bl_right = node->bl_right;
-
- /* if the successor was the node->bl_right itself,
- bintree_remove_**child may touch node->bl_right,
- so only the successor->bl_right may be NULL
- by above assignment */
- successor->bl_left->parent = successor;
- if (successor->bl_right)
- successor->bl_right->parent = successor;
-
- if (successor->parent == NULL)
- tree->root = successor;
- else
- successor->parent->link[successor->parent_link] = successor;
-
- free (node);
- tree->count--;
- return 0;
- }
-
- /* not reached */
- return -1;
-}
-
-/* in-order traversal */
-
-void
-bintree_head (struct bintree *tree, struct bintree_node *node)
-{
- struct bintree_node *head;
-
- head = bintree_lookup_node_min (tree->root);
- if (head == NULL)
- {
- node->parent = NULL;
- node->bl_left = NULL;
- node->bl_right = NULL;
- node->data = NULL;
- return;
- }
-
- node->tree = head->tree;
- node->parent = head->parent;
- node->parent_link = head->parent_link;
- node->bl_left = head->bl_left;
- node->bl_right = head->bl_right;
- node->data = head->data;
-}
-
-int
-bintree_end (struct bintree_node *node)
-{
- if (node->parent || node->bl_left || node->bl_right || node->data)
- return 0;
- return 1;
-}
-
-#define GOTO_PROCED_SUBTREE_TOP(node) \
- while (node->parent && node->parent->bl_right && \
- node->parent->bl_right->data == node->data) \
- { \
- node->data = node->parent->data; \
- node->bl_left = node->parent->bl_left; \
- node->bl_right = node->parent->bl_right; \
- node->parent_link = node->parent->parent_link; \
- node->parent = node->parent->parent; \
- }
-
-void
-bintree_next (struct bintree_node *node)
-{
- struct bintree_node *next = NULL;
-
- /* if node have just been removed, current point should have just been
- replaced with its successor. that certainly will not be processed
- yet, so process it */
- if (node->parent == NULL)
- {
- if (node->tree->root == NULL)
- {
- assert (node->tree->count == 0);
- node->parent = NULL;
- node->bl_left = NULL;
- node->bl_right = NULL;
- node->data = NULL;
- return;
- }
- else if (node->tree->root->data != node->data)
- next = node->tree->root;
- }
- else if (node->parent->link[node->parent_link] == NULL)
- {
- if (node->parent_link == BL_LEFT)
- next = node->parent;
- else
- {
- GOTO_PROCED_SUBTREE_TOP (node);
- next = node->parent;
- }
- }
- else if (node->parent->link[node->parent_link]->data != node->data)
- next = node->parent->link[node->parent_link];
-
- if (next == NULL)
- {
- if (node->bl_right)
- next = bintree_lookup_node_min (node->bl_right);
- else
- {
- GOTO_PROCED_SUBTREE_TOP (node);
- next = node->parent;
- }
- }
-
- if (next)
- {
- node->tree = next->tree;
- node->parent = next->parent;
- node->parent_link = next->parent_link;
- node->bl_left = next->bl_left;
- node->bl_right = next->bl_right;
- node->data = next->data;
- }
- else
- {
- node->parent = NULL;
- node->bl_left = NULL;
- node->bl_right = NULL;
- node->data = NULL;
- }
-}
-
-struct bintree *
-bintree_create ()
-{
- struct bintree *tree;
-
- tree = malloc (sizeof (struct bintree));
- memset (tree, 0, sizeof (struct bintree));
-
- return tree;
-}
-
-void
-bintree_delete (struct bintree *tree)
-{
- struct bintree_node node;
-
- for (bintree_head (tree, &node); ! bintree_end (&node);
- bintree_next (&node))
- bintree_remove (node.data, tree);
-
- assert (tree->count == 0);
- free (tree);
-}
-
-int indent_num = 0;
-
-void
-bintree_print_sub (void (*print) (int, void *), struct bintree_node *subroot)
-{
- if (subroot == NULL)
- return;
-
- if (subroot->bl_right)
- {
- indent_num++;
- bintree_print_sub (print, subroot->bl_right);
- indent_num--;
- }
-
- (*print) (indent_num, subroot->data);
-
- if (subroot->bl_left)
- {
- indent_num++;
- bintree_print_sub (print, subroot->bl_left);
- indent_num--;
- }
-}
-
-void
-bintree_print (void (*print) (int, void *), struct bintree *tree)
-{
- indent_num = 0;
- bintree_print_sub (print, tree->root);
-}
-
-
diff --git a/ospf6d/ospf6_bintree.h b/ospf6d/ospf6_bintree.h
deleted file mode 100644
index fad8bbd..0000000
--- a/ospf6d/ospf6_bintree.h
+++ /dev/null
@@ -1,47 +0,0 @@
-
-#ifndef _BINTREE_H_
-#define _BINTREE_H_
-
-struct bintree_node
-{
- struct bintree *tree;
-
- struct bintree_node *parent;
- int parent_link;
-
-#define BL_LEFT 0
-#define BL_RIGHT 1
-#define BL_MAX 2
- struct bintree_node *link[BL_MAX];
-#define bl_left link[BL_LEFT]
-#define bl_right link[BL_RIGHT]
-
- void *data;
-};
-
-struct bintree
-{
- int count;
- struct bintree_node *root;
-
- int (*cmp) (void *, void *);
-};
-
-void *bintree_lookup (void *data, struct bintree *tree);
-void *bintree_lookup_min (struct bintree *tree);
-void *bintree_lookup_max (struct bintree *tree);
-
-int bintree_add (void *data, struct bintree *tree);
-int bintree_remove (void *data, struct bintree *tree);
-
-void bintree_head (struct bintree *tree, struct bintree_node *node);
-int bintree_end (struct bintree_node *node);
-void bintree_next (struct bintree_node *node);
-
-struct bintree *bintree_create ();
-void bintree_delete (struct bintree *);
-
-void bintree_print (void (*print) (int, void *), struct bintree *);
-
-#endif /*_BINTREE_H_*/
-
diff --git a/ospf6d/ospf6_damp.c b/ospf6d/ospf6_damp.c
deleted file mode 100644
index 40cf798..0000000
--- a/ospf6d/ospf6_damp.c
+++ /dev/null
@@ -1,748 +0,0 @@
-/*
- * OSPF flap dampening by Manav Bhatia
- * Copyright (C) 2002
- *
- * 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 <math.h>
-
-#include "log.h"
-#include "prefix.h"
-#include "thread.h"
-#include "table.h"
-#include "command.h"
-#include "vty.h"
-
-extern struct thread_master *master;
-
-#include "ospf6_damp.h"
-
-#ifdef HAVE_OSPF6_DAMP
-
-#define DELTA_REUSE 10 /* Time granularity for reuse lists */
-#define DELTA_T 5 /* Time granularity for decay arrays */
-#define DEFAULT_HALF_LIFE 60 /* (sec) 1 min */
-
-#define DEFAULT_PENALTY 1000
-#define DEFAULT_REUSE 750
-#define DEFAULT_SUPPRESS 2000
-
-#define REUSE_LIST_SIZE 256
-#define REUSE_ARRAY_SIZE 1024
-
-/* Global variable to access damping configuration */
-struct ospf6_damp_config damp_config;
-struct ospf6_damp_config *dc = &damp_config;
-u_int reuse_array_offset = 0;
-struct route_table *damp_info_table[OSPF6_DAMP_TYPE_MAX];
-struct thread *ospf6_reuse_thread = NULL;
-
-int ospf6_damp_debug = 0;
-#define IS_OSPF6_DEBUG_DAMP (ospf6_damp_debug)
-
-static struct ospf6_damp_info *
-ospf6_damp_lookup (u_short type, struct prefix *name)
-{
- struct route_node *node;
-
- node = route_node_lookup (damp_info_table[type], name);
- if (node && node->info)
- return (struct ospf6_damp_info *) node->info;
- return NULL;
-}
-
-static struct ospf6_damp_info *
-ospf6_damp_create (u_short type, struct prefix *name)
-{
- struct route_node *node;
- struct ospf6_damp_info *di;
- char namebuf[64];
-
- di = ospf6_damp_lookup (type, name);
- if (di)
- return di;
-
- if (IS_OSPF6_DEBUG_DAMP)
- {
- prefix2str (name, namebuf, sizeof (namebuf));
- zlog_info ("DAMP: create: type: %d, name: %s", type, namebuf);
- }
-
- di = (struct ospf6_damp_info *)
- malloc (sizeof (struct ospf6_damp_info));
- memset (di, 0, sizeof (struct ospf6_damp_info));
- di->type = type;
- prefix_copy (&di->name, name);
-
- node = route_node_get (damp_info_table[type], name);
- node->info = di;
-
- return di;
-}
-
-static void
-ospf6_damp_delete (u_short type, struct prefix *name)
-{
- struct route_node *node;
- struct ospf6_damp_info *di;
- char namebuf[64];
-
- node = route_node_lookup (damp_info_table[type], name);
- if (! node || ! node->info)
- return;
-
- di = node->info;
-
- if (IS_OSPF6_DEBUG_DAMP)
- {
- prefix2str (&di->name, namebuf, sizeof (namebuf));
- zlog_info ("DAMP: delete: type: %d, name: %s",
- di->type, namebuf);
- }
-
- node->info = NULL;
- free (di);
-}
-
-/* compute and fill the configuration parameter */
-void
-ospf6_damp_init_config (u_int half_life, u_int reuse,
- u_int suppress, u_int t_hold)
-{
- int i;
- double max_ratio, max_ratio1, max_ratio2;
-
- dc->half_life = half_life ? half_life : DEFAULT_HALF_LIFE;
- dc->reuse = reuse ? reuse : DEFAULT_REUSE;
- dc->suppress = suppress ? suppress : DEFAULT_SUPPRESS;
- dc->t_hold = t_hold ? t_hold : 4 * dc->half_life;
-
- /* Initialize system-wide params */
- dc->delta_t = DELTA_T;
- dc->delta_reuse = DELTA_REUSE;
- dc->default_penalty = DEFAULT_PENALTY;
- dc->reuse_index_array_size = REUSE_ARRAY_SIZE;
-
- /* ceiling is the maximum penalty a route may attain */
- /* ceiling = reuse * 2^(T-hold/half-life) */
- dc->ceiling = (int)
- (dc->reuse * (pow (2, (double) dc->t_hold / dc->half_life)));
-
- /* Decay-array computations */
- /* decay_array_size = decay memory/time granularity */
- dc->decay_array_size = ceil ((double) dc->t_hold / dc->delta_t);
- dc->decay_array = malloc (sizeof (double) * (dc->decay_array_size));
-
- /* Each i-th element is per tick delay raised to the i-th power */
- dc->decay_array[0] = 1.0;
- dc->decay_array[1] = exp ((1.0 / (dc->half_life / dc->delta_t)) * log (0.5));
- for (i = 2; i < dc->decay_array_size; i++)
- dc->decay_array[i] = dc->decay_array[i - 1] * dc->decay_array[1];
-
- /* Reuse-list computations (reuse queue head array ?) */
- dc->reuse_list_size = ceil ((double) dc->t_hold / dc->delta_reuse) + 1;
- if (dc->reuse_list_size == 0 || dc->reuse_list_size > REUSE_LIST_SIZE)
- dc->reuse_list_size = REUSE_LIST_SIZE;
- dc->reuse_list_array = (struct ospf6_damp_info **)
- malloc (dc->reuse_list_size * sizeof (struct ospf6_reuse_list *));
- memset (dc->reuse_list_array, 0x00,
- dc->reuse_list_size * sizeof (struct ospf6_reuse_list *));
-
- /* Reuse-array computations */
- dc->reuse_index_array = malloc (sizeof (int) * dc->reuse_index_array_size);
-
- /*
- * This is the maximum ratio between the current value of the penalty and
- * the reuse value which can be indexed by the reuse array. It will be
- * limited by the ceiling or by the amount of time that the reuse list
- * covers
- */
- max_ratio1 = (double) dc->ceiling / dc->reuse;
- max_ratio2 = exp ((double) dc->t_hold / dc->half_life) * log10 (2.0);
- max_ratio = (max_ratio2 != 0 && max_ratio2 < max_ratio1 ?
- max_ratio2 : max_ratio1);
-
- /*
- * reuse array is just an estimator and we need something
- * to use the full array
- */
- dc->scale_factor = (double) dc->reuse_index_array_size / (max_ratio - 1);
-
- for (i = 0; i < dc->reuse_index_array_size; i++)
- {
- dc->reuse_index_array[i] = (int)
- (((double) dc->half_life / dc->delta_reuse) *
- log10 (1.0 / (dc->reuse * (1.0 + ((double) i / dc->scale_factor))))
- / log10 (0.5));
- }
-
- dc->enabled = ON;
-}
-
-static double
-ospf6_damp_decay (time_t tdiff)
-{
- int index = tdiff / dc->delta_t;
-
- if (index >= dc->decay_array_size)
- return 0;
-
- return dc->decay_array[index];
-}
-
-static int
-ospf6_damp_reuse_index (int penalty)
-{
- int index;
-
- index = (int) (((double) penalty / dc->reuse - 1.0) * dc->scale_factor);
-
- if (index >= dc->reuse_index_array_size)
- index = dc->reuse_index_array_size - 1;
-
- return (dc->reuse_index_array[index] - dc->reuse_index_array[0]);
-}
-
-static int
-ospf6_reuse_list_lookup (struct ospf6_damp_info *di)
-{
- struct ospf6_damp_info *info;
-
- for (info = dc->reuse_list_array[di->index]; info; info = info->next)
- {
- if (info == di)
- return 1;
- }
- return 0;
-}
-
-static void
-ospf6_reuse_list_remove (struct ospf6_damp_info *di)
-{
- if (di->prev)
- di->prev->next = di->next;
- else
- dc->reuse_list_array[di->index] = di->next;
- if (di->next)
- di->next->prev = di->prev;
-
- di->index = -1;
- di->prev = NULL;
- di->next = NULL;
-}
-
-static void
-ospf6_reuse_list_add (struct ospf6_damp_info *di)
-{
- /* set the index of reuse-array */
- di->index = (reuse_array_offset + (ospf6_damp_reuse_index (di->penalty)))
- % dc->reuse_list_size;
-
- /* insert to the head of the reuse list */
- di->next = dc->reuse_list_array[di->index];
- if (di->next)
- di->next->prev = di;
- di->prev = NULL;
- dc->reuse_list_array[di->index] = di;
-}
-
-/* When we quit damping for a target, we should execute proper event
- which have been postponed during damping */
-static void
-ospf6_damp_stop (struct ospf6_damp_info *di)
-{
- time_t t_now;
- char namebuf[64];
- struct timeval now;
-
- if (IS_OSPF6_DEBUG_DAMP)
- {
- t_now = time (NULL);
- prefix2str (&di->name, namebuf, sizeof (namebuf));
- gettimeofday (&now, NULL);
- zlog_info ("DAMP: %lu.%06lu stop damping: %ld: type: %d, name: %s",
- now.tv_sec, now.tv_usec,
- (long)t_now, di->type, namebuf);
- }
-
- /* set flag indicates that we're damping this target */
- di->damping = OFF;
-
- /* if the target's current status differ from that it should be,
- execute the proper event to repair his status */
- if (di->target_status != di->event_type)
- {
- (*(di->event)) (di->target);
- di->target_status = di->event_type;
-
- di->event = NULL;
- di->event_type = event_none;
- }
-}
-
-/* ospf6_reuse_timer is called every DELTA_REUSE seconds.
- Each route in the current reuse-list is evaluated
- and is used or requeued */
-int
-ospf6_damp_reuse_timer (struct thread *t)
-{
- struct ospf6_damp_info *di, *next;
- time_t t_now, t_diff;
- char namebuf[64];
- struct timeval now;
-
- /* Restart the reuse timer */
- ospf6_reuse_thread =
- thread_add_timer (master, ospf6_damp_reuse_timer, NULL, dc->delta_reuse);
-
- t_now = time (NULL);
-
- /* get the damp info list head */
- di = dc->reuse_list_array[reuse_array_offset];
- dc->reuse_list_array[reuse_array_offset] = NULL;
-
- /* rotate the circular reuse list head array */
- reuse_array_offset = (reuse_array_offset + 1) % dc->reuse_list_size;
-
- /* for each damp info */
- while (di)
- {
- next = di->next;
- di->next = NULL;
-
- /* Update penalty */
- t_diff = t_now - di->t_updated;
- di->t_updated = t_now;
- di->penalty = (int)
- ((double) di->penalty * ospf6_damp_decay (t_diff));
- /* configration of ceiling may be just changed */
- if (di->penalty > dc->ceiling)
- di->penalty = dc->ceiling;
-
- if (IS_OSPF6_DEBUG_DAMP)
- {
- prefix2str (&di->name, namebuf, sizeof (namebuf));
- gettimeofday (&now, NULL);
- zlog_info ("DAMP: %lu.%06lu update penalty: type: %d, name: %s, penalty: %d",
- now.tv_sec, now.tv_usec,
- di->type, namebuf, di->penalty);
- }
-
- /* If the penalty becomes under reuse,
- call real event that we have been postponed. */
- if (di->penalty < dc->reuse && di->damping == ON)
- ospf6_damp_stop (di);
-
- /* If the penalty becomes less than the half of the
- reuse value, this damp info will be freed from reuse-list,
- by assuming that it is considered to be stable enough already,
- and there's no need to maintain flapping history for this. */
- if (di->penalty <= dc->reuse / 2)
- {
- ospf6_damp_delete (di->type, &di->name);
- di = next;
- continue;
- }
-
- /* re-insert to the reuse-list */
- ospf6_reuse_list_add (di);
-
- di = next;
- }
-
- return 0;
-}
-
-static void
-ospf6_damp_event (damp_event_t event_type,
- u_short type, struct prefix *name,
- int (*event) (void *), void *target)
-{
- time_t t_now, t_diff;
- struct ospf6_damp_info *di;
- char namebuf[64];
- struct timeval now;
-
- if (dc->enabled == OFF)
- {
- (*event) (target);
- return;
- }
-
- di = ospf6_damp_lookup (type, name);
- if (! di)
- di = ospf6_damp_create (type, name);
-
- t_now = time (NULL);
-
- di->event = event;
- di->target = target;
- di->event_type = event_type;
-
- if (! ospf6_reuse_list_lookup (di))
- di->t_start = t_now;
- else
- {
- ospf6_reuse_list_remove (di);
-
- t_diff = t_now - di->t_updated;
- di->penalty = (int) (di->penalty * ospf6_damp_decay (t_diff));
- }
-
- /* penalty only on down event */
- if (event_type == event_down)
- {
- di->flap++;
- di->penalty += dc->default_penalty;
- }
-
- /* limit penalty up to ceiling */
- if (di->penalty > dc->ceiling)
- di->penalty = dc->ceiling;
-
- if (IS_OSPF6_DEBUG_DAMP)
- {
- prefix2str (&di->name, namebuf, sizeof (namebuf));
- gettimeofday (&now, NULL);
- zlog_info ("DAMP: %lu.%06lu update penalty: type: %d, name: %s, penalty: %d",
- now.tv_sec, now.tv_usec,
- di->type, namebuf, di->penalty);
- }
-
- /* if penalty < reuse, stop damping here */
- if (di->penalty < dc->reuse && di->damping == ON)
- {
- if (IS_OSPF6_DEBUG_DAMP)
- {
- prefix2str (&di->name, namebuf, sizeof (namebuf));
- gettimeofday (&now, NULL);
- zlog_info ("DAMP: %lu.%06lu stop damping: %ld: type: %d, name: %s",
- now.tv_sec, now.tv_usec,
- (long)t_now, di->type, namebuf);
- }
- di->damping = OFF;
- }
-
- /* if event == up and if penalty >= suppress , start damping here */
- if (di->event_type == event_up && di->penalty >= dc->suppress &&
- di->damping == OFF)
- {
- if (IS_OSPF6_DEBUG_DAMP)
- {
- prefix2str (&di->name, namebuf, sizeof (namebuf));
- gettimeofday (&now, NULL);
- zlog_info ("DAMP: %lu.%06lu start damping: %ld: type: %d, name: %s",
- now.tv_sec, now.tv_usec,
- (long)t_now, type, namebuf);
- }
- di->damping = ON;
- }
-
- /* execute event if we're not damping */
- if (di->damping == OFF)
- {
- (*(di->event)) (di->target);
- di->target_status = di->event_type;
- }
-
- /* if the penalty goes beyond suppress value, start damping */
- if (di->penalty >= dc->suppress && di->damping == OFF)
- {
- if (IS_OSPF6_DEBUG_DAMP)
- {
- prefix2str (name, namebuf, sizeof (namebuf));
- gettimeofday (&now, NULL);
- zlog_info ("DAMP: %lu.%06lu start damping: %ld: type: %d, name: %s",
- now.tv_sec, now.tv_usec,
- (long) t_now, type, namebuf);
- }
- di->damping = ON;
- }
-
- /* update last-updated-time field */
- di->t_updated = t_now;
-
- /* Insert it into the reuse list */
- ospf6_reuse_list_add (di);
-}
-
-void
-ospf6_damp_event_up (u_short type, struct prefix *name,
- int (*event) (void *), void *target)
-{
- struct timeval now;
-
- gettimeofday (&now, NULL);
- if (IS_OSPF6_DEBUG_DAMP)
- zlog_info ("DAMP: Up Event at %lu.%06lu", now.tv_sec, now.tv_usec);
-
- ospf6_damp_event (event_up, type, name, event, target);
-}
-
-void
-ospf6_damp_event_down (u_short type, struct prefix *name,
- int (*event) (void *), void *target)
-{
- struct timeval now;
-
- gettimeofday (&now, NULL);
- if (IS_OSPF6_DEBUG_DAMP)
- zlog_info ("DAMP: Down Event at %lu.%06lu", now.tv_sec, now.tv_usec);
-
- ospf6_damp_event (event_down, type, name, event, target);
-}
-
-int
-ospf6_damp_debug_thread (struct thread *thread)
-{
- int i;
- struct ospf6_damp_info *di;
- char buf[256];
- time_t t_now;
- struct timeval now;
-
- for (i = 0; i < dc->reuse_list_size; i++)
- {
- for (di = dc->reuse_list_array[i]; di; di = di->next)
- {
- t_now = time (NULL);
- gettimeofday (&now, NULL);
- prefix2str (&di->name, buf, sizeof (buf));
- zlog_info ("DAMP: %lu.%06lu %c %-32s penalty %7u",
- now.tv_sec, now.tv_usec,
- (di->damping == ON ? 'D' : 'A'), buf,
- (u_int) (di->penalty *
- ospf6_damp_decay (t_now - di->t_updated)));
- }
- }
- thread_add_timer (master, ospf6_damp_debug_thread, NULL, 1);
- return 0;
-}
-
-DEFUN (show_ipv6_ospf6_route_flapping,
- show_ipv6_ospf6_route_flapping_cmd,
- "show ipv6 ospf6 route flapping",
- SHOW_STR
- IP6_STR
- OSPF6_STR)
-{
- int i;
- struct ospf6_damp_info *di;
- char buf[256];
- time_t t_now;
-
- t_now = time (NULL);
- vty_out (vty, "%c %-32s %7s%s", ' ', "Prefix", "penalty", VTY_NEWLINE);
-
- for (i = 0; i < dc->reuse_list_size; i++)
- {
- for (di = dc->reuse_list_array[i]; di; di = di->next)
- {
- prefix2str (&di->name, buf, sizeof (buf));
- vty_out (vty, "%c %-32s %7u%s",
- (di->damping == ON ? 'D' : ' '), buf,
- (u_int) (di->penalty *
- ospf6_damp_decay (t_now - di->t_updated)),
- VTY_NEWLINE);
- }
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ospf6_flap_damping_route,
- ospf6_flap_damping_route_cmd,
- "flap-damping route <0-4294967295> <0-4294967295> "
- "<0-4294967295> <0-4294967295>",
- "enable flap dampening\n"
- "enable route flap dampening\n"
- "half-life in second\n"
- "reuse value\n"
- "suppress value\n"
- "t-hold in second (maximum time that the target can be damped)\n"
- )
-{
- u_int half_life, reuse, suppress, t_hold;
-
- if (argc)
- {
- half_life = (u_int) strtoul (argv[0], NULL, 10);
- reuse = (u_int) strtoul (argv[1], NULL, 10);
- suppress = (u_int) strtoul (argv[2], NULL, 10);
- t_hold = (u_int) strtoul (argv[3], NULL, 10);
- }
- else
- {
- half_life = (u_int) DEFAULT_HALF_LIFE;
- reuse = (u_int) DEFAULT_REUSE;
- suppress = (u_int) DEFAULT_SUPPRESS;
- t_hold = (u_int) DEFAULT_HALF_LIFE * 4;
- }
-
- if (reuse && suppress && reuse >= suppress)
- {
- vty_out (vty, "reuse value exceeded suppress value, failed%s\n",
- VTY_NEWLINE);
- return CMD_SUCCESS;
- }
-
- if (half_life && t_hold && half_life >= t_hold)
- {
- vty_out (vty, "half-life exceeded t-hold, failed%s\n", VTY_NEWLINE);
- return CMD_SUCCESS;
- }
-
- ospf6_damp_init_config (half_life, reuse, suppress, t_hold);
-
- if (ospf6_reuse_thread == NULL)
- ospf6_reuse_thread =
- thread_add_timer (master, ospf6_damp_reuse_timer, NULL, dc->delta_reuse);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (show_ipv6_ospf6_damp_config,
- show_ipv6_ospf6_camp_config_cmd,
- "show ipv6 ospf6 damp config",
- SHOW_STR
- IP6_STR
- OSPF6_STR
- "Flap-dampening information\n"
- "shows dampening configuration\n"
- )
-{
- int i;
-
- vty_out (vty, "%10s %10s %10s %10s%s",
- "Half life", "Suppress", "Reuse", "T-hold",
- VTY_NEWLINE);
- vty_out (vty, "%10u %10u %10u %10u%s",
- dc->half_life, dc->suppress, dc->reuse, dc->t_hold,
- VTY_NEWLINE);
- vty_out (vty, "%s", VTY_NEWLINE);
-
- vty_out (vty, "Delta-t = %u%s", dc->delta_t, VTY_NEWLINE);
- vty_out (vty, "Delta-Reuse = %u%s", dc->delta_reuse, VTY_NEWLINE);
- vty_out (vty, "Default-Penalty = %u%s", dc->default_penalty, VTY_NEWLINE);
- vty_out (vty, "Ceiling = %u%s", dc->ceiling, VTY_NEWLINE);
- vty_out (vty, "ScaleFactor = %f%s", dc->scale_factor, VTY_NEWLINE);
-
- vty_out (vty, "DecayArray(%d) =%s", dc->decay_array_size, VTY_NEWLINE);
- for (i = 0; i < dc->decay_array_size; i++)
- {
- if (i % 10 == 0)
- vty_out (vty, " ");
- vty_out (vty, " %f", dc->decay_array[i]);
- if (i % 10 == 0)
- vty_out (vty, "%s", VTY_NEWLINE);
- }
- vty_out (vty, "%s", VTY_NEWLINE);
-
- vty_out (vty, "ReuseIndexArray(%d) =%s",
- dc->reuse_index_array_size, VTY_NEWLINE);
- for (i = 0; i < dc->reuse_index_array_size; i++)
- {
- if (i % 10 == 0)
- vty_out (vty, " ");
- vty_out (vty, " %d", dc->reuse_index_array[i]);
- if (i % 10 == 0)
- vty_out (vty, "%s", VTY_NEWLINE);
- }
- vty_out (vty, "%s", VTY_NEWLINE);
-
- return CMD_SUCCESS;
-}
-
-void
-ospf6_damp_config_write (struct vty *vty)
-{
- if (dc->enabled == ON)
- {
- vty_out (vty, " flap-damping route %u %u %u %u%s",
- dc->half_life, dc->reuse, dc->suppress, dc->t_hold,
- VTY_NEWLINE);
- }
-}
-
-DEFUN (debug_ospf6_damp,
- debug_ospf6_damp_cmd,
- "debug ospf6 damp",
- DEBUG_STR
- OSPF6_STR
- "Flap-dampening information\n"
- )
-{
- ospf6_damp_debug = 1;
- return CMD_SUCCESS;
-}
-
-DEFUN (no_debug_ospf6_damp,
- no_debug_ospf6_damp_cmd,
- "no debug ospf6 damp",
- NO_STR
- DEBUG_STR
- OSPF6_STR
- "Flap-dampening information\n"
- )
-{
- ospf6_damp_debug = 0;
- return CMD_SUCCESS;
-}
-
-DEFUN (show_debug_ospf6_damp,
- show_debug_ospf6_damp_cmd,
- "show debugging ospf6 damp",
- SHOW_STR
- DEBUG_STR
- OSPF6_STR
- "Flap-dampening information\n"
- )
-{
- vty_out (vty, "debugging ospf6 damp is ");
- if (IS_OSPF6_DEBUG_DAMP)
- vty_out (vty, "enabled.");
- else
- vty_out (vty, "disabled.");
- vty_out (vty, "%s", VTY_NEWLINE);
- return CMD_SUCCESS;
-}
-
-void
-ospf6_damp_init ()
-{
- int i;
- for (i = 0; i < OSPF6_DAMP_TYPE_MAX; i++)
- damp_info_table[i] = route_table_init ();
-
- install_element (VIEW_NODE, &show_ipv6_ospf6_route_flapping_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_route_flapping_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_camp_config_cmd);
- install_element (OSPF6_NODE, &ospf6_flap_damping_route_cmd);
-
- install_element (ENABLE_NODE, &show_debug_ospf6_damp_cmd);
- install_element (CONFIG_NODE, &debug_ospf6_damp_cmd);
- install_element (CONFIG_NODE, &no_debug_ospf6_damp_cmd);
-
- thread_add_event (master, ospf6_damp_debug_thread, NULL, 0);
-}
-
-#endif /* HAVE_OSPF6_DAMP */
-
-
diff --git a/ospf6d/ospf6_damp.h b/ospf6d/ospf6_damp.h
deleted file mode 100644
index 19bdbc7..0000000
--- a/ospf6d/ospf6_damp.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * OSPF flap dampening by Manav Bhatia
- * Copyright (C) 2002
- *
- * 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.
- */
-
-/*
- * Flap Damping (target e.g. link/route)
- */
-
-#define HAVE_OSPF6_DAMP
-
-typedef enum
-{
- OFF,
- ON,
-} onoff_t;
-
-typedef enum
-{
- event_none,
- event_up,
- event_down,
-} damp_event_t;
-
-/* Structure maintained per target basis */
-struct ospf6_damp_info
-{
- /* identifier to decide which target */
- u_short type;
- struct prefix name;
-
- /* do we damping this info */
- onoff_t damping;
-
- u_int penalty;
- u_int flap;
- time_t t_start; /* First flap (down event) time */
- time_t t_updated; /* Last time the penalty was updated */
-
- /* index and double-link for reuse list */
- int index;
- struct ospf6_damp_info *next;
- struct ospf6_damp_info *prev;
-
- /* the last event that we are avoiding */
- int (*event) (void *target);
- void *target;
- damp_event_t event_type;
- damp_event_t target_status;
-};
-
-#define OSPF6_DAMP_TYPE_ROUTE 0
-#define OSPF6_DAMP_TYPE_MAX 1
-
-/* Global Configuration Parameters */
-struct ospf6_damp_config
-{
- /* is damping enabled ? */
- onoff_t enabled;
-
- /* configurable parameters */
- u_int half_life;
- u_int suppress;
- u_int reuse;
- u_int t_hold; /* Maximum hold down time */
-
- /* Non configurable parameters */
- u_int delta_t;
- u_int delta_reuse;
- u_int default_penalty;
- u_int ceiling; /* Max value a penalty can attain */
- double scale_factor;
-
- int decay_array_size; /* Calculated using config parameters */
- double *decay_array; /* Storage for decay values */
-
- int reuse_index_array_size; /* Size of reuse index array */
- int *reuse_index_array;
-
- int reuse_list_size; /* Number of reuse lists */
- struct ospf6_damp_info **reuse_list_array;
-};
-
-int ospf6_damp_reuse_timer (struct thread *);
-void ospf6_damp_event_up (u_short type, struct prefix *name,
- int (*exec_up) (void *), void *target);
-void ospf6_damp_event_down (u_short type, struct prefix *name,
- int (*exec_down) (void *), void *target);
-
-void ospf6_damp_config_write (struct vty *);
-void ospf6_damp_init ();
-
diff --git a/ospf6d/ospf6_dbex.c b/ospf6d/ospf6_dbex.c
deleted file mode 100644
index b10d9ae..0000000
--- a/ospf6d/ospf6_dbex.c
+++ /dev/null
@@ -1,704 +0,0 @@
-/*
- * Copyright (C) 1999 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 "ospf6d.h"
-
-/* check validity and put lsa in reqestlist if needed. */
-/* returns -1 if SeqNumMismatch required. */
-int
-ospf6_dbex_check_dbdesc_lsa_header (struct ospf6_lsa_header *lsa_header,
- struct ospf6_neighbor *from)
-{
- struct ospf6_lsa *received = NULL;
- struct ospf6_lsa *have = NULL;
-
- received = ospf6_lsa_summary_create
- ((struct ospf6_lsa_header__ *) lsa_header);
-
- /* case when received is AS-External though neighbor belongs stub area */
- if (lsa_header->type == htons (OSPF6_LSA_TYPE_AS_EXTERNAL) &&
- ospf6_area_is_stub (from->ospf6_interface->area))
- {
- zlog_err ("DbDesc %s receive from %s", from->str, received->str);
- zlog_err (" E-bit mismatch: %s", received->str);
- ospf6_lsa_delete (received);
- return -1;
- }
-
- /* if already have newer database copy, check next LSA */
- have = ospf6_lsdb_lookup (lsa_header->type, lsa_header->ls_id,
- lsa_header->advrtr,
- ospf6_lsa_get_scope (lsa_header->type,
- from->ospf6_interface));
- if (! have)
- {
- /* if we don't have database copy, add request */
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("Have no database copy, Request");
- ospf6_neighbor_request_add (received, from);
- }
- else if (have)
- {
- /* if database copy is less recent, add request */
- if (ospf6_lsa_check_recent (received, have) < 0)
- {
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("Database copy less recent, Request");
- ospf6_neighbor_request_add (received, from);
- }
- }
-
- return 0;
-}
-
-/* Direct acknowledgement */
-static void
-ospf6_dbex_acknowledge_direct (struct ospf6_lsa *lsa,
- struct ospf6_neighbor *o6n)
-{
- struct iovec directack[MAXIOVLIST];
- assert (lsa);
-
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: [%s:%s] direct ack %s ",
- o6n->str, o6n->ospf6_interface->interface->name,
- lsa->str);
-
- /* clear pointers to fragments of packet for direct acknowledgement */
- iov_clear (directack, MAXIOVLIST);
-
- /* set pointer of LSA to send */
- OSPF6_MESSAGE_ATTACH (directack, lsa->header,
- sizeof (struct ospf6_lsa_header));
-
- /* age update and add InfTransDelay */
- ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay);
-
- /* send unicast packet to neighbor's ipaddress */
- ospf6_message_send (OSPF6_MESSAGE_TYPE_LSACK, directack, &o6n->hisaddr,
- o6n->ospf6_interface->if_id);
-}
-
-/* Delayed acknowledgement */
-void
-ospf6_dbex_acknowledge_delayed (struct ospf6_lsa *lsa,
- struct ospf6_interface *o6i)
-{
- assert (o6i);
-
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: [%s] delayed ack %s", o6i->interface->name, lsa->str);
-
- /* attach delayed acknowledge list */
- ospf6_lsa_age_current (lsa);
- ospf6_interface_delayed_ack_add (lsa, o6i);
-
- /* if not yet, schedule delayed acknowledge RxmtInterval later.
- timers should be *less than* RxmtInterval
- or needless retrans will ensue */
- if (o6i->thread_send_lsack_delayed == NULL)
- o6i->thread_send_lsack_delayed
- = thread_add_timer (master, ospf6_send_lsack_delayed,
- o6i, o6i->rxmt_interval - 1);
-
- return;
-}
-
-/* RFC2328 section 13 (4):
- if MaxAge LSA and if we have no instance, and no neighbor
- is in states Exchange or Loading */
-/* returns 1 if match this case, else returns 0 */
-static int
-ospf6_dbex_is_maxage_to_be_dropped (struct ospf6_lsa *received,
- struct ospf6_neighbor *from)
-{
- int count;
-
- if (! IS_LSA_MAXAGE (received))
- return 0;
-
- if (ospf6_lsdb_lookup (received->header->type, received->header->id,
- received->header->adv_router,
- ospf6_lsa_get_scope (received->header->type,
- from->ospf6_interface)))
- return 0;
-
- if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (ntohs (received->header->type)))
- {
- count = 0;
- (*from->ospf6_interface->foreach_nei)
- (from->ospf6_interface, &count, NBS_EXCHANGE, ospf6_count_state);
- (*from->ospf6_interface->foreach_nei)
- (from->ospf6_interface, &count, NBS_LOADING, ospf6_count_state);
- if (count)
- return 0;
- }
- else if (OSPF6_LSA_IS_SCOPE_AREA (ntohs (received->header->type)))
- {
- count = 0;
- (*from->ospf6_interface->area->foreach_nei)
- (from->ospf6_interface->area, &count, NBS_EXCHANGE, ospf6_count_state);
- (*from->ospf6_interface->area->foreach_nei)
- (from->ospf6_interface->area, &count, NBS_LOADING, ospf6_count_state);
- if (count)
- return 0;
- }
- else if (OSPF6_LSA_IS_SCOPE_AS (ntohs (received->header->type)))
- {
- count = 0;
- (*from->ospf6_interface->area->ospf6->foreach_nei)
- (from->ospf6_interface->area->ospf6, &count, NBS_EXCHANGE,
- ospf6_count_state);
- (*from->ospf6_interface->area->ospf6->foreach_nei)
- (from->ospf6_interface->area->ospf6, &count, NBS_LOADING,
- ospf6_count_state);
- if (count)
- return 0;
- }
-
- return 1;
-}
-
-static void
-ospf6_dbex_remove_retrans (void *arg, int val, void *obj)
-{
- struct ospf6_lsa *rem;
- struct ospf6_neighbor *nei = (struct ospf6_neighbor *) obj;
- struct ospf6_lsa *lsa = (struct ospf6_lsa *) arg;
-
- rem = ospf6_lsdb_lookup_lsdb (lsa->header->type, lsa->header->id,
- lsa->header->adv_router, nei->retrans_list);
- if (rem)
- {
- ospf6_neighbor_retrans_remove (rem, nei);
- ospf6_maxage_remover ();
- }
-}
-
-void
-ospf6_dbex_remove_from_all_retrans_list (struct ospf6_lsa *lsa)
-{
- struct ospf6_interface *o6i;
- struct ospf6_area *o6a;
-
- if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (htons (lsa->header->type)))
- {
- o6i = lsa->scope;
- (*o6i->foreach_nei) (o6i, lsa, 0, ospf6_dbex_remove_retrans);
- }
- else if (OSPF6_LSA_IS_SCOPE_AREA (htons (lsa->header->type)))
- {
- o6a = lsa->scope;
- (*o6a->foreach_nei) (o6a, lsa, 0, ospf6_dbex_remove_retrans);
- }
- else if (OSPF6_LSA_IS_SCOPE_AS (htons (lsa->header->type)))
- {
- (*ospf6->foreach_nei) (ospf6, lsa, 0, ospf6_dbex_remove_retrans);
- }
-}
-
-/* RFC2328 section 13 */
-void
-ospf6_dbex_receive_lsa (struct ospf6_lsa_header *lsa_header,
- struct ospf6_neighbor *from)
-{
- struct ospf6_lsa *received, *have, *rem;
- struct timeval now;
- int ismore_recent, acktype;
- unsigned short cksum;
- struct ospf6_lsa_slot *slot;
-
- received = have = (struct ospf6_lsa *)NULL;
- ismore_recent = -1;
- recent_reason = "no instance";
-
- zlog_info ("Receive LSA (header -> %p)", lsa_header);
-
- /* make lsa structure for received lsa */
- received = ospf6_lsa_create (lsa_header);
-
- /* set LSA scope */
- if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (htons (lsa_header->type)))
- received->scope = from->ospf6_interface;
- else if (OSPF6_LSA_IS_SCOPE_AREA (htons (lsa_header->type)))
- received->scope = from->ospf6_interface->area;
- else if (OSPF6_LSA_IS_SCOPE_AS (htons (lsa_header->type)))
- received->scope = from->ospf6_interface->area->ospf6;
-
- /* (1) LSA Checksum */
- cksum = ntohs (lsa_header->checksum);
- if (ntohs (ospf6_lsa_checksum (lsa_header)) != cksum)
- {
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: received %s from %s%%%s"
- ": wrong checksum, drop",
- received->str, from->str,
- from->ospf6_interface->interface->name);
- ospf6_lsa_delete (received);
- return;
- }
-
- /* (3) Ebit Missmatch: AS-External-LSA */
- if (lsa_header->type == htons (OSPF6_LSA_TYPE_AS_EXTERNAL) &&
- ospf6_area_is_stub (from->ospf6_interface->area))
- {
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: received %s from %s%%%s"
- ": E-bit mismatch, drop",
- received->str, from->str,
- from->ospf6_interface->interface->name);
- ospf6_lsa_delete (received);
- return;
- }
-
- /* (4) if MaxAge LSA and if we have no instance, and no neighbor
- is in states Exchange or Loading */
- if (ospf6_dbex_is_maxage_to_be_dropped (received, from))
- {
- /* log */
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: received %s from %s%%%s"
- ": MaxAge, no instance, no neighbor exchange, drop",
- received->str, from->str,
- from->ospf6_interface->interface->name);
-
- /* a) Acknowledge back to neighbor (13.5) */
- /* Direct Acknowledgement */
- ospf6_dbex_acknowledge_direct (received, from);
-
- /* b) Discard */
- ospf6_lsa_delete (received);
- return;
- }
-
- /* (5) */
- /* lookup the same database copy in lsdb */
- have = ospf6_lsdb_lookup (lsa_header->type, lsa_header->ls_id,
- lsa_header->advrtr,
- ospf6_lsa_get_scope (lsa_header->type,
- from->ospf6_interface));
- if (have)
- {
- ismore_recent = ospf6_lsa_check_recent (received, have);
- if (ntohl (received->header->seqnum) == ntohl (have->header->seqnum))
- SET_FLAG (received->flag, OSPF6_LSA_FLAG_DUPLICATE);
- }
-
- /* if no database copy or received is more recent */
- if (!have || ismore_recent < 0)
- {
- /* in case we have no database copy */
- ismore_recent = -1;
-
- /* (a) MinLSArrival check */
- gettimeofday (&now, (struct timezone *)NULL);
- if (have && SEC_TVDIFF (&now, &have->installed) < OSPF6_MIN_LS_ARRIVAL)
- {
- //if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: Receive new LSA from %s: %s seq: %#x age: %d "
- "within MinLSArrival, drop: %ld.%06ld",
- from->str, received->str,
- ntohl (received->header->seqnum),
- ntohs (received->header->age),
- now.tv_sec, now.tv_usec);
-
- /* this will do free this lsa */
- ospf6_lsa_delete (received);
- return; /* examin next lsa */
- }
-
- //if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: Receive new LSA from %s: %s seq: %#x age: %d: "
- "%ld.%06ld",
- from->str, received->str,
- ntohl (received->header->seqnum),
- ntohs (received->header->age),
- now.tv_sec, now.tv_usec);
-
- /* (b) immediately flood */
- ospf6_dbex_flood (received, from);
-
-#if 0
- /* Because New LSDB do not permit two LSA having the same identifier
- exist in a LSDB list, above ospf6_dbex_flood() will remove
- the old instance automatically. thus bellow is not needed. */
- /* (c) remove database copy from all neighbor's retranslist */
- if (have)
- ospf6_dbex_remove_from_all_retrans_list (have);
-#endif
-
- /* (d), installing lsdb, which may cause routing
- table calculation (replacing database copy) */
- ospf6_lsdb_install (received);
-
- /* (e) possibly acknowledge */
- acktype = ack_type (received, ismore_recent, from);
- if (acktype == DIRECT_ACK)
- {
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: Direct Ack to %s", from->str);
- ospf6_dbex_acknowledge_direct (received, from);
- }
- else if (acktype == DELAYED_ACK)
- {
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: Delayed Ack to %s", from->str);
- ospf6_dbex_acknowledge_delayed (received, from->ospf6_interface);
- }
- else
- {
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: No Ack to %s", from->str);
- }
-
- /* (f) */
- /* Self Originated LSA, section 13.4 */
- if (received->lsa_hdr->lsh_advrtr == ospf6->router_id
- && (! have || ismore_recent < 0))
- {
- /* we're going to make new lsa or to flush this LSA. */
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: Self-originated LSA %s from %s:%s",
- received->str, from->str,
- from->ospf6_interface->interface->name);
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: %s: Make new one/Flush", received->str);
-
- SET_FLAG (received->flag, OSPF6_LSA_FLAG_REFRESH);
- slot = ospf6_lsa_slot_get (received->header->type);
- if (slot && slot->func_refresh)
- {
- (*slot->func_refresh) (received);
- return;
- }
-
- zlog_warn ("Can't Refresh LSA: Unknown type: %#x, Flush",
- ntohs (received->header->type));
- ospf6_lsa_premature_aging (received);
- return;
- }
- }
- else if (ospf6_lsdb_lookup_lsdb (received->header->type,
- received->header->id,
- received->header->adv_router,
- from->request_list))
- /* (6) if there is instance on sending neighbor's request list */
- {
- /* if no database copy, should go above state (5) */
- assert (have);
-
- zlog_warn ("DBEX: [%s:%s] received LSA %s is not newer,"
- " and is on his requestlist: Generate BadLSReq",
- from->str, from->ospf6_interface->interface->name,
- received->str);
-
- /* BadLSReq */
- thread_add_event (master, bad_lsreq, from, 0);
-
- ospf6_lsa_delete (received);
- }
- else if (ismore_recent == 0) /* (7) if neither is more recent */
- {
- /* (a) if on retranslist, Treat this LSA as an Ack: Implied Ack */
- rem = ospf6_lsdb_lookup_lsdb (received->header->type,
- received->header->id,
- received->header->adv_router,
- from->retrans_list);
- if (rem)
- {
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: Implied Ack from %s, (remove retrans)",
- from->str);
- SET_FLAG (received->flag, OSPF6_LSA_FLAG_IMPLIEDACK);
- ospf6_neighbor_retrans_remove (rem, from);
- }
-
- /* (b) possibly acknowledge */
- acktype = ack_type (received, ismore_recent, from);
- if (acktype == DIRECT_ACK)
- {
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: Direct Ack to %s", from->str);
- ospf6_dbex_acknowledge_direct (received, from);
- }
- else if (acktype == DELAYED_ACK)
- {
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: Delayed Ack to %s", from->str);
- ospf6_dbex_acknowledge_delayed (received, from->ospf6_interface);
- }
- else
- {
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: No Ack to %s", from->str);
- }
- ospf6_lsa_delete (received);
- }
- else /* (8) previous database copy is more recent */
- {
- /* If Seqnumber Wrapping, simply discard
- Otherwise, Send database copy of this LSA to this neighbor */
- if (! IS_LSA_MAXAGE (received) ||
- received->lsa_hdr->lsh_seqnum != MAX_SEQUENCE_NUMBER)
- {
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: database is more recent: send back to %s",
- from->str);
- ospf6_send_lsupdate_direct (have, from);
- }
- ospf6_lsa_delete (received);
- }
-}
-
-/* RFC2328: Table 19: Sending link state acknowledgements. */
-int
-ack_type (struct ospf6_lsa *newp, int ismore_recent,
- struct ospf6_neighbor *from)
-{
- struct ospf6_interface *ospf6_interface;
- struct ospf6_lsa *have;
- int count;
-
- assert (from && from->ospf6_interface);
- ospf6_interface = from->ospf6_interface;
-
- if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_FLOODBACK))
- return NO_ACK;
-
- if (ismore_recent < 0)
- {
- if (ospf6_interface->state != IFS_BDR)
- return DELAYED_ACK;
-
- if (ospf6_interface->dr == from->router_id)
- return DELAYED_ACK;
- return NO_ACK;
- }
-
- if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_DUPLICATE) &&
- CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_IMPLIEDACK))
- {
- if (ospf6_interface->state != IFS_BDR)
- return NO_ACK;
-
- if (ospf6_interface->dr == from->router_id)
- return DELAYED_ACK;
-
- return NO_ACK;
- }
-
- if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_DUPLICATE) &&
- ! CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_IMPLIEDACK))
- return DIRECT_ACK;
-
- have = ospf6_lsdb_lookup (newp->header->type, newp->header->id,
- newp->header->adv_router,
- ospf6_lsa_get_scope (newp->header->type,
- from->ospf6_interface));
-
- count = 0;
- ospf6->foreach_nei (ospf6, &count, NBS_EXCHANGE, ospf6_count_state);
- ospf6->foreach_nei (ospf6, &count, NBS_LOADING, ospf6_count_state);
-
- if (IS_LSA_MAXAGE (newp) && have == NULL && count == 0)
- return DIRECT_ACK;
-
- return NO_ACK;
-}
-
-static void
-ospf6_dbex_flood_linklocal (struct ospf6_lsa *lsa, struct ospf6_interface *o6i,
- struct ospf6_neighbor *from)
-{
- struct ospf6_neighbor *o6n = (struct ospf6_neighbor *) NULL;
- int ismore_recent, addretrans = 0;
- listnode n;
- struct ospf6_lsa *req;
-
- /* (1) for each neighbor */
- for (n = listhead (o6i->neighbor_list); n; nextnode (n))
- {
- o6n = (struct ospf6_neighbor *) getdata (n);
-
- /* (a) */
- if (o6n->state < NBS_EXCHANGE)
- continue; /* examin next neighbor */
-
- /* (b) */
- if (o6n->state == NBS_EXCHANGE
- || o6n->state == NBS_LOADING)
- {
- req = ospf6_lsdb_lookup_lsdb (lsa->header->type,
- lsa->header->id,
- lsa->header->adv_router,
- o6n->request_list);
- if (req)
- {
- ismore_recent = ospf6_lsa_check_recent (lsa, req);
- if (ismore_recent > 0)
- {
- continue; /* examin next neighbor */
- }
- else if (ismore_recent == 0)
- {
- ospf6_neighbor_request_remove (req, o6n);
- continue; /* examin next neighbor */
- }
- else /* ismore_recent < 0 (the new LSA is more recent) */
- {
- ospf6_neighbor_request_remove (req, o6n);
- }
- }
- }
-
- /* (c) */
- if (from && from->router_id == o6n->router_id)
- continue; /* examin next neighbor */
-
- /* (d) add retranslist */
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: schedule flooding [%s:%s]: %s",
- o6n->str, o6n->ospf6_interface->interface->name,
- lsa->str);
- ospf6_neighbor_retrans_add (lsa, o6n);
- addretrans++;
- if (o6n->send_update == (struct thread *) NULL)
- o6n->send_update =
- thread_add_timer (master, ospf6_send_lsupdate_rxmt, o6n,
- o6n->ospf6_interface->rxmt_interval);
- }
-
- /* (2) */
- if (addretrans == 0)
- return; /* examin next interface */
-
- if (from && from->ospf6_interface == o6i)
- {
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("DBEX: flood back %s to %s",
- lsa->str, o6i->interface->name);
- /* note occurence of floodback */
- SET_FLAG (lsa->flag, OSPF6_LSA_FLAG_FLOODBACK);
- }
-
- /* (3) */
- if (from && from->ospf6_interface == o6i)
- {
- /* if from DR or BDR, don't need to flood this interface */
- if (from->router_id == from->ospf6_interface->dr ||
- from->router_id == from->ospf6_interface->bdr)
- return; /* examin next interface */
- }
-
- /* (4) if I'm BDR, DR will flood this interface */
- if (from && from->ospf6_interface == o6i
- && o6i->state == IFS_BDR)
- return; /* examin next interface */
-
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("Flood to interface %s", o6i->interface->name);
-
- /* (5) send LinkState Update */
- ospf6_send_lsupdate_flood (lsa, o6i);
-
- return;
-}
-
-/* RFC2328 section 13.3 */
-static void
-ospf6_dbex_flood_area (struct ospf6_lsa *lsa, struct ospf6_area *area,
- struct ospf6_neighbor *from)
-{
- listnode n;
- struct ospf6_interface *ospf6_interface;
-
- assert (lsa && lsa->lsa_hdr && area);
-
- /* for each eligible ospf_ifs */
- for (n = listhead (area->if_list); n; nextnode (n))
- {
- ospf6_interface = (struct ospf6_interface *) getdata (n);
- ospf6_dbex_flood_linklocal (lsa, ospf6_interface, from);
- }
-}
-
-static void
-ospf6_dbex_flood_as (struct ospf6_lsa *lsa, struct ospf6 *ospf6,
- struct ospf6_neighbor *from)
-{
- listnode n;
- struct ospf6_area *o6a;
-
- assert (lsa && lsa->lsa_hdr && ospf6);
-
- /* for each attached area */
- for (n = listhead (ospf6->area_list); n; nextnode (n))
- {
- o6a = (struct ospf6_area *) getdata (n);
- ospf6_dbex_flood_area (lsa, o6a, from);
- }
-}
-
-/* flood ospf6_lsa within appropriate scope */
-void
-ospf6_dbex_flood (struct ospf6_lsa *lsa, struct ospf6_neighbor *from)
-{
- struct ospf6_area *o6a;
- struct ospf6_interface *o6i;
- struct ospf6 *o6;
- struct ospf6_lsa_header *lsa_header;
-
- lsa_header = (struct ospf6_lsa_header *) lsa->lsa_hdr;
-
- if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (ntohs (lsa_header->type)))
- {
- o6i = (struct ospf6_interface *) lsa->scope;
- assert (o6i);
-
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("Flood Linklocal: %s", o6i->interface->name);
- ospf6_dbex_flood_linklocal (lsa, o6i, from);
- }
- else if (OSPF6_LSA_IS_SCOPE_AREA (ntohs (lsa_header->type)))
- {
- o6a = (struct ospf6_area *) lsa->scope;
- assert (o6a);
-
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("Flood Area: %s", o6a->str);
- ospf6_dbex_flood_area (lsa, o6a, from);
- }
- else if (OSPF6_LSA_IS_SCOPE_AS (ntohs (lsa_header->type)))
- {
- o6 = (struct ospf6 *) lsa->scope;
- assert (o6);
-
- if (IS_OSPF6_DUMP_DBEX)
- zlog_info ("Flood AS");
- ospf6_dbex_flood_as (lsa, o6, from);
- }
- else
- {
- zlog_warn ("Can't Flood %s: scope unknown", lsa->str);
- }
-}
-
-
diff --git a/ospf6d/ospf6_dbex.h b/ospf6d/ospf6_dbex.h
deleted file mode 100644
index fbb7dc5..0000000
--- a/ospf6d/ospf6_dbex.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 1999 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.
- */
-
-#ifndef OSPF6_DBEX_H
-#define OSPF6_DBEX_H
-
-/* for ack_type() */
-#define NO_ACK 0
-#define DELAYED_ACK 1
-#define DIRECT_ACK 2
-
-/* Function Prototypes */
-void
-ospf6_add_delayed_ack (struct ospf6_lsa *, struct ospf6_interface *);
-void
-ospf6_remove_delayed_ack (struct ospf6_lsa *, struct ospf6_interface *);
-void ospf6_lsa_delayed_ack_remove_all (struct ospf6_lsa *lsa);
-
-void ospf6_dbex_prepare_summary (struct ospf6_neighbor *);
-
-int
-ospf6_dbex_check_dbdesc_lsa_header (struct ospf6_lsa_header *lsa_header,
- struct ospf6_neighbor *from);
-
-void
-ospf6_dbex_acknowledge_delayed (struct ospf6_lsa *lsa,
- struct ospf6_interface *o6i);
-
-void
-ospf6_dbex_receive_lsa (struct ospf6_lsa_header *,
- struct ospf6_neighbor *);
-
-int ack_type (struct ospf6_lsa *, int, struct ospf6_neighbor *);
-
-void ospf6_dbex_flood (struct ospf6_lsa *, struct ospf6_neighbor *);
-
-void
-ospf6_dbex_remove_from_all_retrans_list (struct ospf6_lsa *lsa);
-
-#endif /* OSPF6_DBEX_H */
-
diff --git a/ospf6d/ospf6_dump.c b/ospf6d/ospf6_dump.c
deleted file mode 100644
index 1e3c0c4..0000000
--- a/ospf6d/ospf6_dump.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Logging function
- * Copyright (C) 1999-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 other stuffs */
-#include "log.h"
-#include "command.h"
-#include "ospf6_dump.h"
-
-#define CMD_SHOW 0
-#define CMD_ENABLE 1
-#define CMD_DISABLE 2
-#define CMD_MAX 3
-
-struct ospf6_dump
-{
- struct cmd_element cmd[CMD_MAX];
- char *name;
- int config;
-};
-
-#define DUMP_MAX 512
-struct ospf6_dump *ospf6_dump[DUMP_MAX];
-unsigned int dump_size = 0;
-
-static int
-ospf6_dump_index (struct cmd_element *cmd, int command)
-{
- int i;
-
- for (i = 0; i < DUMP_MAX; i++)
- {
- if (cmd != &ospf6_dump[i]->cmd[command])
- continue;
- break;
- }
-
- if (i == DUMP_MAX)
- return -1;
- return i;
-}
-
-int
-ospf6_dump_is_on (int index)
-{
- if (ospf6_dump[index] == NULL)
- return 0;
-
- return ospf6_dump[index]->config;
-}
-
-int
-ospf6_dump_show (struct cmd_element *cmd,
- struct vty *vty, int argc, char **argv)
-{
- int index;
-
- index = ospf6_dump_index (cmd, CMD_SHOW);
- assert (index != -1);
-
- vty_out (vty, " %-16s: %s%s", ospf6_dump[index]->name,
- (ospf6_dump[index]->config ? "on" : "off"),
- VTY_NEWLINE);
- return CMD_SUCCESS;
-}
-
-int
-ospf6_dump_enable (struct cmd_element *cmd,
- struct vty *vty, int argc, char **argv)
-{
- int index;
-
- index = ospf6_dump_index (cmd, CMD_ENABLE);
- assert (index != -1);
-
- ospf6_dump[index]->config = 1;
- return CMD_SUCCESS;
-}
-
-int
-ospf6_dump_disable (struct cmd_element *cmd,
- struct vty *vty, int argc, char **argv)
-{
- int index;
-
- index = ospf6_dump_index (cmd, CMD_DISABLE);
- assert (index != -1);
-
- ospf6_dump[index]->config = 0;
- return CMD_SUCCESS;
-}
-
-int
-ospf6_dump_install (char *name, char *help)
-{
- struct cmd_element *cmd;
- char string[256];
- char helpstring[256];
-
- if (dump_size + 1 >= DUMP_MAX)
- return -1;
-
- ospf6_dump[dump_size] = malloc (sizeof (struct ospf6_dump));
- if (ospf6_dump[dump_size] == NULL)
- return -1;
- memset (ospf6_dump[dump_size], 0, sizeof (struct ospf6_dump));
-
- ospf6_dump[dump_size]->name = strdup (name);
-
- cmd = &ospf6_dump[dump_size]->cmd[CMD_SHOW];
- snprintf (string, sizeof (string), "show debugging ospf6 %s", name);
- snprintf (helpstring, sizeof (helpstring), "%s%s%s%s",
- SHOW_STR, DEBUG_STR, OSPF6_STR, help);
- memset (cmd, 0, sizeof (struct cmd_element));
- cmd->string = strdup (string);
- cmd->func = ospf6_dump_show;
- cmd->doc = strdup (helpstring);
- install_element (VIEW_NODE, cmd);
- install_element (ENABLE_NODE, cmd);
-
- cmd = &ospf6_dump[dump_size]->cmd[CMD_ENABLE];
- snprintf (string, sizeof (string), "debug ospf6 %s", name);
- snprintf (helpstring, sizeof (helpstring), "%s%s%s",
- DEBUG_STR, OSPF6_STR, help);
- memset (cmd, 0, sizeof (struct cmd_element));
- cmd->string = strdup (string);
- cmd->func = ospf6_dump_enable;
- cmd->doc = strdup (helpstring);
- install_element (CONFIG_NODE, cmd);
-
- cmd = &ospf6_dump[dump_size]->cmd[CMD_DISABLE];
- snprintf (string, sizeof (string), "no debug ospf6 %s", name);
- snprintf (helpstring, sizeof (helpstring), "%s%s%s%s",
- NO_STR, DEBUG_STR, OSPF6_STR, help);
- memset (cmd, 0, sizeof (struct cmd_element));
- cmd->string = strdup (string);
- cmd->func = ospf6_dump_disable;
- cmd->doc = strdup (helpstring);
- install_element (CONFIG_NODE, cmd);
-
- return dump_size++;
-}
-
-DEFUN(show_debug_ospf6,
- show_debug_ospf6_cmd,
- "show debugging ospf6",
- SHOW_STR
- DEBUG_STR
- OSPF6_STR)
-{
- int i;
-
- vty_out (vty, "OSPF6 debugging status:%s", VTY_NEWLINE);
-
- for (i = 0; i < DUMP_MAX; i++)
- {
- if (ospf6_dump[i] == NULL)
- continue;
- ospf6_dump_show (&ospf6_dump[i]->cmd[CMD_SHOW], vty, 0, NULL);
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (debug_ospf6_all,
- debug_ospf6_all_cmd,
- "debug ospf6 all",
- DEBUG_STR
- OSPF6_STR
- "Turn on ALL OSPFv3 debugging\n")
-{
- int i;
-
- for (i = 0; i < DUMP_MAX; i++)
- {
- if (ospf6_dump[i] == NULL)
- continue;
- ospf6_dump_enable (&ospf6_dump[i]->cmd[CMD_ENABLE], vty, 0, NULL);
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_debug_ospf6_all,
- no_debug_ospf6_all_cmd,
- "no debug ospf6 all",
- NO_STR
- DEBUG_STR
- OSPF6_STR
- "Turn off ALL OSPFv3 debugging\n")
-{
- int i;
-
- for (i = 0; i < DUMP_MAX; i++)
- {
- if (ospf6_dump[i] == NULL)
- continue;
- ospf6_dump_disable (&ospf6_dump[i]->cmd[CMD_DISABLE], vty, 0, NULL);
- }
-
- return CMD_SUCCESS;
-}
-
-struct cmd_node debug_node =
-{
- DEBUG_NODE,
- "",
- vtysh: 1
-};
-
-int
-ospf6_dump_config_write (struct vty *vty)
-{
- int i;
-
- for (i = 0; i < dump_size; i++)
- {
- if (ospf6_dump[i] == NULL)
- continue;
-
- if (ospf6_dump[i]->config == 0)
- continue;
-
- vty_out (vty, "debug ospf6 %s%s", ospf6_dump[i]->name, VTY_NEWLINE);
- }
-
- vty_out (vty, "!%s", VTY_NEWLINE);
- return 0;
-}
-
-char dump_index[OSPF6_DUMP_MAX];
-
-void
-ospf6_dump_init ()
-{
- memset (ospf6_dump, 0, sizeof (ospf6_dump));
-
- install_node (&debug_node, ospf6_dump_config_write);
-
- install_element (VIEW_NODE, &show_debug_ospf6_cmd);
- install_element (ENABLE_NODE, &show_debug_ospf6_cmd);
-
- install_element (CONFIG_NODE, &debug_ospf6_all_cmd);
- install_element (CONFIG_NODE, &no_debug_ospf6_all_cmd);
-
- /* bellow is for backward compatibility
- should be moved to each modules */
-
-#define MESSAGE_STR "OSPFv3 Messages\n"
-
- dump_index[OSPF6_DUMP_HELLO] =
- ospf6_dump_install ("message hello",
- MESSAGE_STR "Hello\n");
- dump_index[OSPF6_DUMP_DBDESC] =
- ospf6_dump_install ("message dbdesc",
- MESSAGE_STR "Database Description\n");
- dump_index[OSPF6_DUMP_LSREQ] =
- ospf6_dump_install ("message lsreq",
- MESSAGE_STR "Link State Request\n");
- dump_index[OSPF6_DUMP_LSUPDATE] =
- ospf6_dump_install ("message lsupdate",
- MESSAGE_STR "Link State Update\n");
- dump_index[OSPF6_DUMP_LSACK] =
- ospf6_dump_install ("message lsack",
- MESSAGE_STR "Link State Acknowledge\n");
- dump_index[OSPF6_DUMP_NEIGHBOR] =
- ospf6_dump_install ("neighbor", "Neighbors\n");
- dump_index[OSPF6_DUMP_INTERFACE] =
- ospf6_dump_install ("interface", "Interfaces\n");
- dump_index[OSPF6_DUMP_LSA] =
- ospf6_dump_install ("lsa", "Link State Advertisement\n");
- dump_index[OSPF6_DUMP_ZEBRA] =
- ospf6_dump_install ("zebra", "Communication with zebra\n");
- dump_index[OSPF6_DUMP_CONFIG] =
- ospf6_dump_install ("config", "Configuration Changes\n");
- dump_index[OSPF6_DUMP_DBEX] =
- ospf6_dump_install ("dbex", "Database Exchange/Flooding\n");
- dump_index[OSPF6_DUMP_SPF] =
- ospf6_dump_install ("spf", "SPF Calculation\n");
- dump_index[OSPF6_DUMP_ROUTE] =
- ospf6_dump_install ("route", "Route Calculation\n");
- dump_index[OSPF6_DUMP_LSDB] =
- ospf6_dump_install ("lsdb", "Link State Database\n");
- dump_index[OSPF6_DUMP_REDISTRIBUTE] =
- ospf6_dump_install ("redistribute",
- "Route Exchange with other protocols\n");
- dump_index[OSPF6_DUMP_HOOK] =
- ospf6_dump_install ("hook", "Hooks\n");
- dump_index[OSPF6_DUMP_ASBR] =
- ospf6_dump_install ("asbr", "AS Boundary Router function\n");
- dump_index[OSPF6_DUMP_PREFIX] =
- ospf6_dump_install ("prefix", "Prefix\n");
-}
-
-
diff --git a/ospf6d/ospf6_dump.h b/ospf6d/ospf6_dump.h
deleted file mode 100644
index 18a6e46..0000000
--- a/ospf6d/ospf6_dump.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Logging function
- * Copyright (C) 1999-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.
- */
-
-#ifndef OSPF6_DUMP_H
-#define OSPF6_DUMP_H
-
-enum ospf6_dump_type
-{
- OSPF6_DUMP_HELLO,
- OSPF6_DUMP_DBDESC,
- OSPF6_DUMP_LSREQ,
- OSPF6_DUMP_LSUPDATE,
- OSPF6_DUMP_LSACK,
- OSPF6_DUMP_NEIGHBOR,
- OSPF6_DUMP_INTERFACE,
- OSPF6_DUMP_AREA,
- OSPF6_DUMP_LSA,
- OSPF6_DUMP_ZEBRA,
- OSPF6_DUMP_CONFIG,
- OSPF6_DUMP_DBEX,
- OSPF6_DUMP_SPF,
- OSPF6_DUMP_ROUTE,
- OSPF6_DUMP_LSDB,
- OSPF6_DUMP_REDISTRIBUTE,
- OSPF6_DUMP_HOOK,
- OSPF6_DUMP_ASBR,
- OSPF6_DUMP_PREFIX,
- OSPF6_DUMP_ABR,
- OSPF6_DUMP_MAX
-};
-
-#define IS_OSPF6_DUMP_HELLO \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_HELLO]))
-#define IS_OSPF6_DUMP_DBDESC \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_DBDESC]))
-#define IS_OSPF6_DUMP_LSREQ \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_LSREQ]))
-#define IS_OSPF6_DUMP_LSUPDATE \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_LSUPDATE]))
-#define IS_OSPF6_DUMP_LSACK \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_LSACK]))
-#define IS_OSPF6_DUMP_NEIGHBOR \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_NEIGHBOR]))
-#define IS_OSPF6_DUMP_INTERFACE \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_INTERFACE]))
-#define IS_OSPF6_DUMP_LSA \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_LSA]))
-#define IS_OSPF6_DUMP_ZEBRA \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_ZEBRA]))
-#define IS_OSPF6_DUMP_CONFIG \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_CONFIG]))
-#define IS_OSPF6_DUMP_DBEX \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_DBEX]))
-#define IS_OSPF6_DUMP_SPF \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_SPF]))
-#define IS_OSPF6_DUMP_ROUTE \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_ROUTE]))
-#define IS_OSPF6_DUMP_LSDB \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_LSDB]))
-#define IS_OSPF6_DUMP_REDISTRIBUTE \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_REDISTRIBUTE]))
-#define IS_OSPF6_DUMP_HOOK \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_HOOK]))
-#define IS_OSPF6_DUMP_ASBR \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_ASBR]))
-#define IS_OSPF6_DUMP_PREFIX \
- (ospf6_dump_is_on (dump_index[OSPF6_DUMP_PREFIX]))
-
-extern char dump_index[OSPF6_DUMP_MAX];
-
-void ospf6_dump_init ();
-int ospf6_dump_is_on (int index);
-int ospf6_dump_install (char *name, char *help);
-
-#endif /* OSPF6_DUMP_H */
-
diff --git a/ospf6d/ospf6_hook.c b/ospf6d/ospf6_hook.c
deleted file mode 100644
index fc9e185..0000000
--- a/ospf6d/ospf6_hook.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2001 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 "log.h"
-#include "memory.h"
-
-#include "ospf6_hook.h"
-
-struct ospf6_hook_master neighbor_hook;
-struct ospf6_hook_master interface_hook;
-struct ospf6_hook_master area_hook;
-struct ospf6_hook_master top_hook;
-struct ospf6_hook_master database_hook;
-struct ospf6_hook_master intra_topology_hook;
-struct ospf6_hook_master inter_topology_hook;
-struct ospf6_hook_master route_hook;
-struct ospf6_hook_master redistribute_hook;
-
-static struct ospf6_hook *
-ospf6_hook_create ()
-{
- struct ospf6_hook *new;
- new = XMALLOC (MTYPE_OSPF6_OTHER, sizeof (struct ospf6_hook));
- if (new == NULL)
- return NULL;
- memset (new, 0, sizeof (struct ospf6_hook));
- return new;
-}
-
-static void
-ospf6_hook_delete (struct ospf6_hook *hook)
-{
- XFREE (MTYPE_OSPF6_OTHER, hook);
-}
-
-static int
-ospf6_hook_issame (struct ospf6_hook *hook1, struct ospf6_hook *hook2)
-{
- if (hook1->name && hook2->name &&
- strcmp (hook1->name, hook2->name) != 0)
- return 0;
- if (hook1->hook_add != hook2->hook_add)
- return 0;
- if (hook1->hook_change != hook2->hook_change)
- return 0;
- if (hook1->hook_remove != hook2->hook_remove)
- return 0;
- return 1;
-}
-
-void
-ospf6_hook_register (struct ospf6_hook *hook,
- struct ospf6_hook_master *master)
-{
- struct ospf6_hook *new;
-
- new = ospf6_hook_create ();
-
- if (hook->name)
- new->name = strdup (hook->name);
- new->hook_add = hook->hook_add;
- new->hook_change = hook->hook_change;
- new->hook_remove = hook->hook_remove;
-
- new->prev = master->tail;
- if (master->tail)
- master->tail->next = new;
-
- master->tail = new;
- if (! master->head)
- master->head = new;
-
- master->count++;
-
- if (IS_OSPF6_DUMP_HOOK)
- {
- zlog_info ("HOOK: Register hook%s%s%s%s",
- (hook->name ? " " : ""),
- (hook->name ? hook->name : ""),
- (master->name ? " to " : ""),
- (master->name ? master->name : ""));
- }
-}
-
-void
-ospf6_hook_unregister (struct ospf6_hook *req,
- struct ospf6_hook_master *master)
-{
- struct ospf6_hook *hook;
-
- for (hook = master->head; hook; hook = hook->next)
- {
- if (ospf6_hook_issame (hook, req))
- break;
- }
- if (! hook)
- return;
-
- if (hook->prev)
- hook->prev->next = hook->next;
- if (hook->next)
- hook->next->prev = hook->prev;
- if (master->head == hook)
- master->head = hook->next;
- if (master->tail == hook)
- master->tail = hook->prev;
-
- master->count--;
-
- if (IS_OSPF6_DUMP_HOOK)
- {
- zlog_info ("HOOK: Unregister hook%s%s%s%s",
- (hook->name ? " " : ""),
- (hook->name ? hook->name : ""),
- (master->name ? " to " : ""),
- (master->name ? master->name : ""));
- }
-
- if (hook->name)
- free (hook->name);
- ospf6_hook_delete (hook);
-}
-
-void
-ospf6_hook_unregister_all (struct ospf6_hook_master *master)
-{
- struct ospf6_hook *hook, *next;
-
- for (hook = master->head; hook; hook = next)
- {
- next = hook->next;
- ospf6_hook_delete (hook);
- }
-
- master->head = NULL;
- master->tail = NULL;
- master->count = 0;
-}
-
-
-void
-ospf6_hook_init ()
-{
- neighbor_hook.name = "Neighbor Hooklist";
- interface_hook.name = "Interface Hooklist";
- area_hook.name = "Area Hooklist";
- top_hook.name = "Top Hooklist";
- database_hook.name = "Database Hooklist";
- intra_topology_hook.name = "IntraTopology Hooklist";
- inter_topology_hook.name = "InterTopology Hooklist";
- route_hook.name = "Route Hooklist";
-}
-
-
diff --git a/ospf6d/ospf6_hook.h b/ospf6d/ospf6_hook.h
deleted file mode 100644
index fa882a5..0000000
--- a/ospf6d/ospf6_hook.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2001 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.
- */
-
-#ifndef OSPF6_HOOK_H
-#define OSPF6_HOOK_H
-
-#include "ospf6_dump.h"
-
-struct ospf6_hook
-{
- struct ospf6_hook *prev;
- struct ospf6_hook *next;
-
- char *name;
- int (*hook_add) (void *);
- int (*hook_change) (void *);
- int (*hook_remove) (void *);
-};
-
-struct ospf6_hook_master
-{
- char *name;
- struct ospf6_hook *head;
- struct ospf6_hook *tail;
- int count;
-};
-
-#define CALL_HOOKS(master,hookname,hookstr,data) \
- {\
- struct ospf6_hook *hook;\
- for (hook = (master)->head; hook; hook = hook->next)\
- {\
- if (hook->hookname)\
- {\
- if (IS_OSPF6_DUMP_HOOK)\
- zlog_info ("HOOK: Call %s hook: %s", (hookstr), hook->name);\
- (*(hook->hookname)) (data);\
- }\
- }\
- }
-#define CALL_ADD_HOOK(master,data) \
- { CALL_HOOKS ((master), hook_add, "ADD", (data)) }
-#define CALL_CHANGE_HOOK(master,data) \
- { CALL_HOOKS ((master), hook_change, "CHANGE", (data)) }
-#define CALL_REMOVE_HOOK(master,data) \
- { CALL_HOOKS ((master), hook_remove, "REMOVE", (data)) }
-
-#define IS_HOOK_SET(hook) \
- ((hook)->hook_add || (hook)->hook_change || (hook)->hook_remove)
-
-extern struct ospf6_hook_master neighbor_hook;
-extern struct ospf6_hook_master interface_hook;
-extern struct ospf6_hook_master area_hook;
-extern struct ospf6_hook_master top_hook;
-extern struct ospf6_hook_master database_hook;
-extern struct ospf6_hook_master intra_topology_hook;
-extern struct ospf6_hook_master inter_topology_hook;
-extern struct ospf6_hook_master route_hook;
-extern struct ospf6_hook_master redistribute_hook;
-
-void ospf6_hook_register (struct ospf6_hook *,
- struct ospf6_hook_master *);
-void ospf6_hook_unregister (struct ospf6_hook *,
- struct ospf6_hook_master *);
-void ospf6_hook_unregister_all (struct ospf6_hook_master *);
-void ospf6_hook_init ();
-
-#endif /*OSPF6_HOOK_H*/
-
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index 4d632b2..8f01e7d 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -19,161 +19,215 @@
* Boston, MA 02111-1307, USA.
*/
-#include "ospf6d.h"
+#include <zebra.h>
+#include "memory.h"
#include "if.h"
#include "log.h"
#include "command.h"
+#include "thread.h"
+#include "prefix.h"
+#include "plist.h"
+#include "ospf6d.h"
+#include "ospf6_lsa.h"
#include "ospf6_lsdb.h"
-
+#include "ospf6_network.h"
+#include "ospf6_message.h"
+#include "ospf6_route.h"
#include "ospf6_top.h"
#include "ospf6_area.h"
#include "ospf6_interface.h"
+#include "ospf6_neighbor.h"
+#include "ospf6_intra.h"
+#include "ospf6_spf.h"
-char *ospf6_interface_state_string[] =
+unsigned char conf_debug_ospf6_interface = 0;
+
+char *ospf6_interface_state_str[] =
{
- "None", "Down", "Loopback", "Waiting", "PointToPoint",
- "DROther", "BDR", "DR", NULL
+ "None",
+ "Down",
+ "Loopback",
+ "Waiting",
+ "PointToPoint",
+ "DROther",
+ "BDR",
+ "DR",
+ NULL
};
-static void
-ospf6_interface_foreach_neighbor (struct ospf6_interface *o6i,
- void *arg, int val,
- void (*func) (void *, int, void *))
+struct ospf6_interface *
+ospf6_interface_lookup_by_ifindex (int ifindex)
{
- listnode node;
- struct ospf6_neighbor *nei;
+ struct ospf6_interface *oi;
+ struct interface *ifp;
- for (node = listhead (o6i->neighbor_list); node; nextnode (node))
- {
- nei = (struct ospf6_neighbor *) getdata (node);
- (*func) (arg, val, nei);
- }
+ ifp = if_lookup_by_index (ifindex);
+ if (ifp == NULL)
+ return (struct ospf6_interface *) NULL;
+
+ oi = (struct ospf6_interface *) ifp->info;
+ return oi;
}
-static int
-ospf6_interface_maxage_remover (struct thread *t)
+struct ospf6_interface *
+ospf6_interface_lookup_by_name (char *ifname)
{
- int count;
- struct ospf6_interface *o6i = (struct ospf6_interface *) THREAD_ARG (t);
+ struct ospf6_interface *oi;
+ struct interface *ifp;
- o6i->maxage_remover = (struct thread *) NULL;
+ ifp = if_lookup_by_name (ifname);
+ if (ifp == NULL)
+ return (struct ospf6_interface *) NULL;
- count = 0;
- o6i->foreach_nei (o6i, &count, NBS_EXCHANGE, ospf6_count_state);
- o6i->foreach_nei (o6i, &count, NBS_LOADING, ospf6_count_state);
- if (count != 0)
- return 0;
-
- ospf6_lsdb_remove_maxage (o6i->lsdb);
- return 0;
+ oi = (struct ospf6_interface *) ifp->info;
+ return oi;
}
+/* schedule routing table recalculation */
void
-ospf6_interface_schedule_maxage_remover (void *arg, int val, void *obj)
+ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa)
{
- struct ospf6_interface *o6i = (struct ospf6_interface *) obj;
+ struct ospf6_interface *oi;
- if (o6i->maxage_remover != NULL)
- return;
+ oi = (struct ospf6_interface *) lsa->scope;
+ switch (ntohs (lsa->header->type))
+ {
+ case OSPF6_LSTYPE_LINK:
+ if (oi->state == OSPF6_INTERFACE_DR)
+ OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
+ ospf6_spf_schedule (oi->area);
+ break;
- o6i->maxage_remover =
- thread_add_event (master, ospf6_interface_maxage_remover, o6i, 0);
+ default:
+ if (IS_OSPF6_DEBUG_LSA (RECV))
+ zlog_info ("Unknown LSA in Interface %s's lsdb",
+ oi->interface->name);
+ break;
+ }
}
/* Create new ospf6 interface structure */
struct ospf6_interface *
ospf6_interface_create (struct interface *ifp)
{
- struct ospf6_interface *o6i;
+ struct ospf6_interface *oi;
- o6i = (struct ospf6_interface *)
+ oi = (struct ospf6_interface *)
XMALLOC (MTYPE_OSPF6_IF, sizeof (struct ospf6_interface));
- if (o6i)
- memset (o6i, 0, sizeof (struct ospf6_interface));
+ if (oi)
+ memset (oi, 0, sizeof (struct ospf6_interface));
else
{
zlog_err ("Can't malloc ospf6_interface for ifindex %d", ifp->ifindex);
return (struct ospf6_interface *) NULL;
}
- o6i->instance_id = 0;
- o6i->if_id = ifp->ifindex;
- o6i->lladdr = (struct in6_addr *) NULL;
- o6i->area = (struct ospf6_area *) NULL;
- o6i->state = IFS_DOWN;
- o6i->flag = 0;
- o6i->neighbor_list = list_new ();
+ oi->area = (struct ospf6_area *) NULL;
+ oi->neighbor_list = list_new ();
+ oi->neighbor_list->cmp = ospf6_neighbor_cmp;
+ oi->linklocal_addr = (struct in6_addr *) NULL;
+ oi->instance_id = 0;
+ oi->transdelay = 1;
+ oi->priority = 1;
- o6i->ack_list = ospf6_lsdb_create ();
- o6i->lsdb = ospf6_lsdb_create ();
+ oi->hello_interval = 10;
+ oi->dead_interval = 40;
+ oi->rxmt_interval = 5;
+ oi->cost = 1;
+ oi->ifmtu = ifp->mtu;
+ oi->state = OSPF6_INTERFACE_DOWN;
+ oi->flag = 0;
- o6i->transdelay = 1;
- o6i->priority = 1;
- o6i->hello_interval = 10;
- o6i->dead_interval = 40;
- o6i->rxmt_interval = 5;
- o6i->cost = 1;
- o6i->ifmtu = 1280;
+ oi->lsupdate_list = ospf6_lsdb_create ();
+ oi->lsack_list = ospf6_lsdb_create ();
+ oi->lsdb = ospf6_lsdb_create ();
+ oi->lsdb->hook_add = ospf6_interface_lsdb_hook;
+ oi->lsdb->hook_remove = ospf6_interface_lsdb_hook;
- o6i->foreach_nei = ospf6_interface_foreach_neighbor;
+ oi->route_connected = ospf6_route_table_create ();
/* link both */
- o6i->interface = ifp;
- ifp->info = o6i;
+ oi->interface = ifp;
+ ifp->info = oi;
- CALL_ADD_HOOK (&interface_hook, o6i);
-
- /* Get the interface's link-local if any */
- ospf6_interface_address_update(ifp);
-
- return o6i;
+ return oi;
}
void
-ospf6_interface_delete (struct ospf6_interface *o6i)
+ospf6_interface_delete (struct ospf6_interface *oi)
{
listnode n;
- struct ospf6_neighbor *o6n;
+ struct ospf6_neighbor *on;
- CALL_REMOVE_HOOK (&interface_hook, o6i);
-
- for (n = listhead (o6i->neighbor_list); n; nextnode (n))
+ for (n = listhead (oi->neighbor_list); n; nextnode (n))
{
- o6n = (struct ospf6_neighbor *) getdata (n);
- ospf6_neighbor_delete (o6n);
+ on = (struct ospf6_neighbor *) getdata (n);
+ ospf6_neighbor_delete (on);
}
- list_delete (o6i->neighbor_list);
+ list_delete (oi->neighbor_list);
- if (o6i->thread_send_hello)
- {
- thread_cancel (o6i->thread_send_hello);
- o6i->thread_send_hello = NULL;
- }
- if (o6i->thread_send_lsack_delayed)
- {
- thread_cancel (o6i->thread_send_lsack_delayed);
- o6i->thread_send_lsack_delayed = NULL;
- }
+ THREAD_OFF (oi->thread_send_hello);
+ THREAD_OFF (oi->thread_send_lsupdate);
+ THREAD_OFF (oi->thread_send_lsack);
- ospf6_lsdb_delete (o6i->ack_list);
- ospf6_lsdb_remove_all (o6i->lsdb);
- ospf6_lsdb_delete (o6i->lsdb);
+ ospf6_lsdb_remove_all (oi->lsdb);
+ ospf6_lsdb_remove_all (oi->lsupdate_list);
+ ospf6_lsdb_remove_all (oi->lsack_list);
+
+ ospf6_lsdb_delete (oi->lsdb);
+ ospf6_lsdb_delete (oi->lsupdate_list);
+ ospf6_lsdb_delete (oi->lsack_list);
+
+ ospf6_route_table_delete (oi->route_connected);
/* cut link */
- o6i->interface->info = NULL;
+ oi->interface->info = NULL;
/* plist_name */
- if (o6i->plist_name)
- XFREE (MTYPE_PREFIX_LIST_STR, o6i->plist_name);
+ if (oi->plist_name)
+ XFREE (MTYPE_PREFIX_LIST_STR, oi->plist_name);
- XFREE (MTYPE_OSPF6_IF, o6i);
+ XFREE (MTYPE_OSPF6_IF, oi);
+}
+
+void
+ospf6_interface_enable (struct ospf6_interface *oi)
+{
+ UNSET_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE);
+
+ oi->thread_send_hello =
+ thread_add_event (master, ospf6_hello_send, oi, 0);
+}
+
+void
+ospf6_interface_disable (struct ospf6_interface *oi)
+{
+ listnode i;
+ struct ospf6_neighbor *on;
+
+ SET_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE);
+
+ for (i = listhead (oi->neighbor_list); i; nextnode (i))
+ {
+ on = (struct ospf6_neighbor *) getdata (i);
+ ospf6_neighbor_delete (on);
+ }
+ list_delete_all_node (oi->neighbor_list);
+
+ ospf6_lsdb_remove_all (oi->lsdb);
+ ospf6_lsdb_remove_all (oi->lsupdate_list);
+ ospf6_lsdb_remove_all (oi->lsack_list);
+
+ THREAD_OFF (oi->thread_send_hello);
+ THREAD_OFF (oi->thread_send_lsupdate);
+ THREAD_OFF (oi->thread_send_lsack);
}
static struct in6_addr *
-ospf6_interface_update_linklocal_address (struct interface *ifp)
+ospf6_interface_get_linklocal_address (struct interface *ifp)
{
listnode n;
struct connected *c;
@@ -198,222 +252,532 @@
void
ospf6_interface_if_add (struct interface *ifp)
{
- struct ospf6_interface *o6i;
+ struct ospf6_interface *oi;
- o6i = (struct ospf6_interface *) ifp->info;
- if (!o6i)
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
return;
- o6i->if_id = ifp->ifindex;
-
- ospf6_interface_address_update (ifp);
+ oi->ifmtu = ifp->mtu;
/* interface start */
- if (o6i->area)
- thread_add_event (master, interface_up, o6i, 0);
+ if (oi->area)
+ thread_add_event (master, interface_up, oi, 0);
}
void
ospf6_interface_if_del (struct interface *ifp)
{
- struct ospf6_interface *o6i;
+ struct ospf6_interface *oi;
- o6i = (struct ospf6_interface *) ifp->info;
- if (!o6i)
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
return;
/* interface stop */
- if (o6i->area)
- thread_execute (master, interface_down, o6i, 0);
+ if (oi->area)
+ thread_execute (master, interface_down, oi, 0);
- listnode_delete (o6i->area->if_list, o6i);
- o6i->area = (struct ospf6_area *) NULL;
+ listnode_delete (oi->area->if_list, oi);
+ oi->area = (struct ospf6_area *) NULL;
/* cut link */
- o6i->interface = NULL;
+ oi->interface = NULL;
ifp->info = NULL;
- ospf6_interface_delete (o6i);
+ ospf6_interface_delete (oi);
}
void
ospf6_interface_state_update (struct interface *ifp)
{
- struct ospf6_interface *o6i;
+ struct ospf6_interface *oi;
- o6i = (struct ospf6_interface *) ifp->info;
- if (! o6i)
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
return;
- if (! o6i->area)
+ if (oi->area == NULL)
return;
if (if_is_up (ifp))
- thread_add_event (master, interface_up, o6i, 0);
+ thread_add_event (master, interface_up, oi, 0);
else
- thread_add_event (master, interface_down, o6i, 0);
+ thread_add_event (master, interface_down, oi, 0);
return;
}
void
-ospf6_interface_address_update (struct interface *ifp)
+ospf6_interface_connected_route_update (struct interface *ifp)
{
- struct ospf6_interface *o6i;
+ struct ospf6_interface *oi;
+ struct ospf6_route *route;
+ struct connected *c;
+ listnode i;
- o6i = (struct ospf6_interface *) ifp->info;
- if (! o6i)
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
return;
/* reset linklocal pointer */
- o6i->lladdr = ospf6_interface_update_linklocal_address (ifp);
+ oi->linklocal_addr = ospf6_interface_get_linklocal_address (ifp);
- /* if area is null, can't make link-lsa */
- if (! o6i->area)
+ /* if area is null, do not make connected-route list */
+ if (oi->area == NULL)
return;
+ /* update "route to advertise" interface route table */
+ ospf6_route_remove_all (oi->route_connected);
+ for (i = listhead (oi->interface->connected); i; nextnode (i))
+ {
+ c = (struct connected *) getdata (i);
+
+ if (c->address->family != AF_INET6)
+ continue;
+
+ CONTINUE_IF_ADDRESS_LINKLOCAL (c->address);
+ CONTINUE_IF_ADDRESS_UNSPECIFIED (c->address);
+ CONTINUE_IF_ADDRESS_LOOPBACK (c->address);
+ CONTINUE_IF_ADDRESS_V4COMPAT (c->address);
+ CONTINUE_IF_ADDRESS_V4MAPPED (c->address);
+
+ /* apply filter */
+ if (oi->plist_name)
+ {
+ struct prefix_list *plist;
+ enum prefix_list_type ret;
+ char buf[128];
+
+ prefix2str (c->address, buf, sizeof (buf));
+ plist = prefix_list_lookup (AFI_IP6, oi->plist_name);
+ ret = prefix_list_apply (plist, (void *) c->address);
+ if (ret == PREFIX_DENY)
+ {
+ zlog_info ("%s on %s filtered by prefix-list %s ",
+ buf, oi->interface->name, oi->plist_name);
+ continue;
+ }
+ }
+
+ route = ospf6_route_create ();
+ memcpy (&route->prefix, c->address, sizeof (struct prefix));
+ apply_mask (&route->prefix);
+ route->type = OSPF6_DEST_TYPE_NETWORK;
+ route->path.area_id = oi->area->area_id;
+ route->path.type = OSPF6_PATH_TYPE_INTRA;
+ route->path.cost = oi->cost;
+ route->nexthop[0].ifindex = oi->interface->ifindex;
+ inet_pton (AF_INET6, "::1", &route->nexthop[0].address);
+ ospf6_route_add (route, oi->route_connected);
+ }
+
/* create new Link-LSA */
- CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, o6i);
-
- CALL_CHANGE_HOOK (&interface_hook, o6i);
+ OSPF6_LINK_LSA_SCHEDULE (oi);
+ OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
+ OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
}
-struct ospf6_interface *
-ospf6_interface_lookup_by_index (int ifindex)
+static void
+ospf6_interface_state_change (u_char next_state, struct ospf6_interface *oi)
{
- struct ospf6_interface *o6i;
- struct interface *ifp;
+ u_char prev_state;
- ifp = if_lookup_by_index (ifindex);
+ prev_state = oi->state;
+ oi->state = next_state;
- if (! ifp)
- return (struct ospf6_interface *) NULL;
+ if (prev_state == next_state)
+ return;
- o6i = (struct ospf6_interface *) ifp->info;
- return o6i;
-}
-
-struct ospf6_interface *
-ospf6_interface_lookup_by_name (char *ifname)
-{
- struct ospf6_interface *o6i;
- struct interface *ifp;
-
- ifp = if_lookup_by_name (ifname);
-
- if (! ifp)
- return (struct ospf6_interface *) NULL;
-
- o6i = (struct ospf6_interface *) ifp->info;
- return o6i;
-}
-
-int
-ospf6_interface_count_neighbor_in_state (u_char state,
- struct ospf6_interface *o6i)
-{
- listnode n;
- struct ospf6_neighbor *o6n;
- int count = 0;
-
- for (n = listhead (o6i->neighbor_list); n; nextnode (n))
+ /* log */
+ if (IS_OSPF6_DEBUG_INTERFACE)
{
- o6n = (struct ospf6_neighbor *) getdata (n);
- if (o6n->state == state)
- count++;
+ zlog_info ("Interface state change %s: %s -> %s", oi->interface->name,
+ ospf6_interface_state_str[prev_state],
+ ospf6_interface_state_str[next_state]);
}
- return count;
-}
-int
-ospf6_interface_count_full_neighbor (struct ospf6_interface *o6i)
-{
- listnode n;
- struct ospf6_neighbor *o6n;
- int count = 0;
+ if ((prev_state == OSPF6_INTERFACE_DR ||
+ prev_state == OSPF6_INTERFACE_BDR) &&
+ (next_state != OSPF6_INTERFACE_DR &&
+ next_state != OSPF6_INTERFACE_BDR))
+ ospf6_leave_alldrouters (oi->interface->ifindex);
+ if ((prev_state != OSPF6_INTERFACE_DR &&
+ prev_state != OSPF6_INTERFACE_BDR) &&
+ (next_state == OSPF6_INTERFACE_DR ||
+ next_state == OSPF6_INTERFACE_BDR))
+ ospf6_join_alldrouters (oi->interface->ifindex);
- for (n = listhead (o6i->neighbor_list); n; nextnode (n))
+ OSPF6_ROUTER_LSA_SCHEDULE (oi->area);
+ if (prev_state == OSPF6_INTERFACE_DR || next_state == OSPF6_INTERFACE_DR)
{
- o6n = (struct ospf6_neighbor *) getdata (n);
- if (o6n->state == NBS_FULL)
- count++;
+ OSPF6_NETWORK_LSA_SCHEDULE (oi);
+ OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
+ OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
}
- return count;
+}
+
+
+/* DR Election, RFC2328 section 9.4 */
+
+#define IS_ELIGIBLE(n) \
+ ((n)->state >= OSPF6_NEIGHBOR_TWOWAY && (n)->priority != 0)
+
+static struct ospf6_neighbor *
+better_bdrouter (struct ospf6_neighbor *a, struct ospf6_neighbor *b)
+{
+ if ((a == NULL || ! IS_ELIGIBLE (a) || a->drouter == a->router_id) &&
+ (b == NULL || ! IS_ELIGIBLE (b) || b->drouter == b->router_id))
+ return NULL;
+ else if (a == NULL || ! IS_ELIGIBLE (a) || a->drouter == a->router_id)
+ return b;
+ else if (b == NULL || ! IS_ELIGIBLE (b) || b->drouter == b->router_id)
+ return a;
+
+ if (a->bdrouter == a->router_id && b->bdrouter != b->router_id)
+ return a;
+ if (a->bdrouter != a->router_id && b->bdrouter == b->router_id)
+ return b;
+
+ if (a->priority > b->priority)
+ return a;
+ if (a->priority < b->priority)
+ return b;
+
+ if (ntohl (a->router_id) > ntohl (b->router_id))
+ return a;
+ if (ntohl (a->router_id) < ntohl (b->router_id))
+ return b;
+
+ zlog_warn ("Router-ID duplicate ?");
+ return a;
+}
+
+static struct ospf6_neighbor *
+better_drouter (struct ospf6_neighbor *a, struct ospf6_neighbor *b)
+{
+ if ((a == NULL || ! IS_ELIGIBLE (a) || a->drouter != a->router_id) &&
+ (b == NULL || ! IS_ELIGIBLE (b) || b->drouter != b->router_id))
+ return NULL;
+ else if (a == NULL || ! IS_ELIGIBLE (a) || a->drouter != a->router_id)
+ return b;
+ else if (b == NULL || ! IS_ELIGIBLE (b) || b->drouter != b->router_id)
+ return a;
+
+ if (a->drouter == a->router_id && b->drouter != b->router_id)
+ return a;
+ if (a->drouter != a->router_id && b->drouter == b->router_id)
+ return b;
+
+ if (a->priority > b->priority)
+ return a;
+ if (a->priority < b->priority)
+ return b;
+
+ if (ntohl (a->router_id) > ntohl (b->router_id))
+ return a;
+ if (ntohl (a->router_id) < ntohl (b->router_id))
+ return b;
+
+ zlog_warn ("Router-ID duplicate ?");
+ return a;
+}
+
+static u_char
+dr_election (struct ospf6_interface *oi)
+{
+ listnode i;
+ struct ospf6_neighbor *on, *drouter, *bdrouter, myself;
+ struct ospf6_neighbor *best_drouter, *best_bdrouter;
+ u_char next_state = 0;
+
+ drouter = bdrouter = NULL;
+ best_drouter = best_bdrouter = NULL;
+
+ /* pseudo neighbor myself, including noting current DR/BDR (1) */
+ memset (&myself, 0, sizeof (myself));
+ inet_ntop (AF_INET, &oi->area->ospf6->router_id, myself.name,
+ sizeof (myself.name));
+ myself.state = OSPF6_NEIGHBOR_TWOWAY;
+ myself.drouter = oi->drouter;
+ myself.bdrouter = oi->bdrouter;
+ myself.priority = oi->priority;
+ myself.router_id = oi->area->ospf6->router_id;
+
+ /* Electing BDR (2) */
+ for (i = listhead (oi->neighbor_list); i; nextnode (i))
+ {
+ on = (struct ospf6_neighbor *) getdata (i);
+ bdrouter = better_bdrouter (bdrouter, on);
+ }
+ best_bdrouter = bdrouter;
+ bdrouter = better_bdrouter (best_bdrouter, &myself);
+
+ /* Electing DR (3) */
+ for (i = listhead (oi->neighbor_list); i; nextnode (i))
+ {
+ on = (struct ospf6_neighbor *) getdata (i);
+ drouter = better_drouter (drouter, on);
+ }
+ best_drouter = drouter;
+ drouter = better_drouter (best_drouter, &myself);
+ if (drouter == NULL)
+ drouter = bdrouter;
+
+ /* the router itself is newly/no longer DR/BDR (4) */
+ if ((drouter == &myself && myself.drouter != myself.router_id) ||
+ (drouter != &myself && myself.drouter == myself.router_id) ||
+ (bdrouter == &myself && myself.bdrouter != myself.router_id) ||
+ (bdrouter != &myself && myself.bdrouter == myself.router_id))
+ {
+ myself.drouter = (drouter ? drouter->router_id : htonl (0));
+ myself.bdrouter = (bdrouter ? bdrouter->router_id : htonl (0));
+
+ /* compatible to Electing BDR (2) */
+ bdrouter = better_bdrouter (best_bdrouter, &myself);
+
+ /* compatible to Electing DR (3) */
+ drouter = better_drouter (best_drouter, &myself);
+ if (drouter == NULL)
+ drouter = bdrouter;
+ }
+
+ /* Set interface state accordingly (5) */
+ if (drouter && drouter == &myself)
+ next_state = OSPF6_INTERFACE_DR;
+ else if (bdrouter && bdrouter == &myself)
+ next_state = OSPF6_INTERFACE_BDR;
+ else
+ next_state = OSPF6_INTERFACE_DROTHER;
+
+ /* If NBMA, schedule Start for each neighbor having priority of 0 (6) */
+ /* XXX */
+
+ /* If DR or BDR change, invoke AdjOK? for each neighbor (7) */
+ /* RFC 2328 section 12.4. Originating LSAs (3) will be handled
+ accordingly after AdjOK */
+ if (oi->drouter != (drouter ? drouter->router_id : htonl (0)) ||
+ oi->bdrouter != (bdrouter ? bdrouter->router_id : htonl (0)))
+ {
+ if (IS_OSPF6_DEBUG_INTERFACE)
+ zlog_info ("DR Election on %s: DR: %s BDR: %s", oi->interface->name,
+ (drouter ? drouter->name : "0.0.0.0"),
+ (bdrouter ? bdrouter->name : "0.0.0.0"));
+
+ for (i = listhead (oi->neighbor_list); i; nextnode (i))
+ {
+ on = (struct ospf6_neighbor *) getdata (i);
+ if (on->state < OSPF6_NEIGHBOR_TWOWAY)
+ continue;
+ /* Schedule AdjOK. */
+ thread_add_event (master, adj_ok, on, 0);
+ }
+ }
+
+ oi->drouter = (drouter ? drouter->router_id : htonl (0));
+ oi->bdrouter = (bdrouter ? bdrouter->router_id : htonl (0));
+ return next_state;
+}
+
+
+/* Interface State Machine */
+int
+interface_up (struct thread *thread)
+{
+ struct ospf6_interface *oi;
+
+ oi = (struct ospf6_interface *) THREAD_ARG (thread);
+ assert (oi && oi->interface);
+
+ if (IS_OSPF6_DEBUG_INTERFACE)
+ zlog_info ("Interface Event %s: [InterfaceUp]",
+ oi->interface->name);
+
+ /* check physical interface is up */
+ if (! if_is_up (oi->interface))
+ {
+ if (IS_OSPF6_DEBUG_INTERFACE)
+ zlog_info ("Interface %s is down, can't execute [InterfaceUp]",
+ oi->interface->name);
+ return 0;
+ }
+
+ /* if already enabled, do nothing */
+ if (oi->state > OSPF6_INTERFACE_DOWN)
+ {
+ if (IS_OSPF6_DEBUG_INTERFACE)
+ zlog_info ("Interface %s already enabled",
+ oi->interface->name);
+ return 0;
+ }
+
+ /* Join AllSPFRouters */
+ ospf6_join_allspfrouters (oi->interface->ifindex);
+
+ /* Update interface route */
+ ospf6_interface_connected_route_update (oi->interface);
+
+ /* Schedule Hello */
+ if (! CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
+ thread_add_event (master, ospf6_hello_send, oi, 0);
+
+ /* decide next interface state */
+ if (if_is_pointopoint (oi->interface))
+ ospf6_interface_state_change (OSPF6_INTERFACE_POINTTOPOINT, oi);
+ else if (oi->priority == 0)
+ ospf6_interface_state_change (OSPF6_INTERFACE_DROTHER, oi);
+ else
+ {
+ ospf6_interface_state_change (OSPF6_INTERFACE_WAITING, oi);
+ thread_add_timer (master, wait_timer, oi, oi->dead_interval);
+ }
+
+ return 0;
}
int
-ospf6_interface_is_enabled (unsigned int ifindex)
+wait_timer (struct thread *thread)
{
- struct ospf6_interface *o6i;
+ struct ospf6_interface *oi;
- o6i = ospf6_interface_lookup_by_index (ifindex);
- if (! o6i)
- return 0;
+ oi = (struct ospf6_interface *) THREAD_ARG (thread);
+ assert (oi && oi->interface);
- if (! o6i->area)
- return 0;
+ if (IS_OSPF6_DEBUG_INTERFACE)
+ zlog_info ("Interface Event %s: [WaitTimer]",
+ oi->interface->name);
- if (o6i->state <= IFS_DOWN)
- return 0;
+ if (oi->state == OSPF6_INTERFACE_WAITING)
+ ospf6_interface_state_change (dr_election (oi), oi);
- return 1;
+ return 0;
}
-void
-ospf6_interface_delayed_ack_add (struct ospf6_lsa *lsa,
- struct ospf6_interface *o6i)
+int
+backup_seen (struct thread *thread)
{
- struct ospf6_lsa *summary;
- summary = ospf6_lsa_summary_create (lsa->header);
- ospf6_lsdb_add (summary, o6i->ack_list);
+ struct ospf6_interface *oi;
+
+ oi = (struct ospf6_interface *) THREAD_ARG (thread);
+ assert (oi && oi->interface);
+
+ if (IS_OSPF6_DEBUG_INTERFACE)
+ zlog_info ("Interface Event %s: [BackupSeen]",
+ oi->interface->name);
+
+ if (oi->state == OSPF6_INTERFACE_WAITING)
+ ospf6_interface_state_change (dr_election (oi), oi);
+
+ return 0;
}
-void
-ospf6_interface_delayed_ack_remove (struct ospf6_lsa *lsa,
- struct ospf6_interface *o6i)
+int
+neighbor_change (struct thread *thread)
{
- struct ospf6_lsa *summary;
- summary = ospf6_lsdb_lookup_lsdb (lsa->header->type, lsa->header->id,
- lsa->header->adv_router, o6i->ack_list);
- ospf6_lsdb_remove (summary, o6i->ack_list);
+ struct ospf6_interface *oi;
+
+ oi = (struct ospf6_interface *) THREAD_ARG (thread);
+ assert (oi && oi->interface);
+
+ if (IS_OSPF6_DEBUG_INTERFACE)
+ zlog_info ("Interface Event %s: [NeighborChange]",
+ oi->interface->name);
+
+ if (oi->state == OSPF6_INTERFACE_DROTHER ||
+ oi->state == OSPF6_INTERFACE_BDR ||
+ oi->state == OSPF6_INTERFACE_DR)
+ ospf6_interface_state_change (dr_election (oi), oi);
+
+ return 0;
}
+int
+loopind (struct thread *thread)
+{
+ struct ospf6_interface *oi;
+
+ oi = (struct ospf6_interface *) THREAD_ARG (thread);
+ assert (oi && oi->interface);
+
+ if (IS_OSPF6_DEBUG_INTERFACE)
+ zlog_info ("Interface Event %s: [LoopInd]",
+ oi->interface->name);
+
+ /* XXX not yet */
+
+ return 0;
+}
+
+int
+interface_down (struct thread *thread)
+{
+ struct ospf6_interface *oi;
+ listnode n;
+ struct ospf6_neighbor *on;
+
+ oi = (struct ospf6_interface *) THREAD_ARG (thread);
+ assert (oi && oi->interface);
+
+ if (IS_OSPF6_DEBUG_INTERFACE)
+ zlog_info ("Interface Event %s: [InterfaceDown]",
+ oi->interface->name);
+
+ /* Leave AllSPFRouters */
+ if (oi->state > OSPF6_INTERFACE_DOWN)
+ ospf6_leave_allspfrouters (oi->interface->ifindex);
+
+ ospf6_interface_state_change (OSPF6_INTERFACE_DOWN, oi);
+
+ for (n = listhead (oi->neighbor_list); n; nextnode (n))
+ {
+ on = (struct ospf6_neighbor *) getdata (n);
+ ospf6_neighbor_delete (on);
+ }
+ list_delete_all_node (oi->neighbor_list);
+
+ return 0;
+}
+
+
/* show specified interface structure */
int
-ospf6_interface_show (struct vty *vty, struct interface *iface)
+ospf6_interface_show (struct vty *vty, struct interface *ifp)
{
- struct ospf6_interface *ospf6_interface;
+ struct ospf6_interface *oi;
struct connected *c;
struct prefix *p;
listnode i;
- char strbuf[64], dr[32], bdr[32];
+ char strbuf[64], drouter[32], bdrouter[32];
char *updown[3] = {"down", "up", NULL};
char *type;
+ struct timeval res, now;
+ char duration[32];
+ struct ospf6_lsa *lsa;
/* check physical interface type */
- if (if_is_loopback (iface))
+ if (if_is_loopback (ifp))
type = "LOOPBACK";
- else if (if_is_broadcast (iface))
+ else if (if_is_broadcast (ifp))
type = "BROADCAST";
- else if (if_is_pointopoint (iface))
+ else if (if_is_pointopoint (ifp))
type = "POINTOPOINT";
else
type = "UNKNOWN";
vty_out (vty, "%s is %s, type %s%s",
- iface->name, updown[if_is_up (iface)], type,
+ ifp->name, updown[if_is_up (ifp)], type,
VTY_NEWLINE);
- vty_out (vty, " Interface ID: %d%s", iface->ifindex, VTY_NEWLINE);
+ vty_out (vty, " Interface ID: %d%s", ifp->ifindex, VTY_NEWLINE);
- if (iface->info == NULL)
+ if (ifp->info == NULL)
{
vty_out (vty, " OSPF not enabled on this interface%s", VTY_NEWLINE);
return 0;
}
else
- ospf6_interface = (struct ospf6_interface *) iface->info;
+ oi = (struct ospf6_interface *) ifp->info;
vty_out (vty, " Internet Address:%s", VTY_NEWLINE);
- for (i = listhead (iface->connected); i; nextnode (i))
+ for (i = listhead (ifp->connected); i; nextnode (i))
{
c = (struct connected *)getdata (i);
p = c->address;
@@ -421,103 +785,75 @@
switch (p->family)
{
case AF_INET:
- vty_out (vty, " inet : %s%s", strbuf,
+ vty_out (vty, " inet : %s%s", strbuf,
VTY_NEWLINE);
break;
case AF_INET6:
- vty_out (vty, " inet6: %s%s", strbuf,
+ vty_out (vty, " inet6: %s%s", strbuf,
VTY_NEWLINE);
break;
default:
- vty_out (vty, " ??? : %s%s", strbuf,
+ vty_out (vty, " ??? : %s%s", strbuf,
VTY_NEWLINE);
break;
}
}
- if (ospf6_interface->area)
+ if (oi->area)
{
- inet_ntop (AF_INET, &ospf6_interface->area->ospf6->router_id,
+ vty_out (vty, " Instance ID %d, Interface MTU %d (autodetect: %d)%s",
+ oi->instance_id, oi->ifmtu, ifp->mtu, VTY_NEWLINE);
+ inet_ntop (AF_INET, &oi->area->area_id,
strbuf, sizeof (strbuf));
- vty_out (vty, " Instance ID %d, Router ID %s%s",
- ospf6_interface->instance_id, strbuf,
+ vty_out (vty, " Area ID %s, Cost %hu%s", strbuf, oi->cost,
VTY_NEWLINE);
- inet_ntop (AF_INET, &ospf6_interface->area->area_id,
- strbuf, sizeof (strbuf));
- vty_out (vty, " Area ID %s, Cost %hu%s", strbuf,
- ospf6_interface->cost, VTY_NEWLINE);
}
else
vty_out (vty, " Not Attached to Area%s", VTY_NEWLINE);
vty_out (vty, " State %s, Transmit Delay %d sec, Priority %d%s",
- ospf6_interface_state_string[ospf6_interface->state],
- ospf6_interface->transdelay,
- ospf6_interface->priority,
+ ospf6_interface_state_str[oi->state],
+ oi->transdelay, oi->priority,
VTY_NEWLINE);
vty_out (vty, " Timer intervals configured:%s", VTY_NEWLINE);
vty_out (vty, " Hello %d, Dead %d, Retransmit %d%s",
- ospf6_interface->hello_interval,
- ospf6_interface->dead_interval,
- ospf6_interface->rxmt_interval,
+ oi->hello_interval, oi->dead_interval, oi->rxmt_interval,
VTY_NEWLINE);
- inet_ntop (AF_INET, &ospf6_interface->dr, dr, sizeof (dr));
- inet_ntop (AF_INET, &ospf6_interface->bdr, bdr, sizeof (bdr));
- vty_out (vty, " DR:%s BDR:%s%s", dr, bdr, VTY_NEWLINE);
+ inet_ntop (AF_INET, &oi->drouter, drouter, sizeof (drouter));
+ inet_ntop (AF_INET, &oi->bdrouter, bdrouter, sizeof (bdrouter));
+ vty_out (vty, " DR: %s BDR: %s%s", drouter, bdrouter, VTY_NEWLINE);
vty_out (vty, " Number of I/F scoped LSAs is %u%s",
- ospf6_interface->lsdb->count, VTY_NEWLINE);
- vty_out (vty, " %-16s %5d times, %-16s %5d times%s",
- "DRElection", ospf6_interface->ospf6_stat_dr_election,
- "DelayedLSAck", ospf6_interface->ospf6_stat_delayed_lsack,
- VTY_NEWLINE);
-
- return 0;
-}
-
-void
-ospf6_interface_statistics_show (struct vty *vty, struct ospf6_interface *o6i)
-{
- struct timeval now, uptime;
- u_long recv_total, send_total;
- u_long bps_total_avg, bps_tx_avg, bps_rx_avg;
- int i;
+ oi->lsdb->count, VTY_NEWLINE);
gettimeofday (&now, (struct timezone *) NULL);
- ospf6_timeval_sub (&now, &ospf6->starttime, &uptime);
- recv_total = send_total = 0;
- for (i = 0; i < OSPF6_MESSAGE_TYPE_MAX; i++)
- {
- recv_total += o6i->message_stat[i].recv_octet;
- send_total += o6i->message_stat[i].send_octet;
- }
- bps_total_avg = (recv_total + send_total) * 8 / uptime.tv_sec;
- bps_tx_avg = send_total * 8 / uptime.tv_sec;
- bps_rx_avg = recv_total * 8 / uptime.tv_sec;
+ timerclear (&res);
+ if (oi->thread_send_lsupdate)
+ timersub (&oi->thread_send_lsupdate->u.sands, &now, &res);
+ timerstring (&res, duration, sizeof (duration));
+ vty_out (vty, " %d Pending LSAs for LSUpdate in Time %s [thread %s]%s",
+ oi->lsupdate_list->count, duration,
+ (oi->thread_send_lsupdate ? "on" : "off"),
+ VTY_NEWLINE);
+ for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ vty_out (vty, " %s%s", lsa->name, VTY_NEWLINE);
- vty_out (vty, " Statistics of interface %s%s",
- o6i->interface->name, VTY_NEWLINE);
- vty_out (vty, " Number of Neighbor: %d%s",
- listcount (o6i->neighbor_list), VTY_NEWLINE);
+ timerclear (&res);
+ if (oi->thread_send_lsack)
+ timersub (&oi->thread_send_lsack->u.sands, &now, &res);
+ timerstring (&res, duration, sizeof (duration));
+ vty_out (vty, " %d Pending LSAs for LSAck in Time %s [thread %s]%s",
+ oi->lsack_list->count, duration,
+ (oi->thread_send_lsack ? "on" : "off"),
+ VTY_NEWLINE);
+ for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ vty_out (vty, " %s%s", lsa->name, VTY_NEWLINE);
- vty_out (vty, " %-8s %6s %6s %8s %8s%s",
- "Type", "tx", "rx", "tx-byte", "rx-byte", VTY_NEWLINE);
- for (i = 0; i < OSPF6_MESSAGE_TYPE_MAX; i++)
- {
- vty_out (vty, " %-8s %6d %6d %8d %8d%s",
- ospf6_message_type_string[i],
- o6i->message_stat[i].send,
- o6i->message_stat[i].recv,
- o6i->message_stat[i].send_octet,
- o6i->message_stat[i].recv_octet,
- VTY_NEWLINE);
- }
-
- vty_out (vty, " Average Link bandwidth: %ldbps"
- " (Tx: %ldbps Rx: %ldbps)%s",
- bps_total_avg, bps_tx_avg, bps_rx_avg, VTY_NEWLINE);
+ return 0;
}
/* show interface */
@@ -537,10 +873,10 @@
if (argc)
{
ifp = if_lookup_by_name (argv[0]);
- if (!ifp)
+ if (ifp == NULL)
{
vty_out (vty, "No such Interface: %s%s", argv[0],
- VTY_NEWLINE);
+ VTY_NEWLINE);
return CMD_WARNING;
}
ospf6_interface_show (vty, ifp);
@@ -549,10 +885,11 @@
{
for (i = listhead (iflist); i; nextnode (i))
{
- ifp = (struct interface *)getdata (i);
+ ifp = (struct interface *) getdata (i);
ospf6_interface_show (vty, ifp);
}
}
+
return CMD_SUCCESS;
}
@@ -563,188 +900,316 @@
IP6_STR
OSPF6_STR
INTERFACE_STR
- )
+ );
-/* interface variable set command */
-DEFUN (ipv6_ospf6_cost,
- ipv6_ospf6_cost_cmd,
- "ipv6 ospf6 cost COST",
+DEFUN (show_ipv6_ospf6_interface_ifname_prefix,
+ show_ipv6_ospf6_interface_ifname_prefix_cmd,
+ "show ipv6 ospf6 interface IFNAME prefix",
+ SHOW_STR
IP6_STR
OSPF6_STR
- "Interface cost\n"
- "<1-65535> Cost\n"
+ INTERFACE_STR
+ IFNAME_STR
+ "Display connected prefixes to advertise\n"
)
{
- struct ospf6_interface *o6i;
struct interface *ifp;
+ struct ospf6_interface *oi;
- ifp = (struct interface *)vty->index;
- assert (ifp);
+ ifp = if_lookup_by_name (argv[0]);
+ if (ifp == NULL)
+ {
+ vty_out (vty, "No such Interface: %s%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
- o6i = (struct ospf6_interface *)ifp->info;
- if (!o6i)
- o6i = ospf6_interface_create (ifp);
- assert (o6i);
+ oi = ifp->info;
+ if (oi == NULL)
+ {
+ vty_out (vty, "OSPFv3 is not enabled on %s%s", argv[0], VTY_NEWLINE);
+ return CMD_WARNING;
+ }
- if (o6i->cost == strtol (argv[0], NULL, 10))
- return CMD_SUCCESS;
-
- o6i->cost = strtol (argv[0], NULL, 10);
-
- /* execute LSA hooks */
- CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, o6i);
-
- CALL_CHANGE_HOOK (&interface_hook, o6i);
+ argc--;
+ argv++;
+ ospf6_route_table_show (vty, argc, argv, oi->route_connected);
return CMD_SUCCESS;
}
-/* interface variable set command */
-DEFUN (ipv6_ospf6_hellointerval,
- ipv6_ospf6_hellointerval_cmd,
- "ipv6 ospf6 hello-interval HELLO_INTERVAL",
+ALIAS (show_ipv6_ospf6_interface_ifname_prefix,
+ show_ipv6_ospf6_interface_ifname_prefix_detail_cmd,
+ "show ipv6 ospf6 interface IFNAME prefix (X:X::X:X|X:X::X:X/M|detail)",
+ SHOW_STR
IP6_STR
OSPF6_STR
- "Time between HELLO packets\n"
- SECONDS_STR
+ INTERFACE_STR
+ IFNAME_STR
+ "Display connected prefixes to advertise\n"
+ OSPF6_ROUTE_ADDRESS_STR
+ OSPF6_ROUTE_PREFIX_STR
+ "Dispaly details of the prefixes\n"
+ );
+
+ALIAS (show_ipv6_ospf6_interface_ifname_prefix,
+ show_ipv6_ospf6_interface_ifname_prefix_match_cmd,
+ "show ipv6 ospf6 interface IFNAME prefix X:X::X:X/M (match|detail)",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ INTERFACE_STR
+ IFNAME_STR
+ "Display connected prefixes to advertise\n"
+ OSPF6_ROUTE_PREFIX_STR
+ OSPF6_ROUTE_MATCH_STR
+ "Dispaly details of the prefixes\n"
+ );
+
+DEFUN (show_ipv6_ospf6_interface_prefix,
+ show_ipv6_ospf6_interface_prefix_cmd,
+ "show ipv6 ospf6 interface prefix",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ INTERFACE_STR
+ "Display connected prefixes to advertise\n"
)
{
- struct ospf6_interface *ospf6_interface;
+ listnode i;
+ struct ospf6_interface *oi;
+ struct interface *ifp;
+
+ for (i = listhead (iflist); i; nextnode (i))
+ {
+ ifp = (struct interface *) getdata (i);
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
+ continue;
+
+ ospf6_route_table_show (vty, argc, argv, oi->route_connected);
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_interface_prefix,
+ show_ipv6_ospf6_interface_prefix_detail_cmd,
+ "show ipv6 ospf6 interface prefix (X:X::X:X|X:X::X:X/M|detail)",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ INTERFACE_STR
+ "Display connected prefixes to advertise\n"
+ OSPF6_ROUTE_ADDRESS_STR
+ OSPF6_ROUTE_PREFIX_STR
+ "Dispaly details of the prefixes\n"
+ );
+
+ALIAS (show_ipv6_ospf6_interface_prefix,
+ show_ipv6_ospf6_interface_prefix_match_cmd,
+ "show ipv6 ospf6 interface prefix X:X::X:X/M (match|detail)",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ INTERFACE_STR
+ "Display connected prefixes to advertise\n"
+ OSPF6_ROUTE_PREFIX_STR
+ OSPF6_ROUTE_MATCH_STR
+ "Dispaly details of the prefixes\n"
+ );
+
+
+/* interface variable set command */
+DEFUN (ipv6_ospf6_cost,
+ ipv6_ospf6_cost_cmd,
+ "ipv6 ospf6 cost <1-65535>",
+ IP6_STR
+ OSPF6_STR
+ "Interface cost\n"
+ "Outgoing metric of this interface\n"
+ )
+{
+ struct ospf6_interface *oi;
struct interface *ifp;
ifp = (struct interface *) vty->index;
assert (ifp);
- ospf6_interface = (struct ospf6_interface *) ifp->info;
- if (!ospf6_interface)
- ospf6_interface = ospf6_interface_create (ifp);
- assert (ospf6_interface);
- ospf6_interface->hello_interval = strtol (argv[0], NULL, 10);
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create (ifp);
+ assert (oi);
+
+ if (oi->cost == strtol (argv[0], NULL, 10))
+ return CMD_SUCCESS;
+
+ oi->cost = strtol (argv[0], NULL, 10);
+
+ /* update cost held in route_connected list in ospf6_interface */
+ ospf6_interface_connected_route_update (oi->interface);
+
+ /* execute LSA hooks */
+ if (oi->area)
+ {
+ OSPF6_LINK_LSA_SCHEDULE (oi);
+ OSPF6_ROUTER_LSA_SCHEDULE (oi->area);
+ OSPF6_NETWORK_LSA_SCHEDULE (oi);
+ OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
+ OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (ipv6_ospf6_hellointerval,
+ ipv6_ospf6_hellointerval_cmd,
+ "ipv6 ospf6 hello-interval <1-65535>",
+ IP6_STR
+ OSPF6_STR
+ "Interval time of Hello packets\n"
+ SECONDS_STR
+ )
+{
+ struct ospf6_interface *oi;
+ struct interface *ifp;
+
+ ifp = (struct interface *) vty->index;
+ assert (ifp);
+
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create (ifp);
+ assert (oi);
+
+ oi->hello_interval = strtol (argv[0], NULL, 10);
return CMD_SUCCESS;
}
/* interface variable set command */
DEFUN (ipv6_ospf6_deadinterval,
ipv6_ospf6_deadinterval_cmd,
- "ipv6 ospf6 dead-interval ROUTER_DEAD_INTERVAL",
+ "ipv6 ospf6 dead-interval <1-65535>",
IP6_STR
OSPF6_STR
- "Interval after which a neighbor is declared dead\n"
+ "Interval time after which a neighbor is declared down\n"
SECONDS_STR
)
{
- struct ospf6_interface *ospf6_interface;
+ struct ospf6_interface *oi;
struct interface *ifp;
ifp = (struct interface *) vty->index;
assert (ifp);
- ospf6_interface = (struct ospf6_interface *) ifp->info;
- if (!ospf6_interface)
- ospf6_interface = ospf6_interface_create (ifp);
- assert (ospf6_interface);
- ospf6_interface->dead_interval = strtol (argv[0], NULL, 10);
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create (ifp);
+ assert (oi);
+
+ oi->dead_interval = strtol (argv[0], NULL, 10);
return CMD_SUCCESS;
}
/* interface variable set command */
DEFUN (ipv6_ospf6_transmitdelay,
ipv6_ospf6_transmitdelay_cmd,
- "ipv6 ospf6 transmit-delay TRANSMITDELAY",
+ "ipv6 ospf6 transmit-delay <1-3600>",
IP6_STR
OSPF6_STR
- "Link state transmit delay\n"
+ "Transmit delay of this interface\n"
SECONDS_STR
)
{
- struct ospf6_interface *ospf6_interface;
+ struct ospf6_interface *oi;
struct interface *ifp;
ifp = (struct interface *) vty->index;
assert (ifp);
- ospf6_interface = (struct ospf6_interface *) ifp->info;
- if (!ospf6_interface)
- ospf6_interface = ospf6_interface_create (ifp);
- assert (ospf6_interface);
- ospf6_interface->transdelay = strtol (argv[0], NULL, 10);
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create (ifp);
+ assert (oi);
+
+ oi->transdelay = strtol (argv[0], NULL, 10);
return CMD_SUCCESS;
}
/* interface variable set command */
DEFUN (ipv6_ospf6_retransmitinterval,
ipv6_ospf6_retransmitinterval_cmd,
- "ipv6 ospf6 retransmit-interval RXMTINTERVAL",
+ "ipv6 ospf6 retransmit-interval <1-65535>",
IP6_STR
OSPF6_STR
"Time between retransmitting lost link state advertisements\n"
SECONDS_STR
)
{
- struct ospf6_interface *ospf6_interface;
+ struct ospf6_interface *oi;
struct interface *ifp;
ifp = (struct interface *) vty->index;
assert (ifp);
- ospf6_interface = (struct ospf6_interface *) ifp->info;
- if (!ospf6_interface)
- ospf6_interface = ospf6_interface_create (ifp);
- assert (ospf6_interface);
- ospf6_interface->rxmt_interval = strtol (argv[0], NULL, 10);
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create (ifp);
+ assert (oi);
+
+ oi->rxmt_interval = strtol (argv[0], NULL, 10);
return CMD_SUCCESS;
}
/* interface variable set command */
DEFUN (ipv6_ospf6_priority,
ipv6_ospf6_priority_cmd,
- "ipv6 ospf6 priority PRIORITY",
+ "ipv6 ospf6 priority <0-255>",
IP6_STR
OSPF6_STR
"Router priority\n"
- "<0-255> Priority\n"
+ "Priority value\n"
)
{
- struct ospf6_interface *ospf6_interface;
+ struct ospf6_interface *oi;
struct interface *ifp;
ifp = (struct interface *) vty->index;
assert (ifp);
- ospf6_interface = (struct ospf6_interface *) ifp->info;
- if (!ospf6_interface)
- ospf6_interface = ospf6_interface_create (ifp);
- assert (ospf6_interface);
- ospf6_interface->priority = strtol (argv[0], NULL, 10);
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create (ifp);
+ assert (oi);
- if (ospf6_interface->area)
- ifs_change (dr_election (ospf6_interface), "Priority reconfigured",
- ospf6_interface);
+ oi->priority = strtol (argv[0], NULL, 10);
+
+ if (oi->area)
+ ospf6_interface_state_change (dr_election (oi), oi);
return CMD_SUCCESS;
}
DEFUN (ipv6_ospf6_instance,
ipv6_ospf6_instance_cmd,
- "ipv6 ospf6 instance-id INSTANCE",
+ "ipv6 ospf6 instance-id <0-255>",
IP6_STR
OSPF6_STR
- "Instance ID\n"
- "<0-255> Instance ID\n"
+ "Instance ID for this interface\n"
+ "Instance ID value\n"
)
{
- struct ospf6_interface *ospf6_interface;
+ struct ospf6_interface *oi;
struct interface *ifp;
ifp = (struct interface *)vty->index;
assert (ifp);
- ospf6_interface = (struct ospf6_interface *)ifp->info;
- if (!ospf6_interface)
- ospf6_interface = ospf6_interface_create (ifp);
- assert (ospf6_interface);
+ oi = (struct ospf6_interface *)ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create (ifp);
+ assert (oi);
- ospf6_interface->instance_id = strtol (argv[0], NULL, 10);
+ oi->instance_id = strtol (argv[0], NULL, 10);
return CMD_SUCCESS;
}
@@ -753,34 +1218,30 @@
"ipv6 ospf6 passive",
IP6_STR
OSPF6_STR
- "passive interface: No Adjacency will be formed on this I/F\n"
+ "passive interface, No adjacency will be formed on this interface\n"
)
{
- struct ospf6_interface *o6i;
+ struct ospf6_interface *oi;
struct interface *ifp;
listnode node;
- struct ospf6_neighbor *o6n;
+ struct ospf6_neighbor *on;
ifp = (struct interface *) vty->index;
assert (ifp);
- o6i = (struct ospf6_interface *) ifp->info;
- if (! o6i)
- o6i = ospf6_interface_create (ifp);
- assert (o6i);
- SET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE);
- if (o6i->thread_send_hello)
- {
- thread_cancel (o6i->thread_send_hello);
- o6i->thread_send_hello = (struct thread *) NULL;
- }
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create (ifp);
+ assert (oi);
- for (node = listhead (o6i->neighbor_list); node; nextnode (node))
+ SET_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE);
+ THREAD_OFF (oi->thread_send_hello);
+
+ for (node = listhead (oi->neighbor_list); node; nextnode (node))
{
- o6n = getdata (node);
- if (o6n->inactivity_timer)
- thread_cancel (o6n->inactivity_timer);
- thread_execute (master, inactivity_timer, o6n, 0);
+ on = (struct ospf6_neighbor *) getdata (node);
+ THREAD_OFF (on->inactivity_timer);
+ thread_execute (master, inactivity_timer, on, 0);
}
return CMD_SUCCESS;
@@ -795,86 +1256,21 @@
"passive interface: No Adjacency will be formed on this I/F\n"
)
{
- struct ospf6_interface *o6i;
+ struct ospf6_interface *oi;
struct interface *ifp;
ifp = (struct interface *) vty->index;
assert (ifp);
- o6i = (struct ospf6_interface *) ifp->info;
- if (! o6i)
- o6i = ospf6_interface_create (ifp);
- assert (o6i);
- UNSET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE);
- if (o6i->thread_send_hello == NULL)
- thread_add_event (master, ospf6_send_hello, o6i, 0);
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create (ifp);
+ assert (oi);
- return CMD_SUCCESS;
-}
-
-
-DEFUN (ipv6_ospf6_advertise_force_prefix,
- ipv6_ospf6_advertise_force_prefix_cmd,
- "ipv6 ospf6 advertise force-prefix",
- IP6_STR
- OSPF6_STR
- "Advertising options\n"
- "Force advertising prefix, applicable if Loopback or P-to-P\n"
- )
-{
- struct ospf6_interface *o6i;
- struct interface *ifp;
-
- ifp = (struct interface *) vty->index;
- assert (ifp);
- o6i = (struct ospf6_interface *) ifp->info;
- if (! o6i)
- o6i = ospf6_interface_create (ifp);
- assert (o6i);
-
- if (! if_is_loopback (ifp) && ! if_is_pointopoint (ifp))
- {
- vty_out (vty, "Interface not Loopback nor PointToPoint%s",
- VTY_NEWLINE);
- return CMD_ERR_NOTHING_TODO;
- }
-
- SET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_FORCE_PREFIX);
-
- /* execute LSA hooks */
- CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, o6i);
-
- CALL_CHANGE_HOOK (&interface_hook, o6i);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_ospf6_advertise_force_prefix,
- no_ipv6_ospf6_advertise_force_prefix_cmd,
- "no ipv6 ospf6 advertise force-prefix",
- NO_STR
- IP6_STR
- OSPF6_STR
- "Advertising options\n"
- "Force to advertise prefix, applicable if Loopback or P-to-P\n"
- )
-{
- struct ospf6_interface *o6i;
- struct interface *ifp;
-
- ifp = (struct interface *) vty->index;
- assert (ifp);
- o6i = (struct ospf6_interface *) ifp->info;
- if (! o6i)
- o6i = ospf6_interface_create (ifp);
- assert (o6i);
-
- UNSET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_FORCE_PREFIX);
-
- /* execute LSA hooks */
- CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, o6i);
-
- CALL_CHANGE_HOOK (&interface_hook, o6i);
+ UNSET_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE);
+ THREAD_OFF (oi->thread_send_hello);
+ oi->thread_send_hello =
+ thread_add_event (master, ospf6_hello_send, oi, 0);
return CMD_SUCCESS;
}
@@ -889,24 +1285,29 @@
"Prefix list name\n"
)
{
- struct ospf6_interface *o6i;
+ struct ospf6_interface *oi;
struct interface *ifp;
ifp = (struct interface *) vty->index;
assert (ifp);
- o6i = (struct ospf6_interface *) ifp->info;
- if (! o6i)
- o6i = ospf6_interface_create (ifp);
- assert (o6i);
- if (o6i->plist_name)
- XFREE (MTYPE_PREFIX_LIST_STR, o6i->plist_name);
- o6i->plist_name = XSTRDUP (MTYPE_PREFIX_LIST_STR, argv[0]);
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create (ifp);
+ assert (oi);
- /* execute LSA hooks */
- CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, o6i);
+ if (oi->plist_name)
+ XFREE (MTYPE_PREFIX_LIST_STR, oi->plist_name);
+ oi->plist_name = XSTRDUP (MTYPE_PREFIX_LIST_STR, argv[0]);
- CALL_CHANGE_HOOK (&interface_hook, o6i);
+ ospf6_interface_connected_route_update (oi->interface);
+ OSPF6_LINK_LSA_SCHEDULE (oi);
+ if (oi->state == OSPF6_INTERFACE_DR)
+ {
+ OSPF6_NETWORK_LSA_SCHEDULE (oi);
+ OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
+ }
+ OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
return CMD_SUCCESS;
}
@@ -921,75 +1322,75 @@
"Filter prefix using prefix-list\n"
)
{
- struct ospf6_interface *o6i;
+ struct ospf6_interface *oi;
struct interface *ifp;
ifp = (struct interface *) vty->index;
assert (ifp);
- o6i = (struct ospf6_interface *) ifp->info;
- if (! o6i)
- o6i = ospf6_interface_create (ifp);
- assert (o6i);
- if (o6i->plist_name)
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create (ifp);
+ assert (oi);
+
+ if (oi->plist_name)
{
- XFREE (MTYPE_PREFIX_LIST_STR, o6i->plist_name);
- o6i->plist_name = NULL;
+ XFREE (MTYPE_PREFIX_LIST_STR, oi->plist_name);
+ oi->plist_name = NULL;
}
- /* execute LSA hooks */
- CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, o6i);
-
- CALL_CHANGE_HOOK (&interface_hook, o6i);
+ ospf6_interface_connected_route_update (oi->interface);
+ OSPF6_LINK_LSA_SCHEDULE (oi);
+ if (oi->state == OSPF6_INTERFACE_DR)
+ {
+ OSPF6_NETWORK_LSA_SCHEDULE (oi);
+ OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
+ }
+ OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
return CMD_SUCCESS;
}
int
-ospf6_interface_config_write (struct vty *vty)
+config_write_ospf6_interface (struct vty *vty)
{
listnode i;
- struct ospf6_interface *o6i;
+ struct ospf6_interface *oi;
struct interface *ifp;
for (i = listhead (iflist); i; nextnode (i))
{
ifp = (struct interface *) getdata (i);
- o6i = (struct ospf6_interface *) ifp->info;
- if (! o6i)
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
continue;
vty_out (vty, "interface %s%s",
- o6i->interface->name, VTY_NEWLINE);
- if (o6i->cost != 1)
+ oi->interface->name, VTY_NEWLINE);
+
+ if (ifp->desc)
+ vty_out (vty, " description %s%s", ifp->desc, VTY_NEWLINE);
+
vty_out (vty, " ipv6 ospf6 cost %d%s",
- o6i->cost, VTY_NEWLINE);
- if (o6i->hello_interval != 10)
+ oi->cost, VTY_NEWLINE);
vty_out (vty, " ipv6 ospf6 hello-interval %d%s",
- o6i->hello_interval, VTY_NEWLINE);
- if (o6i->dead_interval != 40)
+ oi->hello_interval, VTY_NEWLINE);
vty_out (vty, " ipv6 ospf6 dead-interval %d%s",
- o6i->dead_interval, VTY_NEWLINE);
- if (o6i->rxmt_interval != 5)
+ oi->dead_interval, VTY_NEWLINE);
vty_out (vty, " ipv6 ospf6 retransmit-interval %d%s",
- o6i->rxmt_interval, VTY_NEWLINE);
- if (o6i->priority != 1)
+ oi->rxmt_interval, VTY_NEWLINE);
vty_out (vty, " ipv6 ospf6 priority %d%s",
- o6i->priority, VTY_NEWLINE);
- if (o6i->transdelay != 1)
+ oi->priority, VTY_NEWLINE);
vty_out (vty, " ipv6 ospf6 transmit-delay %d%s",
- o6i->transdelay, VTY_NEWLINE);
- if (o6i->instance_id != 0)
+ oi->transdelay, VTY_NEWLINE);
vty_out (vty, " ipv6 ospf6 instance-id %d%s",
- o6i->instance_id, VTY_NEWLINE);
+ oi->instance_id, VTY_NEWLINE);
- if (CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_FORCE_PREFIX))
- vty_out (vty, " ipv6 ospf6 advertise force-prefix%s", VTY_NEWLINE);
- if (o6i->plist_name)
+ if (oi->plist_name)
vty_out (vty, " ipv6 ospf6 advertise prefix-list %s%s",
- o6i->plist_name, VTY_NEWLINE);
+ oi->plist_name, VTY_NEWLINE);
- if (CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE))
+ if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
vty_out (vty, " ipv6 ospf6 passive%s", VTY_NEWLINE);
vty_out (vty, "!%s", VTY_NEWLINE);
@@ -1001,20 +1402,32 @@
{
INTERFACE_NODE,
"%s(config-if)# ",
- vtysh: 1
};
void
ospf6_interface_init ()
{
/* Install interface node. */
- install_node (&interface_node, ospf6_interface_config_write);
+ install_node (&interface_node, config_write_ospf6_interface);
install_element (VIEW_NODE, &show_ipv6_ospf6_interface_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_interface_prefix_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_interface_prefix_detail_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_interface_prefix_match_cmd);
install_element (VIEW_NODE, &show_ipv6_ospf6_interface_ifname_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_interface_ifname_prefix_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_interface_ifname_prefix_detail_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_interface_ifname_prefix_match_cmd);
install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_prefix_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_prefix_detail_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_prefix_match_cmd);
install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_ifname_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_ifname_prefix_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_ifname_prefix_detail_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_interface_ifname_prefix_match_cmd);
+ install_element (CONFIG_NODE, &interface_cmd);
install_default (INTERFACE_NODE);
install_element (INTERFACE_NODE, &interface_desc_cmd);
install_element (INTERFACE_NODE, &no_interface_desc_cmd);
@@ -1025,12 +1438,54 @@
install_element (INTERFACE_NODE, &ipv6_ospf6_retransmitinterval_cmd);
install_element (INTERFACE_NODE, &ipv6_ospf6_transmitdelay_cmd);
install_element (INTERFACE_NODE, &ipv6_ospf6_instance_cmd);
- install_element (INTERFACE_NODE, &ipv6_ospf6_advertise_force_prefix_cmd);
- install_element (INTERFACE_NODE, &no_ipv6_ospf6_advertise_force_prefix_cmd);
- install_element (INTERFACE_NODE, &ipv6_ospf6_advertise_prefix_list_cmd);
- install_element (INTERFACE_NODE, &no_ipv6_ospf6_advertise_prefix_list_cmd);
+
install_element (INTERFACE_NODE, &ipv6_ospf6_passive_cmd);
install_element (INTERFACE_NODE, &no_ipv6_ospf6_passive_cmd);
+
+ install_element (INTERFACE_NODE, &ipv6_ospf6_advertise_prefix_list_cmd);
+ install_element (INTERFACE_NODE, &no_ipv6_ospf6_advertise_prefix_list_cmd);
+}
+
+DEFUN (debug_ospf6_interface,
+ debug_ospf6_interface_cmd,
+ "debug ospf6 interface",
+ DEBUG_STR
+ OSPF6_STR
+ "Debug OSPFv3 Interface\n"
+ )
+{
+ OSPF6_DEBUG_INTERFACE_ON ();
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_ospf6_interface,
+ no_debug_ospf6_interface_cmd,
+ "no debug ospf6 interface",
+ NO_STR
+ DEBUG_STR
+ OSPF6_STR
+ "Debug OSPFv3 Interface\n"
+ )
+{
+ OSPF6_DEBUG_INTERFACE_ON ();
+ return CMD_SUCCESS;
+}
+
+int
+config_write_ospf6_debug_interface (struct vty *vty)
+{
+ if (IS_OSPF6_DEBUG_INTERFACE)
+ vty_out (vty, "debug ospf6 interface%s", VTY_NEWLINE);
+ return 0;
+}
+
+void
+install_element_ospf6_debug_interface ()
+{
+ install_element (ENABLE_NODE, &debug_ospf6_interface_cmd);
+ install_element (ENABLE_NODE, &no_debug_ospf6_interface_cmd);
+ install_element (CONFIG_NODE, &debug_ospf6_interface_cmd);
+ install_element (CONFIG_NODE, &no_debug_ospf6_interface_cmd);
}
diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h
index a96ef25..48b56fc 100644
--- a/ospf6d/ospf6_interface.h
+++ b/ospf6d/ospf6_interface.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -22,10 +22,18 @@
#ifndef OSPF6_INTERFACE_H
#define OSPF6_INTERFACE_H
-#include "ospf6_message.h"
+#include "if.h"
-/* This file defines interface data structure. */
+/* Debug option */
+extern unsigned char conf_debug_ospf6_interface;
+#define OSPF6_DEBUG_INTERFACE_ON() \
+ (conf_debug_ospf6_interface = 1)
+#define OSPF6_DEBUG_INTERFACE_OFF() \
+ (conf_debug_ospf6_interface = 0)
+#define IS_OSPF6_DEBUG_INTERFACE \
+ (conf_debug_ospf6_interface)
+/* Interface structure */
struct ospf6_interface
{
/* IF info from zebra */
@@ -38,10 +46,9 @@
list neighbor_list;
/* linklocal address of this I/F */
- struct in6_addr *lladdr;
+ struct in6_addr *linklocal_addr;
- /* Interface ID; same as ifindex */
- u_int32_t if_id;
+ /* Interface ID; use interface->ifindex */
/* ospf6 instance id */
u_char instance_id;
@@ -52,7 +59,7 @@
/* Router Priority */
u_char priority;
- /* Timers */
+ /* Time Interval */
u_int16_t hello_interval;
u_int16_t dead_interval;
u_int32_t rxmt_interval;
@@ -70,84 +77,76 @@
char flag;
/* Decision of DR Election */
- u_int32_t dr;
- u_int32_t bdr;
- u_int32_t prevdr;
- u_int32_t prevbdr;
-
- /* Ongoing Tasks */
- struct thread *thread_send_hello;
- struct thread *thread_send_lsack_delayed;
-
- /* LSAs to Delayed Acknowledge */
- struct ospf6_lsdb *ack_list;
+ u_int32_t drouter;
+ u_int32_t bdrouter;
+ u_int32_t prev_drouter;
+ u_int32_t prev_bdrouter;
/* Linklocal LSA Database: includes Link-LSA */
struct ospf6_lsdb *lsdb;
- /* statistics */
- u_int ospf6_stat_dr_election;
- u_int ospf6_stat_delayed_lsack;
+ struct ospf6_lsdb *lsupdate_list;
+ struct ospf6_lsdb *lsack_list;
- struct ospf6_message_stat message_stat[OSPF6_MESSAGE_TYPE_MAX];
+ /* Ongoing Tasks */
+ struct thread *thread_send_hello;
+ struct thread *thread_send_lsupdate;
+ struct thread *thread_send_lsack;
- void (*foreach_nei) (struct ospf6_interface *, void *, int,
- void (*func) (void *, int, void *));
+ struct thread *thread_network_lsa;
+ struct thread *thread_link_lsa;
+ struct thread *thread_intra_prefix_lsa;
- struct thread *maxage_remover;
+ struct ospf6_route_table *route_connected;
- /* route-map to filter connected prefix */
+ /* prefix-list name to filter connected prefix */
char *plist_name;
};
-extern char *ospf6_interface_state_string[];
+/* interface state */
+#define OSPF6_INTERFACE_NONE 0
+#define OSPF6_INTERFACE_DOWN 1
+#define OSPF6_INTERFACE_LOOPBACK 2
+#define OSPF6_INTERFACE_WAITING 3
+#define OSPF6_INTERFACE_POINTTOPOINT 4
+#define OSPF6_INTERFACE_DROTHER 5
+#define OSPF6_INTERFACE_BDR 6
+#define OSPF6_INTERFACE_DR 7
+#define OSPF6_INTERFACE_MAX 8
-#define OSPF6_INTERFACE_FLAG_PASSIVE 0x01
-#define OSPF6_INTERFACE_FLAG_FORCE_PREFIX 0x02
+extern char *ospf6_interface_state_str[];
+
+/* flags */
+#define OSPF6_INTERFACE_DISABLE 0x01
+#define OSPF6_INTERFACE_PASSIVE 0x02
/* Function Prototypes */
-void
-ospf6_interface_schedule_maxage_remover (void *arg, int val, void *obj);
+struct ospf6_interface *ospf6_interface_lookup_by_ifindex (int);
+struct ospf6_interface *ospf6_interface_lookup_by_name (char *);
+struct ospf6_interface *ospf6_interface_create (struct interface *);
+void ospf6_interface_delete (struct ospf6_interface *);
-struct ospf6_interface *
-ospf6_interface_create (struct interface *);
-void
-ospf6_interface_delete (struct ospf6_interface *);
-
-struct ospf6_interface *
-ospf6_interface_lookup_by_index (int);
-struct ospf6_interface *
-ospf6_interface_lookup_by_name (char *);
+void ospf6_interface_enable (struct ospf6_interface *);
+void ospf6_interface_disable (struct ospf6_interface *);
void ospf6_interface_if_add (struct interface *);
void ospf6_interface_if_del (struct interface *);
void ospf6_interface_state_update (struct interface *);
-void ospf6_interface_address_update (struct interface *);
+void ospf6_interface_connected_route_update (struct interface *);
+
+/* interface event */
+int interface_up (struct thread *);
+int interface_down (struct thread *);
+int wait_timer (struct thread *);
+int backup_seen (struct thread *);
+int neighbor_change (struct thread *);
void ospf6_interface_init ();
-#if 0
-int
-ospf6_interface_count_neighbor_in_state (u_char state,
- struct ospf6_interface *o6i);
-int
-ospf6_interface_count_full_neighbor (struct ospf6_interface *);
-#endif
-
-int ospf6_interface_is_enabled (u_int32_t ifindex);
-
-void
-ospf6_interface_delayed_ack_add (struct ospf6_lsa *lsa,
- struct ospf6_interface *o6i);
-void
-ospf6_interface_delayed_ack_remove (struct ospf6_lsa *lsa,
- struct ospf6_interface *o6i);
-
-void
-ospf6_interface_statistics_show (struct vty *vty,
- struct ospf6_interface *o6i);
+int config_write_ospf6_debug_interface (struct vty *vty);
+void install_element_ospf6_debug_interface ();
#endif /* OSPF6_INTERFACE_H */
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index b9c9ebd..47cbd39 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -19,356 +19,537 @@
* Boston, MA 02111-1307, USA.
*/
+#include <zebra.h>
+
+#include "log.h"
+#include "linklist.h"
+#include "thread.h"
+#include "memory.h"
+#include "if.h"
+#include "prefix.h"
+#include "table.h"
+#include "vty.h"
+#include "command.h"
+
#include "ospf6d.h"
+#include "ospf6_proto.h"
+#include "ospf6_message.h"
+#include "ospf6_route.h"
+#include "ospf6_lsa.h"
+#include "ospf6_lsdb.h"
-static int intra_index;
-#define IS_OSPF6_DUMP_INTRA (ospf6_dump_is_on (intra_index))
+#include "ospf6_top.h"
+#include "ospf6_area.h"
+#include "ospf6_interface.h"
+#include "ospf6_neighbor.h"
+#include "ospf6_intra.h"
+#include "ospf6_asbr.h"
-#define ADD 0
-#define REMOVE 1
+/******************************/
+/* RFC2740 3.4.3.1 Router-LSA */
+/******************************/
-static void
-ospf6_intra_route_calculate (int type, struct ospf6_lsa *lsa,
- struct ospf6_route_req *topo_entry)
+int
+ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
{
- struct ospf6_intra_area_prefix_lsa *intra_prefix;
- char *start, *end;
- struct ospf6_prefix *ospf6_prefix;
- struct ospf6_route_req request;
- struct ospf6_area *area;
+ char *start, *end, *current;
+ char buf[32], name[32], bits[16], options[32];
+ struct ospf6_router_lsa *router_lsa;
+ struct ospf6_router_lsdesc *lsdesc;
- if (IS_OSPF6_DUMP_INTRA)
- {
- char buf[64];
- struct prefix_ls *p_ls;
- p_ls = (struct prefix_ls *) &topo_entry->route.prefix;
- inet_ntop (AF_INET, &p_ls->adv_router, buf, sizeof (buf));
- zlog_info ("INTRA: Calculate [%s] %s and %s",
- (type == ADD ? "add" : "remove"), lsa->str, buf);
- }
+ router_lsa = (struct ospf6_router_lsa *)
+ ((char *) lsa->header + sizeof (struct ospf6_lsa_header));
- intra_prefix = OSPF6_LSA_HEADER_END (lsa->header);
+ ospf6_capability_printbuf (router_lsa->bits, bits, sizeof (bits));
+ ospf6_options_printbuf (router_lsa->options, options, sizeof (options));
+ vty_out (vty, " Bits: %s Options: %s%s", bits, options, VTY_NEWLINE);
- area = lsa->scope;
- assert (area);
-
- start = (char *) (intra_prefix + 1);
+ start = (char *) router_lsa + sizeof (struct ospf6_router_lsa);
end = (char *) lsa->header + ntohs (lsa->header->length);
- for (ospf6_prefix = (struct ospf6_prefix *) start;
- (char *) ospf6_prefix < end;
- ospf6_prefix = OSPF6_NEXT_PREFIX (ospf6_prefix))
+ for (current = start; current + sizeof (struct ospf6_router_lsdesc) <= end;
+ current += sizeof (struct ospf6_router_lsdesc))
{
- memset (&request, 0, sizeof (request));
+ lsdesc = (struct ospf6_router_lsdesc *) current;
- request.route.type = OSPF6_DEST_TYPE_NETWORK;
- request.route.prefix.family = AF_INET6;
- request.route.prefix.prefixlen = ospf6_prefix->prefix_length;
- ospf6_prefix_in6_addr (ospf6_prefix, &request.route.prefix.u.prefix6);
-
- request.path.type = OSPF6_PATH_TYPE_INTRA;
- request.path.area_id = area->area_id;
- request.path.origin.type = lsa->header->type;
- request.path.origin.id = lsa->header->id;
- request.path.origin.adv_router = lsa->header->adv_router;
- request.path.cost = topo_entry->path.cost +
- ntohs (ospf6_prefix->prefix_metric);
- request.path.capability[0] = topo_entry->path.capability[0];
- request.path.capability[1] = topo_entry->path.capability[1];
- request.path.capability[2] = topo_entry->path.capability[2];
-
- memcpy (&request.nexthop.address, &topo_entry->nexthop.address,
- sizeof (request.nexthop.address));
- request.nexthop.ifindex = topo_entry->nexthop.ifindex;
-
- if (type == ADD)
- ospf6_route_add (&request, area->route_table);
- else if (type == REMOVE)
- ospf6_route_remove (&request, area->route_table);
+ if (lsdesc->type == OSPF6_ROUTER_LSDESC_POINTTOPOINT)
+ snprintf (name, sizeof (name), "Point-To-Point");
+ else if (lsdesc->type == OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK)
+ snprintf (name, sizeof (name), "Transit-Network");
+ else if (lsdesc->type == OSPF6_ROUTER_LSDESC_STUB_NETWORK)
+ snprintf (name, sizeof (name), "Stub-Network");
+ else if (lsdesc->type == OSPF6_ROUTER_LSDESC_VIRTUAL_LINK)
+ snprintf (name, sizeof (name), "Virtual-Link");
else
- assert (0);
- }
-}
+ snprintf (name, sizeof (name), "Unknown (%#x)", lsdesc->type);
-int
-ospf6_intra_prefix_database_hook_remove (void *data)
-{
- struct ospf6_lsa *lsa = data;
- struct ospf6_area *area;
- struct ospf6_intra_area_prefix_lsa *iap;
- struct prefix_ls prefix_ls;
- struct ospf6_route_req topo_entry;
-
- if (lsa->header->type != htons (OSPF6_LSA_TYPE_INTRA_PREFIX))
- return 0;
-
- area = (struct ospf6_area *) lsa->scope;
- assert (area);
-
- if (IS_OSPF6_DUMP_INTRA)
- zlog_info ("INTRA: area %s remove: %s", area->str, lsa->str);
-
- iap = OSPF6_LSA_HEADER_END (lsa->header);
- memset (&prefix_ls, 0, sizeof (prefix_ls));
- prefix_ls.prefixlen = 64;
- prefix_ls.adv_router.s_addr = iap->refer_advrtr;
- prefix_ls.id.s_addr = iap->refer_lsid;
-
- if (iap->refer_lstype == htons (OSPF6_LSA_TYPE_ROUTER) &&
- iap->refer_lsid != htonl (0))
- {
- zlog_warn ("SPF: Malformed ID %lu of Router reference in %s",
- (u_long) ntohl (iap->refer_lsid), lsa->str);
- prefix_ls.id.s_addr = htonl (0);
- }
-
- ospf6_route_lookup (&topo_entry, (struct prefix *) &prefix_ls,
- area->table_topology);
-
- while (iap->refer_lstype == topo_entry.path.origin.type &&
- iap->refer_lsid == topo_entry.path.origin.id &&
- iap->refer_advrtr == topo_entry.path.origin.adv_router)
- {
- ospf6_intra_route_calculate (REMOVE, lsa, &topo_entry);
- ospf6_route_next (&topo_entry);
- }
- return 0;
-}
-
-int
-ospf6_intra_prefix_database_hook_add (void *data)
-{
- struct ospf6_lsa *lsa = data;
- struct ospf6_area *area;
- struct ospf6_intra_area_prefix_lsa *iap;
- struct prefix_ls prefix_ls;
- struct ospf6_route_req topo_entry;
-
- if (lsa->header->type != htons (OSPF6_LSA_TYPE_INTRA_PREFIX))
- return 0;
-
- area = (struct ospf6_area *) lsa->scope;
- assert (area);
-
- if (IS_LSA_MAXAGE (lsa))
- {
- ospf6_intra_prefix_database_hook_remove (lsa);
- return 0;
- }
-
- if (IS_OSPF6_DUMP_INTRA)
- zlog_info ("INTRA: area %s add: %s", area->str, lsa->str);
-
- iap = OSPF6_LSA_HEADER_END (lsa->header);
-
- memset (&prefix_ls, 0, sizeof (struct prefix_ls));
- prefix_ls.prefixlen = 64;
- prefix_ls.adv_router.s_addr = iap->refer_advrtr;
- prefix_ls.id.s_addr = iap->refer_lsid;
-
- if (iap->refer_lstype == htons (OSPF6_LSA_TYPE_ROUTER) &&
- iap->refer_lsid != htonl (0))
- {
- zlog_warn ("INTRA: Malformed ID %lu of Router reference in %s",
- (u_long) ntohl (iap->refer_lsid), lsa->str);
- prefix_ls.id.s_addr = htonl (0);
- }
-
- ospf6_route_lookup (&topo_entry, (struct prefix *) &prefix_ls,
- area->table_topology);
-
- while (iap->refer_lstype == topo_entry.path.origin.type &&
- iap->refer_lsid == topo_entry.path.origin.id &&
- iap->refer_advrtr == topo_entry.path.origin.adv_router)
- {
- ospf6_intra_route_calculate (ADD, lsa, &topo_entry);
- ospf6_route_next (&topo_entry);
+ vty_out (vty, " Type: %s Metric: %d%s",
+ name, ntohs (lsdesc->metric), VTY_NEWLINE);
+ vty_out (vty, " Interface ID: %s%s",
+ inet_ntop (AF_INET, &lsdesc->interface_id,
+ buf, sizeof (buf)), VTY_NEWLINE);
+ vty_out (vty, " Neighbor Interface ID: %s%s",
+ inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
+ buf, sizeof (buf)), VTY_NEWLINE);
+ vty_out (vty, " Neighbor Router ID: %s%s",
+ inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
+ buf, sizeof (buf)), VTY_NEWLINE);
}
return 0;
}
void
-ospf6_intra_topology_add (void *data)
+ospf6_router_lsa_originate_sub (struct ospf6_area *oa, int force)
{
- struct ospf6_route_req *topo_entry = data;
- struct ospf6_area *area;
- struct ospf6_intra_area_prefix_lsa *iap;
- struct ospf6_lsdb_node node;
+ char buffer [OSPF6_MAX_LSASIZE];
+ struct ospf6_lsa_header *lsa_header;
+ struct ospf6_lsa *lsa;
- area = ospf6_area_lookup (topo_entry->path.area_id, ospf6);
- if (! area)
- return;
+ u_int32_t link_state_id = 0;
+ listnode i, j;
+ struct ospf6_interface *oi;
+ struct ospf6_neighbor *on, *drouter = NULL;
+ struct ospf6_router_lsa *router_lsa;
+ struct ospf6_router_lsdesc *lsdesc;
+ u_int16_t type;
+ u_int32_t router;
+ int count;
- if (topo_entry->route.type == OSPF6_DEST_TYPE_ROUTER &&
- (CHECK_FLAG (topo_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_B) ||
- CHECK_FLAG (topo_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_E)))
- ospf6_route_add (topo_entry, ospf6->topology_table);
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info ("Originate Router-LSA for Area %s", oa->name);
- for (ospf6_lsdb_type (&node, htons (OSPF6_LSA_TYPE_INTRA_PREFIX),
- area->lsdb);
- ! ospf6_lsdb_is_end (&node);
- ospf6_lsdb_next (&node))
+ memset (buffer, 0, sizeof (buffer));
+ lsa_header = (struct ospf6_lsa_header *) buffer;
+ router_lsa = (struct ospf6_router_lsa *)
+ ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
+
+ OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_V6);
+ OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_E);
+ OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_MC);
+ OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_N);
+ OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_R);
+ OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_DC);
+
+ UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
+ if (ospf6_asbr_is_asbr (ospf6))
+ SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
+ else
+ UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
+ UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_V);
+ UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_W);
+
+ /* describe links for each interfaces */
+ lsdesc = (struct ospf6_router_lsdesc *)
+ ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa));
+
+ for (i = listhead (oa->if_list); i; nextnode (i))
{
- if (IS_LSA_MAXAGE (node.lsa))
+ oi = (struct ospf6_interface *) getdata (i);
+
+ /* Interfaces in state Down or Loopback are not described */
+ if (oi->state == OSPF6_INTERFACE_DOWN ||
+ oi->state == OSPF6_INTERFACE_LOOPBACK)
continue;
- iap = OSPF6_LSA_HEADER_END (node.lsa->header);
-
- if (iap->refer_lstype == htons (OSPF6_LSA_TYPE_ROUTER) &&
- iap->refer_lsid != htonl (0))
+ /* Nor are interfaces without any full adjacencies described */
+ count = 0;
+ for (j = listhead (oi->neighbor_list); j; nextnode (j))
{
- zlog_warn ("INTRA: Malformed ID %lu of Router reference in %s",
- (u_long) ntohl (iap->refer_lsid), node.lsa->str);
+ on = (struct ospf6_neighbor *) getdata (j);
+ if (on->state == OSPF6_NEIGHBOR_FULL)
+ count++;
+ }
+ if (count == 0)
+ continue;
+
+ /* Multiple Router-LSA instance according to size limit setting */
+ if (oa->router_lsa_size_limit != 0 &&
+ (caddr_t) lsdesc + sizeof (struct ospf6_router_lsdesc) -
+ (caddr_t) buffer > oa->router_lsa_size_limit)
+ {
+ if ((caddr_t) lsdesc == (caddr_t) router_lsa +
+ sizeof (struct ospf6_router_lsa))
+ {
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info ("Size limit setting for Router-LSA too short");
+ return;
+ }
+
+ /* Fill LSA Header */
+ lsa_header->age = 0;
+ lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
+ lsa_header->id = htonl (link_state_id);
+ lsa_header->adv_router = oa->ospf6->router_id;
+ lsa_header->seqnum =
+ ospf6_lsa_new_seqnum (lsa_header->type, lsa_header->id,
+ lsa_header->adv_router, oa);
+ lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
+
+ /* LSA checksum */
+ ospf6_lsa_checksum (lsa_header);
+
+ /* create LSA */
+ lsa = ospf6_lsa_create (lsa_header);
+ lsa->scope = oa;
+ if (force)
+ SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
+
+ /* Originate */
+ ospf6_lsa_originate (lsa);
+
+ /* Reset setting for consecutive origination */
+ memset ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa),
+ 0, (caddr_t) lsdesc - (caddr_t) router_lsa);
+ lsdesc = (struct ospf6_router_lsdesc *)
+ ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa));
+ link_state_id ++;
}
- if (iap->refer_lstype != topo_entry->path.origin.type ||
- iap->refer_lsid != topo_entry->path.origin.id ||
- iap->refer_advrtr != topo_entry->path.origin.adv_router)
- continue;
+ /* Point-to-Point interfaces */
+ if (if_is_pointopoint (oi->interface))
+ {
+ for (j = listhead (oi->neighbor_list); j; nextnode (j))
+ {
+ on = (struct ospf6_neighbor *) getdata (j);
+ if (on->state != OSPF6_NEIGHBOR_FULL)
+ continue;
- ospf6_intra_route_calculate (ADD, node.lsa, topo_entry);
+ lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT;
+ lsdesc->metric = htons (oi->cost);
+ lsdesc->interface_id = htonl (oi->interface->ifindex);
+ lsdesc->neighbor_interface_id = htonl (on->ifindex);
+ lsdesc->neighbor_router_id = on->router_id;
+
+ lsdesc++;
+ }
+ }
+
+ /* Broadcast and NBMA interfaces */
+ if (if_is_broadcast (oi->interface))
+ {
+ /* If this router is not DR,
+ and If this router not fully adjacent with DR,
+ this interface is not transit yet: ignore. */
+ if (oi->state != OSPF6_INTERFACE_DR)
+ {
+ drouter = ospf6_neighbor_lookup (oi->drouter, oi);
+ if (drouter == NULL || drouter->state != OSPF6_NEIGHBOR_FULL)
+ continue;
+ }
+
+ lsdesc->type = OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK;
+ lsdesc->metric = htons (oi->cost);
+ lsdesc->interface_id = htonl (oi->interface->ifindex);
+ if (oi->state != OSPF6_INTERFACE_DR)
+ {
+ lsdesc->neighbor_interface_id = htonl (drouter->ifindex);
+ lsdesc->neighbor_router_id = drouter->router_id;
+ }
+ else
+ {
+ lsdesc->neighbor_interface_id = htonl (oi->interface->ifindex);
+ lsdesc->neighbor_router_id = oi->area->ospf6->router_id;
+ }
+
+ lsdesc++;
+ }
+
+ /* Virtual links */
+ /* xxx */
+ /* Point-to-Multipoint interfaces */
+ /* xxx */
}
+
+ if ((caddr_t) lsdesc != (caddr_t) router_lsa +
+ sizeof (struct ospf6_router_lsa))
+ {
+ /* Fill LSA Header */
+ lsa_header->age = 0;
+ lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
+ lsa_header->id = htonl (link_state_id);
+ lsa_header->adv_router = oa->ospf6->router_id;
+ lsa_header->seqnum =
+ ospf6_lsa_new_seqnum (lsa_header->type, lsa_header->id,
+ lsa_header->adv_router, oa);
+ lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
+
+ /* LSA checksum */
+ ospf6_lsa_checksum (lsa_header);
+
+ /* create LSA */
+ lsa = ospf6_lsa_create (lsa_header);
+ lsa->scope = oa;
+ if (force)
+ SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
+
+ /* Originate */
+ ospf6_lsa_originate (lsa);
+
+ link_state_id ++;
+ }
+
+ /* Do premature-aging of rest, undesired Router-LSAs */
+ type = ntohs (OSPF6_LSTYPE_ROUTER);
+ router = oa->ospf6->router_id;
+ for (lsa = ospf6_lsdb_type_router_head (type, router, oa->lsdb); lsa;
+ lsa = ospf6_lsdb_type_router_next (type, router, lsa))
+ {
+ if (ntohl (lsa->header->id) < link_state_id)
+ continue;
+ ospf6_lsa_premature_aging (lsa);
+ }
+}
+
+int
+ospf6_router_lsa_originate (struct thread *thread)
+{
+ struct ospf6_area *oa;
+ int force = 0;
+
+ oa = (struct ospf6_area *) THREAD_ARG (thread);
+ oa->thread_router_lsa = NULL;
+ ospf6_router_lsa_originate_sub (oa, force);
+
+ return 0;
+}
+
+int
+ospf6_router_lsa_reoriginate (struct ospf6_lsa *lsa)
+{
+ struct ospf6_area *oa;
+ int force = 1;
+
+ oa = (struct ospf6_area *) lsa->scope;
+ ospf6_router_lsa_originate_sub (oa, force);
+
+ return 0;
+}
+
+
+/*******************************/
+/* RFC2740 3.4.3.2 Network-LSA */
+/*******************************/
+
+int
+ospf6_network_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
+{
+ char *start, *end, *current;
+ struct ospf6_network_lsa *network_lsa;
+ struct ospf6_network_lsdesc *lsdesc;
+ char buf[128], options[32];
+
+ network_lsa = (struct ospf6_network_lsa *)
+ ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
+
+ ospf6_options_printbuf (network_lsa->options, options, sizeof (options));
+ vty_out (vty, " Options: %s%s", options, VTY_NEWLINE);
+
+ start = (char *) network_lsa + sizeof (struct ospf6_network_lsa);
+ end = (char *) lsa->header + ntohs (lsa->header->length);
+ for (current = start; current + sizeof (struct ospf6_network_lsdesc) <= end;
+ current += sizeof (struct ospf6_network_lsdesc))
+ {
+ lsdesc = (struct ospf6_network_lsdesc *) current;
+ inet_ntop (AF_INET, &lsdesc->router_id, buf, sizeof (buf));
+ vty_out (vty, " Attached Router: %s%s", buf, VTY_NEWLINE);
+ }
+ return 0;
}
void
-ospf6_intra_topology_remove (void *data)
+ospf6_network_lsa_originate_sub (struct ospf6_interface *oi, int force)
{
- struct ospf6_route_req *topo_entry = data;
- struct ospf6_area *area;
- struct ospf6_intra_area_prefix_lsa *iap;
- struct ospf6_lsdb_node node;
+ char buffer [OSPF6_MAX_LSASIZE];
+ struct ospf6_lsa_header *lsa_header;
- area = ospf6_area_lookup (topo_entry->path.area_id, ospf6);
- if (! area)
+ int count;
+ struct ospf6_lsa *old, *lsa;
+ struct ospf6_network_lsa *network_lsa;
+ struct ospf6_network_lsdesc *lsdesc;
+ struct ospf6_neighbor *on;
+ struct ospf6_link_lsa *link_lsa;
+ listnode i;
+ u_int16_t type;
+
+ /* If self-originated Network-LSA for currently unenabled I/F
+ (but was once enabled, so other routers send it to this router),
+ we can't find oi->area for ospf6_lsdb_lookup (), and so can't
+ do premature aging of the Network-LSA. Just let the LSA flow
+ in network (other routers LSDB) for maximum duration of
+ MaxAge. The contents of this router's Router-LSA will preclude
+ the stale Network-LSA to be involved in routing calculation. */
+ if (oi->area == NULL)
return;
- if (topo_entry->route.type == OSPF6_DEST_TYPE_ROUTER &&
- (CHECK_FLAG (topo_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_B) ||
- CHECK_FLAG (topo_entry->path.router_bits, OSPF6_ROUTER_LSA_BIT_E)))
- ospf6_route_remove (topo_entry, ospf6->topology_table);
+ old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_NETWORK),
+ htonl (oi->interface->ifindex),
+ oi->area->ospf6->router_id, oi->area->lsdb);
- for (ospf6_lsdb_type (&node, htons (OSPF6_LSA_TYPE_INTRA_PREFIX),
- area->lsdb);
- ! ospf6_lsdb_is_end (&node);
- ospf6_lsdb_next (&node))
+ /* Do not originate Network-LSA if not DR */
+ if (oi->state != OSPF6_INTERFACE_DR)
{
- if (IS_LSA_MAXAGE (node.lsa))
- continue;
-
- iap = OSPF6_LSA_HEADER_END (node.lsa->header);
-
- if (iap->refer_lstype == htons (OSPF6_LSA_TYPE_ROUTER) &&
- iap->refer_lsid != htonl (0))
- zlog_warn ("SPF: Malformed ID %lu of Router reference in %s",
- (u_long) ntohl (iap->refer_lsid), node.lsa->str);
-
- if (iap->refer_lstype != topo_entry->path.origin.type ||
- iap->refer_lsid != topo_entry->path.origin.id ||
- iap->refer_advrtr != topo_entry->path.origin.adv_router)
- continue;
-
- ospf6_intra_route_calculate (REMOVE, node.lsa, topo_entry);
+ if (old)
+ ospf6_lsa_premature_aging (old);
+ return;
}
+
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info ("Originate Network-LSA for Interface %s", oi->interface->name);
+
+ /* If none of neighbor is adjacent to us */
+ count = 0;
+ for (i = listhead (oi->neighbor_list); i; nextnode (i))
+ {
+ on = (struct ospf6_neighbor *) getdata (i);
+ if (on->state == OSPF6_NEIGHBOR_FULL)
+ count++;
+ }
+ if (count == 0)
+ {
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info ("Interface stub, ignore");
+ if (old)
+ ospf6_lsa_premature_aging (old);
+ return;
+ }
+
+ /* prepare buffer */
+ memset (buffer, 0, sizeof (buffer));
+ lsa_header = (struct ospf6_lsa_header *) buffer;
+ network_lsa = (struct ospf6_network_lsa *)
+ ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
+
+ /* Collect the interface's Link-LSAs to describe
+ network's optional capabilities */
+ type = htons (OSPF6_LSTYPE_LINK);
+ for (lsa = ospf6_lsdb_type_head (type, oi->lsdb); lsa;
+ lsa = ospf6_lsdb_type_next (type, lsa))
+ {
+ link_lsa = (struct ospf6_link_lsa *)
+ ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
+ network_lsa->options[0] |= link_lsa->options[0];
+ network_lsa->options[1] |= link_lsa->options[1];
+ network_lsa->options[2] |= link_lsa->options[2];
+ }
+
+ lsdesc = (struct ospf6_network_lsdesc *)
+ ((caddr_t) network_lsa + sizeof (struct ospf6_network_lsa));
+
+ /* set Link Description to the router itself */
+ lsdesc->router_id = oi->area->ospf6->router_id;
+ lsdesc++;
+
+ /* Walk through the neighbors */
+ for (i = listhead (oi->neighbor_list); i; nextnode (i))
+ {
+ on = (struct ospf6_neighbor *) getdata (i);
+
+ if (on->state != OSPF6_NEIGHBOR_FULL)
+ continue;
+
+ /* set this neighbor's Router-ID to LSA */
+ lsdesc->router_id = on->router_id;
+ lsdesc++;
+ }
+
+ /* Fill LSA Header */
+ lsa_header->age = 0;
+ lsa_header->type = htons (OSPF6_LSTYPE_NETWORK);
+ lsa_header->id = htonl (oi->interface->ifindex);
+ lsa_header->adv_router = oi->area->ospf6->router_id;
+ lsa_header->seqnum =
+ ospf6_lsa_new_seqnum (lsa_header->type, lsa_header->id,
+ lsa_header->adv_router, oi->area);
+ lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
+
+ /* LSA checksum */
+ ospf6_lsa_checksum (lsa_header);
+
+ /* create LSA */
+ lsa = ospf6_lsa_create (lsa_header);
+ lsa->scope = oi->area;
+ if (force)
+ SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
+
+ /* Originate */
+ ospf6_lsa_originate (lsa);
}
-
-/*****************************************/
-/* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
-/*****************************************/
+int
+ospf6_network_lsa_originate (struct thread *thread)
+{
+ struct ospf6_interface *oi;
+ int force = 0;
-#define CONTINUE_IF_ADDRESS_LINKLOCAL(addr)\
- if (IN6_IS_ADDR_LINKLOCAL (&(addr)->u.prefix6))\
- {\
- char buf[64];\
- prefix2str (addr, buf, sizeof (buf));\
- if (IS_OSPF6_DUMP_PREFIX)\
- zlog_info (" Filter out Linklocal: %s", buf);\
- continue;\
- }
+ oi = (struct ospf6_interface *) THREAD_ARG (thread);
+ oi->thread_network_lsa = NULL;
+ ospf6_network_lsa_originate_sub (oi, force);
-#define CONTINUE_IF_ADDRESS_UNSPECIFIED(addr)\
- if (IN6_IS_ADDR_UNSPECIFIED (&(addr)->u.prefix6))\
- {\
- char buf[64];\
- prefix2str (addr, buf, sizeof (buf));\
- if (IS_OSPF6_DUMP_PREFIX)\
- zlog_info (" Filter out Unspecified: %s", buf);\
- continue;\
- }
-
-#define CONTINUE_IF_ADDRESS_LOOPBACK(addr)\
- if (IN6_IS_ADDR_LOOPBACK (&(addr)->u.prefix6))\
- {\
- char buf[64];\
- prefix2str (addr, buf, sizeof (buf));\
- if (IS_OSPF6_DUMP_PREFIX)\
- zlog_info (" Filter out Loopback: %s", buf);\
- continue;\
- }
-
-#define CONTINUE_IF_ADDRESS_V4COMPAT(addr)\
- if (IN6_IS_ADDR_V4COMPAT (&(addr)->u.prefix6))\
- {\
- char buf[64];\
- prefix2str (addr, buf, sizeof (buf));\
- if (IS_OSPF6_DUMP_PREFIX)\
- zlog_info (" Filter out V4Compat: %s", buf);\
- continue;\
- }
-
-#define CONTINUE_IF_ADDRESS_V4MAPPED(addr)\
- if (IN6_IS_ADDR_V4MAPPED (&(addr)->u.prefix6))\
- {\
- char buf[64];\
- prefix2str (addr, buf, sizeof (buf));\
- if (IS_OSPF6_DUMP_PREFIX)\
- zlog_info (" Filter out V4Mapped: %s", buf);\
- continue;\
- }
-
+ return 0;
+}
int
-ospf6_lsa_intra_prefix_show (struct vty *vty, struct ospf6_lsa *lsa)
+ospf6_network_lsa_reoriginate (struct ospf6_lsa *lsa)
{
- struct ospf6_intra_area_prefix_lsa *iap_lsa;
- struct ospf6_prefix *prefix;
- unsigned short prefixnum;
- char buf[128], type[32], id[32], adv_router[32];
- struct in6_addr in6;
+ struct ospf6_interface *oi;
+ int force = 1;
+
+ oi = ospf6_interface_lookup_by_ifindex (ntohl (lsa->header->id));
+ ospf6_network_lsa_originate_sub (oi, force);
+
+ return 0;
+}
+
+
+/****************************/
+/* RFC2740 3.4.3.6 Link-LSA */
+/****************************/
+
+int
+ospf6_link_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
+{
char *start, *end, *current;
+ struct ospf6_link_lsa *link_lsa;
+ int prefixnum;
+ char buf[128], options[32];
+ struct ospf6_prefix *prefix;
+ char *p, *mc, *la, *nu;
+ struct in6_addr in6;
- assert (lsa->header);
- iap_lsa = (struct ospf6_intra_area_prefix_lsa *) (lsa->header + 1);
+ link_lsa = (struct ospf6_link_lsa *)
+ ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
- prefixnum = ntohs (iap_lsa->prefix_number);
- ospf6_lsa_type_string (iap_lsa->refer_lstype, type, sizeof (type));
- inet_ntop (AF_INET, &iap_lsa->refer_lsid, id, sizeof (id));
- inet_ntop (AF_INET, &iap_lsa->refer_advrtr, adv_router,
- sizeof (adv_router));
+ ospf6_options_printbuf (link_lsa->options, options, sizeof (options));
+ inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));
+ prefixnum = ntohl (link_lsa->prefix_num);
+ vty_out (vty, " Priority: %d Options: %s%s",
+ link_lsa->priority, options, VTY_NEWLINE);
+ vty_out (vty, " LinkLocal Address: %s%s", buf, VTY_NEWLINE);
vty_out (vty, " Number of Prefix: %d%s", prefixnum, VTY_NEWLINE);
- vty_out (vty, " Referenced LS Type: %s%s", type, VTY_NEWLINE);
- vty_out (vty, " Referenced LS ID: %s%s", id, VTY_NEWLINE);
- vty_out (vty, " Referenced Advertising Router: %s%s", adv_router,
- VTY_NEWLINE);
- start = (char *) lsa->header + sizeof (struct ospf6_lsa_header)
- + sizeof (struct ospf6_intra_area_prefix_lsa);
- end = (char *) lsa->header + ntohs (lsa->header->length);
-
+ start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
+ end = (char *) lsa->header + ntohs (lsa->header->length);
for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
{
prefix = (struct ospf6_prefix *) current;
- if (current + OSPF6_PREFIX_SIZE (prefix) > end)
- {
- vty_out (vty, " Trailing %d byte garbage ... Malformed%s",
- end - current, VTY_NEWLINE);
- return -1;
- }
+ if (prefix->prefix_length == 0 ||
+ current + OSPF6_PREFIX_SIZE (prefix) > end)
+ break;
- ospf6_prefix_options_str (prefix->prefix_options, buf, sizeof (buf));
- vty_out (vty, " Prefix Options: %s%s", buf, VTY_NEWLINE);
+ p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ?
+ "P" : "--");
+ mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ?
+ "MC" : "--");
+ la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ?
+ "LA" : "--");
+ nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ?
+ "NU" : "--");
+ vty_out (vty, " Prefix Options: %s|%s|%s|%s%s",
+ p, mc, la, nu, VTY_NEWLINE);
- ospf6_prefix_in6_addr (prefix, &in6);
+ memset (&in6, 0, sizeof (in6));
+ memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
+ OSPF6_PREFIX_SPACE (prefix->prefix_length));
inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
vty_out (vty, " Prefix: %s/%d%s",
buf, prefix->prefix_length, VTY_NEWLINE);
@@ -378,519 +559,890 @@
}
void
-ospf6_lsa_intra_prefix_update_transit (char *ifname)
+ospf6_link_lsa_originate_sub (struct ospf6_interface *oi, int force)
{
- char buffer [MAXLSASIZE];
- u_int16_t size;
- struct ospf6_lsa *old;
- struct interface *ifp;
- struct ospf6_interface *o6i;
- struct ospf6_neighbor *o6n;
+ char buffer[OSPF6_MAX_LSASIZE];
+ struct ospf6_lsa_header *lsa_header;
+ struct ospf6_lsa *old, *lsa;
- struct ospf6_intra_area_prefix_lsa *iap;
- struct ospf6_lsdb_node n;
- listnode node;
- char *start, *end, *current;
- struct ospf6_prefix *prefix, *dup, *src, *dst;
- struct ospf6_link_lsa *link;
- char buf[128];
- int count, prefix_num;
+ struct ospf6_link_lsa *link_lsa;
+ struct ospf6_route *route;
+ struct ospf6_prefix *op;
- list adv_list;
-
- ifp = if_lookup_by_name (ifname);
- if (! ifp)
- {
- zlog_warn ("Update Intra-Prefix (Transit): No such Interface: %s",
- ifname);
- return;
- }
-
- o6i = (struct ospf6_interface *) ifp->info;
- if (! o6i || ! o6i->area)
- {
- zlog_warn ("Update Intra-Prefix (Transit): Interface not enabled: %s",
- ifname);
- return;
- }
+ if (oi->area == NULL)
+ return;
/* find previous LSA */
- old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_INTRA_PREFIX),
- htonl (o6i->if_id), ospf6->router_id,
- o6i->area);
+ old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_LINK),
+ htonl (oi->interface->ifindex),
+ oi->area->ospf6->router_id, oi->lsdb);
- /* Don't originate Network-LSA if not DR */
- if (o6i->state != IFS_DR)
+ if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
{
if (old)
- {
- if (IS_OSPF6_DUMP_PREFIX)
- zlog_info ("Update Intra-Prefix (Transit): %s not DR",
- o6i->interface->name);
- ospf6_lsa_premature_aging (old);
- }
- return;
- }
-
- /* If none of neighbor is adjacent to us */
- count = 0;
- o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state);
- if (count == 0)
- {
- if (IS_OSPF6_DUMP_PREFIX)
- zlog_info ("Update Intra-Prefix (Transit): %s is Stub",
- o6i->interface->name);
- if (old)
ospf6_lsa_premature_aging (old);
return;
}
- if (IS_OSPF6_DUMP_PREFIX)
- zlog_info ("Update Intra-Prefix (Transit): Interface %s",
- o6i->interface->name);
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info ("Originate Link-LSA for Interface %s", oi->interface->name);
- adv_list = list_new ();
-
- /* foreach Link-LSA associated with this Link */
- for (ospf6_lsdb_type (&n, htons (OSPF6_LSA_TYPE_LINK), o6i->lsdb);
- ! ospf6_lsdb_is_end (&n); ospf6_lsdb_next (&n))
+ /* can't make Link-LSA if linklocal address not set */
+ if (oi->linklocal_addr == NULL)
{
- if (IS_LSA_MAXAGE (n.lsa))
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info ("No Linklocal address on %s, defer originating",
+ oi->interface->name);
+ if (old)
+ ospf6_lsa_premature_aging (old);
+ return;
+ }
+
+ /* prepare buffer */
+ memset (buffer, 0, sizeof (buffer));
+ lsa_header = (struct ospf6_lsa_header *) buffer;
+ link_lsa = (struct ospf6_link_lsa *)
+ ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
+
+ /* Fill Link-LSA */
+ link_lsa->priority = oi->priority;
+ memcpy (link_lsa->options, oi->area->options, 3);
+ memcpy (&link_lsa->linklocal_addr, oi->linklocal_addr,
+ sizeof (struct in6_addr));
+ link_lsa->prefix_num = htonl (oi->route_connected->count);
+
+ op = (struct ospf6_prefix *)
+ ((caddr_t) link_lsa + sizeof (struct ospf6_link_lsa));
+
+ /* connected prefix to advertise */
+ for (route = ospf6_route_head (oi->route_connected); route;
+ route = ospf6_route_next (route))
+ {
+ op->prefix_length = route->prefix.prefixlen;
+ op->prefix_options = route->path.prefix_options;
+ op->prefix_metric = htons (0);
+ memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
+ OSPF6_PREFIX_SPACE (op->prefix_length));
+ op = OSPF6_PREFIX_NEXT (op);
+ }
+
+ /* Fill LSA Header */
+ lsa_header->age = 0;
+ lsa_header->type = htons (OSPF6_LSTYPE_LINK);
+ lsa_header->id = htonl (oi->interface->ifindex);
+ lsa_header->adv_router = oi->area->ospf6->router_id;
+ lsa_header->seqnum =
+ ospf6_lsa_new_seqnum (lsa_header->type, lsa_header->id,
+ lsa_header->adv_router, oi);
+ lsa_header->length = htons ((caddr_t) op - (caddr_t) buffer);
+
+ /* LSA checksum */
+ ospf6_lsa_checksum (lsa_header);
+
+ /* create LSA */
+ lsa = ospf6_lsa_create (lsa_header);
+ lsa->scope = oi;
+ if (force)
+ SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
+
+ /* Originate */
+ ospf6_lsa_originate (lsa);
+}
+
+int
+ospf6_link_lsa_originate (struct thread *thread)
+{
+ struct ospf6_interface *oi;
+ int force = 0;
+
+ oi = (struct ospf6_interface *) THREAD_ARG (thread);
+ oi->thread_link_lsa = NULL;
+ ospf6_link_lsa_originate_sub (oi, force);
+
+ return 0;
+}
+
+int
+ospf6_link_lsa_reoriginate (struct ospf6_lsa *lsa)
+{
+ struct ospf6_interface *oi;
+ int force = 1;
+
+ oi = ospf6_interface_lookup_by_ifindex (ntohl (lsa->header->id));
+ ospf6_link_lsa_originate_sub (oi, force);
+
+ return 0;
+}
+
+
+/*****************************************/
+/* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
+/*****************************************/
+
+int
+ospf6_intra_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
+{
+ char *start, *end, *current;
+ struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
+ int prefixnum;
+ char buf[128];
+ struct ospf6_prefix *prefix;
+ char id[16], adv_router[16];
+ char *p, *mc, *la, *nu;
+ struct in6_addr in6;
+
+ intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
+ ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
+
+ prefixnum = ntohs (intra_prefix_lsa->prefix_num);
+
+ vty_out (vty, " Number of Prefix: %d%s", prefixnum, VTY_NEWLINE);
+
+ inet_ntop (AF_INET, &intra_prefix_lsa->ref_id, id, sizeof (id));
+ inet_ntop (AF_INET, &intra_prefix_lsa->ref_adv_router,
+ adv_router, sizeof (adv_router));
+ vty_out (vty, " Reference: %s Id: %s Adv: %s%s",
+ OSPF6_LSTYPE_NAME (intra_prefix_lsa->ref_type), id, adv_router,
+ VTY_NEWLINE);
+
+ start = (char *) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa);
+ end = (char *) lsa->header + ntohs (lsa->header->length);
+ for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
+ {
+ prefix = (struct ospf6_prefix *) current;
+ if (prefix->prefix_length == 0 ||
+ current + OSPF6_PREFIX_SIZE (prefix) > end)
+ break;
+
+ p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ?
+ "P" : "--");
+ mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ?
+ "MC" : "--");
+ la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ?
+ "LA" : "--");
+ nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ?
+ "NU" : "--");
+ vty_out (vty, " Prefix Options: %s|%s|%s|%s%s",
+ p, mc, la, nu, VTY_NEWLINE);
+
+ memset (&in6, 0, sizeof (in6));
+ memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
+ OSPF6_PREFIX_SPACE (prefix->prefix_length));
+ inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
+ vty_out (vty, " Prefix: %s/%d%s",
+ buf, prefix->prefix_length, VTY_NEWLINE);
+ }
+
+ return 0;
+}
+
+void
+ospf6_intra_prefix_lsa_originate_stub_sub (struct ospf6_area *oa,
+ int force)
+{
+ char buffer[OSPF6_MAX_LSASIZE];
+ struct ospf6_lsa_header *lsa_header;
+ struct ospf6_lsa *old, *lsa;
+
+ struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
+ struct ospf6_interface *oi;
+ struct ospf6_neighbor *on;
+ struct ospf6_route *route;
+ struct ospf6_prefix *op;
+ listnode i, j;
+ int full_count = 0;
+ unsigned short prefix_num = 0;
+ char buf[BUFSIZ];
+ struct ospf6_route_table *route_advertise;
+
+ /* find previous LSA */
+ old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
+ htonl (0), oa->ospf6->router_id, oa->lsdb);
+
+ if (CHECK_FLAG (oa->flag, OSPF6_AREA_DISABLE))
+ {
+ if (old)
+ ospf6_lsa_premature_aging (old);
+ return;
+ }
+
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info ("Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
+ oa->name);
+
+ /* prepare buffer */
+ memset (buffer, 0, sizeof (buffer));
+ lsa_header = (struct ospf6_lsa_header *) buffer;
+ intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
+ ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
+
+ /* Fill Intra-Area-Prefix-LSA */
+ intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_ROUTER);
+ intra_prefix_lsa->ref_id = htonl (0);
+ intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id;
+
+ route_advertise = ospf6_route_table_create ();
+
+ for (i = listhead (oa->if_list); i; nextnode (i))
+ {
+ oi = (struct ospf6_interface *) getdata (i);
+
+ if (oi->state == OSPF6_INTERFACE_DOWN)
+ {
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info (" Interface %s is down, ignore", oi->interface->name);
+ continue;
+ }
+
+ full_count = 0;
+ for (j = listhead (oi->neighbor_list); j; nextnode (j))
+ {
+ on = (struct ospf6_neighbor *) getdata (j);
+ if (on->state == OSPF6_NEIGHBOR_FULL)
+ full_count++;
+ }
+ if (oi->state != OSPF6_INTERFACE_LOOPBACK &&
+ oi->state != OSPF6_INTERFACE_POINTTOPOINT &&
+ full_count != 0)
+ {
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info (" Interface %s is not stub, ignore",
+ oi->interface->name);
+ continue;
+ }
+
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info (" Interface %s:", oi->interface->name);
+
+ /* connected prefix to advertise */
+ for (route = ospf6_route_head (oi->route_connected); route;
+ route = ospf6_route_best_next (route))
+ {
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ {
+ prefix2str (&route->prefix, buf, sizeof (buf));
+ zlog_info (" include %s", buf);
+ }
+ ospf6_route_add (ospf6_route_copy (route), route_advertise);
+ }
+ }
+
+ if (route_advertise->count == 0)
+ {
+ if (old)
+ ospf6_lsa_premature_aging (old);
+ ospf6_route_table_delete (route_advertise);
+ return;
+ }
+
+ /* put prefixes to advertise */
+ prefix_num = 0;
+ op = (struct ospf6_prefix *)
+ ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa));
+ for (route = ospf6_route_head (route_advertise); route;
+ route = ospf6_route_best_next (route))
+ {
+ op->prefix_length = route->prefix.prefixlen;
+ op->prefix_options = route->path.prefix_options;
+ op->prefix_metric = htons (route->path.cost);
+ memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
+ OSPF6_PREFIX_SPACE (op->prefix_length));
+ op = OSPF6_PREFIX_NEXT (op);
+ prefix_num++;
+ }
+
+ ospf6_route_table_delete (route_advertise);
+
+ if (prefix_num == 0)
+ {
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info ("Quit to Advertise Intra-Prefix: no route to advertise");
+ return;
+ }
+
+ intra_prefix_lsa->prefix_num = htons (prefix_num);
+
+ /* Fill LSA Header */
+ lsa_header->age = 0;
+ lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
+ lsa_header->id = htonl (0);
+ lsa_header->adv_router = oa->ospf6->router_id;
+ lsa_header->seqnum =
+ ospf6_lsa_new_seqnum (lsa_header->type, lsa_header->id,
+ lsa_header->adv_router, oa);
+ lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
+
+ /* LSA checksum */
+ ospf6_lsa_checksum (lsa_header);
+
+ /* create LSA */
+ lsa = ospf6_lsa_create (lsa_header);
+ lsa->scope = oa;
+ if (force)
+ SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
+
+ /* Originate */
+ ospf6_lsa_originate (lsa);
+}
+
+void
+ospf6_intra_prefix_lsa_originate_transit_sub (struct ospf6_interface *oi,
+ int force)
+{
+ char buffer[OSPF6_MAX_LSASIZE];
+ struct ospf6_lsa_header *lsa_header;
+ struct ospf6_lsa *old, *lsa;
+
+ struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
+ struct ospf6_neighbor *on;
+ struct ospf6_route *route;
+ struct ospf6_prefix *op;
+ listnode i;
+ int full_count = 0;
+ unsigned short prefix_num = 0;
+ struct ospf6_route_table *route_advertise;
+ struct ospf6_link_lsa *link_lsa;
+ char *start, *end, *current;
+ u_int16_t type;
+ char buf[BUFSIZ];
+
+ if (oi->area == NULL)
+ return;
+
+ /* find previous LSA */
+ old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
+ htonl (oi->interface->ifindex),
+ oi->area->ospf6->router_id, oi->area->lsdb);
+
+ if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
+ {
+ if (old)
+ ospf6_lsa_premature_aging (old);
+ return;
+ }
+
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info ("Originate Intra-Area-Prefix-LSA for interface %s's prefix",
+ oi->interface->name);
+
+ /* prepare buffer */
+ memset (buffer, 0, sizeof (buffer));
+ lsa_header = (struct ospf6_lsa_header *) buffer;
+ intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
+ ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
+
+ /* Fill Intra-Area-Prefix-LSA */
+ intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_NETWORK);
+ intra_prefix_lsa->ref_id = htonl (oi->interface->ifindex);
+ intra_prefix_lsa->ref_adv_router = oi->area->ospf6->router_id;
+
+ if (oi->state != OSPF6_INTERFACE_DR)
+ {
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info (" Interface is not DR");
+ if (old)
+ ospf6_lsa_premature_aging (old);
+ return;
+ }
+
+ full_count = 0;
+ for (i = listhead (oi->neighbor_list); i; nextnode (i))
+ {
+ on = (struct ospf6_neighbor *) getdata (i);
+ if (on->state == OSPF6_NEIGHBOR_FULL)
+ full_count++;
+ }
+ if (full_count == 0)
+ {
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info (" Interface is stub");
+ if (old)
+ ospf6_lsa_premature_aging (old);
+ return;
+ }
+
+ /* connected prefix to advertise */
+ route_advertise = ospf6_route_table_create ();
+
+ type = ntohs (OSPF6_LSTYPE_LINK);
+ for (lsa = ospf6_lsdb_type_head (type, oi->lsdb); lsa;
+ lsa = ospf6_lsdb_type_next (type, lsa))
+ {
+ if (OSPF6_LSA_IS_MAXAGE (lsa))
continue;
- if (IS_OSPF6_DUMP_PREFIX)
- zlog_info ("Update Intra-Prefix (Transit): Checking %s",
- n.lsa->str);
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info (" include prefix from %s", lsa->name);
- /* Check status of the advertising router */
- if (n.lsa->header->adv_router != o6i->area->ospf6->router_id)
+ if (lsa->header->adv_router != oi->area->ospf6->router_id)
{
- o6n = ospf6_neighbor_lookup (n.lsa->header->adv_router, o6i);
- if (! o6n)
+ on = ospf6_neighbor_lookup (lsa->header->adv_router, oi);
+ if (on == NULL || on->state != OSPF6_NEIGHBOR_FULL)
{
- if (IS_OSPF6_DUMP_PREFIX)
- zlog_info ("Update Intra-Prefix (Transit): neighbor not found");
- continue;
- }
-
- if (o6n->state != NBS_FULL)
- {
- if (IS_OSPF6_DUMP_PREFIX)
- zlog_info ("Update Intra-Prefix (Transit): %s not FULL",
- o6n->str);
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info (" Neighbor not found or not Full, ignore");
continue;
}
}
- /* For each Prefix in this Link-LSA */
- link = (struct ospf6_link_lsa *) (n.lsa->header + 1);
- prefix_num = ntohl (link->llsa_prefix_num);
+ link_lsa = (struct ospf6_link_lsa *)
+ ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
- if (IS_OSPF6_DUMP_PREFIX)
- zlog_info (" Prefix #%d", prefix_num);
-
- start = (char *) (link + 1);
- end = (char *) (n.lsa->header) + ntohs (n.lsa->header->length);
- prefix = (struct ospf6_prefix *) start;
- for (current = start; current < end;
- current += OSPF6_PREFIX_SIZE (prefix))
+ prefix_num = (unsigned short) ntohl (link_lsa->prefix_num);
+ start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
+ end = (char *) lsa->header + ntohs (lsa->header->length);
+ for (current = start; current < end && prefix_num;
+ current += OSPF6_PREFIX_SIZE (op))
{
- prefix = (struct ospf6_prefix *) current;
- ospf6_prefix_string (prefix, buf, sizeof (buf));
+ op = (struct ospf6_prefix *) current;
+ if (op->prefix_length == 0 ||
+ current + OSPF6_PREFIX_SIZE (op) > end)
+ break;
- /* Check duplicate prefix */
- dup = ospf6_prefix_lookup (adv_list, prefix);
- if (dup)
+ route = ospf6_route_create ();
+
+ route->type = OSPF6_DEST_TYPE_NETWORK;
+ route->prefix.family = AF_INET6;
+ route->prefix.prefixlen = op->prefix_length;
+ memset (&route->prefix.u.prefix6, 0, sizeof (struct in6_addr));
+ memcpy (&route->prefix.u.prefix6, OSPF6_PREFIX_BODY (op),
+ OSPF6_PREFIX_SPACE (op->prefix_length));
+
+ route->path.origin.type = lsa->header->type;
+ route->path.origin.id = lsa->header->id;
+ route->path.origin.adv_router = lsa->header->adv_router;
+ route->path.options[0] = link_lsa->options[0];
+ route->path.options[1] = link_lsa->options[1];
+ route->path.options[2] = link_lsa->options[2];
+ route->path.prefix_options = op->prefix_options;
+ route->path.area_id = oi->area->area_id;
+ route->path.type = OSPF6_PATH_TYPE_INTRA;
+
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
{
- if (IS_OSPF6_DUMP_PREFIX)
- zlog_info (" Duplicate %s", buf);
- dup->prefix_options |= prefix->prefix_options;
- continue;
+ prefix2str (&route->prefix, buf, sizeof (buf));
+ zlog_info (" include %s", buf);
}
- if (prefix_num <= 0)
- {
- zlog_warn (" Wong prefix number ...");
- break;
- }
-
- if (IS_OSPF6_DUMP_PREFIX)
- zlog_info (" Prefix %s", buf);
-
- /* copy prefix to advertise list */
- ospf6_prefix_add (adv_list, prefix);
-
- prefix_num --;
+ ospf6_route_add (route, route_advertise);
+ prefix_num--;
}
+ if (current != end && IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info ("Trailing garbage in %s", lsa->name);
}
- /* if no prefix to advertise, return */
- if (listcount (adv_list) == 0)
+ op = (struct ospf6_prefix *)
+ ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa));
+
+ prefix_num = 0;
+ for (route = ospf6_route_head (route_advertise); route;
+ route = ospf6_route_best_next (route))
{
- if (IS_OSPF6_DUMP_PREFIX)
- zlog_info (" No Prefix to advertise");
- if (old)
- ospf6_lsa_premature_aging (old);
+ op->prefix_length = route->prefix.prefixlen;
+ op->prefix_options = route->path.prefix_options;
+ op->prefix_metric = htons (0);
+ memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
+ OSPF6_PREFIX_SPACE (op->prefix_length));
+ op = OSPF6_PREFIX_NEXT (op);
+ prefix_num++;
+ }
+
+ ospf6_route_table_delete (route_advertise);
+
+ if (prefix_num == 0)
+ {
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info ("Quit to Advertise Intra-Prefix: no route to advertise");
return;
}
- /* prepare buffer */
- memset (buffer, 0, sizeof (buffer));
- size = sizeof (struct ospf6_intra_area_prefix_lsa);
- iap = (struct ospf6_intra_area_prefix_lsa *) buffer;
+ intra_prefix_lsa->prefix_num = htons (prefix_num);
- /* Set Referenced LSA field */
- iap->refer_lstype = htons (OSPF6_LSA_TYPE_NETWORK);
- iap->refer_lsid = htonl (o6i->if_id);
- iap->refer_advrtr = o6i->area->ospf6->router_id;
+ /* Fill LSA Header */
+ lsa_header->age = 0;
+ lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
+ lsa_header->id = htonl (oi->interface->ifindex);
+ lsa_header->adv_router = oi->area->ospf6->router_id;
+ lsa_header->seqnum =
+ ospf6_lsa_new_seqnum (lsa_header->type, lsa_header->id,
+ lsa_header->adv_router, oi->area);
+ lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
- dst = (struct ospf6_prefix *) (iap + 1);
- for (node = listhead (adv_list); node; nextnode (node))
- {
- src = (struct ospf6_prefix *) getdata (node);
+ /* LSA checksum */
+ ospf6_lsa_checksum (lsa_header);
- memcpy (dst, src, OSPF6_PREFIX_SIZE (src));
+ /* create LSA */
+ lsa = ospf6_lsa_create (lsa_header);
+ lsa->scope = oi->area;
+ if (force)
+ SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
- size += OSPF6_PREFIX_SIZE (dst);
- dst = OSPF6_NEXT_PREFIX (dst);
- }
- iap->prefix_number = htons (listcount (adv_list));
-
- while ((node = listhead (adv_list)) != NULL)
- {
- prefix = getdata (node);
- ospf6_prefix_delete (prefix);
- listnode_delete (adv_list, prefix);
- }
- list_delete (adv_list);
-
- ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_INTRA_PREFIX),
- htonl (o6i->if_id), ospf6->router_id,
- buffer, size, o6i->area);
-}
-
-void
-ospf6_lsa_intra_prefix_update_stub (u_int32_t area_id)
-{
- char buffer [MAXLSASIZE];
- u_int16_t size;
- struct ospf6_lsa *old;
- struct ospf6_area *o6a;
- int count;
-
- struct ospf6_intra_area_prefix_lsa *iap;
- listnode i,j;
- struct ospf6_interface *o6i = NULL;
- struct ospf6_prefix *prefix, *dst, *src;
- struct connected *c;
- char buf[128];
-
- list adv_list;
- listnode node;
- char prefix_buf[sizeof (struct ospf6_prefix) + sizeof (struct in6_addr)];
-
- o6a = ospf6_area_lookup (area_id, ospf6);
- if (! o6a)
- {
- char tmp[16];
- inet_ntop (AF_INET, &area_id, tmp, sizeof (tmp));
- zlog_warn ("Update Intra-Prefix (Stub): No such area: %s", tmp);
- return;
- }
- else if (IS_OSPF6_DUMP_PREFIX)
- {
- zlog_info ("Update Intra-Prefix (Stub): area: %s", o6a->str);
- }
-
- /* find previous LSA */
- old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_INTRA_PREFIX),
- htonl (0), ospf6->router_id,
- o6a); /* xxx, ls-id */
-
- adv_list = list_new ();
-
- /* Examin for each interface */
- for (i = listhead (o6a->if_list); i; nextnode (i))
- {
- o6i = (struct ospf6_interface *) getdata (i);
-
- if (o6i->state == IFS_DOWN)
- {
- if (IS_OSPF6_DUMP_PREFIX)
- zlog_info (" Interface %s: down", o6i->interface->name);
- continue;
- }
-
- count = 0;
- o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state);
- if (o6i->state != IFS_LOOPBACK && o6i->state != IFS_PTOP &&
- count != 0)
- {
- /* This interface's prefix will be included in DR's */
- if (IS_OSPF6_DUMP_PREFIX)
- zlog_info (" Interface %s: not stub", o6i->interface->name);
- continue;
- }
-
- if (IS_OSPF6_DUMP_PREFIX)
- zlog_info (" Interface %s:", o6i->interface->name);
-
- /* copy foreach address prefix */
- for (j = listhead (o6i->interface->connected); j; nextnode (j))
- {
- c = (struct connected *) getdata (j);
-
- /* filter prefix not IPv6 */
- if (c->address->family != AF_INET6)
- continue;
-
- /* for log */
- prefix2str (c->address, buf, sizeof (buf));
-
- CONTINUE_IF_ADDRESS_LINKLOCAL (c->address);
- CONTINUE_IF_ADDRESS_UNSPECIFIED (c->address);
- CONTINUE_IF_ADDRESS_LOOPBACK (c->address);
- CONTINUE_IF_ADDRESS_V4COMPAT (c->address);
- CONTINUE_IF_ADDRESS_V4MAPPED (c->address);
-
- /* filter prefix specified by configuration */
- if (o6i->plist_name)
- {
- struct prefix_list *plist;
- enum prefix_list_type result = PREFIX_PERMIT;
-
- plist = prefix_list_lookup (AFI_IP6, o6i->plist_name);
- if (plist)
- result = prefix_list_apply (plist, c->address);
- else
- zlog_warn ("Update Intra-Prefix (Stub): "
- "Prefix list \"%s\" not found",
- o6i->plist_name);
-
- if (result == PREFIX_DENY)
- {
- if (IS_OSPF6_DUMP_PREFIX)
- zlog_info (" %s: Filtered by %s",
- buf, o6i->plist_name);
- continue;
- }
- }
-
- /* initialize buffer for ospf6 prefix */
- memset (prefix_buf, 0, sizeof (prefix_buf));
- prefix = (struct ospf6_prefix *) prefix_buf;
-
- /* set ospf6 prefix according to its state */
- /* xxx, virtual links */
- if (! CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_FORCE_PREFIX) &&
- (o6i->state == IFS_LOOPBACK || o6i->state == IFS_PTOP
- /* xxx, PoinToMultiPoint I/F type */ ))
- {
- prefix->prefix_length = 128;
- prefix->prefix_options = OSPF6_PREFIX_OPTION_LA;
- prefix->prefix_metric = htons (0);
- memcpy (prefix + 1, &c->address->u.prefix6,
- OSPF6_PREFIX_SPACE (prefix->prefix_length));
- }
- else
- {
- struct prefix_ipv6 prefix_ipv6;
- /* apply mask */
- prefix_copy ((struct prefix *) &prefix_ipv6, c->address);
- apply_mask_ipv6 (&prefix_ipv6);
-
- prefix->prefix_length = prefix_ipv6.prefixlen;
- prefix->prefix_options = 0; /* xxx, no options yet */
- prefix->prefix_metric = htons (o6i->cost);
- memcpy (prefix + 1, &prefix_ipv6.prefix,
- OSPF6_PREFIX_SPACE (prefix->prefix_length));
- }
-
- ospf6_prefix_string (prefix, buf, sizeof (buf));
- if (IS_OSPF6_DUMP_PREFIX)
- zlog_info (" Advertise %s", buf);
-
- /* check in the prefix to advertising prefix list */
- ospf6_prefix_add (adv_list, prefix);
- }
- }
-
- /* If no prefix to advertise */
- if (listcount (adv_list) == 0)
- {
- if (IS_OSPF6_DUMP_PREFIX)
- zlog_info (" No prefix to advertise");
- if (old)
- ospf6_lsa_premature_aging (old);
- return;
- }
-
- /* prepare buffer */
- memset (buffer, 0, sizeof (buffer));
- size = sizeof (struct ospf6_intra_area_prefix_lsa);
- iap = (struct ospf6_intra_area_prefix_lsa *) buffer;
-
- /* Set Referenced LSA field */
- iap->refer_lstype = htons (OSPF6_LSA_TYPE_ROUTER);
- iap->refer_lsid = htonl (0);
- iap->refer_advrtr = o6a->ospf6->router_id;
-
- dst = (struct ospf6_prefix *) (iap + 1);
- for (node = listhead (adv_list); node; nextnode (node))
- {
- src = (struct ospf6_prefix *) getdata (node);
-
- memcpy (dst, src, OSPF6_PREFIX_SIZE (src));
-
- size += OSPF6_PREFIX_SIZE (dst);
- dst = OSPF6_NEXT_PREFIX (dst);
- }
- iap->prefix_number = htons (listcount (adv_list));
-
- while ((node = listhead (adv_list)) != NULL)
- {
- prefix = getdata (node);
- ospf6_prefix_delete (prefix);
- listnode_delete (adv_list, prefix);
- }
- list_delete (adv_list);
-
- ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_INTRA_PREFIX),
- htonl (0) /* xxx */, ospf6->router_id,
- buffer, size, o6a);
+ /* Originate */
+ ospf6_lsa_originate (lsa);
}
int
-ospf6_lsa_intra_prefix_hook_interface (void *interface)
+ospf6_intra_prefix_lsa_originate_stub (struct thread *thread)
{
- struct ospf6_interface *o6i = interface;
- if (o6i->area)
- {
- ospf6_lsa_intra_prefix_update_transit (o6i->interface->name);
- ospf6_lsa_intra_prefix_update_stub (o6i->area->area_id);
- }
+ struct ospf6_area *oa;
+ int force = 0;
+
+ oa = (struct ospf6_area *) THREAD_ARG (thread);
+ oa->thread_intra_prefix_lsa = NULL;
+ ospf6_intra_prefix_lsa_originate_stub_sub (oa, force);
+
return 0;
}
int
-ospf6_lsa_intra_prefix_hook_neighbor (void *neighbor)
+ospf6_intra_prefix_lsa_originate_transit (struct thread *thread)
{
- struct ospf6_neighbor *o6n = neighbor;
- if (o6n->ospf6_interface->area)
- {
- ospf6_lsa_intra_prefix_update_transit (o6n->ospf6_interface->interface->name);
- ospf6_lsa_intra_prefix_update_stub (o6n->ospf6_interface->area->area_id);
- }
+ struct ospf6_interface *oi;
+ int force = 0;
+
+ oi = (struct ospf6_interface *) THREAD_ARG (thread);
+ oi->thread_intra_prefix_lsa = NULL;
+ ospf6_intra_prefix_lsa_originate_transit_sub (oi, force);
+
return 0;
}
int
-ospf6_intra_prefix_link_database_hook (void *new)
+ospf6_intra_prefix_lsa_reoriginate (struct ospf6_lsa *lsa)
{
- struct ospf6_lsa *lsa = new;
- struct ospf6_interface *o6i;
-
- if (lsa->header->type != htons (OSPF6_LSA_TYPE_LINK))
- return 0;
-
- o6i = lsa->scope;
- if (o6i->state != IFS_DR)
- return 0;
-
- ospf6_lsa_intra_prefix_update_transit (o6i->interface->name);
- ospf6_lsa_intra_prefix_update_stub (o6i->area->area_id);
- return 0;
-}
-
-int
-ospf6_lsa_intra_prefix_refresh (void *old)
-{
- struct ospf6_lsa *lsa = old;
- struct ospf6_interface *o6i;
- struct ospf6_area *o6a;
+ struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
+ u_int16_t type;
u_int32_t id;
+ struct ospf6_area *oa;
+ struct ospf6_interface *oi;
+ int force = 1;
- id = ntohl (lsa->header->id);
- if (id)
+ intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
+ ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
+ type = ntohs (intra_prefix_lsa->ref_type);
+ id = ntohl (intra_prefix_lsa->ref_id);
+
+ if (type == OSPF6_LSTYPE_ROUTER && id == 0)
{
- o6i = ospf6_interface_lookup_by_index (id);
- if (o6i)
- ospf6_lsa_intra_prefix_update_transit (o6i->interface->name);
- else
+ oa = (struct ospf6_area *) lsa->scope;
+ ospf6_intra_prefix_lsa_originate_stub_sub (oa, force);
+ }
+ else if (type == OSPF6_LSTYPE_NETWORK && id != 0)
+ {
+ if (intra_prefix_lsa->ref_id != lsa->header->id)
ospf6_lsa_premature_aging (lsa);
+ oi = ospf6_interface_lookup_by_ifindex (id);
+ ospf6_intra_prefix_lsa_originate_transit_sub (oi, force);
}
else
- {
- o6a = lsa->scope;
- ospf6_lsa_intra_prefix_update_stub (o6a->area_id);
- }
+ ospf6_lsa_premature_aging (lsa);
return 0;
}
void
-ospf6_intra_prefix_register ()
+ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
{
- struct ospf6_lsa_slot slot, *sp;
- struct ospf6_hook hook;
+ struct ospf6_area *oa;
+ struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
+ struct prefix ls_prefix;
+ struct ospf6_route *route, *ls_entry;
+ int i, prefix_num;
+ struct ospf6_prefix *op;
+ char *start, *current, *end;
+ char buf[64];
- memset (&slot, 0, sizeof (struct ospf6_lsa_slot));
- slot.type = htons (OSPF6_LSA_TYPE_INTRA_PREFIX);
- slot.name = "Intra-Prefix";
- slot.func_show = ospf6_lsa_intra_prefix_show;
- slot.func_refresh = ospf6_lsa_intra_prefix_refresh;
- ospf6_lsa_slot_register (&slot);
+ if (IS_OSPF6_DEBUG_ROUTE (INTRA))
+ zlog_info ("%s found", lsa->name);
- memset (&hook, 0, sizeof (hook));
- hook.name = "OriginateIntraPrefix";
- hook.hook_add = ospf6_lsa_intra_prefix_hook_interface;
- hook.hook_change = ospf6_lsa_intra_prefix_hook_interface;
- hook.hook_remove = NULL; /* XXX */
- ospf6_hook_register (&hook, &interface_hook);
+ oa = (struct ospf6_area *) lsa->scope;
+ intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
+ OSPF6_LSA_HEADER_END (lsa->header);
+ if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_ROUTER))
+ ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
+ htonl (0), &ls_prefix);
+ else if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_NETWORK))
+ ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
+ intra_prefix_lsa->ref_id, &ls_prefix);
+ else
+ {
+ if (IS_OSPF6_DEBUG_ROUTE (INTRA))
+ zlog_info ("Unknown reference LS-type: %#hx",
+ ntohs (intra_prefix_lsa->ref_type));
+ return;
+ }
- memset (&hook, 0, sizeof (hook));
- hook.name = "OriginateIntraPrefix";
- hook.hook_add = ospf6_lsa_intra_prefix_hook_neighbor;
- hook.hook_change = ospf6_lsa_intra_prefix_hook_neighbor;
- hook.hook_remove = ospf6_lsa_intra_prefix_hook_neighbor;
- ospf6_hook_register (&hook, &neighbor_hook);
+ ls_entry = ospf6_route_lookup (&ls_prefix, oa->spf_table);
+ if (ls_entry == NULL)
+ {
+ if (IS_OSPF6_DEBUG_ROUTE (INTRA))
+ {
+ ospf6_linkstate_prefix2str (&ls_prefix, buf, sizeof (buf));
+ zlog_info ("LS entry does not exist: %s", buf);
+ }
+ return;
+ }
- sp = ospf6_lsa_slot_get (htons (OSPF6_LSA_TYPE_INTRA_PREFIX));
- hook.name = "CalculateIntraPrefix";
- hook.hook_add = ospf6_intra_prefix_database_hook_add;
- hook.hook_change = ospf6_intra_prefix_database_hook_add;
- hook.hook_remove = ospf6_intra_prefix_database_hook_remove;
- ospf6_hook_register (&hook, &sp->database_hook);
+ prefix_num = ntohs (intra_prefix_lsa->prefix_num);
+ start = (caddr_t) intra_prefix_lsa +
+ sizeof (struct ospf6_intra_prefix_lsa);
+ end = OSPF6_LSA_END (lsa->header);
+ for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
+ {
+ op = (struct ospf6_prefix *) current;
+ if (prefix_num == 0)
+ break;
+ if (end < current + OSPF6_PREFIX_SIZE (op))
+ break;
+
+ route = ospf6_route_create ();
+ route->prefix.prefixlen = op->prefix_length;
+ route->prefix.family = AF_INET6;
+ memcpy (&route->prefix.u.prefix6, OSPF6_PREFIX_BODY (op),
+ OSPF6_PREFIX_SPACE (op->prefix_length));
+ route->type = OSPF6_DEST_TYPE_NETWORK;
+ route->path.origin.type = lsa->header->type;
+ route->path.origin.id = lsa->header->id;
+ route->path.origin.adv_router = lsa->header->adv_router;
+ route->path.prefix_options = op->prefix_options;
+ route->path.area_id = oa->area_id;
+ route->path.type = OSPF6_PATH_TYPE_INTRA;
+ route->path.metric_type = 1;
+ route->path.cost = ls_entry->path.cost +
+ ntohs (op->prefix_metric);
+
+ for (i = 0; ospf6_nexthop_is_set (&ls_entry->nexthop[i]) &&
+ i < OSPF6_MULTI_PATH_LIMIT; i++)
+ ospf6_nexthop_copy (&route->nexthop[i], &ls_entry->nexthop[i]);
+
+ if (IS_OSPF6_DEBUG_ROUTE (INTRA))
+ {
+ prefix2str (&route->prefix, buf, sizeof (buf));
+ zlog_info (" add %s", buf);
+ }
+
+ ospf6_route_add (route, oa->route_table);
+ prefix_num--;
+ }
+
+ if (current != end && IS_OSPF6_DEBUG_ROUTE (INTRA))
+ zlog_info ("Trailing garbage ignored");
}
void
-ospf6_intra_database_hook_intra_prefix (struct ospf6_lsa *old,
- struct ospf6_lsa *new)
+ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa)
{
- if (old)
- ospf6_intra_prefix_database_hook_remove (old);
- if (new && ! IS_LSA_MAXAGE (new))
- ospf6_intra_prefix_database_hook_add (new);
+ struct ospf6_area *oa;
+ struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
+ struct prefix prefix;
+ struct ospf6_route *route;
+ int prefix_num;
+ struct ospf6_prefix *op;
+ char *start, *current, *end;
+ char buf[64];
+
+ if (IS_OSPF6_DEBUG_ROUTE (INTRA))
+ zlog_info ("%s disappearing", lsa->name);
+
+ oa = (struct ospf6_area *) lsa->scope;
+ intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
+ OSPF6_LSA_HEADER_END (lsa->header);
+
+ prefix_num = ntohs (intra_prefix_lsa->prefix_num);
+ start = (caddr_t) intra_prefix_lsa +
+ sizeof (struct ospf6_intra_prefix_lsa);
+ end = OSPF6_LSA_END (lsa->header);
+ for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
+ {
+ op = (struct ospf6_prefix *) current;
+ if (prefix_num == 0)
+ break;
+ if (end < current + OSPF6_PREFIX_SIZE (op))
+ break;
+ prefix_num--;
+
+ prefix.family = AF_INET6;
+ prefix.prefixlen = op->prefix_length;
+ ospf6_prefix_in6_addr (&prefix.u.prefix6, op);
+
+ route = ospf6_route_lookup (&prefix, oa->route_table);
+ if (route == NULL)
+ continue;
+
+ for (ospf6_route_lock (route);
+ route && ospf6_route_is_prefix (&prefix, route);
+ route = ospf6_route_next (route))
+ {
+ if (route->type != OSPF6_DEST_TYPE_NETWORK)
+ continue;
+ if (route->path.area_id != oa->area_id)
+ continue;
+ if (route->path.type != OSPF6_PATH_TYPE_INTRA)
+ continue;
+ if (route->path.origin.type != lsa->header->type ||
+ route->path.origin.id != lsa->header->id ||
+ route->path.origin.adv_router != lsa->header->adv_router)
+ continue;
+
+ if (IS_OSPF6_DEBUG_ROUTE (INTRA))
+ {
+ prefix2str (&route->prefix, buf, sizeof (buf));
+ zlog_info ("remove %s", buf);
+ }
+ ospf6_route_remove (route, oa->route_table);
+ }
+ }
+
+ if (current != end && IS_OSPF6_DEBUG_ROUTE (INTRA))
+ zlog_info ("Trailing garbage ignored");
}
void
-ospf6_intra_database_hook_link (struct ospf6_lsa *old,
- struct ospf6_lsa *new)
+ospf6_intra_route_calculation (struct ospf6_area *oa)
{
- ospf6_intra_prefix_link_database_hook (new);
- ospf6_spf_database_hook (old, new);
+ struct ospf6_route *route;
+ u_int16_t type;
+ struct ospf6_lsa *lsa;
+ void (*hook_add) (struct ospf6_route *) = NULL;
+ void (*hook_remove) (struct ospf6_route *) = NULL;
+
+ if (IS_OSPF6_DEBUG_ROUTE (INTRA))
+ zlog_info ("Intra-area routing table calculation for area %s",
+ oa->name);
+
+ hook_add = oa->route_table->hook_add;
+ hook_remove = oa->route_table->hook_remove;
+ oa->route_table->hook_add = NULL;
+ oa->route_table->hook_remove = NULL;
+
+ for (route = ospf6_route_head (oa->route_table); route;
+ route = ospf6_route_next (route))
+ route->flag = OSPF6_ROUTE_REMOVE;
+
+ type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
+ for (lsa = ospf6_lsdb_type_head (type, oa->lsdb); lsa;
+ lsa = ospf6_lsdb_type_next (type, lsa))
+ ospf6_intra_prefix_lsa_add (lsa);
+
+ oa->route_table->hook_add = hook_add;
+ oa->route_table->hook_remove = hook_remove;
+
+ for (route = ospf6_route_head (oa->route_table); route;
+ route = ospf6_route_next (route))
+ {
+ if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) &&
+ CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD))
+ {
+ UNSET_FLAG (route->flag, OSPF6_ROUTE_REMOVE);
+ UNSET_FLAG (route->flag, OSPF6_ROUTE_ADD);
+ }
+
+ if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE))
+ ospf6_route_remove (route, oa->route_table);
+ else if (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ||
+ CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE))
+ {
+ if (hook_add)
+ (*hook_add) (route);
+ }
+
+ route->flag = 0;
+ }
+
+ if (IS_OSPF6_DEBUG_ROUTE (INTRA))
+ zlog_info ("Intra-area routing table calculation for area %s: Done",
+ oa->name);
+}
+
+void
+ospf6_intra_asbr_calculation (struct ospf6_area *oa)
+{
+ struct ospf6_route *lsentry, *copy;
+ void (*hook_add) (struct ospf6_route *) = NULL;
+ void (*hook_remove) (struct ospf6_route *) = NULL;
+
+ if (IS_OSPF6_DEBUG_ASBR)
+ zlog_info ("Intra-area ASBR calculation for area %s", oa->name);
+
+ hook_add = oa->ospf6->asbr_table->hook_add;
+ hook_remove = oa->ospf6->asbr_table->hook_remove;
+ oa->ospf6->asbr_table->hook_add = NULL;
+ oa->ospf6->asbr_table->hook_remove = NULL;
+
+ for (lsentry = ospf6_route_head (oa->ospf6->asbr_table); lsentry;
+ lsentry = ospf6_route_next (lsentry))
+ {
+ if (lsentry->path.area_id != oa->area_id)
+ continue;
+ lsentry->flag = OSPF6_ROUTE_REMOVE;
+ }
+
+ for (lsentry = ospf6_route_head (oa->spf_table); lsentry;
+ lsentry = ospf6_route_next (lsentry))
+ {
+ if (lsentry->type != OSPF6_DEST_TYPE_LINKSTATE)
+ continue;
+ if (ospf6_linkstate_prefix_id (&lsentry->prefix) != htonl (0))
+ continue;
+ if (! CHECK_FLAG (lsentry->path.router_bits, OSPF6_ROUTER_BIT_E))
+ continue;
+
+ copy = ospf6_route_copy (lsentry);
+ copy->type = OSPF6_DEST_TYPE_ROUTER;
+ copy->prefix.family = AF_INET;
+ copy->prefix.prefixlen = 32;
+ ospf6_route_add (copy, oa->ospf6->asbr_table);
+ }
+
+ oa->ospf6->asbr_table->hook_add = hook_add;
+ oa->ospf6->asbr_table->hook_remove = hook_remove;
+
+ for (lsentry = ospf6_route_head (oa->ospf6->asbr_table); lsentry;
+ lsentry = ospf6_route_next (lsentry))
+ {
+ if (lsentry->path.area_id != oa->area_id)
+ continue;
+
+ if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_REMOVE) &&
+ CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_ADD))
+ {
+ UNSET_FLAG (lsentry->flag, OSPF6_ROUTE_REMOVE);
+ UNSET_FLAG (lsentry->flag, OSPF6_ROUTE_ADD);
+ }
+
+ if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_REMOVE))
+ ospf6_route_remove (lsentry, oa->ospf6->asbr_table);
+ else if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_ADD) ||
+ CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_CHANGE))
+ {
+ if (hook_add)
+ (*hook_add) (lsentry);
+ }
+
+ lsentry->flag = 0;
+ }
+
+ if (IS_OSPF6_DEBUG_ASBR)
+ zlog_info ("Intra-area ASBR calculation for area %s: Done", oa->name);
}
void
ospf6_intra_init ()
{
- ospf6_lsdb_hook[OSPF6_LSA_TYPE_INTRA_PREFIX & OSPF6_LSTYPE_CODE_MASK].hook =
- ospf6_intra_database_hook_intra_prefix;
- ospf6_lsdb_hook[OSPF6_LSA_TYPE_LINK & OSPF6_LSTYPE_CODE_MASK].hook =
- ospf6_intra_database_hook_link;
+ ospf6_lstype[1].name = "Router";
+ ospf6_lstype[2].name = "Network";
+ ospf6_lstype[8].name = "Link";
+ ospf6_lstype[9].name = "Intra-Prefix";
- intra_index = ospf6_dump_install ("intra-area", "Intra-area calculation\n");
- ospf6_intra_prefix_register ();
+ ospf6_lstype[1].reoriginate = ospf6_router_lsa_reoriginate;
+ ospf6_lstype[2].reoriginate = ospf6_network_lsa_reoriginate;
+ ospf6_lstype[8].reoriginate = ospf6_link_lsa_reoriginate;
+ ospf6_lstype[9].reoriginate = ospf6_intra_prefix_lsa_reoriginate;
+
+ ospf6_lstype[1].show = ospf6_router_lsa_show;
+ ospf6_lstype[2].show = ospf6_network_lsa_show;
+ ospf6_lstype[8].show = ospf6_link_lsa_show;
+ ospf6_lstype[9].show = ospf6_intra_prefix_lsa_show;
}
diff --git a/ospf6d/ospf6_intra.h b/ospf6d/ospf6_intra.h
index 4fb68e9..28780b4 100644
--- a/ospf6d/ospf6_intra.h
+++ b/ospf6d/ospf6_intra.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2001 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -22,10 +22,132 @@
#ifndef OSPF6_INTRA_H
#define OSPF6_INTRA_H
-void ospf6_intra_topology_add (void *);
-void ospf6_intra_topology_remove (void *);
+/* Router-LSA */
+struct ospf6_router_lsa
+{
+ u_char bits;
+ u_char options[3];
+ /* followed by ospf6_router_lsdesc(s) */
+};
+
+/* Link State Description in Router-LSA */
+struct ospf6_router_lsdesc
+{
+ u_char type;
+ u_char reserved;
+ u_int16_t metric; /* output cost */
+ u_int32_t interface_id;
+ u_int32_t neighbor_interface_id;
+ u_int32_t neighbor_router_id;
+};
+
+#define OSPF6_ROUTER_LSDESC_POINTTOPOINT 1
+#define OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK 2
+#define OSPF6_ROUTER_LSDESC_STUB_NETWORK 3
+#define OSPF6_ROUTER_LSDESC_VIRTUAL_LINK 4
+
+#define ROUTER_LSDESC_IS_TYPE(t,x) \
+ ((((struct ospf6_router_lsdesc *)(x))->type == \
+ OSPF6_ROUTER_LSDESC_ ## t) ? 1 : 0)
+#define ROUTER_LSDESC_GET_METRIC(x) \
+ (ntohs (((struct ospf6_router_lsdesc *)(x))->metric))
+#define ROUTER_LSDESC_GET_IFID(x) \
+ (ntohl (((struct ospf6_router_lsdesc *)(x))->interface_id))
+#define ROUTER_LSDESC_GET_NBR_IFID(x) \
+ (ntohl (((struct ospf6_router_lsdesc *)(x))->neighbor_interface_id))
+#define ROUTER_LSDESC_GET_NBR_ROUTERID(x) \
+ (((struct ospf6_router_lsdesc *)(x))->neighbor_router_id)
+
+/* Network-LSA */
+struct ospf6_network_lsa
+{
+ u_char reserved;
+ u_char options[3];
+ /* followed by ospf6_netowrk_lsd(s) */
+};
+
+/* Link State Description in Router-LSA */
+struct ospf6_network_lsdesc
+{
+ u_int32_t router_id;
+};
+#define NETWORK_LSDESC_GET_NBR_ROUTERID(x) \
+ (((struct ospf6_network_lsdesc *)(x))->router_id)
+
+/* Link-LSA */
+struct ospf6_link_lsa
+{
+ u_char priority;
+ u_char options[3];
+ struct in6_addr linklocal_addr;
+ u_int32_t prefix_num;
+ /* followed by ospf6 prefix(es) */
+};
+
+/* Intra-Area-Prefix-LSA */
+struct ospf6_intra_prefix_lsa
+{
+ u_int16_t prefix_num;
+ u_int16_t ref_type;
+ u_int32_t ref_id;
+ u_int32_t ref_adv_router;
+ /* followed by ospf6 prefix(es) */
+};
+
+
+#define OSPF6_ROUTER_LSA_SCHEDULE(oa) \
+ do { \
+ if (! (oa)->thread_router_lsa) \
+ (oa)->thread_router_lsa = \
+ thread_add_event (master, ospf6_router_lsa_originate, oa, 0); \
+ } while (0)
+#define OSPF6_NETWORK_LSA_SCHEDULE(oi) \
+ do { \
+ if (! (oi)->thread_network_lsa) \
+ (oi)->thread_network_lsa = \
+ thread_add_event (master, ospf6_network_lsa_originate, oi, 0); \
+ } while (0)
+#define OSPF6_LINK_LSA_SCHEDULE(oi) \
+ do { \
+ if (! (oi)->thread_link_lsa) \
+ (oi)->thread_link_lsa = \
+ thread_add_event (master, ospf6_link_lsa_originate, oi, 0); \
+ } while (0)
+#define OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oa) \
+ do { \
+ if (! (oa)->thread_intra_prefix_lsa) \
+ (oa)->thread_intra_prefix_lsa = \
+ thread_add_event (master, ospf6_intra_prefix_lsa_originate_stub, \
+ oa, 0); \
+ } while (0)
+#define OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi) \
+ do { \
+ if (! (oi)->thread_intra_prefix_lsa) \
+ (oi)->thread_intra_prefix_lsa = \
+ thread_add_event (master, ospf6_intra_prefix_lsa_originate_transit, \
+ oi, 0); \
+ } while (0)
+
+/* Function Prototypes */
+char *ospf6_router_lsdesc_lookup (u_char type, u_int32_t interface_id,
+ u_int32_t neighbor_interface_id,
+ u_int32_t neighbor_router_id,
+ struct ospf6_lsa *lsa);
+char *ospf6_network_lsdesc_lookup (u_int32_t router_id,
+ struct ospf6_lsa *lsa);
+
+int ospf6_router_lsa_originate (struct thread *);
+int ospf6_network_lsa_originate (struct thread *);
+int ospf6_link_lsa_originate (struct thread *);
+int ospf6_intra_prefix_lsa_originate_transit (struct thread *);
+int ospf6_intra_prefix_lsa_originate_stub (struct thread *);
+void ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa);
+void ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa);
+
+void ospf6_intra_route_calculation (struct ospf6_area *oa);
+void ospf6_intra_asbr_calculation (struct ospf6_area *oa);
void ospf6_intra_init ();
-#endif /* OSPF6_INTRA_H */
+#endif /* OSPF6_LSA_H */
diff --git a/ospf6d/ospf6_ism.c b/ospf6d/ospf6_ism.c
deleted file mode 100644
index bb14604..0000000
--- a/ospf6d/ospf6_ism.c
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- * Copyright (C) 1999 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.
- */
-
-/* Interface State Machine */
-
-#include "ospf6d.h"
-
-int
-ifs_change (state_t ifs_next, char *reason, struct ospf6_interface *o6i)
-{
- state_t ifs_prev;
-
- ifs_prev = o6i->state;
-
- if (ifs_prev == ifs_next)
- return 0;
-
- if (IS_OSPF6_DUMP_INTERFACE)
- zlog_info ("I/F: %s: %s -> %s (%s)",
- o6i->interface->name,
- ospf6_interface_state_string[ifs_prev],
- ospf6_interface_state_string[ifs_next], reason);
-
- if ((ifs_prev == IFS_DR || ifs_prev == IFS_BDR) &&
- (ifs_next != IFS_DR && ifs_next != IFS_BDR))
- ospf6_leave_alldrouters (o6i->interface->ifindex);
- else if ((ifs_prev != IFS_DR && ifs_prev != IFS_BDR) &&
- (ifs_next == IFS_DR || ifs_next == IFS_BDR))
- ospf6_join_alldrouters (o6i->interface->ifindex);
-
- o6i->state = ifs_next;
-
- if (o6i->prevdr != o6i->dr || o6i->prevbdr != o6i->bdr)
- {
- if (IS_OSPF6_DUMP_INTERFACE)
- {
- char dr[16], bdr[16], prevdr[16], prevbdr[16];
- inet_ntop (AF_INET, &o6i->prevdr, prevdr, sizeof (prevdr));
- inet_ntop (AF_INET, &o6i->prevbdr, prevbdr, sizeof (prevbdr));
- inet_ntop (AF_INET, &o6i->dr, dr, sizeof (dr));
- inet_ntop (AF_INET, &o6i->bdr, bdr, sizeof (bdr));
- zlog_info ("I/F: %s: DR: %s -> %s", o6i->interface->name,
- prevdr, dr);
- zlog_info ("I/F: %s: BDR: %s -> %s", o6i->interface->name,
- prevbdr, bdr);
- }
- }
-
- CALL_CHANGE_HOOK (&interface_hook, o6i);
- return 0;
-}
-
-
-/* Interface State Machine */
-int
-interface_up (struct thread *thread)
-{
- struct ospf6_interface *ospf6_interface;
-
- ospf6_interface = (struct ospf6_interface *)THREAD_ARG (thread);
-
- assert (ospf6_interface);
- assert (ospf6_interface->interface);
-
- if (IS_OSPF6_DUMP_INTERFACE)
- zlog_info ("I/F: %s: InterfaceUp",
- ospf6_interface->interface->name);
-
- /* check physical interface is up */
- if (!if_is_up (ospf6_interface->interface))
- {
- if (IS_OSPF6_DUMP_INTERFACE)
- zlog_warn (" interface %s down, can't execute InterfaceUp",
- ospf6_interface->interface->name);
- return -1;
- }
-
- /* if already enabled, do nothing */
- if (ospf6_interface->state > IFS_DOWN)
- {
- zlog_warn ("Interface %s already up",
- ospf6_interface->interface->name);
- return 0;
- }
-
- /* ifid of this interface */
- ospf6_interface->if_id = ospf6_interface->interface->ifindex;
-
- /* Join AllSPFRouters */
- ospf6_join_allspfrouters (ospf6_interface->interface->ifindex);
-
- /* set socket options */
- ospf6_set_reuseaddr ();
- ospf6_reset_mcastloop ();
- ospf6_set_pktinfo ();
- ospf6_set_checksum ();
-
- /* Schedule Hello */
- if (! CHECK_FLAG (ospf6_interface->flag, OSPF6_INTERFACE_FLAG_PASSIVE))
- thread_add_event (master, ospf6_send_hello, ospf6_interface, 0);
-
- /* decide next interface state */
- if (if_is_pointopoint (ospf6_interface->interface))
- ifs_change (IFS_PTOP, "IF Type PointToPoint", ospf6_interface);
- else if (ospf6_interface->priority == 0)
- ifs_change (IFS_DROTHER, "Router Priority = 0", ospf6_interface);
- else
- {
- ifs_change (IFS_WAITING, "Priority > 0", ospf6_interface);
- thread_add_timer (master, wait_timer, ospf6_interface,
- ospf6_interface->dead_interval);
- }
-
- CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, ospf6_interface);
-
- return 0;
-}
-
-int
-wait_timer (struct thread *thread)
-{
- struct ospf6_interface *ospf6_interface;
-
- ospf6_interface = (struct ospf6_interface *)THREAD_ARG (thread);
- assert (ospf6_interface);
-
- if (ospf6_interface->state != IFS_WAITING)
- return 0;
-
- if (IS_OSPF6_DUMP_INTERFACE)
- zlog_info ("I/F: %s: WaitTimer", ospf6_interface->interface->name);
-
- ifs_change (dr_election (ospf6_interface),
- "WaitTimer:DR Election", ospf6_interface);
- return 0;
-}
-
-int backup_seen (struct thread *thread)
-{
- struct ospf6_interface *ospf6_interface;
-
- ospf6_interface = (struct ospf6_interface *)THREAD_ARG (thread);
- assert (ospf6_interface);
-
- if (IS_OSPF6_DUMP_INTERFACE)
- zlog_info ("I/F: %s: BackupSeen", ospf6_interface->interface->name);
-
- if (ospf6_interface->state == IFS_WAITING)
- ifs_change (dr_election (ospf6_interface),
- "BackupSeen:DR Election", ospf6_interface);
-
- return 0;
-}
-
-int neighbor_change (struct thread *thread)
-{
- struct ospf6_interface *ospf6_interface;
-
- ospf6_interface = (struct ospf6_interface *)THREAD_ARG (thread);
- assert (ospf6_interface);
-
- if (ospf6_interface->state != IFS_DROTHER &&
- ospf6_interface->state != IFS_BDR &&
- ospf6_interface->state != IFS_DR)
- return 0;
-
- if (IS_OSPF6_DUMP_INTERFACE)
- zlog_info ("I/F: %s: NeighborChange", ospf6_interface->interface->name);
-
- ifs_change (dr_election (ospf6_interface),
- "NeighborChange:DR Election", ospf6_interface);
-
- return 0;
-}
-
-int
-loopind (struct thread *thread)
-{
- struct ospf6_interface *ospf6_interface;
-
- ospf6_interface = (struct ospf6_interface *)THREAD_ARG (thread);
- assert (ospf6_interface);
-
- if (IS_OSPF6_DUMP_INTERFACE)
- zlog_info ("I/F: %s: LoopInd", ospf6_interface->interface->name);
-
- /* XXX not yet */
-
- return 0;
-}
-
-int
-interface_down (struct thread *thread)
-{
- struct ospf6_interface *ospf6_interface;
-
- ospf6_interface = (struct ospf6_interface *) THREAD_ARG (thread);
- assert (ospf6_interface);
-
- if (IS_OSPF6_DUMP_INTERFACE)
- zlog_info ("I/F: %s: InterfaceDown", ospf6_interface->interface->name);
-
- if (ospf6_interface->state == IFS_NONE)
- return 1;
-
- /* Leave AllSPFRouters */
- if (ospf6_interface_is_enabled (ospf6_interface->interface->ifindex))
- ospf6_leave_allspfrouters (ospf6_interface->interface->ifindex);
-
- ifs_change (IFS_DOWN, "Configured", ospf6_interface);
-
- return 0;
-}
-
-
-/* 9.4 of RFC2328 */
-int
-dr_election (struct ospf6_interface *ospf6_interface)
-{
- list candidate_list = list_new ();
- listnode i, j, n;
- ifid_t prevdr, prevbdr, dr = 0, bdr;
- struct ospf6_neighbor *nbpi, *nbpj, myself, *nbr;
- int declare = 0;
- int gofive = 0;
-
- /* statistics */
- ospf6_interface->ospf6_stat_dr_election++;
-
- /* pseudo neighbor "myself" */
- memset (&myself, 0, sizeof (myself));
- myself.state = NBS_TWOWAY;
- myself.dr = ospf6_interface->dr;
- myself.bdr = ospf6_interface->bdr;
- myself.priority = ospf6_interface->priority;
- myself.ifid = ospf6_interface->if_id;
- myself.router_id = ospf6_interface->area->ospf6->router_id;
-
-/* step_one: */
-
- ospf6_interface->prevdr = prevdr = ospf6_interface->dr;
- ospf6_interface->prevbdr = prevbdr = ospf6_interface->bdr;
-
-step_two:
-
- /* Calculate Backup Designated Router. */
- /* Make Candidate list */
- if (!list_isempty (candidate_list))
- list_delete_all_node (candidate_list);
- declare = 0;
- for (i = listhead (ospf6_interface->neighbor_list); i; nextnode (i))
- {
- nbpi = (struct ospf6_neighbor *)getdata (i);
- if (nbpi->priority == 0)
- continue;
- if (nbpi->state < NBS_TWOWAY)
- continue;
- if (nbpi->dr == nbpi->router_id)
- continue;
- if (nbpi->bdr == nbpi->router_id)
- declare++;
- listnode_add (candidate_list, nbpi);
- }
-
- if (myself.priority)
- {
- if (myself.dr != myself.router_id)
- {
- if (myself.bdr == myself.router_id)
- declare++;
- listnode_add (candidate_list, &myself);
- }
- }
-
- /* Elect BDR */
- for (i = listhead (candidate_list);
- candidate_list->count > 1;
- i = listhead (candidate_list))
- {
- j = i;
- nextnode(j);
- assert (j);
- nbpi = (struct ospf6_neighbor *)getdata (i);
- nbpj = (struct ospf6_neighbor *)getdata (j);
- if (declare)
- {
- int deleted = 0;
- if (nbpi->bdr != nbpi->router_id)
- {
- listnode_delete (candidate_list, nbpi);
- deleted++;
- }
- if (nbpj->bdr != nbpj->router_id)
- {
- listnode_delete (candidate_list, nbpj);
- deleted++;
- }
- if (deleted)
- continue;
- }
- if (nbpi->priority > nbpj->priority)
- {
- listnode_delete (candidate_list, nbpj);
- continue;
- }
- else if (nbpi->priority < nbpj->priority)
- {
- listnode_delete (candidate_list, nbpi);
- continue;
- }
- else /* equal, case of tie */
- {
- if (ntohl (nbpi->router_id) > ntohl (nbpj->router_id))
- {
- listnode_delete (candidate_list, nbpj);
- continue;
- }
- else if (ntohl (nbpi->router_id) < ntohl (nbpj->router_id))
- {
- listnode_delete (candidate_list, nbpi);
- continue;
- }
- else
- assert (0);
- }
- }
-
- if (!list_isempty (candidate_list))
- {
- assert (candidate_list->count == 1);
- n = listhead (candidate_list);
- nbr = (struct ospf6_neighbor *)getdata (n);
- bdr = nbr->router_id;
- }
- else
- bdr = 0;
-
-/* step_three: */
-
- /* Calculate Designated Router. */
- /* Make Candidate list */
- if (!list_isempty (candidate_list))
- list_delete_all_node (candidate_list);
- declare = 0;
- for (i = listhead (ospf6_interface->neighbor_list); i; nextnode (i))
- {
- nbpi = (struct ospf6_neighbor *)getdata (i);
- if (nbpi->priority == 0)
- continue;
- if (nbpi->state < NBS_TWOWAY)
- continue;
- if (nbpi->dr == nbpi->router_id)
- {
- declare++;
- listnode_add (candidate_list, nbpi);
- }
- }
- if (myself.priority)
- {
- if (myself.dr == myself.router_id)
- {
- declare++;
- listnode_add (candidate_list, &myself);
- }
- }
-
- /* Elect DR */
- if (declare == 0)
- {
- assert (list_isempty (candidate_list));
- /* No one declare but candidate_list not empty */
- dr = bdr;
- }
- else
- {
- assert (!list_isempty (candidate_list));
- for (i = listhead (candidate_list);
- candidate_list->count > 1;
- i = listhead (candidate_list))
- {
- j = i;
- nextnode (j);
- assert (j);
- nbpi = (struct ospf6_neighbor *)getdata (i);
- nbpj = (struct ospf6_neighbor *)getdata (j);
-
- if (nbpi->dr != nbpi->router_id)
- {
- list_delete_node (candidate_list, i);
- continue;
- }
- if (nbpj->dr != nbpj->router_id)
- {
- list_delete_node (candidate_list, j);
- continue;
- }
-
- if (nbpi->priority > nbpj->priority)
- {
- list_delete_node (candidate_list, j);
- continue;
- }
- else if (nbpi->priority < nbpj->priority)
- {
- list_delete_node (candidate_list, i);
- continue;
- }
- else /* equal, case of tie */
- {
- if (ntohl (nbpi->router_id) > ntohl (nbpj->router_id))
- {
- list_delete_node (candidate_list, j);
- continue;
- }
- else if (ntohl (nbpi->router_id) < ntohl (nbpj->router_id))
- {
- list_delete_node (candidate_list, i);
- continue;
- }
- else
- {
- zlog_warn ("!!!THE SAME ROUTER ID FOR DIFFERENT NEIGHBOR");
- zlog_warn ("!!!MISCONFIGURATION?");
- list_delete_node (candidate_list, i);
- continue;
- }
- }
- }
- if (!list_isempty (candidate_list))
- {
- assert (candidate_list->count == 1);
- n = listhead (candidate_list);
- nbr = (struct ospf6_neighbor *)getdata (n);
- dr = nbr->router_id;
- }
- else
- assert (0);
- }
-
-/* step_four: */
-
- if (gofive)
- goto step_five;
-
- if (dr != prevdr)
- {
- if ((dr == myself.router_id || prevdr == myself.router_id)
- && !(dr == myself.router_id && prevdr == myself.router_id))
- {
- myself.dr = dr;
- myself.bdr = bdr;
- gofive++;
- goto step_two;
- }
- }
- if (bdr != prevbdr)
- {
- if ((bdr == myself.router_id || prevbdr == myself.router_id)
- && !(bdr == myself.router_id && prevbdr == myself.router_id))
- {
- myself.dr = dr;
- myself.bdr = bdr;
- gofive++;
- goto step_two;
- }
- }
-
-step_five:
-
- ospf6_interface->dr = dr;
- ospf6_interface->bdr = bdr;
-
- if (prevdr != dr || prevbdr != bdr)
- {
- for (i = listhead (ospf6_interface->neighbor_list); i; nextnode (i))
- {
- nbpi = getdata (i);
- if (nbpi->state < NBS_TWOWAY)
- continue;
- /* Schedule or Execute AdjOK. which does "invoke" mean? */
- thread_add_event (master, adj_ok, nbpi, 0);
- }
- }
-
- list_delete (candidate_list);
-
- if (dr == myself.router_id)
- {
- assert (bdr != myself.router_id);
- return IFS_DR;
- }
- else if (bdr == myself.router_id)
- {
- assert (dr != myself.router_id);
- return IFS_BDR;
- }
- else
- return IFS_DROTHER;
-}
-
-
diff --git a/ospf6d/ospf6_ism.h b/ospf6d/ospf6_ism.h
deleted file mode 100644
index 12470d9..0000000
--- a/ospf6d/ospf6_ism.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 1999 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.
- */
-
-#ifndef OSPF6_ISM_H
-#define OSPF6_ISM_H
-
-/* interface state */
-#define IFS_NONE 0
-#define IFS_DOWN 1
-#define IFS_LOOPBACK 2
-#define IFS_WAITING 3
-#define IFS_PTOP 4
-#define IFS_DROTHER 5
-#define IFS_BDR 6
-#define IFS_DR 7
-#define IFS_MAX 8
-
-
-
-/* Function Prototypes */
-/* interface event */
-int interface_up (struct thread *);
-int interface_down (struct thread *);
-int wait_timer (struct thread *);
-int backup_seen (struct thread *);
-int neighbor_change (struct thread *);
-
-
-#include "ospf6_types.h"
-
-int dr_change (struct ospf6_interface *);
-int ifs_change (state_t, char *, struct ospf6_interface *);
-
-#endif /* OSPF6_ISM_H */
-
diff --git a/ospf6d/ospf6_linklist.c b/ospf6d/ospf6_linklist.c
deleted file mode 100644
index 8c17935..0000000
--- a/ospf6d/ospf6_linklist.c
+++ /dev/null
@@ -1,193 +0,0 @@
-
-#include <zebra.h>
-
-#include "ospf6_linklist.h"
-
-static struct linklist_node *
-linklist_lookup_node (void *data, struct linklist *linklist)
-{
- struct linklist_node *node;
-
- for (node = linklist->head; node; node = node->next)
- {
- if (linklist->cmp && (*linklist->cmp) (node->data, data) == 0)
- return node;
- if (node->data == data)
- return node;
- }
-
- return NULL;
-}
-
-void *
-linklist_lookup (void *data, struct linklist *linklist)
-{
- struct linklist_node *node;
-
- node = linklist_lookup_node (data, linklist);
- if (node)
- return node->data;
- return NULL;
-}
-
-int
-linklist_add (void *data, struct linklist *linklist)
-{
- struct linklist_node *node = NULL, *add;
-
- if (linklist_lookup_node (data, linklist))
- return -1;
-
- add = malloc (sizeof (struct linklist_node));
- if (add == NULL)
- return -1;
- memset (add, 0, sizeof (struct linklist_node));
- add->data = data;
-
- if (linklist->cmp)
- {
- for (node = linklist->head; node; node = node->next)
- {
- if ((*linklist->cmp) (node->data, add->data) > 0)
- break;
- }
- }
-
- if (! node)
- {
- /* add to tail */
- if (linklist->tail)
- {
- linklist->tail->next = add;
- add->prev = linklist->tail;
- }
- else
- {
- linklist->head = add;
- add->prev = NULL;
- }
-
- linklist->tail = add;
- add->next = NULL;
- }
- else
- {
- /* insert just before 'node' */
- if (node->prev)
- {
- node->prev->next = add;
- add->prev = node->prev;
- }
- else
- {
- linklist->head = add;
- add->prev = NULL;
- }
-
- add->next = node;
- node->prev = add;
- }
-
- linklist->count++;
- return 0;
-}
-
-int
-linklist_remove (void *data, struct linklist *linklist)
-{
- struct linklist_node *rem;
-
- rem = linklist_lookup_node (data, linklist);
- if (rem == NULL)
- return -1;
-
- if (rem->prev)
- rem->prev->next = rem->next;
- else
- linklist->head = rem->next;
-
- if (rem->next)
- rem->next->prev = rem->prev;
- else
- linklist->tail = rem->prev;
-
- free (rem);
- linklist->count--;
- return 0;
-}
-
-void
-linklist_head (struct linklist *linklist, struct linklist_node *node)
-{
- if (linklist->head == NULL)
- {
- node->prev = NULL;
- node->next = NULL;
- node->data = NULL;
- return;
- }
-
- node->prev = linklist->head->prev;
- node->next = linklist->head->next;
- node->data = linklist->head->data;
-}
-
-int
-linklist_end (struct linklist_node *node)
-{
- if (node->data == NULL && node->next == NULL)
- return 1;
- return 0;
-}
-
-void
-linklist_next (struct linklist_node *node)
-{
- if (node->next == NULL)
- {
- node->prev = NULL;
- node->next = NULL;
- node->data = NULL;
- return;
- }
-
- node->data = node->next->data;
- node->prev = node->next->prev;
- node->next = node->next->next;
-}
-
-struct linklist *
-linklist_create ()
-{
- struct linklist *linklist;
-
- linklist = malloc (sizeof (struct linklist));
- if (linklist == NULL)
- return NULL;
- memset (linklist, 0, sizeof (struct linklist));
-
- return linklist;
-}
-
-void
-linklist_remove_all (struct linklist *linklist)
-{
- struct linklist_node node;
-
- for (linklist_head (linklist, &node); ! linklist_end (&node);
- linklist_next (&node))
- linklist_remove (node.data, linklist);
-}
-
-void
-linklist_delete (struct linklist *linklist)
-{
- linklist_remove_all (linklist);
- assert (linklist->count == 0);
- assert (linklist->head == NULL);
- assert (linklist->tail == NULL);
-
- free (linklist);
-}
-
-
diff --git a/ospf6d/ospf6_linklist.h b/ospf6d/ospf6_linklist.h
deleted file mode 100644
index 6d97899..0000000
--- a/ospf6d/ospf6_linklist.h
+++ /dev/null
@@ -1,35 +0,0 @@
-
-#ifndef _LINKLIST_H_
-#define _LINKLIST_H_
-
-struct linklist_node
-{
- struct linklist_node *prev;
- struct linklist_node *next;
-
- void *data;
-};
-
-struct linklist
-{
- int count;
- struct linklist_node *head;
- struct linklist_node *tail;
-
- int (*cmp) (void *, void *);
-};
-
-void *linklist_lookup (void *data, struct linklist *linklist);
-int linklist_add (void *data, struct linklist *linklist);
-int linklist_remove (void *data, struct linklist *linklist);
-void linklist_remove_all (struct linklist *linklist);
-
-void linklist_head (struct linklist *linklist, struct linklist_node *node);
-int linklist_end (struct linklist_node *node);
-void linklist_next (struct linklist_node *node);
-
-struct linklist *linklist_create ();
-void linklist_delete (struct linklist *);
-
-#endif /*_LINKLIST_H_*/
-
diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c
index 712aa68..13e9a07 100644
--- a/ospf6d/ospf6_lsa.c
+++ b/ospf6d/ospf6_lsa.c
@@ -1,6 +1,5 @@
/*
- * LSA function
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -23,73 +22,56 @@
#include <zebra.h>
/* Include other stuffs */
-#include <lib/version.h>
#include "log.h"
-#include "getopt.h"
#include "linklist.h"
-#include "thread.h"
#include "command.h"
#include "memory.h"
-#include "sockunion.h"
-#include "if.h"
-#include "prefix.h"
-#include "stream.h"
#include "thread.h"
-#include "filter.h"
-#include "zclient.h"
-#include "table.h"
-#include "plist.h"
+#include "ospf6d.h"
#include "ospf6_proto.h"
-#include "ospf6_prefix.h"
#include "ospf6_lsa.h"
#include "ospf6_lsdb.h"
#include "ospf6_message.h"
-#include "ospf6_dump.h"
#include "ospf6_top.h"
#include "ospf6_area.h"
#include "ospf6_interface.h"
#include "ospf6_neighbor.h"
-#include "ospf6_ism.h"
-#include "ospf6_nsm.h"
-#include "ospf6_dbex.h"
-#define HEADER_DEPENDENCY
-#include "ospf6d.h"
-#undef HEADER_DEPENDENCY
+#include "ospf6_flood.h"
-/* test LSAs identity */
-static int
-ospf6_lsa_issame (struct ospf6_lsa_header__ *lsh1,
- struct ospf6_lsa_header__ *lsh2)
+unsigned char conf_debug_ospf6_lsa = 0;
+
+struct ospf6_lstype ospf6_lstype[OSPF6_LSTYPE_SIZE];
+
+char *ospf6_lstype_str[OSPF6_LSTYPE_SIZE] =
+ {"Unknown", "Router", "Network", "Inter-Prefix", "Inter-Router",
+ "AS-External", "Group-Membership", "Type-7", "Link", "Intra-Prefix"};
+
+char *
+ospf6_lstype_name (u_int16_t type)
{
- assert (lsh1 && lsh2);
+ static char buf[8];
+ int index = ntohs (type) & OSPF6_LSTYPE_FCODE_MASK;
- if (lsh1->adv_router != lsh2->adv_router)
- return 0;
+ if (index < OSPF6_LSTYPE_SIZE && ospf6_lstype_str[index])
+ return ospf6_lstype_str[index];
- if (lsh1->id != lsh2->id)
- return 0;
-
- if (lsh1->type != lsh2->type)
- return 0;
-
- return 1;
+ snprintf (buf, sizeof (buf), "0x%04hx", ntohs (type));
+ return buf;
}
/* RFC2328: Section 13.2 */
int
-ospf6_lsa_differ (struct ospf6_lsa *lsa1,
- struct ospf6_lsa *lsa2)
+ospf6_lsa_is_differ (struct ospf6_lsa *lsa1,
+ struct ospf6_lsa *lsa2)
{
- int diff, cmplen;
+ int len;
- if (! ospf6_lsa_issame (lsa1->header, lsa2->header))
- return 1;
+ assert (OSPF6_LSA_IS_SAME (lsa1, lsa2));
- /* check Options field */
- /* xxx */
+ /* XXX, Options ??? */
ospf6_lsa_age_current (lsa1);
ospf6_lsa_age_current (lsa2);
@@ -104,26 +86,26 @@
if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length))
return 1;
- cmplen = ntohs (lsa1->header->length) - sizeof (struct ospf6_lsa_header);
- diff = memcmp (lsa1->header + 1, lsa2->header + 1, cmplen);
-
- return diff;
+ len = ntohs (lsa1->header->length) - sizeof (struct ospf6_lsa_header);
+ return memcmp (lsa1->header + 1, lsa2->header + 1, len);
}
int
-ospf6_lsa_match (u_int16_t type, u_int32_t id, u_int32_t adv_router,
- struct ospf6_lsa_header *lsh)
+ospf6_lsa_is_changed (struct ospf6_lsa *lsa1,
+ struct ospf6_lsa *lsa2)
{
- if (lsh->advrtr != adv_router)
- return 0;
+ int length;
- if (lsh->ls_id != id)
- return 0;
+ if (OSPF6_LSA_IS_MAXAGE (lsa1) ^ OSPF6_LSA_IS_MAXAGE (lsa2))
+ return 1;
+ if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length))
+ return 1;
- if (lsh->type != type)
- return 0;
+ length = OSPF6_LSA_SIZE (lsa1->header) - sizeof (struct ospf6_lsa_header);
+ assert (length > 0);
- return 1;
+ return memcmp (OSPF6_LSA_HEADER_END (lsa1->header),
+ OSPF6_LSA_HEADER_END (lsa2->header), length);
}
/* ospf6 age functions */
@@ -143,7 +125,8 @@
lsa->birth.tv_usec = now.tv_usec;
if (ntohs (lsa->header->age) != MAXAGE)
lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa,
- lsa->birth.tv_sec + MAXAGE - now.tv_sec);
+ MAXAGE + lsa->birth.tv_sec
+ - now.tv_sec);
else
lsa->expire = NULL;
return;
@@ -163,17 +146,14 @@
/* current time */
if (gettimeofday (&now, (struct timezone *)NULL) < 0)
- zlog_warn ("LSA: gettimeofday failed, may fail ages: %s",
+ zlog_warn ("LSA: gettimeofday failed, may fail LSA AGEs: %s",
strerror (errno));
/* calculate age */
ulage = now.tv_sec - lsa->birth.tv_sec;
/* if over MAXAGE, set to it */
- if (ulage > MAXAGE)
- age = MAXAGE;
- else
- age = ulage;
+ age = (ulage > MAXAGE ? MAXAGE : ulage);
lsa->header->age = htons (age);
return age;
@@ -189,22 +169,17 @@
if (age > MAXAGE)
age = MAXAGE;
lsa->header->age = htons (age);
- return;
}
void
ospf6_lsa_premature_aging (struct ospf6_lsa *lsa)
{
/* log */
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("LSA: Premature aging: %s", lsa->str);
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info ("LSA: Premature aging: %s", lsa->name);
- if (lsa->expire)
- thread_cancel (lsa->expire);
- lsa->expire = (struct thread *) NULL;
- if (lsa->refresh)
- thread_cancel (lsa->refresh);
- lsa->refresh = (struct thread *) NULL;
+ THREAD_OFF (lsa->expire);
+ THREAD_OFF (lsa->refresh);
memset (&lsa->birth, 0, sizeof (struct timeval));
thread_execute (master, ospf6_lsa_expire, lsa, 0);
@@ -213,7 +188,7 @@
/* check which is more recent. if a is more recent, return -1;
if the same, return 0; otherwise(b is more recent), return 1 */
int
-ospf6_lsa_check_recent (struct ospf6_lsa *a, struct ospf6_lsa *b)
+ospf6_lsa_compare (struct ospf6_lsa *a, struct ospf6_lsa *b)
{
signed long seqnuma, seqnumb;
u_int16_t cksuma, cksumb;
@@ -221,7 +196,7 @@
assert (a && a->header);
assert (b && b->header);
- assert (ospf6_lsa_issame (a->header, b->header));
+ assert (OSPF6_LSA_IS_SAME (a, b));
seqnuma = ((signed long) ntohl (a->header->seqnum))
- (signed long) INITIAL_SEQUENCE_NUMBER;
@@ -229,8 +204,7 @@
- (signed long) INITIAL_SEQUENCE_NUMBER;
/* compare by sequence number */
- /* xxx, care about LS sequence number wrapping */
- recent_reason = "seqnum";
+ /* XXX, LS sequence number wrapping */
if (seqnuma > seqnumb)
return -1;
else if (seqnuma < seqnumb)
@@ -244,188 +218,89 @@
if (cksuma < cksumb)
return 0;
- /* Age check */
+ /* Update Age */
agea = ospf6_lsa_age_current (a);
ageb = ospf6_lsa_age_current (b);
- /* MaxAge check */
- recent_reason = "max age";
- if (agea == OSPF6_LSA_MAXAGE && ageb != OSPF6_LSA_MAXAGE)
+ /* MaxAge check */
+ if (agea == MAXAGE && ageb != MAXAGE)
return -1;
- else if (agea != OSPF6_LSA_MAXAGE && ageb == OSPF6_LSA_MAXAGE)
+ else if (agea != MAXAGE && ageb == MAXAGE)
return 1;
- recent_reason = "age differ";
- if (agea > ageb && agea - ageb >= OSPF6_LSA_MAXAGEDIFF)
+ /* Age check */
+ if (agea > ageb && agea - ageb >= MAX_AGE_DIFF)
return 1;
- else if (agea < ageb && ageb - agea >= OSPF6_LSA_MAXAGEDIFF)
+ else if (agea < ageb && ageb - agea >= MAX_AGE_DIFF)
return -1;
/* neither recent */
- recent_reason = "the same instance";
return 0;
}
-int
-ospf6_lsa_lsd_num (struct ospf6_lsa_header *lsa_header)
+char *
+ospf6_lsa_printbuf (struct ospf6_lsa *lsa, char *buf, int size)
{
- int ldnum = 0;
- u_int16_t len;
-
- len = ntohs (lsa_header->length);
- len -= sizeof (struct ospf6_lsa_header);
- if (lsa_header->type == htons (OSPF6_LSA_TYPE_ROUTER))
- {
- len -= sizeof (struct ospf6_router_lsa);
- ldnum = len / sizeof (struct ospf6_router_lsd);
- }
- else /* (lsa_header->type == htons (OSPF6_LSA_TYPE_NETWORK)) */
- {
- len -= sizeof (struct ospf6_network_lsa);
- ldnum = len / sizeof (u_int32_t);
- }
-
- return ldnum;
+ char id[16], adv_router[16];
+ inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
+ inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
+ sizeof (adv_router));
+ snprintf (buf, size, "[%s Id:%s Adv:%s]",
+ OSPF6_LSTYPE_NAME (lsa->header->type), id, adv_router);
+ return buf;
}
-void *
-ospf6_lsa_lsd_get (int index, struct ospf6_lsa_header *lsa_header)
+void
+ospf6_lsa_header_print_raw (struct ospf6_lsa_header *header)
{
- void *p;
- struct ospf6_router_lsa *router_lsa;
- struct ospf6_router_lsd *router_lsd;
- struct ospf6_network_lsa *network_lsa;
- struct ospf6_network_lsd *network_lsd;
-
- if (lsa_header->type == htons (OSPF6_LSA_TYPE_ROUTER))
- {
- router_lsa = (struct ospf6_router_lsa *) (lsa_header + 1);
- router_lsd = (struct ospf6_router_lsd *) (router_lsa + 1);
- router_lsd += index;
- p = (void *) router_lsd;
- }
- else if (lsa_header->type == htons (OSPF6_LSA_TYPE_NETWORK))
- {
- network_lsa = (struct ospf6_network_lsa *) (lsa_header + 1);
- network_lsd = (struct ospf6_network_lsd *) (network_lsa + 1);
- network_lsd += index;
- p = (void *) network_lsd;
- }
- else
- {
- p = (void *) NULL;
- }
-
- return p;
+ char id[16], adv_router[16];
+ inet_ntop (AF_INET, &header->id, id, sizeof (id));
+ inet_ntop (AF_INET, &header->adv_router, adv_router,
+ sizeof (adv_router));
+ zlog_info (" [%s Id:%s Adv:%s]",
+ OSPF6_LSTYPE_NAME (header->type), id, adv_router);
+ zlog_info (" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
+ ntohs (header->age), (u_long) ntohl (header->seqnum),
+ ntohs (header->checksum), ntohs (header->length));
}
-/* network_lsd <-> router_lsd */
-static int
-ospf6_lsa_lsd_network_reference_match (struct ospf6_network_lsd *network_lsd1,
- struct ospf6_lsa_header *lsa_header1,
- struct ospf6_router_lsd *router_lsd2,
- struct ospf6_lsa_header *lsa_header2)
+void
+ospf6_lsa_header_print (struct ospf6_lsa *lsa)
{
- if (network_lsd1->adv_router != lsa_header2->advrtr)
- return 0;
- if (router_lsd2->type != OSPF6_ROUTER_LSD_TYPE_TRANSIT_NETWORK)
- return 0;
- if (router_lsd2->neighbor_router_id != lsa_header1->advrtr)
- return 0;
- if (router_lsd2->neighbor_interface_id != lsa_header1->ls_id)
- return 0;
- return 1;
-}
-
-/* router_lsd <-> router_lsd */
-static int
-ospf6_lsa_lsd_router_reference_match (struct ospf6_router_lsd *router_lsd1,
- struct ospf6_lsa_header *lsa_header1,
- struct ospf6_router_lsd *router_lsd2,
- struct ospf6_lsa_header *lsa_header2)
-{
- if (router_lsd1->type != OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT)
- return 0;
- if (router_lsd2->type != OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT)
- return 0;
- if (router_lsd1->neighbor_router_id != lsa_header2->advrtr)
- return 0;
- if (router_lsd2->neighbor_router_id != lsa_header1->advrtr)
- return 0;
- if (router_lsd1->neighbor_interface_id != router_lsd2->interface_id)
- return 0;
- if (router_lsd2->neighbor_interface_id != router_lsd1->interface_id)
- return 0;
- return 1;
-}
-
-int
-ospf6_lsa_lsd_is_refer_ok (int index1, struct ospf6_lsa_header *lsa_header1,
- int index2, struct ospf6_lsa_header *lsa_header2)
-{
- struct ospf6_router_lsd *r1, *r2;
- struct ospf6_network_lsd *n;
-
- r1 = (struct ospf6_router_lsd *) NULL;
- r2 = (struct ospf6_router_lsd *) NULL;
- n = (struct ospf6_network_lsd *) NULL;
- if (lsa_header1->type == htons (OSPF6_LSA_TYPE_ROUTER))
- r1 = (struct ospf6_router_lsd *) ospf6_lsa_lsd_get (index1, lsa_header1);
- else
- n = (struct ospf6_network_lsd *) ospf6_lsa_lsd_get (index1, lsa_header1);
-
- if (lsa_header2->type == htons (OSPF6_LSA_TYPE_ROUTER))
- r2 = (struct ospf6_router_lsd *) ospf6_lsa_lsd_get (index2, lsa_header2);
- else
- n = (struct ospf6_network_lsd *) ospf6_lsa_lsd_get (index2, lsa_header2);
-
- if (r1 && r2)
- return ospf6_lsa_lsd_router_reference_match (r1, lsa_header1,
- r2, lsa_header2);
- else if (r1 && n)
- return ospf6_lsa_lsd_network_reference_match (n, lsa_header2,
- r1, lsa_header1);
- else if (n && r2)
- return ospf6_lsa_lsd_network_reference_match (n, lsa_header1,
- r2, lsa_header2);
- return 0;
+ ospf6_lsa_age_current (lsa);
+ ospf6_lsa_header_print_raw (lsa->header);
}
void
ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
{
- char adv_router[64], id[64], type[32];
+ char adv_router[64], id[64];
+ int index;
- assert (lsa);
- assert (lsa->header);
+ assert (lsa && lsa->header);
- ospf6_lsa_type_string (lsa->header->type, type, sizeof (type));
inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
inet_ntop (AF_INET, &lsa->header->adv_router,
adv_router, sizeof (adv_router));
vty_out (vty, "%s", VTY_NEWLINE);
vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
- type, VTY_NEWLINE);
+ OSPF6_LSTYPE_NAME (lsa->header->type), VTY_NEWLINE);
vty_out (vty, "Link State ID: %s%s", id, VTY_NEWLINE);
vty_out (vty, "Advertising Router: %s%s", adv_router, VTY_NEWLINE);
- vty_out (vty, "LS Sequence Number: %#lx%s", (u_long)ntohl (lsa->header->seqnum),
- VTY_NEWLINE);
- vty_out (vty, "CheckSum: %#hx Length: %hu%s", ntohs (lsa->header->checksum),
+ vty_out (vty, "LS Sequence Number: %#010lx%s",
+ (u_long) ntohl (lsa->header->seqnum), VTY_NEWLINE);
+ vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
+ ntohs (lsa->header->checksum),
ntohs (lsa->header->length), VTY_NEWLINE);
- {
- struct ospf6_lsa_slot *slot;
- slot = ospf6_lsa_slot_get (lsa->header->type);
- if (slot)
- {
- (*slot->func_show) (vty, lsa);
- vty_out (vty, "%s", VTY_NEWLINE);
- return;
- }
- }
+ index = OSPF6_LSTYPE_INDEX (ntohs (lsa->header->type));
+ if (ospf6_lstype[index].show)
+ (*ospf6_lstype[index].show) (vty, lsa);
+ else
+ vty_out (vty, "%sUnknown LSA type ...%s", VTY_NEWLINE, VTY_NEWLINE);
- vty_out (vty, "%sUnknown LSA type ...%s", VTY_NEWLINE, VTY_NEWLINE);
+ vty_out (vty, "%s", VTY_NEWLINE);
}
void
@@ -439,25 +314,24 @@
void
ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa)
{
- char adv_router[16], id[16], type[16];
+ char adv_router[16], id[16];
struct timeval now, res;
char duration[16];
assert (lsa);
assert (lsa->header);
- memset (type, 0, sizeof (type));
- ospf6_lsa_type_string (lsa->header->type, type, 13);
inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
sizeof (adv_router));
gettimeofday (&now, NULL);
- ospf6_timeval_sub (&now, &lsa->installed, &res);
- ospf6_timeval_string_summary (&res, duration, sizeof (duration));
+ timersub (&now, &lsa->installed, &res);
+ timerstring (&res, duration, sizeof (duration));
vty_out (vty, "%-12s %-15s %-15s %4hu %8lx %04hx %4hu %8s%s",
- type, id, adv_router, ospf6_lsa_age_current (lsa),
+ OSPF6_LSTYPE_NAME (lsa->header->type),
+ id, adv_router, ospf6_lsa_age_current (lsa),
(u_long) ntohl (lsa->header->seqnum),
ntohs (lsa->header->checksum), ntohs (lsa->header->length),
duration, VTY_NEWLINE);
@@ -473,7 +347,7 @@
end = (char *) lsa->header + ntohs (lsa->header->length);
vty_out (vty, "%s", VTY_NEWLINE);
- vty_out (vty, "%s:%s", lsa->str, VTY_NEWLINE);
+ vty_out (vty, "%s:%s", lsa->name, VTY_NEWLINE);
for (current = start; current < end; current ++)
{
@@ -489,149 +363,136 @@
vty_out (vty, "%s%s", VTY_NEWLINE, VTY_NEWLINE);
}
+void
+ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa)
+{
+ char adv_router[64], id[64];
+
+ assert (lsa && lsa->header);
+
+ inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
+ inet_ntop (AF_INET, &lsa->header->adv_router,
+ adv_router, sizeof (adv_router));
+
+ vty_out (vty, "%s", VTY_NEWLINE);
+ vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
+ OSPF6_LSTYPE_NAME (lsa->header->type), VTY_NEWLINE);
+ vty_out (vty, "Link State ID: %s%s", id, VTY_NEWLINE);
+ vty_out (vty, "Advertising Router: %s%s", adv_router, VTY_NEWLINE);
+ vty_out (vty, "LS Sequence Number: %#010lx%s",
+ (u_long) ntohl (lsa->header->seqnum), VTY_NEWLINE);
+ vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
+ ntohs (lsa->header->checksum),
+ ntohs (lsa->header->length), VTY_NEWLINE);
+ vty_out (vty, " Prev: %p This: %p Next: %p%s",
+ lsa->prev, lsa, lsa->next, VTY_NEWLINE);
+ vty_out (vty, " Reference count: %ld%s", lsa->refcnt, VTY_NEWLINE);
+ vty_out (vty, " Reference source: %s (%p) %s",
+ (lsa->refsrc ? lsa->refsrc->name : "None"),
+ lsa->refsrc, VTY_NEWLINE);
+ vty_out (vty, "%s", VTY_NEWLINE);
+}
+
/* OSPFv3 LSA creation/deletion function */
/* calculate LS sequence number for my new LSA.
return value is network byte order */
-static signed long
-ospf6_lsa_seqnum_new (u_int16_t type, u_int32_t id, u_int32_t adv_router,
+u_int32_t
+ospf6_lsa_new_seqnum (u_int16_t type, u_int32_t id, u_int32_t adv_router,
void *scope)
{
+ struct ospf6_lsdb *lsdb = NULL;
struct ospf6_lsa *lsa;
- signed long seqnum;
+ signed long seqnum = 0;
/* get current database copy */
- lsa = ospf6_lsdb_lookup (type, id, adv_router, scope);
+ lsdb = ospf6_get_scoped_lsdb (type, scope);
+ if (lsdb == NULL)
+ {
+ zlog_warn ("Can't decide scoped LSDB");
+ return ((u_int32_t) htonl (INITIAL_SEQUENCE_NUMBER));
+ }
/* if current database copy not found, return InitialSequenceNumber */
- if (!lsa)
+ lsa = ospf6_lsdb_lookup (type, id, adv_router, lsdb);
+ if (lsa == NULL)
seqnum = INITIAL_SEQUENCE_NUMBER;
else
seqnum = (signed long) ntohl (lsa->header->seqnum) + 1;
- return (htonl (seqnum));
+ return ((u_int32_t) htonl (seqnum));
}
-#if 0
-static void
-ospf6_lsa_header_set (u_int16_t type, u_int32_t ls_id, u_int32_t advrtr,
- struct ospf6_lsa_header *lsa_header, int bodysize)
-{
- /* fill LSA header */
- lsa_header->age = 0;
- lsa_header->type = type;
- lsa_header->ls_id = ls_id;
- lsa_header->advrtr = advrtr;
- lsa_header->seqnum =
- ospf6_lsa_seqnum_new (lsa_header->type, lsa_header->ls_id,
- lsa_header->advrtr);
- lsa_header->length = htons (sizeof (struct ospf6_lsa_header) + bodysize);
-
- /* LSA checksum */
- ospf6_lsa_checksum (lsa_header);
-}
-#endif /*0*/
-
struct ospf6_lsa *
-ospf6_lsa_create (struct ospf6_lsa_header *source)
+ospf6_lsa_create (struct ospf6_lsa_header *header)
{
struct ospf6_lsa *lsa = NULL;
- struct ospf6_lsa_header *lsa_header = NULL;
+ struct ospf6_lsa_header *new_header = NULL;
u_int16_t lsa_size = 0;
- char buf_router[16], buf_id[16], typebuf[32];
- /* whole length of this LSA */
- lsa_size = ntohs (source->length);
+ /* size of the entire LSA */
+ lsa_size = ntohs (header->length); /* XXX vulnerable */
/* allocate memory for this LSA */
- lsa_header = (struct ospf6_lsa_header *)
+ new_header = (struct ospf6_lsa_header *)
XMALLOC (MTYPE_OSPF6_LSA, lsa_size);
- if (! lsa_header)
- {
- zlog_err ("Can't allocate memory for LSA Header");
- return (struct ospf6_lsa *) NULL;
- }
- memset (lsa_header, 0, lsa_size);
- /* copy LSA from source */
- memcpy (lsa_header, source, lsa_size);
+ /* copy LSA from original header */
+ memcpy (new_header, header, lsa_size);
/* LSA information structure */
/* allocate memory */
lsa = (struct ospf6_lsa *)
- XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
+ XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
memset (lsa, 0, sizeof (struct ospf6_lsa));
- lsa->lsa_hdr = (struct ospf6_lsa_hdr *) lsa_header;
- lsa->header = (struct ospf6_lsa_header__ *) lsa_header;
-
- lsa->summary = 0; /* this is not LSA summary */
+ lsa->header = (struct ospf6_lsa_header *) new_header;
+ lsa->headeronly = 0; /* this is not header only */
/* dump string */
- inet_ntop (AF_INET, &lsa->header->id, buf_id, sizeof (buf_id));
- inet_ntop (AF_INET, &lsa->header->adv_router, buf_router,
- sizeof (buf_router));
- snprintf (lsa->str, sizeof (lsa->str), "[%s ID=%s Adv=%s]",
- ospf6_lsa_type_string (lsa_header->type, typebuf,
- sizeof (typebuf)),
- buf_id, buf_router);
+ ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
/* calculate birth, expire and refresh of this lsa */
ospf6_lsa_age_set (lsa);
-#ifdef DEBUG
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("Create: %s (%p/%p)", lsa->str, lsa, lsa->header);
-#endif /*DEBUG*/
+ if (IS_OSPF6_DEBUG_LSA (MEMORY))
+ zlog_info ("Create LSA Memory: %s (%p/%p)",
+ lsa->name, lsa, lsa->header);
return lsa;
}
struct ospf6_lsa *
-ospf6_lsa_summary_create (struct ospf6_lsa_header__ *source)
+ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header)
{
struct ospf6_lsa *lsa = NULL;
- struct ospf6_lsa_header *lsa_header = NULL;
- u_int16_t lsa_size = 0;
- char buf_router[16], buf_id[16], typebuf[16];
-
- /* LSA summary contains LSA Header only */
- lsa_size = sizeof (struct ospf6_lsa_header);
+ struct ospf6_lsa_header *new_header = NULL;
/* allocate memory for this LSA */
- lsa_header = (struct ospf6_lsa_header *)
- XMALLOC (MTYPE_OSPF6_LSA_SUMMARY, lsa_size);
- memset (lsa_header, 0, lsa_size);
+ new_header = (struct ospf6_lsa_header *)
+ XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa_header));
- /* copy LSA from source */
- memcpy (lsa_header, source, lsa_size);
+ /* copy LSA from original header */
+ memcpy (new_header, header, sizeof (struct ospf6_lsa_header));
/* LSA information structure */
/* allocate memory */
lsa = (struct ospf6_lsa *)
- XMALLOC (MTYPE_OSPF6_LSA_SUMMARY, sizeof (struct ospf6_lsa));
+ XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
memset (lsa, 0, sizeof (struct ospf6_lsa));
- lsa->lsa_hdr = (struct ospf6_lsa_hdr *) lsa_header;
- lsa->header = (struct ospf6_lsa_header__ *) lsa_header;
- lsa->summary = 1; /* this is LSA summary */
+ lsa->header = (struct ospf6_lsa_header *) new_header;
+ lsa->headeronly = 1; /* this is header only */
/* dump string */
- inet_ntop (AF_INET, &lsa->header->id, buf_id, sizeof (buf_id));
- inet_ntop (AF_INET, &lsa->header->adv_router, buf_router,
- sizeof (buf_router));
- snprintf (lsa->str, sizeof (lsa->str), "[%s Summary ID=%s Adv=%s]",
- ospf6_lsa_type_string (lsa->header->type, typebuf,
- sizeof (typebuf)),
- buf_id, buf_router);
+ ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
/* calculate birth, expire and refresh of this lsa */
ospf6_lsa_age_set (lsa);
-#ifdef DEBUG
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("Create: %s (%p/%p)", lsa->str, lsa, lsa->header);
-#endif /*DEBUG*/
+ if (IS_OSPF6_DEBUG_LSA (MEMORY))
+ zlog_info ("Create LSA (Header-only) Memory: %s (%p/%p)",
+ lsa->name, lsa, lsa->header);
return lsa;
}
@@ -639,40 +500,48 @@
void
ospf6_lsa_delete (struct ospf6_lsa *lsa)
{
- /* just to make sure */
- if (lsa->lock != 0)
- {
- zlog_err ("Can't delete %s: lock: %ld", lsa->str, lsa->lock);
- return;
- }
+ assert (lsa->lock == 0);
/* cancel threads */
- if (lsa->expire)
- thread_cancel (lsa->expire);
- lsa->expire = (struct thread *) NULL;
- if (lsa->refresh)
- thread_cancel (lsa->refresh);
- lsa->refresh = (struct thread *) NULL;
+ THREAD_OFF (lsa->expire);
+ THREAD_OFF (lsa->refresh);
-#ifdef DEBUG
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("Delete %s (%p/%p)", lsa->str, lsa, lsa->header);
-#endif /*DEBUG*/
+ if (IS_OSPF6_DEBUG_LSA (MEMORY))
+ zlog_info ("Delete LSA %s Memory: %s (%p/%p)",
+ (lsa->headeronly ? "(Header-only) " : ""),
+ lsa->name, lsa, lsa->header);
/* do free */
- if (lsa->summary)
- XFREE (MTYPE_OSPF6_LSA_SUMMARY, lsa->header);
- else
- XFREE (MTYPE_OSPF6_LSA, lsa->header);
- lsa->header = NULL;
-
- if (lsa->summary)
- XFREE (MTYPE_OSPF6_LSA_SUMMARY, lsa);
- else
- XFREE (MTYPE_OSPF6_LSA, lsa);
+ XFREE (MTYPE_OSPF6_LSA, lsa->header);
+ XFREE (MTYPE_OSPF6_LSA, lsa);
}
-/* increment reference counter of struct ospf6_lsa */
+struct ospf6_lsa *
+ospf6_lsa_copy (struct ospf6_lsa *lsa)
+{
+ struct ospf6_lsa *copy = NULL;
+
+ if (IS_OSPF6_DEBUG_LSA (MEMORY))
+ zlog_info ("Create LSA Copy from %s", lsa->name);
+
+ ospf6_lsa_age_current (lsa);
+ if (lsa->headeronly)
+ copy = ospf6_lsa_create_headeronly (lsa->header);
+ else
+ copy = ospf6_lsa_create (lsa->header);
+ assert (copy->lock == 0);
+
+ copy->installed = lsa->installed;
+ copy->originated = lsa->originated;
+ copy->scope = lsa->scope;
+
+ copy->refsrc = lsa;
+ copy->refsrc->refcnt++;
+
+ return copy;
+}
+
+/* increment reference counter of struct ospf6_lsa */
void
ospf6_lsa_lock (struct ospf6_lsa *lsa)
{
@@ -680,163 +549,156 @@
return;
}
-/* decrement reference counter of struct ospf6_lsa */
+/* decrement reference counter of struct ospf6_lsa */
void
ospf6_lsa_unlock (struct ospf6_lsa *lsa)
{
/* decrement reference counter */
- if (lsa->lock > 0)
- lsa->lock--;
- else
- zlog_warn ("Can't unlock %s: already no lock", lsa->str);
+ assert (lsa->lock > 0);
+ lsa->lock--;
- if (lsa->lock == 0)
- ospf6_lsa_delete (lsa);
+ if (lsa->lock != 0)
+ return;
+
+ if (lsa->refsrc)
+ lsa->refsrc->refcnt--;
+
+ ospf6_lsa_delete (lsa);
}
void
-ospf6_lsa_originate (u_int16_t type, u_int32_t id, u_int32_t adv_router,
- char *data, int data_len, void *scope)
+ospf6_lsa_originate (struct ospf6_lsa *lsa)
{
- char buffer[MAXLSASIZE];
- struct ospf6_lsa_header *lsa_header;
- struct ospf6_lsa *lsa;
struct ospf6_lsa *old;
-
- assert (data_len <= sizeof (buffer) - sizeof (struct ospf6_lsa_header));
-
- lsa_header = (struct ospf6_lsa_header *) buffer;
-
- /* Copy LSA Body */
- memcpy (buffer + sizeof (struct ospf6_lsa_header), data, data_len);
-
- /* Fill LSA Header */
- lsa_header->age = 0;
- lsa_header->type = type;
- lsa_header->ls_id = id;
- lsa_header->advrtr = adv_router;
- lsa_header->seqnum =
- ospf6_lsa_seqnum_new (lsa_header->type, lsa_header->ls_id,
- lsa_header->advrtr, scope);
- lsa_header->length = htons (sizeof (struct ospf6_lsa_header) + data_len);
-
- /* LSA checksum */
- ospf6_lsa_checksum (lsa_header);
-
- /* create LSA */
- lsa = ospf6_lsa_create ((struct ospf6_lsa_header *) buffer);
- lsa->scope = scope;
+ struct ospf6_lsdb *lsdb = NULL;
/* find previous LSA */
+ lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
+ if (lsdb == NULL)
+ {
+ zlog_warn ("Can't decide scoped LSDB");
+ ospf6_lsa_delete (lsa);
+ return;
+ }
+
old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
- lsa->header->adv_router, lsa->scope);
+ lsa->header->adv_router, lsdb);
if (old)
{
- /* Check if this is neither different instance nor refresh, return */
- if (! CHECK_FLAG (old->flag, OSPF6_LSA_FLAG_REFRESH) &&
- ! ospf6_lsa_differ (lsa, old))
+ /* If this origination is neither different instance nor refresh,
+ suppress this origination */
+ if (! CHECK_FLAG (old->flag, OSPF6_LSA_REFRESH) &&
+ ! OSPF6_LSA_IS_DIFFER (lsa, old))
{
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("LSA: Suppress updating %s", lsa->str);
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ zlog_info ("Suppress updating LSA: %s", lsa->name);
ospf6_lsa_delete (lsa);
return;
}
}
lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
- OSPF6_LS_REFRESH_TIME);
- gettimeofday (&lsa->originated, NULL);
+ LS_REFRESH_TIME);
- //if (IS_OSPF6_DUMP_LSA)
- zlog_info ("LSA: originate %s seq: %#x age: %hu %ld.%06ld",
- lsa->str, ntohl (lsa->header->seqnum),
- ospf6_lsa_age_current (lsa),
- lsa->originated.tv_sec, lsa->originated.tv_usec);
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ {
+ zlog_info ("LSA Originate:");
+ ospf6_lsa_header_print (lsa);
+ }
- ospf6_dbex_remove_from_all_retrans_list (lsa);
- ospf6_dbex_flood (lsa, NULL);
- ospf6_lsdb_install (lsa);
+ if (old)
+ ospf6_flood_clear (old);
+ ospf6_flood_lsa (lsa, NULL);
+ ospf6_install_lsa (lsa, lsdb);
+}
+
+void
+ospf6_lsa_re_originate (struct ospf6_lsa *lsa)
+{
+ u_int16_t index;
+
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ {
+ zlog_info ("LSA Reoriginate:");
+ ospf6_lsa_header_print (lsa);
+ }
+
+ index = OSPF6_LSTYPE_INDEX (ntohs (lsa->header->type));
+ if (ospf6_lstype[index].reoriginate)
+ (*ospf6_lstype[index].reoriginate) (lsa);
+ else
+ ospf6_lsa_premature_aging (lsa);
}
-/* ospf6_lsa expired */
+/* ospf6 lsa expiry */
int
ospf6_lsa_expire (struct thread *thread)
{
struct ospf6_lsa *lsa;
struct ospf6_lsdb *lsdb = NULL;
- void (*hook) (struct ospf6_lsa *, struct ospf6_lsa *);
lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
- assert (lsa && lsa->lsa_hdr);
- /* assertion */
- assert (IS_LSA_MAXAGE (lsa));
- assert (!lsa->refresh);
+ assert (lsa && lsa->header);
+ assert (OSPF6_LSA_IS_MAXAGE (lsa));
+ assert (! lsa->refresh);
lsa->expire = (struct thread *) NULL;
- /* log */
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("LSA: Expire: %s", lsa->str);
-
- if (!lsa->summary)
+ if (IS_OSPF6_DEBUG_LSA (TIMER))
{
- /* reflood lsa */
- ospf6_dbex_flood (lsa, NULL);
-
- /* get scoped lsdb, call remove hook */
- if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (ntohs (lsa->header->type)))
- lsdb = ((struct ospf6_interface *) lsa->scope)->lsdb;
- else if (OSPF6_LSA_IS_SCOPE_AREA (ntohs (lsa->header->type)))
- lsdb = ((struct ospf6_area *) lsa->scope)->lsdb;
- else if (OSPF6_LSA_IS_SCOPE_AS (ntohs (lsa->header->type)))
- lsdb = ((struct ospf6 *) lsa->scope)->lsdb;
- else
- assert (0);
-
- /* call LSDB hook to re-process LSA */
- hook = ospf6_lsdb_hook[ntohs (lsa->header->type) &
- OSPF6_LSTYPE_CODE_MASK].hook;
- if (hook)
- (*hook) (NULL, lsa);
-
- /* do not free LSA, and do nothing about lslists.
- wait event (ospf6_lsdb_check_maxage) */
+ zlog_info ("LSA Expire:");
+ ospf6_lsa_header_print (lsa);
}
+ if (lsa->headeronly)
+ return 0; /* dbexchange will do something ... */
+
+ /* reflood lsa */
+ ospf6_flood_lsa (lsa, NULL);
+
+ /* reinstall lsa */
+ lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
+ if (lsdb == NULL)
+ {
+ zlog_warn ("Can't decide scoped LSDB: %s", lsa->name);
+ return 0;
+ }
+ if (IS_OSPF6_DEBUG_LSA (DATABASE))
+ zlog_info ("Reinstall MaxAge %s", lsa->name);
+ ospf6_lsdb_add (lsa, lsdb);
+
+ /* schedule maxage remover */
+ ospf6_maxage_remove (ospf6);
+
return 0;
}
+/* Below will become dummy thread.
+ refresh function must be set individually per each LSAs */
int
ospf6_lsa_refresh (struct thread *thread)
{
struct ospf6_lsa *lsa;
- struct ospf6_lsa_slot *slot;
assert (thread);
- lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
- assert (lsa && lsa->lsa_hdr);
+ lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
+ assert (lsa && lsa->header);
- /* this will be used later as flag to decide really originate */
lsa->refresh = (struct thread *) NULL;
- SET_FLAG (lsa->flag, OSPF6_LSA_FLAG_REFRESH);
- /* log */
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("LSA Refresh: %s", lsa->str);
+ /* this will be used later to decide really originate or not */
+ SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
- slot = ospf6_lsa_slot_get (lsa->header->type);
- if (slot)
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
{
- zlog_info ("LSA Refresh: %s", slot->name);
- (*slot->func_refresh) (lsa);
- return 0;
+ zlog_info ("LSA Refresh:");
+ ospf6_lsa_header_print (lsa);
}
- zlog_warn ("Can't Refresh LSA: Unknown type: %#x",
- ntohs (lsa->header->type));
- return 1;
+ ospf6_lsa_re_originate (lsa);
+ return 0;
}
@@ -885,1042 +747,205 @@
}
int
-ospf6_lsa_is_known_type (struct ospf6_lsa_header *lsa_header)
+ospf6_unknown_reoriginate (struct ospf6_lsa *lsa)
{
- struct ospf6_lsa_slot *slot;
-
- slot = ospf6_lsa_slot_get (lsa_header->type);
- if (slot)
- return 1;
- return 0;
-}
-
-struct ospf6_lsa_slot *slot_head = NULL;
-
-struct ospf6_lsa_slot *
-ospf6_lsa_slot_get (u_int16_t type)
-{
- struct ospf6_lsa_slot *slot;
-
- for (slot = slot_head; slot; slot = slot->next)
- {
- if (slot->type == type)
- return slot;
- }
-
- return NULL;
-}
-
-int
-ospf6_lsa_slot_register (struct ospf6_lsa_slot *src)
-{
- struct ospf6_lsa_slot *new, *slot;
-
- slot = ospf6_lsa_slot_get (src->type);
- if (slot)
- {
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("LSA: Slot register: already exists: %#x %s",
- slot->type, slot->name);
- return -1;
- }
-
- new = (struct ospf6_lsa_slot *)
- XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa_slot));
- if (! new)
- {
- zlog_err ("Can't allocate memory for LSA slot: %s", strerror (errno));
- return -1;
- }
- memset (new, 0, sizeof (struct ospf6_lsa_slot));
- memcpy (new, src, sizeof (struct ospf6_lsa_slot));
-
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("LSA: Slot register: %#x %s", slot->type, slot->name);
-
- if (slot_head == NULL)
- {
- new->prev = NULL;
- new->next = NULL;
- slot_head = new;
- return 0;
- }
-
- slot = slot_head;
- while (slot->next)
- slot = slot->next;
-
- slot->next = new;
- new->prev = slot;
-
+ ospf6_lsa_premature_aging (lsa);
return 0;
}
int
-ospf6_lsa_slot_unregister (u_int16_t type)
+ospf6_unknown_show (struct vty *vty, struct ospf6_lsa *lsa)
{
- struct ospf6_lsa_slot *slot;
+ u_char *start, *end, *current;
+ char byte[4];
- slot = ospf6_lsa_slot_get (type);
- if (slot == NULL)
- {
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("Registering LSA slot: no such slot: %#x", type);
- return -1;
- }
-
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("Unregistering LSA Slot: %#x %s", slot->type, slot->name);
-
- if (slot->prev)
- slot->prev->next = slot->next;
- if (slot->next)
- slot->next->prev = slot->prev;
-
- if (slot_head == slot)
- slot_head = slot->next;
-
- XFREE (MTYPE_OSPF6_LSA, slot);
- return 0;
-}
-
-char *
-ospf6_lsa_type_string (u_int16_t type, char *buf, int bufsize)
-{
- struct ospf6_lsa_slot *slot;
-
- slot = ospf6_lsa_slot_get (type);
- if (slot)
- snprintf (buf, bufsize, "%s", slot->name);
- else
- snprintf (buf, bufsize, "Type=0x%04x", ntohs (type));
-
- return buf;
-}
-
-
-/*******************/
-/* LSA Origination */
-/*******************/
-
-#define CONTINUE_IF_ADDRESS_LINKLOCAL(addr)\
- if (IN6_IS_ADDR_LINKLOCAL (&(addr)->u.prefix6))\
- {\
- char buf[64];\
- prefix2str (addr, buf, sizeof (buf));\
- if (IS_OSPF6_DUMP_LSA)\
- zlog_info (" Filter out Linklocal: %s", buf);\
- continue;\
- }
-
-#define CONTINUE_IF_ADDRESS_UNSPECIFIED(addr)\
- if (IN6_IS_ADDR_UNSPECIFIED (&(addr)->u.prefix6))\
- {\
- char buf[64];\
- prefix2str (addr, buf, sizeof (buf));\
- if (IS_OSPF6_DUMP_LSA)\
- zlog_info (" Filter out Unspecified: %s", buf);\
- continue;\
- }
-
-#define CONTINUE_IF_ADDRESS_LOOPBACK(addr)\
- if (IN6_IS_ADDR_LOOPBACK (&(addr)->u.prefix6))\
- {\
- char buf[64];\
- prefix2str (addr, buf, sizeof (buf));\
- if (IS_OSPF6_DUMP_LSA)\
- zlog_info (" Filter out Loopback: %s", buf);\
- continue;\
- }
-
-#define CONTINUE_IF_ADDRESS_V4COMPAT(addr)\
- if (IN6_IS_ADDR_V4COMPAT (&(addr)->u.prefix6))\
- {\
- char buf[64];\
- prefix2str (addr, buf, sizeof (buf));\
- if (IS_OSPF6_DUMP_LSA)\
- zlog_info (" Filter out V4Compat: %s", buf);\
- continue;\
- }
-
-#define CONTINUE_IF_ADDRESS_V4MAPPED(addr)\
- if (IN6_IS_ADDR_V4MAPPED (&(addr)->u.prefix6))\
- {\
- char buf[64];\
- prefix2str (addr, buf, sizeof (buf));\
- if (IS_OSPF6_DUMP_LSA)\
- zlog_info (" Filter out V4Mapped: %s", buf);\
- continue;\
- }
-
-/******************************/
-/* RFC2740 3.4.3.1 Router-LSA */
-/******************************/
-
-char *
-ospf6_lsa_router_bits_string (u_char router_bits, char *buf, int size)
-{
- char w, v, e, b;
-
- w = (router_bits & OSPF6_ROUTER_LSA_BIT_W ? 'W' : '-');
- v = (router_bits & OSPF6_ROUTER_LSA_BIT_V ? 'V' : '-');
- e = (router_bits & OSPF6_ROUTER_LSA_BIT_E ? 'E' : '-');
- b = (router_bits & OSPF6_ROUTER_LSA_BIT_B ? 'B' : '-');
- snprintf (buf, size, "----%c%c%c%c", w, v, e, b);
- return buf;
-}
-
-int
-ospf6_lsa_router_show (struct vty *vty, struct ospf6_lsa *lsa)
-{
- char *start, *end, *current;
- char buf[32], name[32], bits[32], options[32];
- struct ospf6_router_lsa *router_lsa;
- struct ospf6_router_lsd *lsdesc;
-
- assert (lsa->header);
-
- router_lsa = (struct ospf6_router_lsa *)
- ((char *) lsa->header + sizeof (struct ospf6_lsa_header));
-
- ospf6_lsa_router_bits_string (router_lsa->bits, bits, sizeof (bits));
- ospf6_options_string (router_lsa->options, options, sizeof (options));
- vty_out (vty, " Bits: %s Options: %s%s", bits, options, VTY_NEWLINE);
-
- start = (char *) router_lsa + sizeof (struct ospf6_router_lsa);
+ start = (char *) lsa->header + sizeof (struct ospf6_lsa_header);
end = (char *) lsa->header + ntohs (lsa->header->length);
- for (current = start; current + sizeof (struct ospf6_router_lsd) <= end;
- current += sizeof (struct ospf6_router_lsd))
+
+ vty_out (vty, " Unknown contents:%s", VTY_NEWLINE);
+ for (current = start; current < end; current ++)
{
- lsdesc = (struct ospf6_router_lsd *) current;
+ if ((current - start) % 16 == 0)
+ vty_out (vty, "%s ", VTY_NEWLINE);
+ else if ((current - start) % 4 == 0)
+ vty_out (vty, " ");
- if (lsdesc->type == OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT)
- snprintf (name, sizeof (name), "Point-To-Point");
- else if (lsdesc->type == OSPF6_ROUTER_LSD_TYPE_TRANSIT_NETWORK)
- snprintf (name, sizeof (name), "Transit-Network");
- else if (lsdesc->type == OSPF6_ROUTER_LSD_TYPE_STUB_NETWORK)
- snprintf (name, sizeof (name), "Stub-Network");
- else if (lsdesc->type == OSPF6_ROUTER_LSD_TYPE_VIRTUAL_LINK)
- snprintf (name, sizeof (name), "Virtual-Link");
- else
- snprintf (name, sizeof (name), "Unknown (%#x)", lsdesc->type);
-
- vty_out (vty, " Type: %s Metric: %d%s",
- name, ntohs (lsdesc->metric), VTY_NEWLINE);
- vty_out (vty, " Interface ID: %s%s",
- inet_ntop (AF_INET, &lsdesc->interface_id,
- buf, sizeof (buf)), VTY_NEWLINE);
- vty_out (vty, " Neighbor Interface ID: %s%s",
- inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
- buf, sizeof (buf)), VTY_NEWLINE);
- vty_out (vty, " Neighbor Router ID: %s%s",
- inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
- buf, sizeof (buf)), VTY_NEWLINE);
+ snprintf (byte, sizeof (byte), "%02x", *current);
+ vty_out (vty, "%s", byte);
}
+
+ vty_out (vty, "%s%s", VTY_NEWLINE, VTY_NEWLINE);
return 0;
}
-u_long
-ospf6_lsa_has_elasped (u_int16_t type, u_int32_t id,
- u_int32_t adv_router, void *scope)
-{
- struct ospf6_lsa *old;
- struct timeval now;
-
- if (adv_router != ospf6->router_id)
- zlog_info ("LSA: Router-ID changed ?");
-
- old = ospf6_lsdb_lookup (type, id, adv_router, scope);
- if (! old)
- return OSPF6_LSA_MAXAGE;
-
- gettimeofday (&now, NULL);
- return ((u_long) SEC_TVDIFF (&now, &old->originated));
-}
-
-int
-ospf6_lsa_originate_router (struct thread *thread)
-{
- char buffer [MAXLSASIZE];
- u_int16_t size;
- struct ospf6_area *o6a;
- int count;
- u_int32_t area_id;
-
- struct ospf6_router_lsa *router_lsa;
- struct ospf6_router_lsd *router_lsd;
- listnode i;
- struct ospf6_interface *o6i;
- struct ospf6_neighbor *o6n = NULL;
-
- area_id = (u_int32_t) THREAD_ARG (thread);
-
- o6a = ospf6_area_lookup (area_id, ospf6);
- if (! o6a)
- {
- inet_ntop (AF_INET, &area_id, buffer, sizeof (buffer));
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("LSA: Update Router-LSA: No such area: %s", buffer);
- return 0;
- }
-
- /* clear thread */
- o6a->thread_router_lsa = NULL;
-
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("LSA: originate Router-LSA for Area %s", o6a->str);
-
- size = sizeof (struct ospf6_router_lsa);
- memset (buffer, 0, sizeof (buffer));
- router_lsa = (struct ospf6_router_lsa *) buffer;
-
- OSPF6_OPT_CLEAR_ALL (router_lsa->options);
- OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_V6);
- OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_E);
- OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_MC);
- OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_N);
- OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_R);
- OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_DC);
-
- OSPF6_ROUTER_LSA_CLEAR_ALL_BITS (router_lsa);
- OSPF6_ROUTER_LSA_CLEAR (router_lsa, OSPF6_ROUTER_LSA_BIT_B);
-
- if (ospf6_is_asbr (o6a->ospf6))
- OSPF6_ROUTER_LSA_SET (router_lsa, OSPF6_ROUTER_LSA_BIT_E);
- else
- OSPF6_ROUTER_LSA_CLEAR (router_lsa, OSPF6_ROUTER_LSA_BIT_E);
-
- OSPF6_ROUTER_LSA_CLEAR (router_lsa, OSPF6_ROUTER_LSA_BIT_V);
- OSPF6_ROUTER_LSA_CLEAR (router_lsa, OSPF6_ROUTER_LSA_BIT_W);
-
- /* describe links for each interfaces */
- router_lsd = (struct ospf6_router_lsd *) (router_lsa + 1);
- for (i = listhead (o6a->if_list); i; nextnode (i))
- {
- o6i = (struct ospf6_interface *) getdata (i);
- assert (o6i);
-
- /* Interfaces in state Down or Loopback are not described */
- if (o6i->state == IFS_DOWN || o6i->state == IFS_LOOPBACK)
- continue;
-
- /* Nor are interfaces without any full adjacencies described */
- count = 0;
- o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state);
- if (count == 0)
- continue;
-
- /* Point-to-Point interfaces */
- if (if_is_pointopoint (o6i->interface))
- {
- if (listcount (o6i->neighbor_list) == 0)
- continue;
-
- if (listcount (o6i->neighbor_list) != 1)
- zlog_warn ("LSA: Multiple neighbors on PoinToPoint: %s",
- o6i->interface->name);
-
- o6n = (struct ospf6_neighbor *)
- getdata (listhead (o6i->neighbor_list));
- assert (o6n);
-
- router_lsd->type = OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT;
- router_lsd->metric = htons (o6i->cost);
- router_lsd->interface_id = htonl (o6i->if_id);
- router_lsd->neighbor_interface_id = htonl (o6n->ifid);
- router_lsd->neighbor_router_id = o6n->router_id;
-
- size += sizeof (struct ospf6_router_lsd);
- router_lsd ++;
-
- continue;
- }
-
- /* Broadcast and NBMA interfaces */
- if (if_is_broadcast (o6i->interface))
- {
- /* If this router is not DR,
- and If this router not fully adjacent with DR,
- this interface is not transit yet: ignore. */
- if (o6i->state != IFS_DR)
- {
- o6n = ospf6_neighbor_lookup (o6i->dr, o6i); /* find DR */
- if (o6n == NULL || o6n->state != NBS_FULL)
- continue;
- }
- else
- {
- count = 0;
- o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state);
- if (count == 0)
- continue;
- }
-
- router_lsd->type = OSPF6_ROUTER_LSD_TYPE_TRANSIT_NETWORK;
- router_lsd->metric = htons (o6i->cost);
- router_lsd->interface_id = htonl (o6i->if_id);
- if (o6i->state != IFS_DR)
- {
- router_lsd->neighbor_interface_id = htonl (o6n->ifid);
- router_lsd->neighbor_router_id = o6n->router_id;
- }
- else
- {
- router_lsd->neighbor_interface_id = htonl (o6i->if_id);
- router_lsd->neighbor_router_id = o6i->area->ospf6->router_id;
- }
-
- size += sizeof (struct ospf6_router_lsd);
- router_lsd ++;
-
- continue;
- }
-
- /* Virtual links */
- /* xxx */
- /* Point-to-Multipoint interfaces */
- /* xxx */
- }
-
- ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_ROUTER),
- htonl (0), o6a->ospf6->router_id,
- (char *) router_lsa, size, o6a);
- return 0;
-}
-
-void
-ospf6_lsa_schedule_router (struct ospf6_area *area)
-{
- u_long elasped_time, time = 0;
-
- if (area->thread_router_lsa)
- {
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("LSA: schedule: Router-LSA for Area %s: another thread",
- area->str);
- return;
- }
-
- elasped_time =
- ospf6_lsa_has_elasped (htons (OSPF6_LSA_TYPE_ROUTER), htonl (0),
- area->ospf6->router_id, area);
- if (elasped_time < OSPF6_MIN_LS_INTERVAL)
- time = (u_long) (OSPF6_MIN_LS_INTERVAL - elasped_time);
- else
- time = 0;
-
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("LSA: schedule: Router-LSA for Area %s after %lu sec",
- area->str, time);
-
- if (time)
- area->thread_router_lsa =
- thread_add_timer (master, ospf6_lsa_originate_router,
- (void *) area->area_id, time);
- else
- area->thread_router_lsa =
- thread_add_event (master, ospf6_lsa_originate_router,
- (void *) area->area_id, 0);
-}
-
-int
-ospf6_lsa_router_hook_neighbor (void *neighbor)
-{
- struct ospf6_neighbor *o6n = neighbor;
- if (o6n->ospf6_interface->area)
- ospf6_lsa_schedule_router (o6n->ospf6_interface->area);
- return 0;
-}
-
-int
-ospf6_lsa_router_hook_interface (void *interface)
-{
- struct ospf6_interface *o6i = interface;
- if (o6i->area)
- ospf6_lsa_schedule_router (o6i->area);
- return 0;
-}
-
-int
-ospf6_lsa_router_hook_area (void *area)
-{
- struct ospf6_area *o6a = area;
- ospf6_lsa_schedule_router (o6a);
- return 0;
-}
-
-int
-ospf6_lsa_router_hook_top (void *ospf6)
-{
- struct ospf6 *o6 = ospf6;
- struct ospf6_area *o6a;
- listnode node;
-
- for (node = listhead (o6->area_list); node; nextnode (node))
- {
- o6a = getdata (node);
- ospf6_lsa_schedule_router (o6a);
- }
- return 0;
-}
-
-int
-ospf6_lsa_router_refresh (void *old)
-{
- struct ospf6_lsa *lsa = old;
- struct ospf6_area *o6a;
-
- o6a = lsa->scope;
- ospf6_lsa_schedule_router (o6a);
- return 0;
-}
-
-void
-ospf6_lsa_slot_register_router ()
-{
- struct ospf6_lsa_slot slot;
- struct ospf6_hook hook;
-
- memset (&slot, 0, sizeof (struct ospf6_lsa_slot));
- slot.type = htons (OSPF6_LSA_TYPE_ROUTER);
- slot.name = "Router";
- slot.func_show = ospf6_lsa_router_show;
- slot.func_refresh = ospf6_lsa_router_refresh;
- ospf6_lsa_slot_register (&slot);
-
- ospf6_lsdb_hook[OSPF6_LSA_TYPE_ROUTER & OSPF6_LSTYPE_CODE_MASK].hook =
- ospf6_spf_database_hook;
-
- memset (&hook, 0, sizeof (hook));
- hook.name = "OriginateRouter";
- hook.hook_change = ospf6_lsa_router_hook_neighbor;
- ospf6_hook_register (&hook, &neighbor_hook);
-
- memset (&hook, 0, sizeof (hook));
- hook.name = "OriginateRouter";
- hook.hook_change = ospf6_lsa_router_hook_interface;
- ospf6_hook_register (&hook, &interface_hook);
-
- memset (&hook, 0, sizeof (hook));
- hook.name = "OriginateRouter";
- hook.hook_change = ospf6_lsa_router_hook_area;
- ospf6_hook_register (&hook, &area_hook);
-
- memset (&hook, 0, sizeof (hook));
- hook.name = "OriginateRouter";
- hook.hook_change = ospf6_lsa_router_hook_top;
- ospf6_hook_register (&hook, &top_hook);
-}
-
-/*******************************/
-/* RFC2740 3.4.3.2 Network-LSA */
-/*******************************/
-
-int
-ospf6_lsa_network_show (struct vty *vty, struct ospf6_lsa *lsa)
-{
- char *start, *end, *current;
- struct ospf6_network_lsa *network_lsa;
- u_int32_t *router_id;
- char buf[128], options[32];
-
- assert (lsa->header);
- network_lsa = (struct ospf6_network_lsa *) (lsa->header + 1);
- router_id = (u_int32_t *)(network_lsa + 1);
-
- ospf6_options_string (network_lsa->options, options, sizeof (options));
- vty_out (vty, " Options: %s%s", options, VTY_NEWLINE);
-
- start = (char *) network_lsa + sizeof (struct ospf6_network_lsa);
- end = (char *) lsa->header + ntohs (lsa->header->length);
- for (current = start; current + sizeof (u_int32_t) <= end;
- current += sizeof (u_int32_t))
- {
- router_id = (u_int32_t *) current;
- inet_ntop (AF_INET, router_id, buf, sizeof (buf));
- vty_out (vty, " Attached Router: %s%s", buf, VTY_NEWLINE);
- }
- return 0;
-}
-
-void
-ospf6_lsa_network_update (char *ifname)
-{
- char buffer [MAXLSASIZE];
- u_int16_t size;
- struct ospf6_lsa *old;
- struct interface *ifp;
- struct ospf6_interface *o6i;
- int count;
-
- struct ospf6_network_lsa *network_lsa;
- struct ospf6_neighbor *o6n;
- u_int32_t *router_id;
- listnode node;
-
- ifp = if_lookup_by_name (ifname);
- if (! ifp)
- {
- if (IS_OSPF6_DUMP_LSA)
- zlog_warn ("Update Network: No such Interface: %s", ifname);
- return;
- }
-
- o6i = (struct ospf6_interface *) ifp->info;
- if (! o6i || ! o6i->area)
- {
- if (IS_OSPF6_DUMP_LSA)
- zlog_warn ("Update Network: Interface not enabled: %s", ifname);
- return;
- }
-
- /* find previous LSA */
- old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_NETWORK),
- htonl (o6i->if_id),
- o6i->area->ospf6->router_id, o6i->area);
-
- /* Don't originate Network-LSA if not DR */
- if (o6i->state != IFS_DR)
- {
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("Update Network: Interface %s is not DR",
- o6i->interface->name);
- if (old)
- ospf6_lsa_premature_aging (old);
- return;
- }
-
- /* If none of neighbor is adjacent to us */
- count = 0;
- o6i->foreach_nei (o6i, &count, NBS_FULL, ospf6_count_state);
- if (count == 0)
- {
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("Update Network: Interface %s is Stub",
- o6i->interface->name);
- if (old)
- ospf6_lsa_premature_aging (old);
- return;
- }
-
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("Update Network: Interface %s", o6i->interface->name);
-
- /* prepare buffer */
- memset (buffer, 0, sizeof (buffer));
- size = sizeof (struct ospf6_network_lsa);
- network_lsa = (struct ospf6_network_lsa *) buffer;
- router_id = (u_int32_t *)(network_lsa + 1);
-
- /* set fields of myself */
- *router_id++ = o6i->area->ospf6->router_id;
- size += sizeof (u_int32_t);
- network_lsa->options[0] |= o6i->area->options[0];
- network_lsa->options[1] |= o6i->area->options[1];
- network_lsa->options[2] |= o6i->area->options[2];
-
- /* Walk through neighbors */
- for (node = listhead (o6i->neighbor_list); node; nextnode (node))
- {
- o6n = (struct ospf6_neighbor *) getdata (node);
-
- if (o6n->state != NBS_FULL)
- continue;
-
- /* set this neighbor's Router-ID to LSA */
- *router_id++ = o6n->router_id;
- size += sizeof (u_int32_t);
-
- /* options field is logical OR */
- network_lsa->options[0] |= o6n->options[0];
- network_lsa->options[1] |= o6n->options[1];
- network_lsa->options[2] |= o6n->options[2];
- }
-
- ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_NETWORK),
- htonl (o6i->if_id), o6i->area->ospf6->router_id,
- (char *) network_lsa, size, o6i->area);
-}
-
-int
-ospf6_lsa_network_hook_neighbor (void *neighbor)
-{
- struct ospf6_neighbor *o6n = neighbor;
- ospf6_lsa_network_update (o6n->ospf6_interface->interface->name);
- return 0;
-}
-
-int
-ospf6_lsa_network_hook_interface (void *interface)
-{
- struct ospf6_interface *o6i = interface;
- if (o6i->area)
- ospf6_lsa_network_update (o6i->interface->name);
- return 0;
-}
-
-int
-ospf6_lsa_network_refresh (void *old)
-{
- struct ospf6_lsa *lsa = old;
- struct interface *ifp;
-
- ifp = if_lookup_by_index (ntohl (lsa->header->id));
- if (! ifp)
- ospf6_lsa_premature_aging (old);
- else
- ospf6_lsa_network_update (ifp->name);
-
- return 0;
-}
-
-void
-ospf6_lsa_slot_register_network ()
-{
- struct ospf6_lsa_slot slot;
- struct ospf6_hook hook;
-
- memset (&slot, 0, sizeof (struct ospf6_lsa_slot));
- slot.type = htons (OSPF6_LSA_TYPE_NETWORK);
- slot.name = "Network";
- slot.func_show = ospf6_lsa_network_show;
- slot.func_refresh = ospf6_lsa_network_refresh;
- ospf6_lsa_slot_register (&slot);
-
- ospf6_lsdb_hook[OSPF6_LSA_TYPE_NETWORK & OSPF6_LSTYPE_CODE_MASK].hook =
- ospf6_spf_database_hook;
-
- memset (&hook, 0, sizeof (hook));
- hook.name = "OriginateNetwork";
- hook.hook_change = ospf6_lsa_network_hook_neighbor;
- ospf6_hook_register (&hook, &neighbor_hook);
-
- memset (&hook, 0, sizeof (hook));
- hook.name = "OriginateNetwork";
- hook.hook_change = ospf6_lsa_network_hook_interface;
- ospf6_hook_register (&hook, &interface_hook);
-}
-
-/****************************/
-/* RFC2740 3.4.3.6 Link-LSA */
-/****************************/
-
-int
-ospf6_lsa_link_show (struct vty *vty, struct ospf6_lsa *lsa)
-{
- char *start, *end, *current;
- struct ospf6_link_lsa *link_lsa;
- int prefixnum;
- struct ospf6_prefix *prefix;
- char buf[128];
- struct in6_addr in6;
-
- assert (lsa->header);
-
- link_lsa = (struct ospf6_link_lsa *) (lsa->header + 1);
- prefixnum = ntohl (link_lsa->llsa_prefix_num);
-
- inet_ntop (AF_INET6, (void *)&link_lsa->llsa_linklocal, buf, sizeof (buf));
- vty_out (vty, " LinkLocal Address: %s%s", buf, VTY_NEWLINE);
- vty_out (vty, " Number of Prefix: %d%s", prefixnum, VTY_NEWLINE);
-
- start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
- end = (char *) lsa->header + ntohs (lsa->header->length);
- for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
- {
- prefix = (struct ospf6_prefix *) current;
- if (current + OSPF6_PREFIX_SIZE (prefix) > end)
- {
- vty_out (vty, " Trailing %d byte garbage ... Malformed%s",
- end - current, VTY_NEWLINE);
- return -1;
- }
-
- ospf6_prefix_options_str (prefix->prefix_options, buf, sizeof (buf));
- vty_out (vty, " Prefix Options: %s%s", buf, VTY_NEWLINE);
- ospf6_prefix_in6_addr (prefix, &in6);
- inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
- vty_out (vty, " Prefix: %s/%d%s",
- buf, prefix->prefix_length, VTY_NEWLINE);
- }
-
- return 0;
-}
-
-
-void
-ospf6_lsa_link_update (char *ifname)
-{
- char *cp, buffer [MAXLSASIZE], buf[32];
- u_int16_t size;
- struct ospf6_lsa *old;
- struct interface *ifp;
- struct ospf6_interface *o6i;
-
- struct ospf6_link_lsa *link_lsa;
- struct ospf6_prefix *p;
- list prefix_connected;
- listnode node;
- struct connected *c;
-
- ifp = if_lookup_by_name (ifname);
- if (! ifp)
- {
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("Update Link: No such Interface: %s", ifname);
- return;
- }
-
- o6i = (struct ospf6_interface *) ifp->info;
- if (! o6i || ! o6i->area)
- {
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("Update Link: Interface not enabled: %s", ifname);
- return;
- }
-
-#if 0
- /* Link-LSA is on Broadcast or NBMA */
- if (! if_is_broadcast (o6i->interface) /* && ! NBMA xxx */)
- {
- return;
- }
-#endif /*0*/
-
- /* find previous LSA */
- old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_LINK), htonl (o6i->if_id),
- ospf6->router_id, o6i->area);
-
- /* can't make Link-LSA if linklocal address not set */
- if (! o6i->lladdr)
- {
- if (IS_OSPF6_DUMP_LSA)
- zlog_warn ("Update Link: No Linklocal Address: %s",
- o6i->interface->name);
- if (old)
- ospf6_lsa_premature_aging (old);
- return;
- }
-
- if (IS_OSPF6_DUMP_LSA)
- zlog_info ("Update Link: Interface %s", o6i->interface->name);
-
- if (! ospf6_interface_is_enabled (o6i->interface->ifindex))
- {
- if (IS_OSPF6_DUMP_LSA)
- zlog_info (" Interface %s not enabled", o6i->interface->name);
- if (old)
- ospf6_lsa_premature_aging (old);
- return;
- }
-
- /* check connected prefix */
- prefix_connected = list_new ();
- for (node = listhead (o6i->interface->connected); node; nextnode (node))
- {
- c = (struct connected *) getdata (node);
-
- /* filter prefix not IPv6 */
- if (c->address->family != AF_INET6)
- continue;
-
- /* for log */
- prefix2str (c->address, buf, sizeof (buf));
-
- CONTINUE_IF_ADDRESS_LINKLOCAL (c->address);
- CONTINUE_IF_ADDRESS_UNSPECIFIED (c->address);
- CONTINUE_IF_ADDRESS_LOOPBACK (c->address);
- CONTINUE_IF_ADDRESS_V4COMPAT (c->address);
- CONTINUE_IF_ADDRESS_V4MAPPED (c->address);
-
- /* filter prefix specified by configuration */
- if (o6i->plist_name)
- {
- struct prefix_list *plist;
- enum prefix_list_type result = PREFIX_PERMIT;
-
- plist = prefix_list_lookup (AFI_IP6, o6i->plist_name);
- if (plist)
- result = prefix_list_apply (plist, c->address);
- else if (IS_OSPF6_DUMP_LSA)
- zlog_warn ("Update Intra-Prefix (Stub): "
- "Prefix list \"%s\" not found", o6i->plist_name);
-
- if (result == PREFIX_DENY)
- {
- if (IS_OSPF6_DUMP_LSA)
- zlog_info (" Filter out Prefix-list %s: %s",
- o6i->plist_name, buf);
- continue;
- }
- }
-
- if (IS_OSPF6_DUMP_LSA)
- zlog_info (" Advertise %s", buf);
-
- /* hold prefix in list. duplicate is filtered in ospf6_prefix_add() */
- p = ospf6_prefix_create (0, 0, (struct prefix_ipv6 *) c->address);
- ospf6_prefix_add (prefix_connected, p);
- }
-
- /* Note: even if no prefix configured, still we have to create Link-LSA
- for next-hop resolution */
-
- memset (buffer, 0, sizeof (buffer));
- size = sizeof (struct ospf6_link_lsa);
- link_lsa = (struct ospf6_link_lsa *) buffer;
-
- /* fill Link LSA and calculate size */
- link_lsa->llsa_rtr_pri = o6i->priority;
- link_lsa->llsa_options[0] = o6i->area->options[0];
- link_lsa->llsa_options[1] = o6i->area->options[1];
- link_lsa->llsa_options[2] = o6i->area->options[2];
-
- /* linklocal address */
- memcpy (&link_lsa->llsa_linklocal, o6i->lladdr, sizeof (struct in6_addr));
-
-#ifdef KAME /* clear ifindex */
- if (link_lsa->llsa_linklocal.s6_addr[3] & 0x0f)
- link_lsa->llsa_linklocal.s6_addr[3] &= ~((char)0x0f);
-#endif /* KAME */
-
- link_lsa->llsa_prefix_num = htonl (listcount (prefix_connected));
- cp = (char *)(link_lsa + 1);
- for (node = listhead (prefix_connected); node; nextnode (node))
- {
- p = (struct ospf6_prefix *) getdata (node);
- size += OSPF6_PREFIX_SIZE (p);
- memcpy (cp, p, OSPF6_PREFIX_SIZE (p));
- cp += OSPF6_PREFIX_SIZE (p);
- }
-
- for (node = listhead (prefix_connected); node; nextnode (node))
- {
- p = (struct ospf6_prefix *) getdata (node);
- ospf6_prefix_delete (p);
- }
- list_delete (prefix_connected);
-
- ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_LINK),
- htonl (o6i->if_id), o6i->area->ospf6->router_id,
- (char *) link_lsa, size, o6i);
-}
-
-int
-ospf6_lsa_link_hook_interface (void *interface)
-{
- struct ospf6_interface *o6i = interface;
- if (o6i->area)
- ospf6_lsa_link_update (o6i->interface->name);
- return 0;
-}
-
-int
-ospf6_lsa_link_refresh (void *old)
-{
- struct ospf6_lsa *lsa = old;
- struct interface *ifp;
-
- ifp = if_lookup_by_index (ntohl (lsa->header->id));
- if (! ifp)
- ospf6_lsa_premature_aging (old);
- else
- ospf6_lsa_link_update (ifp->name);
-
- return 0;
-}
-
-void
-ospf6_lsa_slot_register_link ()
-{
- struct ospf6_lsa_slot slot;
-
- memset (&slot, 0, sizeof (struct ospf6_lsa_slot));
- slot.type = htons (OSPF6_LSA_TYPE_LINK);
- slot.name = "Link";
- slot.func_show = ospf6_lsa_link_show;
- slot.func_refresh = ospf6_lsa_link_refresh;
- slot.hook_interface.name = "OriginateLink";
- slot.hook_interface.hook_change = ospf6_lsa_link_hook_interface;
- ospf6_lsa_slot_register (&slot);
-
- /*
- * Link LSA handling will be shift in ospf6_intra.c
- * Currently, only database hook only moved to ospf6_intra.c
- */
-#if 0
- ospf6_lsdb_hook[OSPF6_LSA_TYPE_LINK & OSPF6_LSTYPE_CODE_MASK].hook =
- ospf6_spf_database_hook;
-#endif /*0*/
-}
-
-int
-ospf6_lsa_add_hook (void *data)
-{
- struct ospf6_lsa *lsa = data;
- struct ospf6_lsa_slot *sp;
-
- sp = ospf6_lsa_slot_get (lsa->header->type);
- if (sp)
- {
- CALL_CHANGE_HOOK (&sp->database_hook, lsa);
- }
- else
- zlog_warn ("Unknown LSA added to database: %s", lsa->str);
- return 0;
-}
-
-int
-ospf6_lsa_change_hook (void *data)
-{
- struct ospf6_lsa *lsa = data;
- struct ospf6_lsa_slot *sp;
-
- sp = ospf6_lsa_slot_get (lsa->header->type);
- if (sp)
- {
- CALL_CHANGE_HOOK (&sp->database_hook, lsa);
- }
- else
- zlog_warn ("Unknown LSA changed in database: %s", lsa->str);
- return 0;
-}
-
-int
-ospf6_lsa_remove_hook (void *data)
-{
- struct ospf6_lsa *lsa = data;
- struct ospf6_lsa_slot *sp;
-
- sp = ospf6_lsa_slot_get (lsa->header->type);
- if (sp)
- {
- CALL_REMOVE_HOOK (&sp->database_hook, lsa);
- }
- else
- zlog_warn ("Unknown LSA removed from database: %s", lsa->str);
- return 0;
-}
-
-/* Initialize LSA slots */
void
ospf6_lsa_init ()
{
- struct ospf6_hook hook;
+ memset (ospf6_lstype, 0, sizeof (ospf6_lstype));
- slot_head = NULL;
- ospf6_lsa_slot_register_router ();
- ospf6_lsa_slot_register_network ();
- ospf6_lsa_slot_register_link ();
-#if 0
- ospf6_lsa_slot_register_intra_prefix ();
- ospf6_lsa_slot_register_as_external ();
-#endif /*0*/
-
- hook.name = "LSADatabaseHook";
- hook.hook_add = ospf6_lsa_add_hook;
- hook.hook_change = ospf6_lsa_change_hook;
- hook.hook_remove = ospf6_lsa_remove_hook;
- ospf6_hook_register (&hook, &database_hook);
+ ospf6_lstype[0].name = "Unknown";
+ ospf6_lstype[0].reoriginate = ospf6_unknown_reoriginate;
+ ospf6_lstype[0].show = ospf6_unknown_show;
}
+
+
+DEFUN (debug_ospf6_lsa_sendrecv,
+ debug_ospf6_lsa_sendrecv_cmd,
+ "debug ospf6 lsa (send|recv|originate|timer|database|memory|all)",
+ DEBUG_STR
+ OSPF6_STR
+ "Debug Link State Advertisements (LSAs)\n"
+ "Debug Sending LSAs\n"
+ "Debug Receiving LSAs\n"
+ "Debug Originating LSAs\n"
+ "Debug Timer Event of LSAs\n"
+ "Debug LSA Database\n"
+ "Debug Memory of LSAs\n"
+ "Debug LSAs all\n"
+ )
+{
+ unsigned char level = 0;
+
+ if (argc)
+ {
+ if (! strncmp (argv[0], "s", 1))
+ level = OSPF6_DEBUG_LSA_SEND;
+ else if (! strncmp (argv[0], "r", 1))
+ level = OSPF6_DEBUG_LSA_RECV;
+ else if (! strncmp (argv[0], "o", 1))
+ level = OSPF6_DEBUG_LSA_ORIGINATE;
+ else if (! strncmp (argv[0], "t", 1))
+ level = OSPF6_DEBUG_LSA_TIMER;
+ else if (! strncmp (argv[0], "d", 1))
+ level = OSPF6_DEBUG_LSA_DATABASE;
+ else if (! strncmp (argv[0], "m", 1))
+ level = OSPF6_DEBUG_LSA_MEMORY;
+ else if (! strncmp (argv[0], "a", 1))
+ {
+ level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
+ OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER |
+ OSPF6_DEBUG_LSA_DATABASE | OSPF6_DEBUG_LSA_MEMORY;
+ }
+ }
+ else
+ {
+ level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
+ OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER;
+ }
+
+ OSPF6_DEBUG_LSA_ON (level);
+ return CMD_SUCCESS;
+}
+
+ALIAS (debug_ospf6_lsa_sendrecv,
+ debug_ospf6_lsa_cmd,
+ "debug ospf6 lsa",
+ NO_STR
+ DEBUG_STR
+ OSPF6_STR
+ "Debug Link State Advertisements (LSAs)\n"
+ );
+
+DEFUN (no_debug_ospf6_lsa_sendrecv,
+ no_debug_ospf6_lsa_sendrecv_cmd,
+ "no debug ospf6 lsa (send|recv|originate|timer|database|memory|all)",
+ NO_STR
+ DEBUG_STR
+ OSPF6_STR
+ "Debug Link State Advertisements (LSAs)\n"
+ "Debug Sending LSAs\n"
+ "Debug Receiving LSAs\n"
+ "Debug Originating LSAs\n"
+ "Debug Timer Event of LSAs\n"
+ "Debug LSA Database\n"
+ "Debug Memory of LSAs\n"
+ "Debug LSAs all\n"
+ )
+{
+ unsigned char level = 0;
+
+ if (argc)
+ {
+ if (! strncmp (argv[0], "s", 1))
+ level = OSPF6_DEBUG_LSA_SEND;
+ else if (! strncmp (argv[0], "r", 1))
+ level = OSPF6_DEBUG_LSA_RECV;
+ else if (! strncmp (argv[0], "o", 1))
+ level = OSPF6_DEBUG_LSA_ORIGINATE;
+ else if (! strncmp (argv[0], "t", 1))
+ level = OSPF6_DEBUG_LSA_TIMER;
+ else if (! strncmp (argv[0], "d", 1))
+ level = OSPF6_DEBUG_LSA_DATABASE;
+ else if (! strncmp (argv[0], "m", 1))
+ level = OSPF6_DEBUG_LSA_MEMORY;
+ else if (! strncmp (argv[0], "a", 1))
+ {
+ level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
+ OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER |
+ OSPF6_DEBUG_LSA_DATABASE | OSPF6_DEBUG_LSA_MEMORY;
+ }
+ }
+ else
+ {
+ level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
+ OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER;
+ }
+
+ OSPF6_DEBUG_LSA_OFF (level);
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_ospf6_lsa_sendrecv,
+ no_debug_ospf6_lsa_cmd,
+ "no debug ospf6 lsa",
+ NO_STR
+ DEBUG_STR
+ OSPF6_STR
+ "Debug Link State Advertisements (LSAs)\n"
+ );
+
+int
+config_write_ospf6_debug_lsa (struct vty *vty)
+{
+ if (conf_debug_ospf6_lsa == OSPF6_DEBUG_LSA_ALL)
+ vty_out (vty, "debug ospf6 lsa all%s", VTY_NEWLINE);
+ else
+ {
+ if (conf_debug_ospf6_lsa == OSPF6_DEBUG_LSA_DEFAULT)
+ vty_out (vty, "debug ospf6 lsa%s", VTY_NEWLINE);
+ else
+ {
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ vty_out (vty, "debug ospf6 lsa send%s", VTY_NEWLINE);
+ if (IS_OSPF6_DEBUG_LSA (RECV))
+ vty_out (vty, "debug ospf6 lsa recv%s", VTY_NEWLINE);
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+ vty_out (vty, "debug ospf6 lsa originate%s", VTY_NEWLINE);
+ if (IS_OSPF6_DEBUG_LSA (TIMER))
+ vty_out (vty, "debug ospf6 lsa timer%s", VTY_NEWLINE);
+ }
+
+ if (IS_OSPF6_DEBUG_LSA (DATABASE))
+ vty_out (vty, "debug ospf6 lsa database%s", VTY_NEWLINE);
+ if (IS_OSPF6_DEBUG_LSA (MEMORY))
+ vty_out (vty, "debug ospf6 lsa memory%s", VTY_NEWLINE);
+ }
+
+ return 0;
+}
+
+void
+install_element_ospf6_debug_lsa ()
+{
+ install_element (ENABLE_NODE, &debug_ospf6_lsa_cmd);
+ install_element (ENABLE_NODE, &debug_ospf6_lsa_sendrecv_cmd);
+ install_element (ENABLE_NODE, &no_debug_ospf6_lsa_cmd);
+ install_element (ENABLE_NODE, &no_debug_ospf6_lsa_sendrecv_cmd);
+ install_element (CONFIG_NODE, &debug_ospf6_lsa_cmd);
+ install_element (CONFIG_NODE, &debug_ospf6_lsa_sendrecv_cmd);
+ install_element (CONFIG_NODE, &no_debug_ospf6_lsa_cmd);
+ install_element (CONFIG_NODE, &no_debug_ospf6_lsa_sendrecv_cmd);
+}
+
+
diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h
index 02ad7c6..8b9d5f3 100644
--- a/ospf6d/ospf6_lsa.h
+++ b/ospf6d/ospf6_lsa.h
@@ -1,6 +1,5 @@
/*
- * LSA function
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -23,176 +22,57 @@
#ifndef OSPF6_LSA_H
#define OSPF6_LSA_H
-#include "ospf6_hook.h"
-
-#define ONESECOND_USEC 1000000
-#define USEC_TVDIFF(tv2,tv1) \
- (((tv2)->tv_sec - (tv1)->tv_sec) * ONESECOND_USEC \
- + ((tv2)->tv_usec - (tv1)->tv_usec))
-#define SEC_TVDIFF(tv2,tv1) \
- (USEC_TVDIFF((tv2),(tv1)) / ONESECOND_USEC)
+/* Debug option */
+extern unsigned char conf_debug_ospf6_lsa;
+#define OSPF6_DEBUG_LSA_SEND 0x01
+#define OSPF6_DEBUG_LSA_RECV 0x02
+#define OSPF6_DEBUG_LSA_ORIGINATE 0x04
+#define OSPF6_DEBUG_LSA_TIMER 0x08
+#define OSPF6_DEBUG_LSA_DATABASE 0x10
+#define OSPF6_DEBUG_LSA_MEMORY 0x80
+#define OSPF6_DEBUG_LSA_ALL 0x9f
+#define OSPF6_DEBUG_LSA_DEFAULT 0x0f
+#define OSPF6_DEBUG_LSA_ON(level) \
+ (conf_debug_ospf6_lsa |= (level))
+#define OSPF6_DEBUG_LSA_OFF(level) \
+ (conf_debug_ospf6_lsa &= ~(level))
+#define IS_OSPF6_DEBUG_LSA(e) \
+ (conf_debug_ospf6_lsa & OSPF6_DEBUG_LSA_ ## e)
/* LSA definition */
-#define MAXLSASIZE 1024
-
-#define OSPF6_LSA_MAXAGE 3600 /* 1 hour */
-#define OSPF6_LSA_CHECKAGE 300 /* 5 min */
-#define OSPF6_LSA_MAXAGEDIFF 900 /* 15 min */
+#define OSPF6_MAX_LSASIZE 4096
/* Type */
-#define OSPF6_LSA_TYPE_NONE 0x0000
-#define OSPF6_LSA_TYPE_ROUTER 0x2001
-#define OSPF6_LSA_TYPE_NETWORK 0x2002
-#define OSPF6_LSA_TYPE_INTER_PREFIX 0x2003
-#define OSPF6_LSA_TYPE_INTER_ROUTER 0x2004
-#define OSPF6_LSA_TYPE_AS_EXTERNAL 0x4005
-#define OSPF6_LSA_TYPE_GROUP_MEMBERSHIP 0x2006
-#define OSPF6_LSA_TYPE_TYPE_7 0x2007
-#define OSPF6_LSA_TYPE_LINK 0x0008
-#define OSPF6_LSA_TYPE_INTRA_PREFIX 0x2009
-#define OSPF6_LSA_TYPE_MAX 0x000a
-#define OSPF6_LSA_TYPE_SIZE 0x000b
+#define OSPF6_LSTYPE_UNKNOWN 0x0000
+#define OSPF6_LSTYPE_ROUTER 0x2001
+#define OSPF6_LSTYPE_NETWORK 0x2002
+#define OSPF6_LSTYPE_INTER_PREFIX 0x2003
+#define OSPF6_LSTYPE_INTER_ROUTER 0x2004
+#define OSPF6_LSTYPE_AS_EXTERNAL 0x4005
+#define OSPF6_LSTYPE_GROUP_MEMBERSHIP 0x2006
+#define OSPF6_LSTYPE_TYPE_7 0x2007
+#define OSPF6_LSTYPE_LINK 0x0008
+#define OSPF6_LSTYPE_INTRA_PREFIX 0x2009
+#define OSPF6_LSTYPE_SIZE 0x000a
/* Masks for LS Type : RFC 2740 A.4.2.1 "LS type" */
#define OSPF6_LSTYPE_UBIT_MASK 0x8000
#define OSPF6_LSTYPE_SCOPE_MASK 0x6000
-#define OSPF6_LSTYPE_CODE_MASK 0x1fff
+#define OSPF6_LSTYPE_FCODE_MASK 0x1fff
-#define OSPF6_LSA_TYPESW_MASK OSPF6_LSTYPE_CODE_MASK
-#define OSPF6_LSA_TYPESW(x) (ntohs((x)) & OSPF6_LSA_TYPESW_MASK)
-#define OSPF6_LSA_TYPESW_ISKNOWN(x) (OSPF6_LSA_TYPESW(x) < OSPF6_LSA_TYPE_MAX)
-
-/* lsa scope */
+/* LSA scope */
#define OSPF6_LSA_SCOPE_LINKLOCAL 0x0000
#define OSPF6_LSA_SCOPE_AREA 0x2000
#define OSPF6_LSA_SCOPE_AS 0x4000
#define OSPF6_LSA_SCOPE_RESERVED 0x6000
-#define OSPF6_LSA_IS_SCOPE_LINKLOCAL(x) \
- (((x) & OSPF6_LSTYPE_SCOPE_MASK) == OSPF6_LSA_SCOPE_LINKLOCAL)
-#define OSPF6_LSA_IS_SCOPE_AREA(x) \
- (((x) & OSPF6_LSTYPE_SCOPE_MASK) == OSPF6_LSA_SCOPE_AREA)
-#define OSPF6_LSA_IS_SCOPE_AS(x) \
- (((x) & OSPF6_LSTYPE_SCOPE_MASK) == OSPF6_LSA_SCOPE_AS)
-/* NOTE that all LSAs are kept NETWORK BYTE ORDER */
-
-/* Router-LSA */
-struct ospf6_router_lsa
-{
- u_char bits;
- u_char options[3];
- /* followed by ospf6_router_lsd(s) */
-};
-
-#define OSPF6_ROUTER_LSA_BIT_B (1 << 0)
-#define OSPF6_ROUTER_LSA_BIT_E (1 << 1)
-#define OSPF6_ROUTER_LSA_BIT_V (1 << 2)
-#define OSPF6_ROUTER_LSA_BIT_W (1 << 3)
-
-#define OSPF6_ROUTER_LSA_SET(x,y) ((x)->bits |= (y))
-#define OSPF6_ROUTER_LSA_ISSET(x,y) ((x)->bits & (y))
-#define OSPF6_ROUTER_LSA_CLEAR(x,y) ((x)->bits &= ~(y))
-#define OSPF6_ROUTER_LSA_CLEAR_ALL_BITS(x) ((x)->bits = 0)
-
-/* Link State Description in Router-LSA */
-struct ospf6_router_lsd
-{
- u_char type;
- u_char reserved;
- u_int16_t metric; /* output cost */
- u_int32_t interface_id;
- u_int32_t neighbor_interface_id;
- u_int32_t neighbor_router_id;
-};
-
-#define OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT 1
-#define OSPF6_ROUTER_LSD_TYPE_TRANSIT_NETWORK 2
-#define OSPF6_ROUTER_LSD_TYPE_STUB_NETWORK 3
-#define OSPF6_ROUTER_LSD_TYPE_VIRTUAL_LINK 4
-
-/* Network-LSA */
-struct ospf6_network_lsa
-{
- u_char reserved;
- u_char options[3];
- /* followed by ospf6_netowrk_lsd(s) */
-};
-
-/* Link State Description in Router-LSA */
-struct ospf6_network_lsd
-{
- u_int32_t adv_router;
-};
-
-/* Link-LSA */
-struct ospf6_link_lsa
-{
- u_char llsa_rtr_pri;
- u_char llsa_options[3];
- struct in6_addr llsa_linklocal;
- u_int32_t llsa_prefix_num;
- /* followed by prefix(es) */
-};
-
-/* Intra-Area-Prefix-LSA */
-struct ospf6_intra_area_prefix_lsa
-{
- u_int16_t prefix_number;
- u_int16_t refer_lstype;
- u_int32_t refer_lsid;
- u_int32_t refer_advrtr;
-};
-
-/* AS-External-LSA */
-struct ospf6_as_external_lsa
-{
- u_char ase_bits;
- u_char ase_pre_metric; /* 1st byte of metric */
- u_int16_t ase_metric; /* 2nd, 3rd byte of metric */
-#if 1
- struct ospf6_prefix ospf6_prefix;
-#else
- u_char ase_prefix_len;
- u_char ase_prefix_opt;
- u_int16_t ase_refer_lstype;
- /* followed by one address prefix */
-#endif
- /* followed by none or one forwarding address */
- /* followed by none or one external route tag */
- /* followed by none or one referenced LS-ID */
-};
-#define ASE_LSA_BIT_T (1 << 0)
-#define ASE_LSA_BIT_F (1 << 1)
-#define ASE_LSA_BIT_E (1 << 2)
-
-#define ASE_LSA_SET(x,y) ((x)->ase_bits |= (y))
-#define ASE_LSA_ISSET(x,y) ((x)->ase_bits & (y))
-#define ASE_LSA_CLEAR(x,y) ((x)->ase_bits &= ~(y))
+#define OSPF6_LSA_SCOPE(type) \
+ (ntohs (type) & OSPF6_LSTYPE_SCOPE_MASK)
/* LSA Header */
-struct ospf6_lsa_hdr
-{
- u_int16_t lsh_age; /* LS age */
- u_int16_t lsh_type; /* LS type */
- u_int32_t lsh_id; /* Link State ID */
- u_int32_t lsh_advrtr; /* Advertising Router */
- u_int32_t lsh_seqnum; /* LS sequence number */
- u_int16_t lsh_cksum; /* LS checksum */
- u_int16_t lsh_len; /* length */
-};
struct ospf6_lsa_header
{
- u_int16_t age; /* LS age */
- u_int16_t type; /* LS type */
- u_int32_t ls_id; /* Link State ID */
- u_int32_t advrtr; /* Advertising Router */
- u_int32_t seqnum; /* LS sequence number */
- u_int16_t checksum; /* LS checksum */
- u_int16_t length; /* LSA length */
-};
-struct ospf6_lsa_header__
-{
u_int16_t age; /* LS age */
u_int16_t type; /* LS type */
u_int32_t id; /* Link State ID */
@@ -202,225 +82,175 @@
u_int16_t length; /* LSA length */
};
-#define OSPF6_LSA_NEXT(x) ((struct ospf6_lsa_header *) \
- ((char *)(x) + ntohs ((x)->length)))
-
-#define OSPF6_LSA_HEADER_END(header) \
- ((void *)((char *)(header) + sizeof (struct ospf6_lsa_header)))
+#define OSPF6_LSA_HEADER_END(h) \
+ ((caddr_t)(h) + sizeof (struct ospf6_lsa_header))
+#define OSPF6_LSA_SIZE(h) \
+ (ntohs (((struct ospf6_lsa_header *) (h))->length))
+#define OSPF6_LSA_END(h) \
+ ((caddr_t)(h) + ntohs (((struct ospf6_lsa_header *) (h))->length))
+#define OSPF6_LSA_IS_TYPE(t, L) \
+ ((L)->header->type == htons (OSPF6_LSTYPE_ ## t) ? 1 : 0)
+#define OSPF6_LSA_IS_SAME(L1, L2) \
+ ((L1)->header->adv_router == (L2)->header->adv_router && \
+ (L1)->header->id == (L2)->header->id && \
+ (L1)->header->type == (L2)->header->type)
+#define OSPF6_LSA_IS_MATCH(t, i, a, L) \
+ ((L)->header->adv_router == (a) && (L)->header->id == (i) && \
+ (L)->header->type == (t))
+#define OSPF6_LSA_IS_DIFFER(L1, L2) ospf6_lsa_is_differ (L1, L2)
+#define OSPF6_LSA_IS_MAXAGE(L) (ospf6_lsa_age_current (L) == MAXAGE)
+#define OSPF6_LSA_IS_CHANGED(L1, L2) ospf6_lsa_is_changed (L1, L2)
struct ospf6_lsa
{
- char str[256]; /* dump string */
+ char name[64]; /* dump string */
- u_long lock; /* reference counter */
- int summary; /* indicate this is LS header only */
- void *scope; /* pointer of scoped data structure */
- unsigned char flag; /* to decide ack type and refresh */
- struct timeval birth; /* tv_sec when LS age 0 */
- struct timeval installed; /* installed time */
- struct timeval originated; /* installed time */
- struct thread *expire;
- struct thread *refresh; /* For self-originated LSA */
- u_int32_t from; /* from which neighbor */
+ struct ospf6_lsa *prev;
+ struct ospf6_lsa *next;
+
+ unsigned char lock; /* reference counter */
+ unsigned char flag; /* special meaning (e.g. floodback) */
+
+ struct timeval birth; /* tv_sec when LS age 0 */
+ struct timeval installed; /* used by MinLSArrival check */
+ struct timeval originated; /* used by MinLSInterval check */
+
+ struct thread *expire;
+ struct thread *refresh; /* For self-originated LSA */
+
+ void *scope; /* pointer to scope data structure */
+ int headeronly; /* indicate this is LS header only */
+
+ unsigned long refcnt;
+ struct ospf6_lsa *refsrc;
/* lsa instance */
- struct ospf6_lsa_hdr *lsa_hdr;
- struct ospf6_lsa_header__ *header;
-
- /* statistics */
- u_long turnover_num;
- u_long turnover_total;
- u_long turnover_min;
- u_long turnover_max;
+ struct ospf6_lsa_header *header;
};
-struct ospf6_lsa_slot
+#define OSPF6_LSA_FLOODBACK 0x01
+#define OSPF6_LSA_DUPLICATE 0x02
+#define OSPF6_LSA_IMPLIEDACK 0x04
+#define OSPF6_LSA_REFRESH 0x08
+
+struct ospf6_lstype
{
- struct ospf6_lsa_slot *prev;
- struct ospf6_lsa_slot *next;
-
- u_int16_t type;
- char *name;
-
- int (*func_print) (struct ospf6_lsa *lsa);
- int (*func_show) (struct vty *vty, struct ospf6_lsa *lsa);
- int (*func_refresh) (void *lsa);
-
- int (*database_add) (void *lsa);
- int (*database_remove) (void *lsa);
-
- struct ospf6_hook_master database_hook;
-
- struct ospf6_hook hook_neighbor;
- struct ospf6_hook hook_interface;
- struct ospf6_hook hook_area;
- struct ospf6_hook hook_top;
- struct ospf6_hook hook_database;
- struct ospf6_hook hook_route;
+ char *name;
+ int (*reoriginate) (struct ospf6_lsa *);
+ int (*show) (struct vty *, struct ospf6_lsa *);
};
-#define OSPF6_LSA_FLAG_FLOODBACK 0x01
-#define OSPF6_LSA_FLAG_DUPLICATE 0x02
-#define OSPF6_LSA_FLAG_IMPLIEDACK 0x04
-#define OSPF6_LSA_FLAG_REFRESH 0x08
+extern struct ospf6_lstype ospf6_lstype[OSPF6_LSTYPE_SIZE];
+#define OSPF6_LSTYPE_INDEX(type) \
+ (((type) & OSPF6_LSTYPE_FCODE_MASK) < OSPF6_LSTYPE_SIZE ? \
+ ((type) & OSPF6_LSTYPE_FCODE_MASK) : OSPF6_LSTYPE_UNKNOWN)
-/* Back pointer check, Is X's reference field bound to Y ? */
-#define x_ipl(x) ((struct intra_area_prefix_lsa *)LSH_NEXT((x)->lsa_hdr))
-#define is_reference_network_ok(x,y) \
- ((x_ipl(x))->intra_prefix_refer_lstype == (y)->lsa_hdr->lsh_type &&\
- (x_ipl(x))->intra_prefix_refer_lsid == (y)->lsa_hdr->lsh_id &&\
- (x_ipl(x))->intra_prefix_refer_advrtr == (y)->lsa_hdr->lsh_advrtr)
- /* referencing router's ifid must be 0,
- see draft-ietf-ospf-ospfv6-06.txt */
-#define is_reference_router_ok(x,y) \
- ((x_ipl(x))->intra_prefix_refer_lstype == (y)->lsa_hdr->lsh_type &&\
- (x_ipl(x))->intra_prefix_refer_lsid == htonl (0) &&\
- (x_ipl(x))->intra_prefix_refer_advrtr == (y)->lsa_hdr->lsh_advrtr)
+#if 0
+extern char *ospf6_lstype_str[OSPF6_LSTYPE_SIZE];
+#define OSPF6_LSTYPE_NAME(type) \
+ ((ntohs (type) & OSPF6_LSTYPE_FCODE_MASK) < OSPF6_LSTYPE_SIZE ? \
+ ospf6_lstype_str[ntohs (type) & OSPF6_LSTYPE_FCODE_MASK] : \
+ ospf6_lstype_str[OSPF6_LSTYPE_UNKNOWN])
+#else /*0*/
+#define OSPF6_LSTYPE_NAME(type) (ospf6_lstype_name (type))
+#endif /*0*/
-/* MaxAge check. */
-/* ospf6_lsa_is_maxage (struct ospf6_lsa *lsa) */
-#define IS_LSA_MAXAGE(L) (ospf6_lsa_age_current (L) == OSPF6_LSA_MAXAGE)
+/* Macro for LSA Origination */
+/* void (CONTINUE_IF_...) (struct prefix *addr); */
-struct ospf6_lsa_slot *ospf6_lsa_slot_get (u_int16_t type);
-int ospf6_lsa_slot_register (struct ospf6_lsa_slot *src);
-int ospf6_lsa_slot_unregister (u_int16_t type);
-
-extern struct ospf6_lsa_slot *slot_head;
-#define CALL_FOREACH_LSA_HOOK(hook,func,data) \
- if (ospf6)\
- {\
- struct ospf6_lsa_slot *slot;\
- for (slot = slot_head; slot; slot = slot->next)\
- {\
- if (slot->hook.func)\
- (*slot->hook.func) (data);\
- }\
- }
-#define CALL_LSA_FUNC(type,func,data) \
- if (ospf6)\
- {\
- struct ospf6_lsa_slot *slot;\
- slot = ospf6_lsa_slot_get (type);\
- if (slot && slot->func)\
- {\
- (*slot->func) (data);\
- }\
- else\
- {\
- zlog_warn ("LSA: No slot for type %#x: %s line:%d",\
- ntohs (type), __FILE__, __LINE__);\
- }\
+#define CONTINUE_IF_ADDRESS_LINKLOCAL(addr)\
+ if (IN6_IS_ADDR_LINKLOCAL (&(addr)->u.prefix6)) \
+ { \
+ char buf[64]; \
+ prefix2str (addr, buf, sizeof (buf)); \
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) \
+ zlog_info ("Filter out Linklocal: %s", buf); \
+ continue; \
}
-#define CALL_LSA_DATABASE_ADD(type,data) \
- if (ospf6)\
- {\
- struct ospf6_lsa_slot *slot;\
- slot = ospf6_lsa_slot_get (type);\
- if (slot)\
- {\
- CALL_ADD_HOOK (&slot->database_hook, data);\
- }\
- else\
- {\
- zlog_warn ("LSA: No slot for type %#x: %s line:%d",\
- ntohs (type), __FILE__, __LINE__);\
- }\
- }
-#define CALL_LSA_DATABASE_CHANGE(type,data) \
- if (ospf6)\
- {\
- struct ospf6_lsa_slot *slot;\
- slot = ospf6_lsa_slot_get (type);\
- if (slot)\
- {\
- CALL_CHANGE_HOOK (&slot->database_hook, data);\
- }\
- else\
- {\
- zlog_warn ("LSA: No slot for type %#x: %s line:%d",\
- ntohs (type), __FILE__, __LINE__);\
- }\
- }
-#define CALL_LSA_DATABASE_REMOVE(type,data) \
- if (ospf6)\
- {\
- struct ospf6_lsa_slot *slot;\
- slot = ospf6_lsa_slot_get (type);\
- if (slot)\
- {\
- CALL_REMOVE_HOOK (&slot->database_hook, data);\
- }\
- else\
- {\
- zlog_warn ("LSA: No slot for type %#x: %s line:%d",\
- ntohs (type), __FILE__, __LINE__);\
- }\
+#define CONTINUE_IF_ADDRESS_UNSPECIFIED(addr) \
+ if (IN6_IS_ADDR_UNSPECIFIED (&(addr)->u.prefix6)) \
+ { \
+ char buf[64]; \
+ prefix2str (addr, buf, sizeof (buf)); \
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) \
+ zlog_info ("Filter out Unspecified: %s", buf); \
+ continue; \
}
-void ospf6_lsa_init ();
+#define CONTINUE_IF_ADDRESS_LOOPBACK(addr) \
+ if (IN6_IS_ADDR_LOOPBACK (&(addr)->u.prefix6)) \
+ { \
+ char buf[64]; \
+ prefix2str (addr, buf, sizeof (buf)); \
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) \
+ zlog_info ("Filter out Loopback: %s", buf); \
+ continue; \
+ }
+#define CONTINUE_IF_ADDRESS_V4COMPAT(addr) \
+ if (IN6_IS_ADDR_V4COMPAT (&(addr)->u.prefix6)) \
+ { \
+ char buf[64]; \
+ prefix2str (addr, buf, sizeof (buf)); \
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) \
+ zlog_info ("Filter out V4Compat: %s", buf); \
+ continue; \
+ }
+
+#define CONTINUE_IF_ADDRESS_V4MAPPED(addr) \
+ if (IN6_IS_ADDR_V4MAPPED (&(addr)->u.prefix6)) \
+ { \
+ char buf[64]; \
+ prefix2str (addr, buf, sizeof (buf)); \
+ if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) \
+ zlog_info ("Filter out V4Mapped: %s", buf); \
+ continue; \
+ }
+
+
/* Function Prototypes */
+char *ospf6_lstype_name (u_int16_t type);
+int ospf6_lsa_is_differ (struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2);
+int ospf6_lsa_is_changed (struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2);
+u_int16_t ospf6_lsa_age_current (struct ospf6_lsa *);
+void ospf6_lsa_age_update_to_send (struct ospf6_lsa *, u_int32_t);
+void ospf6_lsa_premature_aging (struct ospf6_lsa *);
+int ospf6_lsa_compare (struct ospf6_lsa *, struct ospf6_lsa *);
-struct router_lsd *
-get_router_lsd (u_int32_t, struct ospf6_lsa *);
-unsigned long get_ifindex_to_router (u_int32_t, struct ospf6_lsa *);
+char *ospf6_lsa_printbuf (struct ospf6_lsa *lsa, char *buf, int size);
+void ospf6_lsa_header_print_raw (struct ospf6_lsa_header *header);
+void ospf6_lsa_header_print (struct ospf6_lsa *lsa);
+void ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa);
+void ospf6_lsa_show_summary_header (struct vty *vty);
+void ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa);
+void ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa);
+void ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa);
-int ospf6_lsa_differ (struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2);
-int ospf6_lsa_match (u_int16_t, u_int32_t, u_int32_t,
- struct ospf6_lsa_header *);
+u_int32_t ospf6_lsa_new_seqnum (u_int16_t type, u_int32_t id,
+ u_int32_t adv_router, void *scope);
-void ospf6_lsa_show (struct vty *, struct ospf6_lsa *);
-void ospf6_lsa_show_dump (struct vty *, struct ospf6_lsa *);
-void ospf6_lsa_show_summary (struct vty *, struct ospf6_lsa *);
-void ospf6_lsa_show_summary_header (struct vty *);
-
-struct ospf6_lsa *
-ospf6_lsa_create (struct ospf6_lsa_header *);
-struct ospf6_lsa *
-ospf6_lsa_summary_create (struct ospf6_lsa_header__ *);
-void
-ospf6_lsa_delete (struct ospf6_lsa *);
+struct ospf6_lsa *ospf6_lsa_create (struct ospf6_lsa_header *header);
+struct ospf6_lsa *ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header);
+void ospf6_lsa_delete (struct ospf6_lsa *lsa);
+struct ospf6_lsa *ospf6_lsa_copy (struct ospf6_lsa *);
void ospf6_lsa_lock (struct ospf6_lsa *);
void ospf6_lsa_unlock (struct ospf6_lsa *);
-unsigned short ospf6_lsa_age_current (struct ospf6_lsa *);
-int ospf6_lsa_is_maxage (struct ospf6_lsa *);
-void ospf6_lsa_age_update_to_send (struct ospf6_lsa *, u_int32_t);
-void ospf6_lsa_premature_aging (struct ospf6_lsa *);
-
-int ospf6_lsa_check_recent (struct ospf6_lsa *, struct ospf6_lsa *);
-
-int
-ospf6_lsa_lsd_num (struct ospf6_lsa_header *lsa_header);
-void *
-ospf6_lsa_lsd_get (int index, struct ospf6_lsa_header *lsa_header);
-int
-ospf6_lsa_lsd_is_refer_ok (int index1, struct ospf6_lsa_header *lsa_header1,
- int index2, struct ospf6_lsa_header *lsa_header2);
-
+void ospf6_lsa_originate (struct ospf6_lsa *);
+void ospf6_lsa_re_originate (struct ospf6_lsa *lsa);
int ospf6_lsa_expire (struct thread *);
int ospf6_lsa_refresh (struct thread *);
-u_short ospf6_lsa_checksum (struct ospf6_lsa_header *);
+unsigned short ospf6_lsa_checksum (struct ospf6_lsa_header *);
+int ospf6_lsa_prohibited_duration (u_int16_t type, u_int32_t id,
+ u_int32_t adv_router, void *scope);
-void ospf6_lsa_update_network (char *ifname);
-void ospf6_lsa_update_link (char *ifname);
-void ospf6_lsa_update_as_external (u_int32_t ls_id);
-void ospf6_lsa_update_intra_prefix_transit (char *ifname);
-void ospf6_lsa_update_intra_prefix_stub (u_int32_t area_id);
+void ospf6_lsa_init ();
-u_int16_t ospf6_lsa_get_scope_type (u_int16_t);
-int ospf6_lsa_is_known_type (struct ospf6_lsa_header *lsa_header);
-
-char *ospf6_lsa_type_string (u_int16_t type, char *buf, int bufsize);
-char *ospf6_lsa_router_bits_string (u_char router_bits, char *buf, int size);
-
-u_long
-ospf6_lsa_has_elasped (u_int16_t, u_int32_t, u_int32_t, void *);
-void
-ospf6_lsa_originate (u_int16_t, u_int32_t, u_int32_t, char *, int, void *);
+int config_write_ospf6_debug_lsa (struct vty *vty);
+void install_element_ospf6_debug_lsa ();
#endif /* OSPF6_LSA_H */
diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c
index ad53eb4..97a278e 100644
--- a/ospf6d/ospf6_lsdb.c
+++ b/ospf6d/ospf6_lsdb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -24,24 +24,14 @@
#include "memory.h"
#include "log.h"
#include "command.h"
-#include "if.h"
+#include "prefix.h"
+#include "table.h"
-#include "ospf6_dump.h"
+#include "ospf6d.h"
+#include "ospf6_proto.h"
+#include "ospf6_lsa.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 0x10
-
-struct ospf6_lsdb_hook_t hooks[0x2000];
-struct ospf6_lsdb_hook_t *ospf6_lsdb_hook = hooks;
-
struct ospf6_lsdb *
ospf6_lsdb_create ()
{
@@ -68,656 +58,351 @@
}
static void
-ospf6_lsdb_set_key (struct prefix_ipv6 *key, int flag,
- u_int16_t type, u_int32_t id, u_int32_t adv_router)
+ospf6_lsdb_set_key (struct prefix_ipv6 *key, void *value, int len)
{
- int len = 0;
- memset (key, 0, sizeof (struct prefix_ipv6));
+ assert (key->prefixlen % 8 == 0);
- 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);
-
+ memcpy ((caddr_t) &key->prefix + key->prefixlen / 8,
+ (caddr_t) value, len);
key->family = AF_INET6;
- key->prefixlen = len * 8;
+ key->prefixlen += len * 8;
}
+#ifndef NDEBUG
+static void
+_lsdb_count_assert (struct ospf6_lsdb *lsdb)
+{
+ struct ospf6_lsa *debug;
+ int num = 0;
+ for (debug = ospf6_lsdb_head (lsdb); debug;
+ debug = ospf6_lsdb_next (debug))
+ num++;
+
+ if (num == lsdb->count)
+ return;
+
+ if (IS_OSPF6_DEBUG_LSA (DATABASE))
+ {
+ zlog_info ("PANIC !! lsdb[%p]->count = %d, real = %d",
+ lsdb, lsdb->count, num);
+ for (debug = ospf6_lsdb_head (lsdb); debug;
+ debug = ospf6_lsdb_next (debug))
+ zlog_info ("%p %p %s", debug->prev, debug->next, debug->name);
+ zlog_info ("DUMP END");
+ }
+ assert (num == lsdb->count);
+}
+#define ospf6_lsdb_count_assert(t) (_lsdb_count_assert (t))
+#else /*NDEBUG*/
+#define ospf6_lsdb_count_assert(t) ((void) 0)
+#endif /*NDEBUG*/
+
void
ospf6_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;
+ struct route_node *current, *nextnode, *prevnode;
+ struct ospf6_lsa *next, *prev, *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);
+ 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));
- rn = route_node_get (lsdb->table, (struct prefix *) &key);
- if (rn->info)
- old = rn->info;
- rn->info = lsa;
+ current = route_node_get (lsdb->table, (struct prefix *) &key);
+ old = current->info;
+ current->info = lsa;
ospf6_lsa_lock (lsa);
if (old)
- ospf6_lsa_unlock (old);
+ {
+ if (old->prev)
+ old->prev->next = lsa;
+ if (old->next)
+ old->next->prev = lsa;
+ lsa->next = old->next;
+ lsa->prev = old->prev;
+ }
else
- lsdb->count++;
+ {
+ /* next link */
+ nextnode = current;
+ route_lock_node (nextnode);
+ do {
+ nextnode = route_next (nextnode);
+ } while (nextnode && nextnode->info == NULL);
+ if (nextnode == NULL)
+ lsa->next = NULL;
+ else
+ {
+ next = nextnode->info;
+ lsa->next = next;
+ next->prev = lsa;
+ route_unlock_node (nextnode);
+ }
+
+ /* prev link */
+ prevnode = current;
+ route_lock_node (prevnode);
+ do {
+ prevnode = route_prev (prevnode);
+ } while (prevnode && prevnode->info == NULL);
+ if (prevnode == NULL)
+ lsa->prev = NULL;
+ else
+ {
+ prev = prevnode->info;
+ lsa->prev = prev;
+ prev->next = lsa;
+ route_unlock_node (prevnode);
+ }
+
+ lsdb->count++;
+ }
+
+ if (old)
+ {
+ 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);
+ }
+ }
+ else
+ {
+ if (lsdb->hook_remove)
+ (*lsdb->hook_remove) (old);
+ if (lsdb->hook_add)
+ (*lsdb->hook_add) (lsa);
+ }
+ }
+ }
+ else if (OSPF6_LSA_IS_MAXAGE (lsa))
+ {
+ if (lsdb->hook_remove)
+ (*lsdb->hook_remove) (lsa);
+ }
+ else
+ {
+ if (lsdb->hook_add)
+ (*lsdb->hook_add) (lsa);
+ }
+
+ if (old)
+ ospf6_lsa_unlock (old);
+
+ ospf6_lsdb_count_assert (lsdb);
}
void
ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
{
- int flag;
+ struct route_node *node;
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);
+ 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));
- 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;
- }
+ node = route_node_lookup (lsdb->table, (struct prefix *) &key);
+ assert (node && node->info == lsa);
- 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;
- }
+ if (lsa->prev)
+ lsa->prev->next = lsa->next;
+ if (lsa->next)
+ lsa->next->prev = lsa->prev;
- rn->info = NULL;
- ospf6_lsa_unlock (old);
+ node->info = NULL;
lsdb->count--;
-}
-static void
-ospf6_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;
+ if (lsdb->hook_remove)
+ (*lsdb->hook_remove) (lsa);
- 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 */
-void
-ospf6_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);
- }
-}
-
-void
-ospf6_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);
- }
-}
-
-void
-ospf6_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);
- }
-}
-
-void
-ospf6_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;
- }
+ ospf6_lsa_unlock (lsa);
+ route_unlock_node (node);
+ ospf6_lsdb_count_assert (lsdb);
}
struct ospf6_lsa *
ospf6_lsdb_lookup (u_int16_t type, u_int32_t id, u_int32_t adv_router,
- void *scope)
+ struct ospf6_lsdb *lsdb)
{
- struct ospf6_interface *o6i;
- struct ospf6_area *o6a;
- listnode i, j;
+ struct route_node *node;
+ struct prefix_ipv6 key;
- if (scope == (void *) ospf6)
- return ospf6_lsdb_lookup_lsdb (type, id, adv_router, ospf6->lsdb);
+ if (lsdb == NULL)
+ return NULL;
- for (i = listhead (ospf6->area_list); i; nextnode (i))
- {
- o6a = getdata (i);
+ 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));
- 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;
+ node = route_node_lookup (lsdb->table, (struct prefix *) &key);
+ if (node == NULL || node->info == NULL)
+ return NULL;
+ return (struct ospf6_lsa *) node->info;
}
-void
-ospf6_lsdb_install (struct ospf6_lsa *new)
+/* Iteration function */
+struct ospf6_lsa *
+ospf6_lsdb_head (struct ospf6_lsdb *lsdb)
{
- struct ospf6_lsdb *lsdb;
- struct ospf6_lsa *old;
- int need_hook = 0;
- void (*hook) (struct ospf6_lsa *, struct ospf6_lsa *);
+ struct route_node *node;
- struct ospf6 *as = NULL;
- struct ospf6_area *area = NULL;
- struct ospf6_interface *linklocal = NULL;
- hook = NULL;
+ node = route_top (lsdb->table);
+ if (node == NULL)
+ return NULL;
- switch (ntohs (new->header->type) & OSPF6_LSTYPE_SCOPE_MASK)
+ /* skip to the existing lsdb entry */
+ while (node && node->info == NULL)
+ node = route_next (node);
+ if (node == NULL)
+ return NULL;
+
+ route_unlock_node (node);
+ if (node->info)
+ ospf6_lsa_lock ((struct ospf6_lsa *) node->info);
+ return (struct ospf6_lsa *) node->info;
+}
+
+struct ospf6_lsa *
+ospf6_lsdb_next (struct ospf6_lsa *lsa)
+{
+ struct ospf6_lsa *next = lsa->next;
+
+ ospf6_lsa_unlock (lsa);
+ if (next)
+ ospf6_lsa_lock (next);
+
+ return next;
+}
+
+/* Macro version of check_bit (). */
+#define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1)
+
+struct ospf6_lsa *
+ospf6_lsdb_type_router_head (u_int16_t type, u_int32_t adv_router,
+ struct ospf6_lsdb *lsdb)
+{
+ struct route_node *node;
+ struct prefix_ipv6 key;
+ struct ospf6_lsa *lsa;
+
+ memset (&key, 0, sizeof (key));
+ ospf6_lsdb_set_key (&key, &type, sizeof (type));
+ ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router));
+
+ node = lsdb->table->top;
+
+ /* Walk down tree. */
+ while (node && node->p.prefixlen <= key.prefixlen &&
+ prefix_match (&node->p, (struct prefix *) &key))
+ node = node->link[CHECK_BIT(&key.prefix, node->p.prefixlen)];
+
+ if (node)
+ route_lock_node (node);
+ while (node && node->info == NULL)
+ node = route_next (node);
+
+ if (node == NULL)
+ return NULL;
+ else
+ route_unlock_node (node);
+
+ if (! prefix_match ((struct prefix *) &key, &node->p))
+ return NULL;
+
+ lsa = node->info;
+ ospf6_lsa_lock (lsa);
+
+ return lsa;
+}
+
+struct ospf6_lsa *
+ospf6_lsdb_type_router_next (u_int16_t type, u_int32_t adv_router,
+ struct ospf6_lsa *lsa)
+{
+ struct ospf6_lsa *next = lsa->next;
+
+ if (next)
{
- 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;
- lsdb = as->lsdb;
- break;
- default:
- zlog_warn ("LSDB: Can't install: scope unknown: %s", new->str);
- return;
+ if (next->header->type != type ||
+ next->header->adv_router != adv_router)
+ next = NULL;
}
- /* whether schedule calculation or not */
- old = ospf6_lsdb_lookup_lsdb (new->header->type, new->header->id,
- new->header->adv_router, lsdb);
+ if (next)
+ ospf6_lsa_lock (next);
+ ospf6_lsa_unlock (lsa);
+ return next;
+}
- if (! old || ospf6_lsa_differ (old, new))
- need_hook++;
+struct ospf6_lsa *
+ospf6_lsdb_type_head (u_int16_t type, struct ospf6_lsdb *lsdb)
+{
+ struct route_node *node;
+ struct prefix_ipv6 key;
+ struct ospf6_lsa *lsa;
- /* log */
- if (IS_OSPF6_DUMP_LSDB)
- zlog_info ("LSDB: Install: %s %s", new->str,
- ((IS_LSA_MAXAGE (new)) ? "(MaxAge)" : ""));
+ memset (&key, 0, sizeof (key));
+ ospf6_lsdb_set_key (&key, &type, sizeof (type));
- if (old)
- ospf6_lsa_lock (old);
+ /* Walk down tree. */
+ node = lsdb->table->top;
+ while (node && node->p.prefixlen <= key.prefixlen &&
+ prefix_match (&node->p, (struct prefix *) &key))
+ node = node->link[CHECK_BIT(&key.prefix, node->p.prefixlen)];
- ospf6_lsdb_add (new, lsdb);
- gettimeofday (&new->installed, NULL);
+ if (node)
+ route_lock_node (node);
+ while (node && node->info == NULL)
+ node = route_next (node);
- hook = ospf6_lsdb_hook[ntohs (new->header->type) &
- OSPF6_LSTYPE_CODE_MASK].hook;
- if (need_hook && hook)
- (*hook) (old, new);
+ if (node == NULL)
+ return NULL;
+ else
+ route_unlock_node (node);
- /* old LSA should be freed here */
- if (old)
- ospf6_lsa_unlock (old);
+ if (! prefix_match ((struct prefix *) &key, &node->p))
+ return NULL;
+
+ lsa = node->info;
+ ospf6_lsa_lock (lsa);
+
+ return lsa;
+}
+
+struct ospf6_lsa *
+ospf6_lsdb_type_next (u_int16_t type, struct ospf6_lsa *lsa)
+{
+ struct ospf6_lsa *next = lsa->next;
+
+ if (next)
+ {
+ if (next->header->type != type)
+ next = NULL;
+ }
+
+ if (next)
+ ospf6_lsa_lock (next);
+ ospf6_lsa_unlock (lsa);
+ return next;
}
void
ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb)
{
- struct ospf6_lsdb_node node;
- for (ospf6_lsdb_head (&node, lsdb); ! ospf6_lsdb_is_end (&node);
- ospf6_lsdb_next (&node))
- ospf6_lsdb_remove (node.lsa, lsdb);
-}
-
-void
-ospf6_lsdb_remove_maxage (struct ospf6_lsdb *lsdb)
-{
- struct ospf6_lsdb_node node;
struct ospf6_lsa *lsa;
-
- for (ospf6_lsdb_head (&node, lsdb); ! ospf6_lsdb_is_end (&node);
- ospf6_lsdb_next (&node))
- {
- lsa = node.lsa;
-
- /* contiue if it's not MaxAge */
- if (! IS_LSA_MAXAGE (lsa))
- continue;
-
- /* continue if it's referenced by some retrans-lists */
- if (lsa->lock != 1)
- continue;
-
- if (IS_OSPF6_DUMP_LSDB)
- zlog_info ("Remove MaxAge LSA: %s", lsa->str);
-
- ospf6_lsdb_remove (lsa, lsdb);
- }
-}
-
-
-
-/* vty functions */
-
-static int
-ospf6_lsdb_match (int flag, u_int16_t type, u_int32_t id,
- u_int32_t adv_router, struct ospf6_lsa *lsa)
-{
- if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_TYPE) &&
- lsa->header->type != type)
- return 0;
-
- if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_ID) &&
- lsa->header->id != id)
- return 0;
-
- if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_ADV_ROUTER) &&
- lsa->header->adv_router != adv_router)
- return 0;
-
- return 1;
-}
-
-int
-show_ipv6_ospf6_lsdb (struct vty *vty, int argc, char **argv,
- struct ospf6_lsdb *lsdb)
-{
- u_int flag;
- u_int16_t type = 0;
- u_int32_t id, adv_router;
- int ret;
- struct ospf6_lsdb_node node;
- char invalid[32], *invalidp;
- int l_argc = argc;
- char **l_argv = argv;
-
- flag = 0;
- memset (invalid, 0, sizeof (invalid));
- invalidp = invalid;
-
- /* chop tail if the words is 'dump' or 'summary' */
- if (l_argc > 0 && ! strcmp (l_argv[l_argc - 1], "dump"))
- {
- SET_FLAG (flag, OSPF6_LSDB_SHOW_DUMP);
- l_argc --;
- }
- else if (l_argc > 0 && ! strcmp (l_argv[l_argc - 1], "detail"))
- {
- SET_FLAG (flag, OSPF6_LSDB_SHOW_DETAIL);
- l_argc --;
- }
-
- if (l_argc > 0)
- {
- SET_FLAG (flag, OSPF6_LSDB_MATCH_TYPE);
- if (! strncmp (l_argv[0], "r", 1))
- type = htons (OSPF6_LSA_TYPE_ROUTER);
- if (! strncmp (l_argv[0], "n", 1))
- type = htons (OSPF6_LSA_TYPE_NETWORK);
- if (! strncmp (l_argv[0], "a", 1))
- type = htons (OSPF6_LSA_TYPE_AS_EXTERNAL);
- if (! strcmp (l_argv[0], "intra-prefix"))
- type = htons (OSPF6_LSA_TYPE_INTRA_PREFIX);
- if (! strcmp (l_argv[0], "inter-router"))
- type = htons (OSPF6_LSA_TYPE_INTER_ROUTER);
- if (! strcmp (l_argv[0], "inter-prefix"))
- type = htons (OSPF6_LSA_TYPE_INTER_PREFIX);
- if (! strncmp (l_argv[0], "l", 1))
- type = htons (OSPF6_LSA_TYPE_LINK);
- if (! strncmp (l_argv[0], "0x", 2) && strlen (l_argv[0]) == 6)
- type = htons ((short) strtol (l_argv[0], (char **)NULL, 16));
- if (! strncmp (l_argv[0], "*", 1))
- UNSET_FLAG (flag, OSPF6_LSDB_MATCH_TYPE);
- }
-
- if (l_argc > 1)
- {
- SET_FLAG (flag, OSPF6_LSDB_MATCH_ID);
- if (! strncmp (l_argv[1], "*", 1))
- UNSET_FLAG (flag, OSPF6_LSDB_MATCH_ID);
- else
- {
- ret = inet_pton (AF_INET, l_argv[1], &id);
- if (ret != 1)
- {
- id = htonl (strtoul (l_argv[1], &invalidp, 10));
- if (invalid[0] != '\0')
- {
- vty_out (vty, "Link State ID is not parsable: %s%s",
- l_argv[1], VTY_NEWLINE);
- return CMD_SUCCESS;
- }
- }
- }
- }
-
- if (l_argc > 2)
- {
- SET_FLAG (flag, OSPF6_LSDB_MATCH_ADV_ROUTER);
- if (! strncmp (l_argv[2], "*", 1))
- UNSET_FLAG (flag, OSPF6_LSDB_MATCH_ADV_ROUTER);
- else
- {
- ret = inet_pton (AF_INET, l_argv[2], &adv_router);
- if (ret != 1)
- {
- adv_router = htonl (strtoul (l_argv[2], &invalidp, 10));
- if (invalid[0] != '\0')
- {
- vty_out (vty, "Advertising Router is not parsable: %s%s",
- l_argv[2], VTY_NEWLINE);
- return CMD_SUCCESS;
- }
- }
- }
- }
-
- if (! CHECK_FLAG (flag, OSPF6_LSDB_SHOW_DETAIL))
- ospf6_lsa_show_summary_header (vty);
-
- for (ospf6_lsdb_head (&node, lsdb); ! ospf6_lsdb_is_end (&node);
- ospf6_lsdb_next (&node))
- {
- if (! ospf6_lsdb_match (flag, type, id, adv_router, node.lsa))
- continue;
-
- if (CHECK_FLAG (flag, OSPF6_LSDB_SHOW_DUMP))
- ospf6_lsa_show_dump (vty, node.lsa);
- else if (CHECK_FLAG (flag, OSPF6_LSDB_SHOW_DETAIL))
- ospf6_lsa_show (vty, node.lsa);
- else
- ospf6_lsa_show_summary (vty, node.lsa);
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (show_ipv6_ospf6_database,
- show_ipv6_ospf6_database_cmd,
- "show ipv6 ospf6 database",
- SHOW_STR
- IP6_STR
- OSPF6_STR
- "LSA Database\n"
- )
-{
- struct ospf6_area *o6a;
- struct ospf6_interface *o6i;
- listnode i, j;
-
- /* call show function for each of LSAs in the LSDBs */
-
- for (i = listhead (ospf6->area_list); i; nextnode (i))
- {
- o6a = (struct ospf6_area *) getdata (i);
-
- /* LinkLocal LSDBs */
- for (j = listhead (o6a->if_list); j; nextnode (j))
- {
- o6i = (struct ospf6_interface *) getdata (j);
-
- vty_out (vty, "%s", VTY_NEWLINE);
- vty_out (vty, " Interface %s (Area: %s):%s",
- o6i->interface->name, o6a->str, VTY_NEWLINE);
- vty_out (vty, "%s", VTY_NEWLINE);
- show_ipv6_ospf6_lsdb (vty, argc, argv, o6i->lsdb);
- }
-
- /* Area LSDBs */
- vty_out (vty, "%s", VTY_NEWLINE);
- vty_out (vty, " Area %s:%s", o6a->str, VTY_NEWLINE);
- vty_out (vty, "%s", VTY_NEWLINE);
- show_ipv6_ospf6_lsdb (vty, argc, argv, o6a->lsdb);
- }
-
- /* AS LSDBs */
- vty_out (vty, "%s", VTY_NEWLINE);
- vty_out (vty, " AS:%s", VTY_NEWLINE);
- vty_out (vty, "%s", VTY_NEWLINE);
- show_ipv6_ospf6_lsdb (vty, argc, argv, ospf6->lsdb);
-
- return CMD_SUCCESS;
-}
-
-ALIAS (show_ipv6_ospf6_database,
- show_ipv6_ospf6_database_type_cmd,
- "show ipv6 ospf6 database (router|network|as-external|intra-prefix|inter-prefix|inter-router|link|*|HEX|dump|detail)",
- SHOW_STR
- IP6_STR
- OSPF6_STR
- "LSA Database\n"
- "Router-LSA\n"
- "Network-LSA\n"
- "AS-External-LSA\n"
- "Intra-Area-Prefix-LSA\n"
- "Inter-Area-Router-LSA\n"
- "Inter-Area-Prefix-LSA\n"
- "Link-LSA\n"
- "All LS Type\n"
- "Specify LS Type by Hex\n"
- "Dump raw LSA data in Hex\n"
- "show detail of LSAs\n"
- )
-
-ALIAS (show_ipv6_ospf6_database,
- show_ipv6_ospf6_database_type_id_cmd,
- "show ipv6 ospf6 database (router|network|as-external|intra-prefix|inter-prefix|inter-router|link|*|HEX) (A.B.C.D|*|dump|detail)",
- SHOW_STR
- IP6_STR
- OSPF6_STR
- "LSA Database\n"
- "Router-LSA\n"
- "Network-LSA\n"
- "AS-External-LSA\n"
- "Intra-Area-Prefix-LSA\n"
- "Inter-Area-Router-LSA\n"
- "Inter-Area-Prefix-LSA\n"
- "Link-LSA\n"
- "All LS Type\n"
- "Specify LS Type by Hex\n"
- "Link State ID\n"
- "All Link State ID\n"
- "Dump raw LSA data in Hex\n"
- "show detail of LSAs\n"
- )
-
-ALIAS (show_ipv6_ospf6_database,
- show_ipv6_ospf6_database_type_id_adv_router_cmd,
- "show ipv6 ospf6 database (router|network|as-external|intra-prefix|inter-prefix|inter-router|link|*|HEX) (A.B.C.D|*) (A.B.C.D|*|dump|detail)",
- SHOW_STR
- IP6_STR
- OSPF6_STR
- "LSA Database\n"
- "Router-LSA\n"
- "Network-LSA\n"
- "AS-External-LSA\n"
- "Intra-Area-Prefix-LSA\n"
- "Inter-Area-Router-LSA\n"
- "Inter-Area-Prefix-LSA\n"
- "Link-LSA\n"
- "All LS Type\n"
- "Specify LS Type by Hex\n"
- "Link State ID\n"
- "All Link State ID\n"
- "Advertising Router\n"
- "All Advertising Router\n"
- "Dump raw LSA data in Hex\n"
- "show detail of LSAs\n"
- )
-
-ALIAS (show_ipv6_ospf6_database,
- show_ipv6_ospf6_database_type_id_adv_router_dump_cmd,
- "show ipv6 ospf6 database (router|network|as-external|intra-prefix|inter-prefix|inter-router|link|*|HEX) (A.B.C.D|*) (A.B.C.D|*) (dump|detail|)",
- SHOW_STR
- IP6_STR
- OSPF6_STR
- "LSA Database\n"
- "Router-LSA\n"
- "Network-LSA\n"
- "AS-External-LSA\n"
- "Intra-Area-Prefix-LSA\n"
- "Inter-Area-Router-LSA\n"
- "Inter-Area-Prefix-LSA\n"
- "Link-LSA\n"
- "All LS Type\n"
- "Specify LS Type by Hex\n"
- "Link State ID\n"
- "All Link State ID\n"
- "Advertising Router\n"
- "All Advertising Router\n"
- "Dump raw LSA data in Hex\n"
- "show detail of LSAs\n"
- )
-
-void
-ospf6_lsdb_init ()
-{
- install_element (VIEW_NODE, &show_ipv6_ospf6_database_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_adv_router_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_adv_router_dump_cmd);
-
- install_element (ENABLE_NODE, &show_ipv6_ospf6_database_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_id_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_id_adv_router_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_id_adv_router_dump_cmd);
+ for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa))
+ ospf6_lsdb_remove (lsa, lsdb);
}
diff --git a/ospf6d/ospf6_lsdb.h b/ospf6d/ospf6_lsdb.h
index 50eedc8..94dfcb6 100644
--- a/ospf6d/ospf6_lsdb.h
+++ b/ospf6d/ospf6_lsdb.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -25,64 +25,146 @@
#include "prefix.h"
#include "table.h"
-#include "ospf6_prefix.h"
-#include "ospf6_lsa.h"
-
-struct ospf6_lsdb_node
-{
- struct prefix_ipv6 key;
-
- struct route_node *node;
- struct route_node *next;
-
- struct ospf6_lsa *lsa;
-};
-
struct ospf6_lsdb
{
struct route_table *table;
u_int32_t count;
- void (*hook) (struct ospf6_lsa *);
+ void (*hook_add) (struct ospf6_lsa *);
+ void (*hook_remove) (struct ospf6_lsa *);
};
-/* int ospf6_lsdb_is_end (struct ospf6_lsdb_node *lsdb_node); */
-#define ospf6_lsdb_is_end(lsdb_node) ((lsdb_node)->node == NULL ? 1 : 0)
+#define LSDB_FOREACH_LSA(vty, func, lsdb) \
+ do { \
+ struct ospf6_lsa *lsa; \
+ for (lsa = ospf6_lsdb_head (lsdb); lsa; \
+ lsa = ospf6_lsdb_next (lsa)) \
+ { \
+ (*(func)) (vty, lsa); \
+ } \
+ } while (0)
+#define LSDB_FOREACH_LSA_T(vty, func, lsdb, type) \
+ do { \
+ struct ospf6_lsa *lsa; \
+ for (lsa = ospf6_lsdb_type_head (type, lsdb); lsa; \
+ lsa = ospf6_lsdb_type_next (type, lsa)) \
+ { \
+ (*(func)) (vty, lsa); \
+ } \
+ } while (0)
+#define LSDB_FOREACH_LSA_I(vty, func, lsdb, id) \
+ do { \
+ struct ospf6_lsa *lsa; \
+ for (lsa = ospf6_lsdb_head (lsdb); lsa; \
+ lsa = ospf6_lsdb_next (lsa)) \
+ { \
+ if (lsa->header->id != id) \
+ continue; \
+ (*(func)) (vty, lsa); \
+ } \
+ } while (0)
+#define LSDB_FOREACH_LSA_R(vty, func, lsdb, router) \
+ do { \
+ struct ospf6_lsa *lsa; \
+ for (lsa = ospf6_lsdb_head (lsdb); lsa; \
+ lsa = ospf6_lsdb_next (lsa)) \
+ { \
+ if (lsa->header->adv_router != router) \
+ continue; \
+ (*(func)) (vty, lsa); \
+ } \
+ } while (0)
+#define LSDB_FOREACH_LSA_TI(vty, func, lsdb, type, id) \
+ do { \
+ struct ospf6_lsa *lsa; \
+ for (lsa = ospf6_lsdb_type_head (type, lsdb); lsa; \
+ lsa = ospf6_lsdb_type_next (type, lsa)) \
+ { \
+ if (lsa->header->id != id) \
+ continue; \
+ (*(func)) (vty, lsa); \
+ } \
+ } while (0)
+#define LSDB_FOREACH_LSA_TR(vty, func, lsdb, type, router) \
+ do { \
+ struct ospf6_lsa *lsa; \
+ for (lsa = ospf6_lsdb_type_router_head (type, router, lsdb); lsa; \
+ lsa = ospf6_lsdb_type_router_next (type, router, lsa)) \
+ { \
+ (*(func)) (vty, lsa); \
+ } \
+ } while (0)
+#define LSDB_FOREACH_LSA_IR(vty, func, lsdb, id, router) \
+ do { \
+ struct ospf6_lsa *lsa; \
+ for (lsa = ospf6_lsdb_head (lsdb); lsa; \
+ lsa = ospf6_lsdb_next (lsa)) \
+ { \
+ if (lsa->header->adv_router != router) \
+ continue; \
+ if (lsa->header->id != id) \
+ continue; \
+ (*(func)) (vty, lsa); \
+ } \
+ } while (0)
+#define LSDB_FOREACH_LSA_TIR(vty, func, lsdb, type, id, router) \
+ do { \
+ struct ospf6_lsa *lsa; \
+ lsa = ospf6_lsdb_lookup (type, id, router, lsdb); \
+ if (lsa) \
+ (*(func)) (vty, lsa); \
+ } while (0)
-/* global holding hooks for each LS type */
-struct ospf6_lsdb_hook_t
-{
- void (*hook) (struct ospf6_lsa *old, struct ospf6_lsa *new);
-};
-extern struct ospf6_lsdb_hook_t *ospf6_lsdb_hook;
+#define OSPF6_LSDB_MAXAGE_REMOVER(lsdb) \
+ do { \
+ struct ospf6_lsa *lsa; \
+ for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa)) \
+ { \
+ if (! OSPF6_LSA_IS_MAXAGE (lsa)) \
+ continue; \
+ if (lsa->refcnt != 0) \
+ continue; \
+ if (IS_OSPF6_DEBUG_LSA (TIMER)) \
+ zlog_info (" remove maxage %s", lsa->name); \
+ ospf6_lsdb_remove (lsa, lsdb); \
+ } \
+ } while (0)
/* Function Prototypes */
-struct ospf6_lsdb * ospf6_lsdb_create ();
+struct ospf6_lsdb *ospf6_lsdb_create ();
void ospf6_lsdb_delete (struct ospf6_lsdb *lsdb);
-void ospf6_lsdb_remove_maxage (struct ospf6_lsdb *lsdb);
-
-struct ospf6_lsa *
-ospf6_lsdb_lookup (u_int16_t type, u_int32_t id, u_int32_t adv_router,
- void *scope);
-
-void ospf6_lsdb_install (struct ospf6_lsa *new);
-
-void ospf6_lsdb_head (struct ospf6_lsdb_node *node, struct ospf6_lsdb *lsdb);
-void ospf6_lsdb_type (struct ospf6_lsdb_node *node, u_int16_t type,
- struct ospf6_lsdb *lsdb);
-void ospf6_lsdb_type_router (struct ospf6_lsdb_node *node, u_int16_t type,
- u_int32_t adv_router, struct ospf6_lsdb *lsdb);
-void ospf6_lsdb_next (struct ospf6_lsdb_node *node);
+struct ospf6_lsa *ospf6_lsdb_lookup (u_int16_t type, u_int32_t id,
+ u_int32_t adv_router,
+ struct ospf6_lsdb *lsdb);
void ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb);
void ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb);
+
+struct ospf6_lsa *ospf6_lsdb_head (struct ospf6_lsdb *lsdb);
+struct ospf6_lsa *ospf6_lsdb_next (struct ospf6_lsa *lsa);
+
+struct ospf6_lsa *ospf6_lsdb_type_router_head (u_int16_t type,
+ u_int32_t adv_router,
+ struct ospf6_lsdb *lsdb);
+struct ospf6_lsa *ospf6_lsdb_type_router_next (u_int16_t type,
+ u_int32_t adv_router,
+ struct ospf6_lsa *lsa);
+
+struct ospf6_lsa *ospf6_lsdb_type_head (u_int16_t type,
+ struct ospf6_lsdb *lsdb);
+struct ospf6_lsa *ospf6_lsdb_type_next (u_int16_t type,
+ struct ospf6_lsa *lsa);
+
void ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb);
-struct ospf6_lsa *
-ospf6_lsdb_lookup_lsdb (u_int16_t type, u_int32_t id, u_int32_t adv_router,
- struct ospf6_lsdb *lsdb);
+int ospf6_lsdb_show (struct vty *vty, int argc, char **argv,
+ struct ospf6_lsdb *lsdb);
+#if 0
void ospf6_lsdb_init ();
+void ospf6_lsdb_remove_maxage (struct ospf6_lsdb *lsdb);
+#endif
#endif /* OSPF6_LSDB_H */
+
diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c
index 3b7cfc9..4dfcdee 100644
--- a/ospf6d/ospf6_main.c
+++ b/ospf6d/ospf6_main.c
@@ -20,32 +20,30 @@
*/
#include <zebra.h>
+
#include "getopt.h"
#include "thread.h"
#include "log.h"
-#include <lib/version.h>
+#include "version.h"
#include "command.h"
#include "vty.h"
#include "memory.h"
+#include "if.h"
+#include "filter.h"
+#include "prefix.h"
+#include "plist.h"
#include "privs.h"
#include "ospf6d.h"
-#include "ospf6_network.h"
-
-void ospf6_init ();
-void ospf6_terminate ();
-void nexthop_init ();
-int ospf6_receive (struct thread *);
-
-extern int ospf6_sock;
/* Default configuration file name for ospf6d. */
#define OSPF6_DEFAULT_CONFIG "ospf6d.conf"
+
/* Default port values. */
#define OSPF6_VTY_PORT 2606
/* ospf6d privileges */
-zebra_capabilities_t _caps_p [] =
+zebra_capabilities_t _caps_p [] =
{
ZCAP_RAW,
ZCAP_BIND
@@ -75,7 +73,6 @@
{ "pid_file", required_argument, NULL, 'i'},
{ "vty_addr", required_argument, NULL, 'A'},
{ "vty_port", required_argument, NULL, 'P'},
- { "user", required_argument, NULL, 'u'},
{ "version", no_argument, NULL, 'v'},
{ "help", no_argument, NULL, 'h'},
{ 0 }
@@ -86,6 +83,7 @@
char config_default[] = SYSCONFDIR OSPF6_DEFAULT_CONFIG;
/* ospf6d program name. */
+char *progname;
/* is daemon? */
int daemon_mode = 0;
@@ -96,19 +94,6 @@
/* Process ID saved for use by init system */
char *pid_file = PATH_OSPF6D_PID;
-/* for reload */
-
-#ifdef MAXPATHLEN
-char _cwd[MAXPATHLEN];
-#else
-char _cwd[64];
-#endif
-
-char _progpath[64];
-int _argc;
-char **_argv;
-char **_envp;
-
/* Help information display. */
static void
usage (char *progname, int status)
@@ -124,43 +109,20 @@
-i, --pid_file Set process identifier file name\n\
-A, --vty_addr Set vty's bind address\n\
-P, --vty_port Set vty's port number\n\
--u, --user User and group to run as\n\
-v, --version Print program version\n\
-h, --help Display this help and exit\n\
\n\
-Report bugs to yasu@sfc.wide.ad.jp\n", progname);
+Report bugs to zebra@zebra.org\n", progname);
}
exit (status);
}
-
-
-void
-_reload ()
-{
- zlog_notice ("OSPF6d (Zebra-%s ospf6d-%s) reloaded",
- QUAGGA_VERSION, OSPF6_DAEMON_VERSION);
- ospf6_zebra_finish ();
- vty_finish ();
- execve (_progpath, _argv, _envp);
-}
-
-void
-terminate (int i)
-{
- ospf6_delete (ospf6);
- unlink (PATH_OSPF6D_PID);
- zlog_notice ("OSPF6d (Zebra-%s ospf6d-%s) terminated",
- QUAGGA_VERSION, OSPF6_DAEMON_VERSION);
- exit (i);
-}
/* SIGHUP handler. */
void
sighup (int sig)
{
zlog_info ("SIGHUP received");
- _reload ();
}
/* SIGINT handler. */
@@ -168,7 +130,7 @@
sigint (int sig)
{
zlog_info ("SIGINT received");
- terminate (0);
+ exit (0);
}
/* SIGTERM handler. */
@@ -176,7 +138,7 @@
sigterm (int sig)
{
zlog_info ("SIGTERM received");
- terminate (0);
+ exit (0);
}
/* SIGUSR1 handler. */
@@ -229,8 +191,8 @@
#endif
signal_set (SIGUSR1, sigusr1);
}
-
-/* Main routine of ospf6d. Treatment of argument and start ospf finite
+
+/* Main routine of ospf6d. Treatment of argument and starting ospf finite
state machine is handled here. */
int
main (int argc, char *argv[], char *envp[])
@@ -238,9 +200,8 @@
char *p;
int opt;
char *vty_addr = NULL;
- int vty_port = OSPF6_VTY_PORT;
+ int vty_port = 0;
char *config_file = NULL;
- char *progname;
struct thread thread;
int flag;
@@ -250,16 +211,6 @@
/* Preserve name of myself. */
progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);
- /* for reload */
- _argc = argc;
- _argv = argv;
- _envp = envp;
- getcwd (_cwd, sizeof (_cwd));
- if (*argv[0] == '.')
- snprintf (_progpath, sizeof (_progpath), "%s/%s", _cwd, _argv[0]);
- else
- snprintf (_progpath, sizeof (_progpath), "%s", argv[0]);
-
/* Command line argument treatment. */
while (1)
{
@@ -287,14 +238,14 @@
case 'P':
/* Deal with atoi() returning 0 on failure, and ospf6d not
listening on ospf6d port... */
- if (strcmp(optarg, "0") == 0)
+ if (strcmp(optarg, "0") == 0)
{
vty_port = 0;
break;
- }
+ }
vty_port = atoi (optarg);
vty_port = (vty_port ? vty_port : OSPF6_VTY_PORT);
- break;
+ break;
case 'u':
ospf6d_privs.user = ospf6d_privs.group = optarg;
break;
@@ -318,17 +269,25 @@
if (! daemon_mode)
flag = ZLOG_STDOUT;
else
- flag = ZLOG_NOLOG;
+ flag = 0;
zlog_default = openzlog (progname, flag, ZLOG_OSPF6,
- LOG_CONS|LOG_NDELAY|LOG_PID,
- LOG_DAEMON);
- zprivs_init (&ospf6d_privs);
+ LOG_CONS|LOG_NDELAY|LOG_PERROR|LOG_PID,
+ LOG_DAEMON);
+ zprivs_init (&ospf6d_privs);
+ /* initialize zebra libraries */
signal_init ();
cmd_init (1);
vty_init (master);
- ospf6_init ();
memory_init ();
+ if_init ();
+ access_list_init ();
+ prefix_list_init ();
+
+ /* initialize ospf6 */
+ ospf6_init ();
+
+ /* sort command vector */
sort_node ();
/* parse config file */
@@ -344,18 +303,13 @@
pid_output (pid_file);
#endif
- /* Make ospf protocol socket. */
- ospf6_serv_sock ();
- thread_add_read (master, ospf6_receive, NULL, ospf6_sock);
+ /* Make ospf6 vty socket. */
+ vty_serv_sock (vty_addr,
+ vty_port ? vty_port : OSPF6_VTY_PORT, OSPF6_VTYSH_PATH);
- /* Make ospf vty socket. */
- vty_serv_sock (vty_addr, vty_port, OSPF6_VTYSH_PATH);
-
-#ifdef DEBUG
/* Print start message */
- zlog_notice ("OSPF6d (Zebra-%s ospf6d-%s) starts",
+ zlog_notice ("OSPF6d (Quagga-%s ospf6d-%s) starts",
QUAGGA_VERSION, OSPF6_DAEMON_VERSION);
-#endif
/* Start finite state machine, here we go! */
while (thread_fetch (master, &thread))
@@ -363,9 +317,9 @@
/* Log in case thread failed */
zlog_warn ("Thread failed");
- terminate (0);
/* Not reached. */
exit (0);
}
+
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index 0e74b65..21b799e 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -19,1954 +19,2056 @@
* Boston, MA 02111-1307, USA.
*/
+#include <zebra.h>
+
+#include "log.h"
+#include "vty.h"
+#include "command.h"
+#include "thread.h"
+#include "linklist.h"
+
#include "ospf6d.h"
+#include "ospf6_proto.h"
+#include "ospf6_lsa.h"
+#include "ospf6_lsdb.h"
+#include "ospf6_network.h"
+#include "ospf6_message.h"
-int
-is_ospf6_message_dump (u_char type)
+#include "ospf6_top.h"
+#include "ospf6_area.h"
+#include "ospf6_neighbor.h"
+#include "ospf6_interface.h"
+
+#include "ospf6_flood.h"
+
+unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};
+char *ospf6_message_type_str[] =
+ { "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck" };
+
+/* print functions */
+
+static void
+ospf6_header_print (struct ospf6_header *oh)
{
- if (type > OSPF6_MESSAGE_TYPE_LSACK)
- type = OSPF6_MESSAGE_TYPE_UNKNOWN;
+ char router_id[16], area_id[16];
+ inet_ntop (AF_INET, &oh->router_id, router_id, sizeof (router_id));
+ inet_ntop (AF_INET, &oh->area_id, area_id, sizeof (area_id));
- switch (type)
- {
- case OSPF6_MESSAGE_TYPE_UNKNOWN:
- return 1;
- break;
- case OSPF6_MESSAGE_TYPE_HELLO:
- if (IS_OSPF6_DUMP_HELLO)
- return 1;
- break;
- case OSPF6_MESSAGE_TYPE_DBDESC:
- if (IS_OSPF6_DUMP_DBDESC)
- return 1;
- break;
- case OSPF6_MESSAGE_TYPE_LSREQ:
- if (IS_OSPF6_DUMP_LSREQ)
- return 1;
- break;
- case OSPF6_MESSAGE_TYPE_LSUPDATE:
- if (IS_OSPF6_DUMP_LSUPDATE)
- return 1;
- break;
- case OSPF6_MESSAGE_TYPE_LSACK:
- if (IS_OSPF6_DUMP_LSACK)
- return 1;
- break;
- default:
- break;
- }
- return 0;
+ zlog_info (" OSPFv%d Type:%d Len:%hu Router-ID:%s",
+ oh->version, oh->type, ntohs (oh->length), router_id);
+ zlog_info (" Area-ID:%s Cksum:%hx Instance-ID:%d",
+ area_id, ntohs (oh->checksum), oh->instance_id);
}
-#define IS_OSPF6_DUMP_MESSAGE(x) (is_ospf6_message_dump(x))
-
-char *ospf6_message_type_string[] =
-{
- "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck", NULL
-};
void
-ospf6_message_log_lsa_header (struct ospf6_lsa_header *lsa_header)
+ospf6_hello_print (struct ospf6_header *oh)
{
- char buf_id[16], buf_router[16], typebuf[32];
-
- inet_ntop (AF_INET, &lsa_header->advrtr, buf_router, sizeof (buf_router));
- inet_ntop (AF_INET, &lsa_header->ls_id, buf_id, sizeof (buf_id));
- zlog_info (" [%s ID=%s Adv=%s]",
- ospf6_lsa_type_string (lsa_header->type, typebuf,
- sizeof (typebuf)),
- buf_id, buf_router);
- zlog_info (" Age=%hu SeqNum=%#lx Cksum=%#hx Len=%hu",
- ntohs (lsa_header->age), (u_long)ntohl (lsa_header->seqnum),
- ntohs (lsa_header->checksum), ntohs (lsa_header->length));
-}
-
-static void
-ospf6_message_log_unknown (struct iovec *message)
-{
- zlog_info ("Message: Unknown");
-}
-
-static void
-ospf6_message_log_hello (struct iovec *message)
-{
- struct ospf6_header *ospf6_header;
- u_int16_t length_left;
struct ospf6_hello *hello;
- char dr_str[16], bdr_str[16];
- char *start, *end, *current;
+ char options[16];
+ char drouter[16], bdrouter[16], neighbor[16];
+ char *p;
- /* calculate length */
- ospf6_header = (struct ospf6_header *) message[0].iov_base;
- length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
- length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ?
- length_left : iov_totallen (message) - sizeof (struct ospf6_header));
+ ospf6_header_print (oh);
+ assert (oh->type == OSPF6_MESSAGE_TYPE_HELLO);
- hello = (struct ospf6_hello *) message[1].iov_base;
+ hello = (struct ospf6_hello *)
+ ((caddr_t) oh + sizeof (struct ospf6_header));
- inet_ntop (AF_INET, &hello->dr, dr_str, sizeof (dr_str));
- inet_ntop (AF_INET, &hello->bdr, bdr_str, sizeof (bdr_str));
+ inet_ntop (AF_INET, &hello->drouter, drouter, sizeof (drouter));
+ inet_ntop (AF_INET, &hello->bdrouter, bdrouter, sizeof (bdrouter));
+ ospf6_options_printbuf (hello->options, options, sizeof (options));
- zlog_info (" IFID:%ld Priority:%d Option:%s",
- (u_long)ntohl (hello->interface_id), hello->rtr_pri, "xxx");
- zlog_info (" HelloInterval:%hu Deadinterval:%hu",
- ntohs (hello->hello_interval),
- ntohs (hello->router_dead_interval));
- zlog_info (" DR:%s BDR:%s", dr_str, bdr_str);
+ zlog_info (" I/F-Id:%ld Priority:%d Option:%s",
+ (u_long) ntohl (hello->interface_id), hello->priority, options);
+ zlog_info (" HelloInterval:%hu DeadInterval:%hu",
+ ntohs (hello->hello_interval), ntohs (hello->dead_interval));
+ zlog_info (" DR:%s BDR:%s", drouter, bdrouter);
- start = (char *) (hello + 1);
- if (start >= (char *) message[1].iov_base + message[1].iov_len)
- start = message[2].iov_base;
- end = (char *) start + (length_left - sizeof (struct ospf6_hello));
-
- for (current = start; current < end; current += sizeof (u_int32_t))
+ for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
+ p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
+ p += sizeof (u_int32_t))
{
- char neighbor[16];
- inet_ntop (AF_INET, current, neighbor, sizeof (neighbor));
+ inet_ntop (AF_INET, (void *) p, neighbor, sizeof (neighbor));
zlog_info (" Neighbor: %s", neighbor);
}
+
+ if (p != OSPF6_MESSAGE_END (oh))
+ zlog_info ("Trailing garbage exists");
}
-static void
-ospf6_message_log_dbdesc (struct iovec *message)
+void
+ospf6_dbdesc_print (struct ospf6_header *oh)
{
- struct ospf6_header *ospf6_header;
- u_int16_t length_left;
struct ospf6_dbdesc *dbdesc;
- int i;
- char buffer[16];
- struct ospf6_lsa_header *lsa_header;
+ char options[16];
+ char *p;
- /* calculate length */
- ospf6_header = (struct ospf6_header *) message[0].iov_base;
- length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
- length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ?
- length_left : iov_totallen (message) - sizeof (struct ospf6_header));
+ ospf6_header_print (oh);
+ assert (oh->type == OSPF6_MESSAGE_TYPE_DBDESC);
- dbdesc = (struct ospf6_dbdesc *) message[1].iov_base;
- ospf6_options_string (dbdesc->options, buffer, sizeof (buffer));
+ dbdesc = (struct ospf6_dbdesc *)
+ ((caddr_t) oh + sizeof (struct ospf6_header));
- zlog_info (" Option:%s IFMTU:%hu", buffer, ntohs (dbdesc->ifmtu));
- zlog_info (" Bits:%s%s%s SeqNum:%#lx",
- (DD_IS_IBIT_SET (dbdesc->bits) ? "I" : "-"),
- (DD_IS_MBIT_SET (dbdesc->bits) ? "M" : "-"),
- (DD_IS_MSBIT_SET (dbdesc->bits) ? "m" : "s"),
- (u_long)ntohl (dbdesc->seqnum));
+ ospf6_options_printbuf (dbdesc->options, options, sizeof (options));
- for (lsa_header = (struct ospf6_lsa_header *) (dbdesc + 1);
- (char *)(lsa_header + 1) <= (char *)(message[1].iov_base + message[1].iov_len) &&
- (char *)(lsa_header + 1) <= (char *)dbdesc + length_left;
- lsa_header++)
- ospf6_message_log_lsa_header (lsa_header);
+ zlog_info (" MBZ: %#x Option: %s IfMTU: %hu",
+ dbdesc->reserved1, options, ntohs (dbdesc->ifmtu));
+ zlog_info (" MBZ: %#x Bits: %s%s%s SeqNum: %#lx",
+ dbdesc->reserved2,
+ (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) ? "I" : "-"),
+ (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) ? "M" : "-"),
+ (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
+ (u_long) ntohl (dbdesc->seqnum));
- length_left -= message[1].iov_len;
- for (i = 2; message[i].iov_base; i++)
- {
- for (lsa_header = (struct ospf6_lsa_header *) message[i].iov_base;
- (char *)(lsa_header + 1) <= (char *) (message[i].iov_base +
- message[i].iov_len) &&
- (char *)(lsa_header + 1) <= (char *) (message[i].iov_base + length_left);
- lsa_header++)
- ospf6_message_log_lsa_header (lsa_header);
- length_left -= message[i].iov_len;
- }
+ for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
+ p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
+ p += sizeof (struct ospf6_lsa_header))
+ ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
+
+ if (p != OSPF6_MESSAGE_END (oh))
+ zlog_info ("Trailing garbage exists");
}
-static void
-ospf6_message_log_lsreq (struct iovec *message)
+void
+ospf6_lsreq_print (struct ospf6_header *oh)
{
- struct ospf6_header *ospf6_header;
- u_int16_t length_left;
- int i;
- struct ospf6_lsreq *lsreq;
- char buf_router[16], buf_id[16], buf_type[16];
+ char id[16], adv_router[16];
+ char *p;
- /* calculate length */
- ospf6_header = (struct ospf6_header *) message[0].iov_base;
- length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
- length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ?
- length_left : iov_totallen (message) - sizeof (struct ospf6_header));
+ ospf6_header_print (oh);
+ assert (oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
- for (i = 1; message[i].iov_base; i++)
+ for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
+ p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
+ p += sizeof (struct ospf6_lsreq_entry))
{
- for (lsreq = (struct ospf6_lsreq *) message[i].iov_base;
- (char *)(lsreq + 1) <= (char *) (message[i].iov_base + message[i].iov_len) &&
- (char *)(lsreq + 1) <= (char *) (message[i].iov_base + length_left);
- lsreq++)
- {
- inet_ntop (AF_INET, &lsreq->adv_router, buf_router, sizeof (buf_router));
- inet_ntop (AF_INET, &lsreq->id, buf_id, sizeof (buf_id));
- zlog_info (" [%s ID=%s Adv=%s]",
- ospf6_lsa_type_string (lsreq->type, buf_type,
- sizeof (buf_type)),
- buf_id, buf_router);
- }
- length_left -= message[i].iov_len;
+ struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *) p;
+ inet_ntop (AF_INET, &e->adv_router, adv_router, sizeof (adv_router));
+ inet_ntop (AF_INET, &e->id, id, sizeof (id));
+ zlog_info (" [%s Id:%s Adv:%s]",
+ OSPF6_LSTYPE_NAME (e->type), id, adv_router);
}
+
+ if (p != OSPF6_MESSAGE_END (oh))
+ zlog_info ("Trailing garbage exists");
}
-static void
-ospf6_message_log_lsupdate (struct iovec *message)
+void
+ospf6_lsupdate_print (struct ospf6_header *oh)
{
- struct ospf6_header *ospf6_header;
- u_int16_t length_left;
- int i, lsanum;
struct ospf6_lsupdate *lsupdate;
- struct ospf6_lsa_header *lsa_header;
+ u_long num;
+ char *p;
- /* calculate length */
- ospf6_header = (struct ospf6_header *) message[0].iov_base;
- length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
- length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ?
- length_left : iov_totallen (message) - sizeof (struct ospf6_header));
+ ospf6_header_print (oh);
+ assert (oh->type == OSPF6_MESSAGE_TYPE_LSUPDATE);
- lsupdate = (struct ospf6_lsupdate *) message[1].iov_base;
- lsanum = ntohl (lsupdate->lsupdate_num);
+ lsupdate = (struct ospf6_lsupdate *)
+ ((caddr_t) oh + sizeof (struct ospf6_header));
- zlog_info (" Number of LSA: #%d", lsanum);
+ num = ntohl (lsupdate->lsa_number);
+ zlog_info (" Number of LSA: %ld", num);
- for (lsa_header = (struct ospf6_lsa_header *) (lsupdate + 1);
- (char *)lsa_header < (char *)(message[1].iov_base + message[1].iov_len) &&
- (char *)lsa_header < (char *)(message[1].iov_base + length_left);
- lsa_header = OSPF6_LSA_NEXT (lsa_header))
- ospf6_message_log_lsa_header (lsa_header);
- length_left -= message[1].iov_len;
-
- for (i = 2; message[i].iov_base; i++)
+ for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
+ p < OSPF6_MESSAGE_END (oh) &&
+ p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
+ p += OSPF6_LSA_SIZE (p))
{
+ ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
+ if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
+ {
+ zlog_info (" Malformed LSA length, quit printing");
+ break;
+ }
+ }
- for (lsa_header = (struct ospf6_lsa_header *) message[i].iov_base;
- (char *)lsa_header < (char *) (message[i].iov_base + message[i].iov_len) &&
- (char *)lsa_header < (char *) (message[i].iov_base + length_left);
- lsa_header = OSPF6_LSA_NEXT (lsa_header))
- ospf6_message_log_lsa_header (lsa_header);
- length_left -= message[i].iov_len;
+ if (p != OSPF6_MESSAGE_END (oh))
+ {
+ char buf[32];
+
+ int num = 0;
+ memset (buf, 0, sizeof (buf));
+
+ zlog_info (" Trailing garbage exists");
+ while (p < OSPF6_MESSAGE_END (oh))
+ {
+ snprintf (buf, sizeof (buf), "%s %2x", buf, *p++);
+ num++;
+ if (num == 8)
+ {
+ zlog_info (" %s", buf);
+ memset (buf, 0, sizeof (buf));
+ num = 0;
+ }
+ }
+ if (num)
+ zlog_info (" %s", buf);
}
}
-static void
-ospf6_message_log_lsack (struct iovec *message)
+void
+ospf6_lsack_print (struct ospf6_header *oh)
{
- struct ospf6_header *ospf6_header;
- u_int16_t length_left;
- struct ospf6_lsa_header *lsa_header;
- int i;
+ char *p;
- /* calculate length */
- ospf6_header = (struct ospf6_header *) message[0].iov_base;
- length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
- length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ?
- length_left : iov_totallen (message) - sizeof (struct ospf6_header));
+ ospf6_header_print (oh);
+ assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
- for (i = 1; message[i].iov_base; i++)
- {
- for (lsa_header = (struct ospf6_lsa_header *) message[i].iov_base;
- (char *)(lsa_header + 1) <= (char *) (message[i].iov_base +
- message[i].iov_len) &&
- (char *)(lsa_header + 1) <= (char *) (message[i].iov_base + length_left);
- lsa_header++)
- ospf6_message_log_lsa_header (lsa_header);
- length_left -= message[i].iov_len;
- }
+ for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
+ p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
+ p += sizeof (struct ospf6_lsa_header))
+ ospf6_lsa_header_print_raw ((struct ospf6_lsa_header *) p);
+
+ if (p != OSPF6_MESSAGE_END (oh))
+ zlog_info ("Trailing garbage exists");
}
-struct {
- void (*message_log) (struct iovec *);
-} ospf6_message_log_body [] =
+/* Receive function */
+#define MSG_OK 0
+#define MSG_NG 1
+static int
+ospf6_header_examin (struct in6_addr *src, struct in6_addr *dst,
+ struct ospf6_interface *oi, struct ospf6_header *oh)
{
- {ospf6_message_log_unknown},
- {ospf6_message_log_hello},
- {ospf6_message_log_dbdesc},
- {ospf6_message_log_lsreq},
- {ospf6_message_log_lsupdate},
- {ospf6_message_log_lsack},
-};
-
-static void
-ospf6_message_log (struct iovec *message)
-{
- struct ospf6_header *o6h;
- char router_id[16], area_id[16];
u_char type;
+ type = OSPF6_MESSAGE_TYPE_CANONICAL (oh->type);
- assert (message[0].iov_len == sizeof (struct ospf6_header));
- o6h = (struct ospf6_header *) message[0].iov_base;
-
- inet_ntop (AF_INET, &o6h->router_id, router_id, sizeof (router_id));
- inet_ntop (AF_INET, &o6h->area_id, area_id, sizeof (area_id));
-
- zlog_info (" OSPFv%d Type:%d Len:%hu RouterID:%s",
- o6h->version, o6h->type, ntohs (o6h->len), router_id);
- zlog_info (" AreaID:%s Cksum:%hx InstanceID:%d",
- area_id, ntohs (o6h->cksum), o6h->instance_id);
-
- type = (OSPF6_MESSAGE_TYPE_UNKNOWN < o6h->type &&
- o6h->type <= OSPF6_MESSAGE_TYPE_LSACK ?
- o6h->type : OSPF6_MESSAGE_TYPE_UNKNOWN);
- (* ospf6_message_log_body[type].message_log) (&message[0]);
-}
-
-int
-ospf6_opt_is_mismatch (unsigned char opt, char *options1, char *options2)
-{
- return (OSPF6_OPT_ISSET (options1, opt) ^ OSPF6_OPT_ISSET (options2, opt));
-}
-
-
-void
-ospf6_process_unknown (struct iovec *message,
- struct in6_addr *src,
- struct in6_addr *dst,
- struct ospf6_interface *o6i,
- u_int32_t router_id)
-{
- zlog_warn ("unknown message type, drop");
-}
-
-void
-ospf6_process_hello (struct iovec *message,
- struct in6_addr *src,
- struct in6_addr *dst,
- struct ospf6_interface *o6i,
- u_int32_t router_id)
-{
- struct ospf6_header *ospf6_header;
- u_int16_t length;
- struct ospf6_hello *hello;
- char changes = 0;
-#define CHANGE_RTRPRI (1 << 0)
-#define CHANGE_DR (1 << 1)
-#define CHANGE_BDR (1 << 2)
- int twoway = 0, backupseen = 0, nbchange = 0;
- u_int32_t *router_id_ptr;
- int i, seenrtrnum = 0, router_id_space = 0;
- char strbuf[64];
- struct ospf6_neighbor *o6n = NULL;
-
- /* assert interface */
- assert (o6i);
-
- /* caluculate length */
- ospf6_header = (struct ospf6_header *) message[0].iov_base;
- length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
- length = (length < message[1].iov_len ? length : message[1].iov_len);
-
- /* set hello pointer */
- hello = (struct ospf6_hello *) message[1].iov_base;
-
- /* find neighbor. if cannot be found, create */
- o6n = ospf6_neighbor_lookup (router_id, o6i);
- if (!o6n)
+ /* version check */
+ if (oh->version != OSPFV3_VERSION)
{
- o6n = ospf6_neighbor_create (router_id, o6i);
- o6n->ifid = ntohl (hello->interface_id);
- o6n->prevdr = o6n->dr = hello->dr;
- o6n->prevbdr = o6n->bdr = hello->bdr;
- o6n->priority = hello->rtr_pri;
- memcpy (&o6n->hisaddr, src, sizeof (struct in6_addr));
+ if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
+ zlog_info ("Message with unknown version");
+ return MSG_NG;
}
+ /* Area-ID check */
+ if (oh->area_id != oi->area->area_id)
+ {
+ if (oh->area_id == 0)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
+ zlog_info ("Message may be via Virtual Link: not supported");
+ return MSG_NG;
+ }
+
+ if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
+ zlog_info ("Area-ID mismatch");
+ return MSG_NG;
+ }
+
+ /* Instance-ID check */
+ if (oh->instance_id != oi->instance_id)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (type, RECV))
+ zlog_info ("Instance-ID mismatch");
+ return MSG_NG;
+ }
+
+ /* Router-ID check */
+ if (oh->router_id == oi->area->ospf6->router_id)
+ zlog_warn ("Detect duplicate Router-ID");
+
+ return MSG_OK;
+}
+
+void
+ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst,
+ struct ospf6_interface *oi, struct ospf6_header *oh)
+{
+ struct ospf6_hello *hello;
+ struct ospf6_neighbor *on;
+ char *p;
+ int twoway = 0;
+ int neighborchange = 0;
+ int backupseen = 0;
+
+ if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
+ return;
+
+ hello = (struct ospf6_hello *)
+ ((caddr_t) oh + sizeof (struct ospf6_header));
+
/* HelloInterval check */
- if (ntohs (hello->hello_interval) != o6i->hello_interval)
+ if (ntohs (hello->hello_interval) != oi->hello_interval)
{
- zlog_warn ("HelloInterval mismatch with %s", o6n->str);
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("HelloInterval mismatch");
return;
}
/* RouterDeadInterval check */
- if (ntohs (hello->router_dead_interval)
- != o6i->dead_interval)
+ if (ntohs (hello->dead_interval) != oi->dead_interval)
{
- zlog_warn ("RouterDeadInterval mismatch with %s", o6n->str);
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("RouterDeadInterval mismatch");
return;
}
- /* check options */
- /* Ebit */
- if (ospf6_opt_is_mismatch (OSPF6_OPT_E, hello->options, o6i->area->options))
+ /* E-bit check */
+ if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) !=
+ OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E))
{
- zlog_warn ("Ebit mismatch with %s", o6n->str);
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("E-bit mismatch");
return;
}
- /* RouterPriority set */
- if (o6n->priority != hello->rtr_pri)
+ /* Find neighbor, create if not exist */
+ on = ospf6_neighbor_lookup (oh->router_id, oi);
+ if (on == NULL)
{
- o6n->priority = hello->rtr_pri;
- if (IS_OSPF6_DUMP_HELLO)
- zlog_info ("%s: RouterPriority changed", o6n->str);
- changes |= CHANGE_RTRPRI;
- }
-
- /* DR set */
- if (o6n->dr != hello->dr)
- {
- /* save previous dr, set current */
- o6n->prevdr = o6n->dr;
- o6n->dr = hello->dr;
- inet_ntop (AF_INET, &o6n->dr, strbuf, sizeof (strbuf));
- if (IS_OSPF6_DUMP_HELLO)
- zlog_info ("%s declare %s as DR", o6n->str, strbuf);
- changes |= CHANGE_DR;
- }
-
- /* BDR set */
- if (o6n->bdr != hello->bdr)
- {
- /* save previous bdr, set current */
- o6n->prevbdr = o6n->bdr;
- o6n->bdr = hello->bdr;
- inet_ntop (AF_INET, &o6n->bdr, strbuf, sizeof (strbuf));
- if (IS_OSPF6_DUMP_HELLO)
- zlog_info ("%s declare %s as BDR", o6n->str, strbuf);
- changes |= CHANGE_BDR;
+ on = ospf6_neighbor_create (oh->router_id, oi);
+ on->prev_drouter = on->drouter = hello->drouter;
+ on->prev_bdrouter = on->bdrouter = hello->bdrouter;
+ on->priority = hello->priority;
+ on->ifindex = ntohl (hello->interface_id);
+ memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr));
}
/* TwoWay check */
- router_id_space = length - sizeof (struct ospf6_hello);
- seenrtrnum = router_id_space / sizeof (u_int32_t);
- router_id_ptr = (u_int32_t *) (hello + 1);
- for (i = 0; i < seenrtrnum; i++)
+ for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello));
+ p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh);
+ p += sizeof (u_int32_t))
{
- if (*router_id_ptr == o6i->area->ospf6->router_id)
+ u_int32_t *router_id = (u_int32_t *) p;
+
+ if (*router_id == oi->area->ospf6->router_id)
twoway++;
- router_id_ptr++;
}
- /* execute neighbor events */
- thread_execute (master, hello_received, o6n, 0);
- if (twoway)
- thread_execute (master, twoway_received, o6n, 0);
- else
- thread_execute (master, oneway_received, o6n, 0);
+ if (p != OSPF6_MESSAGE_END (oh))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Trailing garbage ignored");
+ }
+
+ /* RouterPriority check */
+ if (on->priority != hello->priority)
+ {
+ on->priority = hello->priority;
+ neighborchange++;
+ }
+
+ /* DR check */
+ if (on->drouter != hello->drouter)
+ {
+ on->prev_drouter = on->drouter;
+ on->drouter = hello->drouter;
+ if (on->prev_drouter == on->router_id || on->drouter == on->router_id)
+ neighborchange++;
+ }
+
+ /* BDR check */
+ if (on->bdrouter != hello->bdrouter)
+ {
+ on->prev_bdrouter = on->bdrouter;
+ on->bdrouter = hello->bdrouter;
+ if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id)
+ neighborchange++;
+ }
/* BackupSeen check */
- if (o6i->state == IFS_WAITING)
+ if (oi->state == OSPF6_INTERFACE_WAITING)
{
- if (hello->dr == hello->bdr &&
- hello->dr == o6n->router_id)
- zlog_warn ("*** DR Election of %s is illegal", o6n->str);
-
- if (hello->bdr == o6n->router_id)
+ if (hello->bdrouter == on->router_id)
backupseen++;
- else if (hello->dr == o6n->router_id && hello->bdr == 0)
+ else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0))
backupseen++;
}
- /* NeighborChange check */
- if (changes & CHANGE_RTRPRI)
- nbchange++;
- if (changes & CHANGE_DR)
- if (o6n->prevdr == o6n->router_id || o6n->dr == o6n->router_id)
- nbchange++;
- if (changes & CHANGE_BDR)
- if (o6n->prevbdr == o6n->router_id || o6n->bdr == o6n->router_id)
- nbchange++;
+ /* Execute neighbor events */
+ thread_execute (master, hello_received, on, 0);
+ if (twoway)
+ thread_execute (master, twoway_received, on, 0);
+ else
+ thread_execute (master, oneway_received, on, 0);
- /* schedule interface events */
+ /* Schedule interface events */
if (backupseen)
- thread_add_event (master, backup_seen, o6i, 0);
- if (nbchange)
- thread_add_event (master, neighbor_change, o6i, 0);
-
- return;
+ thread_add_event (master, backup_seen, oi, 0);
+ if (neighborchange)
+ thread_add_event (master, neighbor_change, oi, 0);
}
-int
-ospf6_dbdesc_is_master (struct ospf6_neighbor *o6n)
+static void
+ospf6_dbdesc_recv_master (struct ospf6_header *oh,
+ struct ospf6_neighbor *on)
{
- char buf[128];
-
- if (o6n->router_id == ospf6->router_id)
- {
- inet_ntop (AF_INET6, &o6n->hisaddr, buf, sizeof (buf));
- zlog_warn ("Message: Neighbor router-id conflicts: %s: %s",
- o6n->str, buf);
- return -1;
- }
- else if (ntohl (o6n->router_id) > ntohl (ospf6->router_id))
- return 0;
- return 1;
-}
-
-int
-ospf6_dbdesc_is_duplicate (struct ospf6_dbdesc *received,
- struct ospf6_dbdesc *last_received)
-{
- if (memcmp (received->options, last_received->options, 3) != 0)
- return 0;
- if (received->ifmtu != last_received->ifmtu)
- return 0;
- if (received->bits != last_received->bits)
- return 0;
- if (received->seqnum != last_received->seqnum)
- return 0;
- return 1;
-}
-
-void
-ospf6_process_dbdesc_master (struct iovec *message, struct ospf6_neighbor *o6n)
-{
- struct ospf6_header *ospf6_header;
- u_int16_t length, lsa_count;
struct ospf6_dbdesc *dbdesc;
- struct ospf6_lsa_header *lsa_header;
+ char *p;
- /* caluculate length */
- ospf6_header = (struct ospf6_header *) message[0].iov_base;
- length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
- length = (length < message[1].iov_len ? length : message[1].iov_len);
+ dbdesc = (struct ospf6_dbdesc *)
+ ((caddr_t) oh + sizeof (struct ospf6_header));
- /* set database description pointer */
- dbdesc = (struct ospf6_dbdesc *) message[1].iov_base;
-
- switch (o6n->state)
+ if (on->state < OSPF6_NEIGHBOR_INIT)
{
- case NBS_DOWN:
- case NBS_ATTEMPT:
- case NBS_TWOWAY:
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info ("DbDesc from %s Ignored: state less than Init",
- o6n->str);
- return;
-
- case NBS_INIT:
- thread_execute (master, twoway_received, o6n, 0);
- if (o6n->state != NBS_EXSTART)
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info ("DbDesc from %s Ignored: state less than ExStart",
- o6n->str);
- return;
- }
- /* else fall through to ExStart */
- case NBS_EXSTART:
- if (DDBIT_IS_SLAVE (dbdesc->bits) &&
- !DDBIT_IS_INITIAL (dbdesc->bits) &&
- ntohl (dbdesc->seqnum) == o6n->dbdesc_seqnum)
- {
- ospf6_neighbor_dbex_init (o6n);
-
- if (o6n->thread_rxmt_dbdesc)
- thread_cancel (o6n->thread_rxmt_dbdesc);
- o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
-
- thread_add_event (master, negotiation_done, o6n, 0);
- }
- else
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info (" negotiation failed with %s", o6n->str);
- return;
- }
- break;
-
- case NBS_EXCHANGE:
- /* duplicate dbdesc dropped by master */
- if (!memcmp (dbdesc, &o6n->last_dd,
- sizeof (struct ospf6_dbdesc)))
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info (" duplicate dbdesc, drop");
- return;
- }
-
- /* check Initialize bit and Master/Slave bit */
- if (DDBIT_IS_INITIAL (dbdesc->bits))
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info ("Initialize bit mismatch");
- thread_add_event (master, seqnumber_mismatch, o6n, 0);
- return;
- }
- if (DDBIT_IS_MASTER (dbdesc->bits))
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info ("Master/Slave bit mismatch");
- thread_add_event (master, seqnumber_mismatch, o6n, 0);
- return;
- }
-
- /* dbdesc option check */
- if (memcmp (dbdesc->options, o6n->last_dd.options,
- sizeof (dbdesc->options)))
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info ("dbdesc option field changed");
- thread_add_event (master, seqnumber_mismatch, o6n, 0);
- return;
- }
-
- /* dbdesc sequence number check */
- if (ntohl (dbdesc->seqnum) != o6n->dbdesc_seqnum)
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_warn ("*** dbdesc seqnumber mismatch: %d expected",
- o6n->dbdesc_seqnum);
- thread_add_event (master, seqnumber_mismatch, o6n, 0);
- return;
- }
- break;
-
- case NBS_LOADING:
- case NBS_FULL:
- /* duplicate dbdesc dropped by master */
- if (ospf6_dbdesc_is_duplicate (dbdesc, &o6n->last_dd))
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info (" duplicate dbdesc, drop");
- return;
- }
- else
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info (" not duplicate dbdesc in state %s",
- ospf6_neighbor_state_string[o6n->state]);
- thread_add_event (master, seqnumber_mismatch, o6n, 0);
- return;
- }
- break; /* not reached */
-
- default:
- assert (0);
- break; /* not reached */
- }
-
- /* process LSA headers */
- lsa_count = 0;
- for (lsa_header = (struct ospf6_lsa_header *) (dbdesc + 1);
- (char *)(lsa_header + 1) <= (char *)dbdesc + length;
- lsa_header++)
- {
- if (ospf6_dbex_check_dbdesc_lsa_header (lsa_header, o6n) < 0)
- {
- thread_add_event (master, seqnumber_mismatch, o6n, 0);
- return;
- }
- lsa_count ++;
- }
-
- /* increment dbdesc seqnum */
- o6n->dbdesc_seqnum++;
-
- /* cancel transmission/retransmission thread */
- if (o6n->thread_send_dbdesc)
- thread_cancel (o6n->thread_send_dbdesc);
- o6n->thread_send_dbdesc = (struct thread *) NULL;
- if (o6n->thread_rxmt_dbdesc)
- thread_cancel (o6n->thread_rxmt_dbdesc);
- o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
-
- /* more bit check */
- if (!DD_IS_MBIT_SET (dbdesc->bits) && !DD_IS_MBIT_SET (o6n->dbdesc_bits))
- thread_add_event (master, exchange_done, o6n, 0);
- else
- o6n->thread_send_dbdesc =
- thread_add_event (master, ospf6_send_dbdesc, o6n, 0);
-
- /* save last received dbdesc */
- memcpy (&o6n->last_dd, dbdesc, sizeof (struct ospf6_dbdesc));
-
- /* statistics */
- o6n->lsa_receive[OSPF6_MESSAGE_TYPE_DBDESC] += lsa_count;
-
- return;
-}
-
-void
-ospf6_process_dbdesc_slave (struct iovec *message, struct ospf6_neighbor *o6n)
-{
- struct ospf6_header *ospf6_header;
- u_int16_t length, lsa_count;
- struct ospf6_dbdesc *dbdesc;
- struct ospf6_lsa_header *lsa_header;
-
- /* caluculate length */
- ospf6_header = (struct ospf6_header *) message[0].iov_base;
- length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
- length = (length < message[1].iov_len ? length : message[1].iov_len);
-
- /* set database description pointer */
- dbdesc = (struct ospf6_dbdesc *) message[1].iov_base;
-
- switch (o6n->state)
- {
- case NBS_DOWN:
- case NBS_ATTEMPT:
- case NBS_TWOWAY:
- return;
- case NBS_INIT:
- thread_execute (master, twoway_received, o6n, 0);
- if (o6n->state != NBS_EXSTART)
- {
- return;
- }
- /* else fall through to ExStart */
- case NBS_EXSTART:
- if (DD_IS_IBIT_SET (dbdesc->bits) &&
- DD_IS_MBIT_SET (dbdesc->bits) &&
- DD_IS_MSBIT_SET (dbdesc->bits))
- {
- /* Master/Slave bit set to slave */
- DD_MSBIT_CLEAR (o6n->dbdesc_bits);
- /* Initialize bit clear */
- DD_IBIT_CLEAR (o6n->dbdesc_bits);
- /* sequence number set to master's */
- o6n->dbdesc_seqnum = ntohl (dbdesc->seqnum);
- ospf6_neighbor_dbex_init (o6n);
-
- if (o6n->thread_rxmt_dbdesc)
- thread_cancel (o6n->thread_rxmt_dbdesc);
- o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
-
- thread_add_event (master, negotiation_done, o6n, 0);
- }
- else
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info ("negotiation failed");
- return;
- }
- break;
-
- case NBS_EXCHANGE:
- /* duplicate dbdesc dropped by master */
- if (!memcmp (dbdesc, &o6n->last_dd,
- sizeof (struct ospf6_dbdesc)))
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info (" duplicate dbdesc, retransmit dbdesc");
-
- if (o6n->thread_rxmt_dbdesc)
- thread_cancel (o6n->thread_rxmt_dbdesc);
- o6n->thread_rxmt_dbdesc =
- thread_add_event (master, ospf6_send_dbdesc_rxmt, o6n, 0);
-
- return;
- }
-
- /* check Initialize bit and Master/Slave bit */
- if (DDBIT_IS_INITIAL (dbdesc->bits))
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info ("Initialize bit mismatch");
- thread_add_event (master, seqnumber_mismatch, o6n, 0);
- return;
- }
- if (DDBIT_IS_SLAVE (dbdesc->bits))
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info ("Master/Slave bit mismatch");
- thread_add_event (master, seqnumber_mismatch, o6n, 0);
- return;
- }
-
- /* dbdesc option check */
- if (memcmp (dbdesc->options, o6n->last_dd.options,
- sizeof (dbdesc->options)))
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info ("dbdesc option field changed");
- thread_add_event (master, seqnumber_mismatch, o6n, 0);
- return;
- }
-
- /* dbdesc sequence number check */
- if (ntohl (dbdesc->seqnum) != o6n->dbdesc_seqnum + 1)
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_warn ("*** dbdesc seqnumber mismatch: %d expected",
- o6n->dbdesc_seqnum + 1);
- thread_add_event (master, seqnumber_mismatch, o6n, 0);
- return;
- }
- break;
-
- case NBS_LOADING:
- case NBS_FULL:
- /* duplicate dbdesc cause slave to retransmit */
- if (ospf6_dbdesc_is_duplicate (dbdesc, &o6n->last_dd))
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info (" duplicate dbdesc, retransmit");
-
- if (o6n->thread_rxmt_dbdesc)
- thread_cancel (o6n->thread_rxmt_dbdesc);
- o6n->thread_rxmt_dbdesc =
- thread_add_event (master, ospf6_send_dbdesc_rxmt, o6n, 0);
-
- return;
- }
- else
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info (" not duplicate dbdesc in state %s",
- ospf6_neighbor_state_string[o6n->state]);
- thread_add_event (master, seqnumber_mismatch, o6n, 0);
- return;
- }
- break; /* not reached */
-
- default:
- assert (0);
- break; /* not reached */
- }
-
- /* process LSA headers */
- lsa_count = 0;
- for (lsa_header = (struct ospf6_lsa_header *) (dbdesc + 1);
- (char *)(lsa_header + 1) <= (char *)dbdesc + length;
- lsa_header++)
- {
- if (ospf6_dbex_check_dbdesc_lsa_header (lsa_header, o6n) < 0)
- {
- thread_add_event (master, seqnumber_mismatch, o6n, 0);
- return;
- }
- lsa_count ++;
- }
-
- /* set dbdesc seqnum to master's */
- o6n->dbdesc_seqnum = ntohl (dbdesc->seqnum);
-
- if (o6n->thread_send_dbdesc)
- thread_cancel (o6n->thread_send_dbdesc);
- o6n->thread_send_dbdesc =
- thread_add_event (master, ospf6_send_dbdesc, o6n, 0);
-
- /* save last received dbdesc */
- memcpy (&o6n->last_dd, dbdesc, sizeof (struct ospf6_dbdesc));
-
- /* statistics */
- o6n->lsa_receive[OSPF6_MESSAGE_TYPE_DBDESC] += lsa_count;
-
- return;
-}
-
-void
-ospf6_process_dbdesc (struct iovec *message,
- struct in6_addr *src,
- struct in6_addr *dst,
- struct ospf6_interface *o6i,
- u_int32_t router_id)
-{
- struct ospf6_header *ospf6_header;
- u_int16_t length;
- struct ospf6_neighbor *o6n;
- struct ospf6_dbdesc *dbdesc;
- int Im_master = 0;
-
- /* assert interface */
- assert (o6i);
-
- /* caluculate length */
- ospf6_header = (struct ospf6_header *) message[0].iov_base;
- length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
- length = (length < message[1].iov_len ? length : message[1].iov_len);
-
- /* set database description pointer */
- dbdesc = (struct ospf6_dbdesc *) message[1].iov_base;
-
- /* find neighbor. if cannot be found, reject this message */
- o6n = ospf6_neighbor_lookup (router_id, o6i);
- if (!o6n)
- {
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info ("neighbor not found, reject");
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Neighbor state less than Init, ignore");
return;
}
- if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr)))
+ switch (on->state)
{
- if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
- zlog_info ("From Secondary I/F of the neighbor: ignore");
+ case OSPF6_NEIGHBOR_TWOWAY:
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Neighbor state is 2-Way, ignore");
+ return;
+
+ case OSPF6_NEIGHBOR_INIT:
+ thread_execute (master, twoway_received, on, 0);
+ if (on->state != OSPF6_NEIGHBOR_EXSTART)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Neighbor state is not ExStart, ignore");
+ return;
+ }
+ /* else fall through to ExStart */
+
+ case OSPF6_NEIGHBOR_EXSTART:
+ /* if neighbor obeys us as our slave, schedule negotiation_done
+ and process LSA Headers. Otherwise, ignore this message */
+ if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
+ ! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
+ ntohl (dbdesc->seqnum) == on->dbdesc_seqnum)
+ {
+ /* execute NegotiationDone */
+ thread_execute (master, negotiation_done, on, 0);
+
+ /* Record neighbor options */
+ memcpy (on->options, dbdesc->options, sizeof (on->options));
+ }
+ else
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Negotiation failed");
+ return;
+ }
+ /* fall through to exchange */
+
+ case OSPF6_NEIGHBOR_EXCHANGE:
+ if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
+ {
+ /* Duplicated DatabaseDescription is dropped by master */
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Duplicated dbdesc discarded by Master, ignore");
+ return;
+ }
+
+ if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Master/Slave bit mismatch");
+ thread_add_event (master, seqnumber_mismatch, on, 0);
+ return;
+ }
+
+ if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Initialize bit mismatch");
+ thread_add_event (master, seqnumber_mismatch, on, 0);
+ return;
+ }
+
+ if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Option field mismatch");
+ thread_add_event (master, seqnumber_mismatch, on, 0);
+ return;
+ }
+
+ if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Sequence number mismatch (%#lx expected)",
+ (u_long) on->dbdesc_seqnum);
+ thread_add_event (master, seqnumber_mismatch, on, 0);
+ return;
+ }
+ break;
+
+ case OSPF6_NEIGHBOR_LOADING:
+ case OSPF6_NEIGHBOR_FULL:
+ if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
+ {
+ /* Duplicated DatabaseDescription is dropped by master */
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Duplicated dbdesc discarded by Master, ignore");
+ return;
+ }
+
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Not duplicate dbdesc in state %s",
+ ospf6_neighbor_state_str[on->state]);
+ thread_add_event (master, seqnumber_mismatch, on, 0);
+ return;
+
+ default:
+ assert (0);
+ break;
+ }
+
+ /* Process LSA headers */
+ for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
+ p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
+ p += sizeof (struct ospf6_lsa_header))
+ {
+ struct ospf6_lsa *his, *mine;
+ struct ospf6_lsdb *lsdb = NULL;
+
+ his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
+ his->scope = ospf6_get_lsa_scope (his->header->type, on);
+ lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope);
+ if (lsdb == NULL)
+ {
+ zlog_warn ("Can't decide scoped LSDB");
+ ospf6_lsa_delete (his);
+ thread_add_event (master, seqnumber_mismatch, on, 0);
+ return;
+ }
+
+ if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
+ ospf6_area_is_stub (on->ospf6_if->area))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("E-bit mismatch with LSA Headers");
+ ospf6_lsa_delete (his);
+ thread_add_event (master, seqnumber_mismatch, on, 0);
+ return;
+ }
+
+ mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
+ his->header->adv_router, lsdb);
+ if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
+ {
+ if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (DATABASE))
+ zlog_info ("Add %s's request-list: %s", on->name, his->name);
+ ospf6_lsdb_add (his, on->request_list);
+ }
+ else
+ ospf6_lsa_delete (his);
+ }
+
+ if (p != OSPF6_MESSAGE_END (oh))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Trailing garbage ignored");
+ }
+
+ /* Increment sequence number */
+ on->dbdesc_seqnum ++;
+
+ /* schedule send lsreq */
+ if (on->thread_send_lsreq == NULL)
+ on->thread_send_lsreq =
+ thread_add_event (master, ospf6_lsreq_send, on, 0);
+
+ THREAD_OFF (on->thread_send_dbdesc);
+
+ /* More bit check */
+ if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
+ ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
+ thread_add_event (master, exchange_done, on, 0);
+ else
+ on->thread_send_dbdesc =
+ thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
+
+ /* save last received dbdesc */
+ memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
+}
+
+static void
+ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
+ struct ospf6_neighbor *on)
+{
+ struct ospf6_dbdesc *dbdesc;
+ char *p;
+
+ dbdesc = (struct ospf6_dbdesc *)
+ ((caddr_t) oh + sizeof (struct ospf6_header));
+
+ if (on->state < OSPF6_NEIGHBOR_INIT)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Neighbor state less than Init, ignore");
return;
}
- /* interface mtu check */
- /* xxx */
-
- /* check am I master */
- Im_master = ospf6_dbdesc_is_master (o6n);
- if (Im_master < 0)
+ switch (on->state)
{
- return; /* can't decide which is master, return */
+ case OSPF6_NEIGHBOR_TWOWAY:
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Neighbor state is 2-Way, ignore");
+ return;
+
+ case OSPF6_NEIGHBOR_INIT:
+ thread_execute (master, twoway_received, on, 0);
+ if (on->state != OSPF6_NEIGHBOR_EXSTART)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Neighbor state is not ExStart, ignore");
+ return;
+ }
+ /* else fall through to ExStart */
+
+ case OSPF6_NEIGHBOR_EXSTART:
+ /* If the neighbor is Master, act as Slave. Schedule negotiation_done
+ and process LSA Headers. Otherwise, ignore this message */
+ if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT) &&
+ CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MBIT) &&
+ CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT) &&
+ ntohs (oh->length) == sizeof (struct ospf6_header) +
+ sizeof (struct ospf6_dbdesc))
+ {
+ /* set the master/slave bit to slave */
+ UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
+
+ /* set the DD sequence number to one specified by master */
+ on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
+
+ /* schedule NegotiationDone */
+ thread_execute (master, negotiation_done, on, 0);
+
+ /* Record neighbor options */
+ memcpy (on->options, dbdesc->options, sizeof (on->options));
+ }
+ else
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Negotiation failed");
+ return;
+ }
+ break;
+
+ case OSPF6_NEIGHBOR_EXCHANGE:
+ if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
+ {
+ /* Duplicated DatabaseDescription causes slave to retransmit */
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Duplicated dbdesc causes retransmit");
+ THREAD_OFF (on->thread_send_dbdesc);
+ on->thread_send_dbdesc =
+ thread_add_event (master, ospf6_dbdesc_send, on, 0);
+ return;
+ }
+
+ if (! CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_MSBIT))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Master/Slave bit mismatch");
+ thread_add_event (master, seqnumber_mismatch, on, 0);
+ return;
+ }
+
+ if (CHECK_FLAG (dbdesc->bits, OSPF6_DBDESC_IBIT))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Initialize bit mismatch");
+ thread_add_event (master, seqnumber_mismatch, on, 0);
+ return;
+ }
+
+ if (memcmp (on->options, dbdesc->options, sizeof (on->options)))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Option field mismatch");
+ thread_add_event (master, seqnumber_mismatch, on, 0);
+ return;
+ }
+
+ if (ntohl (dbdesc->seqnum) != on->dbdesc_seqnum + 1)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Sequence number mismatch (%#lx expected)",
+ (u_long) on->dbdesc_seqnum + 1);
+ thread_add_event (master, seqnumber_mismatch, on, 0);
+ return;
+ }
+ break;
+
+ case OSPF6_NEIGHBOR_LOADING:
+ case OSPF6_NEIGHBOR_FULL:
+ if (! memcmp (dbdesc, &on->dbdesc_last, sizeof (struct ospf6_dbdesc)))
+ {
+ /* Duplicated DatabaseDescription causes slave to retransmit */
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Duplicated dbdesc causes retransmit");
+ THREAD_OFF (on->thread_send_dbdesc);
+ on->thread_send_dbdesc =
+ thread_add_event (master, ospf6_dbdesc_send, on, 0);
+ return;
+ }
+
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Not duplicate dbdesc in state %s",
+ ospf6_neighbor_state_str[on->state]);
+ thread_add_event (master, seqnumber_mismatch, on, 0);
+ return;
+
+ default:
+ assert (0);
+ break;
}
- if (Im_master)
- ospf6_process_dbdesc_master (message, o6n);
- else
- ospf6_process_dbdesc_slave (message, o6n);
+ /* Process LSA headers */
+ for (p = (char *) ((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
+ p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
+ p += sizeof (struct ospf6_lsa_header))
+ {
+ struct ospf6_lsa *his, *mine;
+ struct ospf6_lsdb *lsdb = NULL;
- return;
+ his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
+ his->scope = ospf6_get_lsa_scope (his->header->type, on);
+ lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope);
+ if (lsdb == NULL)
+ {
+ zlog_warn ("Can't decide scoped LSDB");
+ ospf6_lsa_delete (his);
+ thread_add_event (master, seqnumber_mismatch, on, 0);
+ return;
+ }
+
+ if (ntohs (his->header->type) == OSPF6_LSTYPE_AS_EXTERNAL &&
+ ospf6_area_is_stub (on->ospf6_if->area))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("E-bit mismatch with LSA Headers");
+ ospf6_lsa_delete (his);
+ thread_add_event (master, seqnumber_mismatch, on, 0);
+ return;
+ }
+
+ mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
+ his->header->adv_router, lsdb);
+ if (mine == NULL || ospf6_lsa_compare (his, mine) < 0)
+ {
+ if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (DATABASE))
+ zlog_info ("Add %s to request-list of %s", his->name, on->name);
+ ospf6_lsdb_add (his, on->request_list);
+ }
+ else
+ ospf6_lsa_delete (his);
+ }
+
+ if (p != OSPF6_MESSAGE_END (oh))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Trailing garbage ignored");
+ }
+
+ /* Set sequence number to Master's */
+ on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
+
+ /* schedule send lsreq */
+ if (on->thread_send_lsreq == NULL)
+ on->thread_send_lsreq =
+ thread_add_event (master, ospf6_lsreq_send, on, 0);
+
+ THREAD_OFF (on->thread_send_dbdesc);
+ on->thread_send_dbdesc =
+ thread_add_event (master, ospf6_dbdesc_send_newone, on, 0);
+
+ /* save last received dbdesc */
+ memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc));
}
void
-ospf6_process_lsreq (struct iovec *message,
- struct in6_addr *src,
- struct in6_addr *dst,
- struct ospf6_interface *o6i,
- u_int32_t router_id)
+ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst,
+ struct ospf6_interface *oi, struct ospf6_header *oh)
{
- struct ospf6_header *ospf6_header;
- u_int16_t length;
- struct ospf6_neighbor *o6n;
- struct ospf6_lsreq *lsreq;
- struct iovec response[OSPF6_MESSAGE_IOVEC_SIZE];
+ struct ospf6_neighbor *on;
+ struct ospf6_dbdesc *dbdesc;
+
+ if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
+ return;
+
+ on = ospf6_neighbor_lookup (oh->router_id, oi);
+ if (on == NULL)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Neighbor not found, ignore");
+ return;
+ }
+
+ if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr)))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Seems to be from Secondary I/F of the neighbor, ignore");
+ return;
+ }
+
+ dbdesc = (struct ospf6_dbdesc *)
+ ((caddr_t) oh + sizeof (struct ospf6_header));
+
+ /* Interface MTU check */
+ if (ntohs (dbdesc->ifmtu) != oi->ifmtu)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("I/F MTU mismatch");
+ return;
+ }
+
+ if (dbdesc->reserved1 || dbdesc->reserved2)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Non-0 reserved field in %s's DbDesc, correct",
+ on->name);
+ dbdesc->reserved1 = 0;
+ dbdesc->reserved2 = 0;
+ }
+
+ if (ntohl (oh->router_id) < ntohl (ospf6->router_id))
+ ospf6_dbdesc_recv_master (oh, on);
+ else if (ntohl (ospf6->router_id) < ntohl (oh->router_id))
+ ospf6_dbdesc_recv_slave (oh, on);
+ else
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Can't decide which is master, ignore");
+ }
+}
+
+void
+ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst,
+ struct ospf6_interface *oi, struct ospf6_header *oh)
+{
+ struct ospf6_neighbor *on;
+ char *p;
+ struct ospf6_lsreq_entry *e;
+ void *scope = NULL;
+ struct ospf6_lsdb *lsdb = NULL;
struct ospf6_lsa *lsa;
- unsigned long lsanum = 0;
- struct ospf6_lsupdate lsupdate;
- char buf_id[16], buf_router[16], buf_type[16];
- /* assert interface */
- assert (o6i);
+ if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
+ return;
- /* caluculate length */
- ospf6_header = (struct ospf6_header *) message[0].iov_base;
- length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
- length = (length < message[1].iov_len ? length : message[1].iov_len);
-
- /* find neighbor. if cannot be found, reject this message */
- o6n = ospf6_neighbor_lookup (router_id, o6i);
- if (!o6n)
+ on = ospf6_neighbor_lookup (oh->router_id, oi);
+ if (on == NULL)
{
- if (IS_OSPF6_DUMP_LSREQ)
- zlog_info (" neighbor not found, reject");
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Neighbor not found, ignore");
return;
}
- if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr)))
+ if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr)))
{
- if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
- zlog_info ("From Secondary I/F of the neighbor: ignore");
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Seems to be from Secondary I/F of the neighbor, ignore");
return;
}
- /* In states other than ExChange, Loading, or Full, the packet
- should be ignored. */
- if (o6n->state != NBS_EXCHANGE && o6n->state != NBS_LOADING
- && o6n->state != NBS_FULL)
+ if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
+ on->state != OSPF6_NEIGHBOR_LOADING &&
+ on->state != OSPF6_NEIGHBOR_FULL)
{
- if (IS_OSPF6_DUMP_LSREQ)
- zlog_info (" neighbor state less than Exchange, reject");
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Neighbor state less than Exchange, ignore");
return;
}
- /* Initialize response LSUpdate packet */
- OSPF6_MESSAGE_CLEAR (response);
- memset (&lsupdate, 0, sizeof (struct ospf6_lsupdate));
- OSPF6_MESSAGE_ATTACH (response, &lsupdate, sizeof (struct ospf6_lsupdate));
-
- /* process each request */
- lsanum = 0;
- for (lsreq = (struct ospf6_lsreq *) message[1].iov_base;
- (char *)(lsreq + 1) <= (char *)(message[1].iov_base + length);
- lsreq++)
+ /* Process each request */
+ for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
+ p + sizeof (struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END (oh);
+ p += sizeof (struct ospf6_lsreq_entry))
{
- inet_ntop (AF_INET, &lsreq->adv_router, buf_router, sizeof (buf_router));
- inet_ntop (AF_INET, &lsreq->id, buf_id, sizeof (buf_id));
+ e = (struct ospf6_lsreq_entry *) p;
+ scope = ospf6_get_lsa_scope (e->type, on);
+ lsdb = ospf6_get_scoped_lsdb (e->type, scope);
- /* find instance of database copy */
- lsa = ospf6_lsdb_lookup (lsreq->type, lsreq->id, lsreq->adv_router,
- ospf6_lsa_get_scope (lsreq->type, o6i));
-
- if (!lsa)
+ /* Find database copy */
+ lsa = ospf6_lsdb_lookup (e->type, e->id, e->adv_router, lsdb);
+ if (lsa == NULL)
{
- if (IS_OSPF6_DUMP_LSREQ)
- zlog_info ("BadLSReq: %s requests [%s ID=%s Adv=%s] not found",
- o6n->str, ospf6_lsa_type_string (lsreq->type, buf_type,
- sizeof (buf_type)),
- buf_id, buf_router);
- thread_add_event (master, bad_lsreq, o6n, 0);
+ char id[16], adv_router[16];
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ {
+ inet_ntop (AF_INET, &e->id, id, sizeof (id));
+ inet_ntop (AF_INET, &e->adv_router, adv_router,
+ sizeof (adv_router));
+ zlog_info ("Can't find requested [%s Id:%s Adv:%s]",
+ OSPF6_LSTYPE_NAME (e->type), id, adv_router);
+ }
+ thread_add_event (master, bad_lsreq, on, 0);
return;
}
- /* I/F MTU check */
- if (sizeof (struct ospf6_header) + sizeof (struct ospf6_lsupdate)
- + iov_totallen (response) + ntohs (lsa->header->length)
- > o6i->ifmtu)
- break;
-
- OSPF6_MESSAGE_ATTACH (response, lsa->header, ntohs (lsa->header->length));
- lsanum++;
+ if (IS_OSPF6_DEBUG_LSA (DATABASE))
+ zlog_info ("Add copy of %s to lsupdate_list of %s",
+ lsa->name, on->name);
+ ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->lsupdate_list);
}
- /* send response LSUpdate to this request */
- if (lsanum)
+ if (p != OSPF6_MESSAGE_END (oh))
{
- lsupdate.lsupdate_num = htonl (lsanum);
-
- ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, response,
- &o6n->hisaddr, o6i->if_id);
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Trailing garbage ignored");
}
- /* statistics */
- o6n->lsa_receive[OSPF6_MESSAGE_TYPE_LSREQ]
- += length / sizeof (struct ospf6_lsreq);
+ /* schedule send lsupdate */
+ THREAD_OFF (on->thread_send_lsupdate);
+ on->thread_send_lsupdate =
+ thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
}
void
-ospf6_process_lsupdate (struct iovec *message,
- struct in6_addr *src,
- struct in6_addr *dst,
- struct ospf6_interface *o6i,
- u_int32_t router_id)
+ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
+ struct ospf6_interface *oi, struct ospf6_header *oh)
{
- struct ospf6_header *ospf6_header;
- u_int16_t length;
+ struct ospf6_neighbor *on;
struct ospf6_lsupdate *lsupdate;
- struct ospf6_neighbor *o6n;
- unsigned long lsanum;
- struct ospf6_lsa_header *lsa_header;
+ unsigned long num;
+ char *p;
- /* assert interface */
- assert (o6i);
+ if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
+ return;
- /* caluculate length */
- ospf6_header = (struct ospf6_header *) message[0].iov_base;
- length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
- length = (length < message[1].iov_len ? length : message[1].iov_len);
-
- /* find neighbor. if cannot be found, reject this message */
- o6n = ospf6_neighbor_lookup (router_id, o6i);
- if (! o6n)
+ on = ospf6_neighbor_lookup (oh->router_id, oi);
+ if (on == NULL)
{
- if (IS_OSPF6_DUMP_LSUPDATE)
- zlog_info (" neighbor not found, reject");
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Neighbor not found, ignore");
return;
}
- if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr)))
+ if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr)))
{
- if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
- zlog_info ("From Secondary I/F of the neighbor: ignore");
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Seems to be from Secondary I/F of the neighbor, ignore");
return;
}
- /* if neighbor state less than ExChange, reject this message */
- if (o6n->state < NBS_EXCHANGE)
+ if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
+ on->state != OSPF6_NEIGHBOR_LOADING &&
+ on->state != OSPF6_NEIGHBOR_FULL)
{
- if (IS_OSPF6_DUMP_LSUPDATE)
- zlog_info (" neighbor state less than Exchange, reject");
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Neighbor state less than Exchange, ignore");
return;
}
- /* set linkstate update pointer */
- lsupdate = (struct ospf6_lsupdate *) message[1].iov_base;
+ lsupdate = (struct ospf6_lsupdate *)
+ ((caddr_t) oh + sizeof (struct ospf6_header));
- /* save linkstate update info */
- lsanum = ntohl (lsupdate->lsupdate_num);
+ num = ntohl (lsupdate->lsa_number);
- /* statistics */
- o6n->ospf6_stat_received_lsa += lsanum;
- o6n->ospf6_stat_received_lsupdate++;
+ /* Process LSAs */
+ for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
+ p < OSPF6_MESSAGE_END (oh) &&
+ p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh);
+ p += OSPF6_LSA_SIZE (p))
+ {
+ if (num == 0)
+ break;
+ if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Malformed LSA length, quit processing");
+ break;
+ }
+
+ ospf6_receive_lsa ((struct ospf6_lsa_header *) p, on);
+ num--;
+ }
+
+ if (num != 0)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Malformed LSA number or LSA length");
+ }
+ if (p != OSPF6_MESSAGE_END (oh))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Trailing garbage ignored");
+ }
/* RFC2328 Section 10.9: When the neighbor responds to these requests
with the proper Link State Update packet(s), the Link state request
list is truncated and a new Link State Request packet is sent. */
-
- /* process LSAs */
- for (lsa_header = (struct ospf6_lsa_header *) (lsupdate + 1);
- lsanum && (char *)lsa_header < (char *)lsupdate + length;
- lsanum--)
- {
- ospf6_dbex_receive_lsa (lsa_header, o6n);
- lsa_header = OSPF6_LSA_NEXT (lsa_header);
- }
-
/* send new Link State Request packet if this LS Update packet
- can be recognized as a response to our previous LS request */
- if (! IN6_IS_ADDR_MULTICAST(dst) &&
- (o6n->state == NBS_EXCHANGE || o6n->state == NBS_LOADING))
- thread_add_event (master, ospf6_send_lsreq, o6n, 0);
-
- return;
+ can be recognized as a response to our previous LS Request */
+ if (! IN6_IS_ADDR_MULTICAST (dst) &&
+ (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
+ on->state == OSPF6_NEIGHBOR_LOADING))
+ {
+ THREAD_OFF (on->thread_send_lsreq);
+ on->thread_send_lsreq =
+ thread_add_event (master, ospf6_lsreq_send, on, 0);
+ }
}
void
-ospf6_process_lsack (struct iovec *message,
- struct in6_addr *src,
- struct in6_addr *dst,
- struct ospf6_interface *o6i,
- u_int32_t router_id)
+ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst,
+ struct ospf6_interface *oi, struct ospf6_header *oh)
{
- struct ospf6_header *ospf6_header;
- u_int16_t length;
- struct ospf6_neighbor *o6n;
- struct ospf6_lsa_header *lsa_header;
- struct ospf6_lsa *lsa, *copy, *rem;
+ struct ospf6_neighbor *on;
+ char *p;
+ struct ospf6_lsa *his, *mine;
+ struct ospf6_lsdb *lsdb = NULL;
- /* assert interface */
- assert (o6i);
+ assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK);
+ if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK)
+ return;
- /* caluculate length */
- ospf6_header = (struct ospf6_header *) message[0].iov_base;
- length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header);
- length = (length < message[1].iov_len ? length : message[1].iov_len);
-
- /* find neighbor. if cannot be found, reject this message */
- o6n = ospf6_neighbor_lookup (router_id, o6i);
- if (!o6n)
+ on = ospf6_neighbor_lookup (oh->router_id, oi);
+ if (on == NULL)
{
- if (IS_OSPF6_DUMP_LSACK)
- zlog_info ("LSACK: neighbor not found, reject");
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Neighbor not found, ignore");
return;
}
- if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr)))
+ if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr)))
{
- if (IS_OSPF6_DUMP_LSACK)
- zlog_info ("LSACK: From Secondary I/F of the neighbor: ignore");
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Seems to be from Secondary I/F of the neighbor, ignore");
return;
}
- /* if neighbor state less than ExChange, reject this message */
- if (o6n->state < NBS_EXCHANGE)
+ if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
+ on->state != OSPF6_NEIGHBOR_LOADING &&
+ on->state != OSPF6_NEIGHBOR_FULL)
{
- if (IS_OSPF6_DUMP_LSACK)
- zlog_info ("LSACK: neighbor state less than Exchange, reject");
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Neighbor state less than Exchange, ignore");
return;
}
- /* process each LSA header */
- for (lsa_header = (struct ospf6_lsa_header *) message[1].iov_base;
- (char *)(lsa_header + 1) <= (char *)(message[1].iov_base + length);
- lsa_header++)
+ for (p = (char *) ((caddr_t) oh + sizeof (struct ospf6_header));
+ p + sizeof (struct ospf6_lsa_header) <= OSPF6_MESSAGE_END (oh);
+ p += sizeof (struct ospf6_lsa_header))
{
- /* find database copy */
- copy = ospf6_lsdb_lookup (lsa_header->type, lsa_header->ls_id,
- lsa_header->advrtr,
- ospf6_lsa_get_scope (lsa_header->type, o6i));
+ his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p);
+ his->scope = ospf6_get_lsa_scope (his->header->type, on);
+ lsdb = ospf6_get_scoped_lsdb (his->header->type, his->scope);
- /* if no database copy */
- if (!copy)
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV) ||
+ IS_OSPF6_DEBUG_LSA (SEND))
+ zlog_info ("%s acknowledged by %s", his->name, on->name);
+
+ /* Find database copy */
+ mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
+ his->header->adv_router, lsdb);
+ if (mine == NULL)
{
- if (IS_OSPF6_DUMP_LSACK)
- zlog_info ("LSACK: no database copy, ignore");
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("No database copy");
+ ospf6_lsa_delete (his);
continue;
}
- /* if not on his retrans list */
- rem = ospf6_lsdb_lookup_lsdb (copy->header->type, copy->header->id,
- copy->header->adv_router,
- o6n->retrans_list);
- if (rem == NULL)
+ /* Check if the LSA is on his retrans-list */
+ mine = ospf6_lsdb_lookup (his->header->type, his->header->id,
+ his->header->adv_router, on->retrans_list);
+ if (mine == NULL)
{
- if (IS_OSPF6_DUMP_LSACK)
- zlog_info ("LSACK: not on %s's retranslist, ignore", o6n->str);
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Not on %s's retrans-list", on->name);
+ ospf6_lsa_delete (his);
continue;
}
- /* create temporary LSA from Ack message */
- lsa = ospf6_lsa_summary_create ((struct ospf6_lsa_header__ *) lsa_header);
-
- /* if the same instance, remove from retrans list.
- else, log and ignore */
- if (ospf6_lsa_check_recent (lsa, copy) == 0)
- ospf6_neighbor_retrans_remove (rem, o6n);
- else
+ if (ospf6_lsa_compare (his, mine) != 0)
{
- /* Log the questionable acknowledgement,
+ /* Log this questionable acknowledgement,
and examine the next one. */
- zlog_info ("LSACK: questionable acknowledge: %s", copy->str);
- zlog_info ("LSACK: received: seq: %#x age: %hu",
- ntohl (lsa->header->seqnum),
- ntohs (lsa->header->age));
- zlog_info ("LSACK: instance: seq: %#x age: %hu",
- ntohl (copy->header->seqnum),
- ospf6_lsa_age_current (copy));
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Questionable acknowledgement");
+ ospf6_lsa_delete (his);
+ continue;
}
- /* release temporary LSA from Ack message */
- ospf6_lsa_delete (lsa);
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV) ||
+ IS_OSPF6_DEBUG_LSA (SEND))
+ zlog_info ("Acknowledged, remove from %s's retrans-list",
+ on->name);
+
+ if (OSPF6_LSA_IS_MAXAGE (mine))
+ ospf6_maxage_remove (on->ospf6_if->area->ospf6);
+
+ if (IS_OSPF6_DEBUG_LSA (DATABASE))
+ zlog_info ("remove %s from retrans_list of %s",
+ mine->name, on->name);
+ ospf6_lsdb_remove (mine, on->retrans_list);
+ ospf6_lsa_delete (his);
}
- ospf6_maxage_remover ();
- return;
+ if (p != OSPF6_MESSAGE_END (oh))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Trailing garbage ignored");
+ }
}
-struct {
- void (*process) (struct iovec *, struct in6_addr *, struct in6_addr *,
- struct ospf6_interface *, u_int32_t);
-} ospf6_message_process_type [] =
-{
- {ospf6_process_unknown},
- {ospf6_process_hello},
- {ospf6_process_dbdesc},
- {ospf6_process_lsreq},
- {ospf6_process_lsupdate},
- {ospf6_process_lsack}
-};
-
-/* process ospf6 protocol header. then, call next process function
- for each message type */
-static void
-ospf6_message_process (struct iovec *message,
- struct in6_addr *src,
- struct in6_addr *dst,
- struct ospf6_interface *o6i)
-{
- struct ospf6_header *ospf6_header = NULL;
- u_char type;
- u_int32_t router_id;
- char srcname[64];
-
- assert (o6i);
- assert (src);
- assert (dst);
-
- /* set ospf6_hdr pointer to head of buffer */
- ospf6_header = (struct ospf6_header *) message[0].iov_base;
-
- /* version check */
- if (ospf6_header->version != OSPF6_VERSION)
- {
- if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
- zlog_info ("version mismatch, drop");
- return;
- }
-
- /* area id check */
- if (ospf6_header->area_id != o6i->area->area_id)
- {
- if (ospf6_header->area_id == 0)
- {
- if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
- zlog_info ("virtual link not yet, drop");
- return;
- }
-
- if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
- zlog_info ("area id mismatch, drop");
- return;
- }
-
- /* instance id check */
- if (ospf6_header->instance_id != o6i->instance_id)
- {
- if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type))
- zlog_info ("instance id mismatch, drop");
- return;
- }
-
- /* message type check */
- type = (ospf6_header->type >= OSPF6_MESSAGE_TYPE_MAX ?
- OSPF6_MESSAGE_TYPE_UNKNOWN : ospf6_header->type);
-
- /* log */
- if (IS_OSPF6_DUMP_MESSAGE (type))
- {
- char srcname[64], dstname[64];
- inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
- inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
- zlog_info ("Receive %s on %s",
- ospf6_message_type_string[type], o6i->interface->name);
- zlog_info (" %s -> %s", srcname, dstname);
- ospf6_message_log (message);
- }
-
- /* router id check */
- router_id = ospf6_header->router_id;
- if (ospf6_header->router_id == o6i->area->ospf6->router_id)
- {
- inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
- zlog_warn ("*** Router-ID mismatch: from %s on %s",
- srcname, o6i->interface->name);
- return;
- }
-
- /* octet statistics relies on some asumption:
- on ethernet, no IPv6 Extention header, etc */
-#define OSPF6_IP6_HEADER_SIZE 40
-#define OSPF6_ETHER_HEADER_SIZE 14
- o6i->message_stat[type].recv++;
- o6i->message_stat[type].recv_octet += ntohs (ospf6_header->len)
- + OSPF6_IP6_HEADER_SIZE + OSPF6_ETHER_HEADER_SIZE;
-
- /* futher process */
- (*ospf6_message_process_type[type].process) (&message[0], src, dst, o6i, router_id);
-
- return;
-}
+char recvbuf[OSPF6_MESSAGE_BUFSIZ];
+char sendbuf[OSPF6_MESSAGE_BUFSIZ];
int
ospf6_receive (struct thread *thread)
{
- int sockfd;
+ int sockfd, len;
+ char srcname[64], dstname[64];
struct in6_addr src, dst;
unsigned int ifindex;
- struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
- struct ospf6_header ospf6_header;
- char buffer[OSPF6_MESSAGE_RECEIVE_BUFSIZE];
- struct ospf6_interface *o6i;
- unsigned char type;
-
- /* get socket */
- sockfd = THREAD_FD (thread);
+ struct iovec iovector[2];
+ struct ospf6_interface *oi;
+ struct ospf6_header *oh;
/* add next read thread */
+ sockfd = THREAD_FD (thread);
thread_add_read (master, ospf6_receive, NULL, sockfd);
/* initialize */
- OSPF6_MESSAGE_CLEAR (message);
- memset (&ospf6_header, 0, sizeof (struct ospf6_header));
-
- OSPF6_MESSAGE_ATTACH (message, &ospf6_header, sizeof (struct ospf6_header));
- OSPF6_MESSAGE_ATTACH (message, buffer, OSPF6_MESSAGE_RECEIVE_BUFSIZE);
+ memset (recvbuf, 0, sizeof (recvbuf));
+ iovector[0].iov_base = recvbuf;
+ iovector[0].iov_len = sizeof (recvbuf);
+ iovector[1].iov_base = NULL;
+ iovector[1].iov_len = 0;
/* receive message */
- ospf6_recvmsg (&src, &dst, &ifindex, message);
-
- type = (OSPF6_MESSAGE_TYPE_UNKNOWN < ospf6_header.type &&
- ospf6_header.type <= OSPF6_MESSAGE_TYPE_LSACK ?
- ospf6_header.type : OSPF6_MESSAGE_TYPE_UNKNOWN);
- o6i = ospf6_interface_lookup_by_index (ifindex);
- if (!o6i || !o6i->area)
+ len = ospf6_recvmsg (&src, &dst, &ifindex, iovector);
+ if (len > sizeof (recvbuf))
{
- //zlog_warn ("*** received interface ospf6 disabled");
+ zlog_err ("Excess message read");
+ return 0;
+ }
+ else if (len < sizeof (struct ospf6_header))
+ {
+ zlog_err ("Deficient message read");
return 0;
}
- /* if not passive, process message */
- if (! CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE))
- ospf6_message_process (message, &src, &dst, o6i);
- else if (IS_OSPF6_DUMP_MESSAGE (type))
- zlog_info ("Ignore message on passive interface %s",
- o6i->interface->name);
+ oi = ospf6_interface_lookup_by_ifindex (ifindex);
+ if (oi == NULL || oi->area == NULL)
+ {
+ zlog_info ("Message received on disabled interface");
+ return 0;
+ }
+
+ oh = (struct ospf6_header *) recvbuf;
+
+ /* Log */
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ {
+ inet_ntop (AF_INET6, &src, srcname, sizeof (srcname));
+ inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname));
+ zlog_info ("%s received on %s",
+ OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
+ zlog_info (" src: %s", srcname);
+ zlog_info (" dst: %s", dstname);
+ if (len != ntohs (oh->length))
+ zlog_info ("Message length does not match actually received: %d", len);
+
+ switch (oh->type)
+ {
+ case OSPF6_MESSAGE_TYPE_HELLO:
+ ospf6_hello_print (oh);
+ break;
+ case OSPF6_MESSAGE_TYPE_DBDESC:
+ ospf6_dbdesc_print (oh);
+ break;
+ case OSPF6_MESSAGE_TYPE_LSREQ:
+ ospf6_lsreq_print (oh);
+ break;
+ case OSPF6_MESSAGE_TYPE_LSUPDATE:
+ ospf6_lsupdate_print (oh);
+ break;
+ case OSPF6_MESSAGE_TYPE_LSACK:
+ ospf6_lsack_print (oh);
+ break;
+ default:
+ zlog_info ("Unknown message");
+ break;
+ }
+ }
+
+ if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
+ zlog_info ("Ignore message on passive interface %s",
+ oi->interface->name);
+ return 0;
+ }
+
+ switch (oh->type)
+ {
+ case OSPF6_MESSAGE_TYPE_HELLO:
+ ospf6_hello_recv (&src, &dst, oi, oh);
+ break;
+
+ case OSPF6_MESSAGE_TYPE_DBDESC:
+ ospf6_dbdesc_recv (&src, &dst, oi, oh);
+ break;
+
+ case OSPF6_MESSAGE_TYPE_LSREQ:
+ ospf6_lsreq_recv (&src, &dst, oi, oh);
+ break;
+
+ case OSPF6_MESSAGE_TYPE_LSUPDATE:
+ ospf6_lsupdate_recv (&src, &dst, oi, oh);
+ break;
+
+ case OSPF6_MESSAGE_TYPE_LSACK:
+ ospf6_lsack_recv (&src, &dst, oi, oh);
+ break;
+
+ default:
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ zlog_info ("Unknown message");
+ break;
+ }
+
+ return 0;
+}
+
+void
+ospf6_send (struct in6_addr *src, struct in6_addr *dst,
+ struct ospf6_interface *oi, struct ospf6_header *oh)
+{
+ int len;
+ char srcname[64], dstname[64];
+ struct iovec iovector[2];
+
+ /* initialize */
+ iovector[0].iov_base = (caddr_t) oh;
+ iovector[0].iov_len = ntohs (oh->length);
+ iovector[1].iov_base = NULL;
+ iovector[1].iov_len = 0;
+
+ /* fill OSPF header */
+ oh->version = OSPFV3_VERSION;
+ /* message type must be set before */
+ /* message length must be set before */
+ oh->router_id = oi->area->ospf6->router_id;
+ oh->area_id = oi->area->area_id;
+ /* checksum is calculated by kernel */
+ oh->instance_id = oi->instance_id;
+ oh->reserved = 0;
+
+ /* Log */
+ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND))
+ {
+ inet_ntop (AF_INET6, dst, dstname, sizeof (dstname));
+ if (src)
+ inet_ntop (AF_INET6, src, srcname, sizeof (srcname));
+ else
+ memset (srcname, 0, sizeof (srcname));
+ zlog_info ("%s send on %s",
+ OSPF6_MESSAGE_TYPE_NAME (oh->type), oi->interface->name);
+ zlog_info (" src: %s", srcname);
+ zlog_info (" dst: %s", dstname);
+
+ switch (oh->type)
+ {
+ case OSPF6_MESSAGE_TYPE_HELLO:
+ ospf6_hello_print (oh);
+ break;
+ case OSPF6_MESSAGE_TYPE_DBDESC:
+ ospf6_dbdesc_print (oh);
+ break;
+ case OSPF6_MESSAGE_TYPE_LSREQ:
+ ospf6_lsreq_print (oh);
+ break;
+ case OSPF6_MESSAGE_TYPE_LSUPDATE:
+ ospf6_lsupdate_print (oh);
+ break;
+ case OSPF6_MESSAGE_TYPE_LSACK:
+ ospf6_lsack_print (oh);
+ break;
+ default:
+ zlog_info ("Unknown message");
+ assert (0);
+ break;
+ }
+ }
+
+ /* send message */
+ len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector);
+ if (len != ntohs (oh->length))
+ zlog_err ("Could not send entire message");
+}
+
+int
+ospf6_hello_send (struct thread *thread)
+{
+ struct ospf6_interface *oi;
+ struct ospf6_header *oh;
+ struct ospf6_hello *hello;
+ char *p;
+ listnode node;
+ struct ospf6_neighbor *on;
+
+ oi = (struct ospf6_interface *) THREAD_ARG (thread);
+ oi->thread_send_hello = (struct thread *) NULL;
+
+ if (oi->state <= OSPF6_INTERFACE_DOWN)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
+ zlog_info ("Unable to send Hello on down interface %s",
+ oi->interface->name);
+ return 0;
+ }
+
+ /* set next thread */
+ oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send,
+ oi, oi->hello_interval);
+
+ memset (sendbuf, 0, sizeof (sendbuf));
+ oh = (struct ospf6_header *) sendbuf;
+ hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header));
+
+ hello->interface_id = htonl (oi->interface->ifindex);
+ hello->priority = oi->priority;
+ hello->options[0] = oi->area->options[0];
+ hello->options[1] = oi->area->options[1];
+ hello->options[2] = oi->area->options[2];
+ hello->hello_interval = htons (oi->hello_interval);
+ hello->dead_interval = htons (oi->dead_interval);
+ hello->drouter = oi->drouter;
+ hello->bdrouter = oi->bdrouter;
+
+ p = (char *)((caddr_t) hello + sizeof (struct ospf6_hello));
+
+ for (node = listhead (oi->neighbor_list); node; nextnode (node))
+ {
+ on = (struct ospf6_neighbor *) getdata (node);
+
+ if (on->state < OSPF6_NEIGHBOR_INIT)
+ continue;
+
+ if (p - sendbuf + sizeof (u_int32_t) > oi->ifmtu)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND))
+ zlog_info ("sending Hello message: exceeds I/F MTU");
+ break;
+ }
+
+ memcpy (p, &on->router_id, sizeof (u_int32_t));
+ p += sizeof (u_int32_t);
+ }
+
+ oh->type = OSPF6_MESSAGE_TYPE_HELLO;
+ oh->length = htons (p - sendbuf);
+
+ ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
+ return 0;
+}
+
+int
+ospf6_dbdesc_send (struct thread *thread)
+{
+ struct ospf6_neighbor *on;
+ struct ospf6_header *oh;
+ struct ospf6_dbdesc *dbdesc;
+ char *p;
+ struct ospf6_lsa *lsa;
+
+ on = (struct ospf6_neighbor *) THREAD_ARG (thread);
+ on->thread_send_dbdesc = (struct thread *) NULL;
+
+ if (on->state < OSPF6_NEIGHBOR_EXSTART)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_DBDESC, SEND))
+ zlog_info ("Quit to send DbDesc to neighbor %s state %s",
+ on->name, ospf6_neighbor_state_str[on->state]);
+ return 0;
+ }
+
+ /* set next thread if master */
+ if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT))
+ on->thread_send_dbdesc =
+ thread_add_timer (master, ospf6_dbdesc_send, on,
+ on->ospf6_if->rxmt_interval);
+
+ memset (sendbuf, 0, sizeof (sendbuf));
+ oh = (struct ospf6_header *) sendbuf;
+ dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh +
+ sizeof (struct ospf6_header));
+
+ /* if this is initial one, initialize sequence number for DbDesc */
+ if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
+ {
+ struct timeval tv;
+ if (gettimeofday (&tv, (struct timezone *) NULL) < 0)
+ tv.tv_sec = 1;
+ on->dbdesc_seqnum = tv.tv_sec;
+ }
+
+ dbdesc->options[0] = on->ospf6_if->area->options[0];
+ dbdesc->options[1] = on->ospf6_if->area->options[1];
+ dbdesc->options[2] = on->ospf6_if->area->options[2];
+ dbdesc->ifmtu = htons (on->ospf6_if->ifmtu);
+ dbdesc->bits = on->dbdesc_bits;
+ dbdesc->seqnum = htonl (on->dbdesc_seqnum);
+
+ /* if this is not initial one, set LSA headers in dbdesc */
+ p = (char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc));
+ if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
+ {
+ for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ {
+ ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
+
+ /* MTU check */
+ if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
+ on->ospf6_if->ifmtu)
+ {
+ ospf6_lsa_unlock (lsa);
+ break;
+ }
+ memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
+ p += sizeof (struct ospf6_lsa_header);
+ }
+ }
+
+ oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
+ oh->length = htons (p - sendbuf);
+
+ ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
+ on->ospf6_if, oh);
+ return 0;
+}
+
+int
+ospf6_dbdesc_send_newone (struct thread *thread)
+{
+ struct ospf6_neighbor *on;
+ struct ospf6_lsa *lsa;
+ unsigned int size = 0;
+
+ on = (struct ospf6_neighbor *) THREAD_ARG (thread);
+ if (IS_OSPF6_DEBUG_LSA (DATABASE))
+ zlog_info ("Remove entire dbdesc_list of %s: sending newone", on->name);
+ ospf6_lsdb_remove_all (on->dbdesc_list);
+
+ /* move LSAs from summary_list to dbdesc_list (within neighbor structure)
+ so that ospf6_send_dbdesc () can send those LSAs */
+ size = sizeof (struct ospf6_lsa_header) + sizeof (struct ospf6_dbdesc);
+ for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ {
+ if (size + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
+ {
+ ospf6_lsa_unlock (lsa);
+ break;
+ }
+
+ if (IS_OSPF6_DEBUG_LSA (DATABASE))
+ zlog_info ("Move %s from summary_list to dbdesc_list of %s",
+ lsa->name, on->name);
+ ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list);
+ ospf6_lsdb_remove (lsa, on->summary_list);
+ size += sizeof (struct ospf6_lsa_header);
+ }
+
+ if (on->summary_list->count == 0)
+ UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
+
+ /* If slave, More bit check must be done here */
+ if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) && /* Slave */
+ ! CHECK_FLAG (on->dbdesc_last.bits, OSPF6_DBDESC_MBIT) &&
+ ! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT))
+ thread_add_event (master, exchange_done, on, 0);
+
+ thread_execute (master, ospf6_dbdesc_send, on, 0);
+ return 0;
+}
+
+int
+ospf6_lsreq_send (struct thread *thread)
+{
+ struct ospf6_neighbor *on;
+ struct ospf6_header *oh;
+ struct ospf6_lsreq_entry *e;
+ char *p;
+ struct ospf6_lsa *lsa;
+
+ on = (struct ospf6_neighbor *) THREAD_ARG (thread);
+ on->thread_send_lsreq = (struct thread *) NULL;
+
+ /* LSReq will be sent only in ExStart or Loading */
+ if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
+ on->state != OSPF6_NEIGHBOR_LOADING)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSREQ, SEND))
+ zlog_info ("Quit to send LSReq to neighbor %s state %s",
+ on->name, ospf6_neighbor_state_str[on->state]);
+ return 0;
+ }
+
+ /* schedule loading_done if request list is empty */
+ if (on->request_list->count == 0)
+ {
+ thread_add_event (master, loading_done, on, 0);
+ return 0;
+ }
+
+ /* set next thread */
+ on->thread_send_lsreq =
+ thread_add_timer (master, ospf6_lsreq_send, on,
+ on->ospf6_if->rxmt_interval);
+
+ memset (sendbuf, 0, sizeof (sendbuf));
+ oh = (struct ospf6_header *) sendbuf;
+
+ /* set Request entries in lsreq */
+ p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
+ for (lsa = ospf6_lsdb_head (on->request_list); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ {
+ /* MTU check */
+ if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > on->ospf6_if->ifmtu)
+ {
+ ospf6_lsa_unlock (lsa);
+ break;
+ }
+
+ e = (struct ospf6_lsreq_entry *) p;
+ e->type = lsa->header->type;
+ e->id = lsa->header->id;
+ e->adv_router = lsa->header->adv_router;
+ p += sizeof (struct ospf6_lsreq_entry);
+ }
+
+ oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
+ oh->length = htons (p - sendbuf);
+
+ ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
+ on->ospf6_if, oh);
+ return 0;
+}
+
+int
+ospf6_lsupdate_send_neighbor (struct thread *thread)
+{
+ struct ospf6_neighbor *on;
+ struct ospf6_header *oh;
+ struct ospf6_lsupdate *lsupdate;
+ char *p;
+ int num;
+ struct ospf6_lsa *lsa;
+
+ on = (struct ospf6_neighbor *) THREAD_ARG (thread);
+ on->thread_send_lsupdate = (struct thread *) NULL;
+
+ if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
+ zlog_info ("Quit to send LSUpdate to neighbor %s state %s",
+ on->name, ospf6_neighbor_state_str[on->state]);
+ return 0;
+ }
+
+ /* if we have nothing to send, return */
+ if (on->lsupdate_list->count == 0 &&
+ on->retrans_list->count == 0)
+ return 0;
+
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ zlog_info ("LSA Send to %s", on->name);
+
+ memset (sendbuf, 0, sizeof (sendbuf));
+ oh = (struct ospf6_header *) sendbuf;
+ lsupdate = (struct ospf6_lsupdate *)
+ ((caddr_t) oh + sizeof (struct ospf6_header));
+
+ p = (char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
+ num = 0;
+
+ /* lsupdate_list lists those LSA which doesn't need to be
+ retransmitted. remove those from the list */
+ for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ {
+ /* MTU check */
+ if (p - sendbuf + OSPF6_LSA_SIZE (lsa->header) > on->ospf6_if->ifmtu)
+ {
+ ospf6_lsa_unlock (lsa);
+ break;
+ }
+
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ ospf6_lsa_header_print (lsa);
+
+ ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
+ memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
+ p += OSPF6_LSA_SIZE (lsa->header);
+ num++;
+
+ assert (lsa->lock == 2);
+ ospf6_lsdb_remove (lsa, on->lsupdate_list);
+ }
+
+ for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ {
+ /* MTU check */
+ if (p - sendbuf + OSPF6_LSA_SIZE (lsa->header) > on->ospf6_if->ifmtu)
+ {
+ ospf6_lsa_unlock (lsa);
+ break;
+ }
+
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ ospf6_lsa_header_print (lsa);
+
+ ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
+ memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
+ p += OSPF6_LSA_SIZE (lsa->header);
+ num++;
+ }
+
+ lsupdate->lsa_number = htonl (num);
+
+ oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
+ oh->length = htons (p - sendbuf);
+
+ ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
+ on->ospf6_if, oh);
+
+ if (on->lsupdate_list->count != 0 ||
+ on->retrans_list->count != 0)
+ {
+ if (on->lsupdate_list->count != 0)
+ on->thread_send_lsupdate =
+ thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
+ else
+ on->thread_send_lsupdate =
+ thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
+ on->ospf6_if->rxmt_interval);
+ }
+
+ return 0;
+}
+
+int
+ospf6_lsupdate_send_interface (struct thread *thread)
+{
+ struct ospf6_interface *oi;
+ struct ospf6_header *oh;
+ struct ospf6_lsupdate *lsupdate;
+ char *p;
+ int num;
+ struct ospf6_lsa *lsa;
+
+ oi = (struct ospf6_interface *) THREAD_ARG (thread);
+ oi->thread_send_lsupdate = (struct thread *) NULL;
+
+ if (oi->state <= OSPF6_INTERFACE_WAITING)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
+ zlog_info ("Quit to send LSUpdate to interface %s state %s",
+ oi->interface->name, ospf6_interface_state_str[oi->state]);
+ return 0;
+ }
+
+ /* if we have nothing to send, return */
+ if (oi->lsupdate_list->count == 0)
+ return 0;
+
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ zlog_info ("LSA Send to %s", oi->interface->name);
+
+ memset (sendbuf, 0, sizeof (sendbuf));
+ oh = (struct ospf6_header *) sendbuf;
+ lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
+ sizeof (struct ospf6_header));
+
+ p = (char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
+ num = 0;
+
+ for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ {
+ /* MTU check */
+ if (p - sendbuf + OSPF6_LSA_SIZE (lsa->header) > oi->ifmtu)
+ {
+ ospf6_lsa_unlock (lsa);
+ break;
+ }
+
+ if (IS_OSPF6_DEBUG_LSA (SEND))
+ ospf6_lsa_header_print (lsa);
+
+ ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
+ memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
+ p += OSPF6_LSA_SIZE (lsa->header);
+ num++;
+
+ assert (lsa->lock == 2);
+ ospf6_lsdb_remove (lsa, oi->lsupdate_list);
+ }
+
+ lsupdate->lsa_number = htonl (num);
+
+ oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
+ oh->length = htons (p - sendbuf);
+
+ if (oi->state == OSPF6_INTERFACE_DR ||
+ oi->state == OSPF6_INTERFACE_BDR)
+ ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
+ else
+ ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
+
+ if (oi->lsupdate_list->count > 0)
+ {
+ oi->thread_send_lsupdate =
+ thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0);
+ }
+
+ return 0;
+}
+
+int
+ospf6_lsack_send_neighbor (struct thread *thread)
+{
+ struct ospf6_neighbor *on;
+ struct ospf6_header *oh;
+ char *p;
+ struct ospf6_lsa *lsa;
+
+ on = (struct ospf6_neighbor *) THREAD_ARG (thread);
+ on->thread_send_lsack = (struct thread *) NULL;
+
+ if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
+ zlog_info ("Quit to send LSAck to neighbor %s state %s",
+ on->name, ospf6_neighbor_state_str[on->state]);
+ return 0;
+ }
+
+ /* if we have nothing to send, return */
+ if (on->lsack_list->count == 0)
+ return 0;
+
+ memset (sendbuf, 0, sizeof (sendbuf));
+ oh = (struct ospf6_header *) sendbuf;
+
+ p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
+
+ for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ {
+ /* MTU check */
+ if (p - sendbuf + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu)
+ {
+ /* if we run out of packet size/space here,
+ better to try again soon. */
+ THREAD_OFF (on->thread_send_lsack);
+ on->thread_send_lsack =
+ thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
+
+ ospf6_lsa_unlock (lsa);
+ break;
+ }
+
+ ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
+ memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
+ p += sizeof (struct ospf6_lsa_header);
+
+ assert (lsa->lock == 2);
+ ospf6_lsdb_remove (lsa, on->lsack_list);
+ }
+
+ oh->type = OSPF6_MESSAGE_TYPE_LSACK;
+ oh->length = htons (p - sendbuf);
+
+ ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
+ on->ospf6_if, oh);
+ return 0;
+}
+
+int
+ospf6_lsack_send_interface (struct thread *thread)
+{
+ struct ospf6_interface *oi;
+ struct ospf6_header *oh;
+ char *p;
+ struct ospf6_lsa *lsa;
+
+ oi = (struct ospf6_interface *) THREAD_ARG (thread);
+ oi->thread_send_lsack = (struct thread *) NULL;
+
+ if (oi->state <= OSPF6_INTERFACE_WAITING)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSACK, SEND))
+ zlog_info ("Quit to send LSAck to interface %s state %s",
+ oi->interface->name, ospf6_interface_state_str[oi->state]);
+ return 0;
+ }
+
+ /* if we have nothing to send, return */
+ if (oi->lsack_list->count == 0)
+ return 0;
+
+ memset (sendbuf, 0, sizeof (sendbuf));
+ oh = (struct ospf6_header *) sendbuf;
+
+ p = (char *)((caddr_t) oh + sizeof (struct ospf6_header));
+
+ for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ {
+ /* MTU check */
+ if (p - sendbuf + sizeof (struct ospf6_lsa_header) > oi->ifmtu)
+ {
+ /* if we run out of packet size/space here,
+ better to try again soon. */
+ THREAD_OFF (oi->thread_send_lsack);
+ oi->thread_send_lsack =
+ thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
+
+ ospf6_lsa_unlock (lsa);
+ break;
+ }
+
+ ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
+ memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
+ p += sizeof (struct ospf6_lsa_header);
+
+ assert (lsa->lock == 2);
+ ospf6_lsdb_remove (lsa, oi->lsack_list);
+ }
+
+ oh->type = OSPF6_MESSAGE_TYPE_LSACK;
+ oh->length = htons (p - sendbuf);
+
+ if (oi->state == OSPF6_INTERFACE_DR ||
+ oi->state == OSPF6_INTERFACE_BDR)
+ ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
+ else
+ ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
+
+ if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
+ {
+ oi->thread_send_lsack =
+ thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
+ }
return 0;
}
-/* send section */
-int
-ospf6_message_length (struct iovec *message)
+/* Commands */
+DEFUN (debug_ospf6_message,
+ debug_ospf6_message_cmd,
+ "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
+ DEBUG_STR
+ OSPF6_STR
+ "Debug OSPFv3 message\n"
+ "Debug Unknown message\n"
+ "Debug Hello message\n"
+ "Debug Database Description message\n"
+ "Debug Link State Request message\n"
+ "Debug Link State Update message\n"
+ "Debug Link State Acknowledgement message\n"
+ "Debug All message\n"
+ )
{
- int i, length = 0;
- for (i = 0; i < OSPF6_MESSAGE_IOVEC_SIZE; i++)
- {
- if (message[i].iov_base == NULL && message[i].iov_len == 0)
- break;
- length += message[i].iov_len;
- }
- return length;
-}
-#define OSPF6_MESSAGE_LENGTH(msg) \
-(ospf6_message_length (msg))
-
-void
-ospf6_message_send (unsigned char type, struct iovec *msg,
- struct in6_addr *dst, u_int ifindex)
-{
- struct ospf6_interface *o6i;
- struct ospf6_header ospf6_header;
- char dst_name[64], src_name[64];
- struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
- int msg_len;
-
- /* ospf6 interface lookup */
- o6i = ospf6_interface_lookup_by_index (ifindex);
- assert (o6i);
-
- msg_len = OSPF6_MESSAGE_LENGTH (msg);
-
- /* I/F MTU check */
-#if 0
- if (msg_len + sizeof (struct ospf6_header) >= o6i->interface->mtu)
-#else
- if (msg_len + sizeof (struct ospf6_header) >= o6i->ifmtu)
-#endif
- {
- /* If Interface MTU is 0, save the case
- since zebra had been failed to get MTU from Kernel */
- if (o6i->interface->mtu != 0)
- {
- zlog_warn ("Message: Send failed on %s: exceeds I/F MTU",
- o6i->interface->name);
- zlog_warn ("Message: while sending %s: Len:%d MTU:%d",
- ospf6_message_type_string[type],
- msg_len + sizeof (struct ospf6_header),
- o6i->ifmtu);
- return;
- }
- else
- {
- zlog_warn ("Message: I/F MTU check ignored on %s",
- o6i->interface->name);
- }
- }
-
- /* Initialize */
- OSPF6_MESSAGE_CLEAR (message);
-
- /* set OSPF header */
- memset (&ospf6_header, 0, sizeof (ospf6_header));
- ospf6_header.version = OSPF6_VERSION;
- ospf6_header.type = type;
- ospf6_header.len = htons (msg_len + sizeof (struct ospf6_header));
- ospf6_header.router_id = ospf6->router_id;
- ospf6_header.area_id = o6i->area->area_id;
- /* checksum is calculated by kernel */
- ospf6_header.instance_id = o6i->instance_id;
- ospf6_header.reserved = 0;
- OSPF6_MESSAGE_ATTACH (message, &ospf6_header, sizeof (struct ospf6_header));
-
- /* Attach rest to message */
- OSPF6_MESSAGE_JOIN (message, msg);
-
- /* statistics */
- if (type >= OSPF6_MESSAGE_TYPE_MAX)
- type = OSPF6_MESSAGE_TYPE_UNKNOWN;
- o6i->message_stat[type].send++;
- o6i->message_stat[type].send_octet += ntohs (ospf6_header.len);
-
- /* log */
- if (IS_OSPF6_DUMP_MESSAGE (type))
- {
- inet_ntop (AF_INET6, dst, dst_name, sizeof (dst_name));
- if (o6i->lladdr)
- inet_ntop (AF_INET6, o6i->lladdr, src_name, sizeof (src_name));
- else
- strcpy (src_name, "Unknown");
- zlog_info ("Send %s on %s",
- ospf6_message_type_string[type], o6i->interface->name);
- zlog_info (" %s -> %s", src_name, dst_name);
- ospf6_message_log (message);
- }
-
- /* send message */
- ospf6_sendmsg (o6i->lladdr, dst, &ifindex, message);
-}
-
-
-int
-ospf6_send_hello (struct thread *thread)
-{
- listnode n;
- struct ospf6_interface *o6i;
- struct ospf6_neighbor *o6n;
- struct in6_addr dst;
- struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
- struct ospf6_hello hello;
- char router_buffer[1024]; /* xxx */
- u_int router_size;
-
- /* which ospf6 interface to send */
- o6i = (struct ospf6_interface *) THREAD_ARG (thread);
- o6i->thread_send_hello = (struct thread *) NULL;
-
- /* assure interface is up */
- if (o6i->state <= IFS_DOWN)
- {
- if (IS_OSPF6_DUMP_HELLO)
- zlog_warn ("Send HELLO Failed: Interface not enabled: %s",
- o6i->interface->name);
- return 0;
- }
-
- /* clear message buffer */
- OSPF6_MESSAGE_CLEAR (message);
-
- /* set Hello fields */
- hello.interface_id = htonl (o6i->if_id);
- hello.rtr_pri = o6i->priority;
- memcpy (hello.options, o6i->area->options, sizeof (hello.options));
- hello.hello_interval = htons (o6i->hello_interval);
- hello.router_dead_interval = htons (o6i->dead_interval);
- hello.dr = o6i->dr;
- hello.bdr = o6i->bdr;
- OSPF6_MESSAGE_ATTACH (message, &hello, sizeof (struct ospf6_hello));
-
- /* set neighbor router id */
- router_size = 0;
- for (n = listhead (o6i->neighbor_list); n; nextnode (n))
- {
- o6n = (struct ospf6_neighbor *) getdata (n);
-
- if (o6n->state < NBS_INIT)
- continue;
-
- if (router_size + sizeof (o6n->router_id) > sizeof (router_buffer))
- {
- zlog_warn ("Send HELLO: Buffer shortage on %s",
- o6i->interface->name);
- break;
- }
-
- /* Copy Router-ID to Buffer */
- memcpy (router_buffer + router_size, &o6n->router_id,
- sizeof (o6n->router_id));
- router_size += sizeof (o6n->router_id);
- }
- OSPF6_MESSAGE_ATTACH (message, router_buffer, router_size);
-
- /* set destionation */
- inet_pton (AF_INET6, ALLSPFROUTERS6, &dst);
-
- /* send hello */
- ospf6_message_send (OSPF6_MESSAGE_TYPE_HELLO, message, &dst,
- o6i->interface->ifindex);
-
- /* set next timer thread */
- o6i->thread_send_hello = thread_add_timer (master, ospf6_send_hello,
- o6i, o6i->hello_interval);
-
- return 0;
-}
-
-void
-ospf6_dbdesc_seqnum_init (struct ospf6_neighbor *o6n)
-{
- struct timeval tv;
-
- if (gettimeofday (&tv, (struct timezone *) NULL) < 0)
- tv.tv_sec = 1;
-
- o6n->dbdesc_seqnum = tv.tv_sec;
-
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info ("set dbdesc seqnum %d for %s", o6n->dbdesc_seqnum, o6n->str);
-}
-
-int
-ospf6_send_dbdesc_rxmt (struct thread *thread)
-{
- struct ospf6_lsdb_node node;
- struct ospf6_neighbor *o6n;
- struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
- struct ospf6_lsa *lsa;
- struct ospf6_lsa_header *lsa_header;
- struct ospf6_dbdesc dbdesc;
-
- o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
- assert (o6n);
-
- /* clear thread */
- o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
-
- /* if state less than ExStart, do nothing */
- if (o6n->state < NBS_EXSTART)
- return 0;
-
- OSPF6_MESSAGE_CLEAR (message);
-
- /* set dbdesc */
- memcpy (dbdesc.options, o6n->ospf6_interface->area->options,
- sizeof (dbdesc.options));
- dbdesc.ifmtu = htons (o6n->ospf6_interface->interface->mtu);
- dbdesc.bits = o6n->dbdesc_bits;
- dbdesc.seqnum = htonl (o6n->dbdesc_seqnum);
- OSPF6_MESSAGE_ATTACH (message, &dbdesc, sizeof (struct ospf6_dbdesc));
-
- /* if this is not initial, set LSA summary to dbdesc */
- if (! DD_IS_IBIT_SET (o6n->dbdesc_bits))
- {
- for (ospf6_lsdb_head (&node, o6n->dbdesc_list);
- ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node))
- {
- lsa = node.lsa;
-
- /* xxx, no MTU check: no support for Dynamic MTU change */
-
- /* set age and add InfTransDelay */
- ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay);
-
- /* set LSA summary to send buffer */
- lsa_header = (struct ospf6_lsa_header *) lsa->lsa_hdr;
- OSPF6_MESSAGE_ATTACH (message, lsa_header,
- sizeof (struct ospf6_lsa_header));
- }
- }
-
- /* send dbdesc */
- ospf6_message_send (OSPF6_MESSAGE_TYPE_DBDESC, message, &o6n->hisaddr,
- o6n->ospf6_interface->interface->ifindex);
-
- /* if master, set futher retransmission */
- if (DD_IS_MSBIT_SET (o6n->dbdesc_bits))
- o6n->thread_rxmt_dbdesc =
- thread_add_timer (master, ospf6_send_dbdesc_rxmt,
- o6n, o6n->ospf6_interface->rxmt_interval);
-
- /* statistics */
- o6n->ospf6_stat_retrans_dbdesc++;
-
- return 0;
-}
-
-int
-ospf6_send_dbdesc (struct thread *thread)
-{
- struct ospf6_neighbor *o6n;
- struct ospf6_lsa *lsa;
- struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
- struct ospf6_dbdesc dbdesc;
- struct ospf6_lsdb_node node;
-
- o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
- assert (o6n);
-
- /* clear thread */
- o6n->thread_send_dbdesc = (struct thread *) NULL;
- if (o6n->thread_rxmt_dbdesc)
- thread_cancel (o6n->thread_rxmt_dbdesc);
- o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
-
- /* if state less than ExStart, do nothing */
- if (o6n->state < NBS_EXSTART)
- return 0;
-
- OSPF6_MESSAGE_CLEAR (message);
- OSPF6_MESSAGE_ATTACH (message, &dbdesc, sizeof (struct ospf6_dbdesc));
-
- /* clear previous LSA summary sent */
- ospf6_lsdb_remove_all (o6n->dbdesc_list);
- assert (o6n->dbdesc_list->count == 0);
-
- /* if this is not initial, set LSA summary to dbdesc */
- if (! DD_IS_IBIT_SET (o6n->dbdesc_bits))
- {
- for (ospf6_lsdb_head (&node, o6n->summary_list);
- ! ospf6_lsdb_is_end (&node);
- ospf6_lsdb_next (&node))
- {
- lsa = node.lsa;
-
- /* MTU check */
- if (OSPF6_MESSAGE_LENGTH (message)
- + sizeof (struct ospf6_lsa_header)
- + sizeof (struct ospf6_header)
- > o6n->ospf6_interface->ifmtu)
- break;
-
- /* debug */
- if (IS_OSPF6_DUMP_DBDESC)
- zlog_info ("Include DbDesc: %s", lsa->str);
-
- /* attach to dbdesclist */
- ospf6_neighbor_dbdesc_add (lsa, o6n);
- /* detach from summarylist */
- ospf6_neighbor_summary_remove (lsa, o6n);
-
- /* set age and add InfTransDelay */
- ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay);
-
- /* set LSA summary to send buffer */
- OSPF6_MESSAGE_ATTACH (message, lsa->header,
- sizeof (struct ospf6_lsa_header));
- }
-
- if (o6n->summary_list->count == 0)
- {
- /* Clear more bit */
- DD_MBIT_CLEAR (o6n->dbdesc_bits);
-
- /* slave must schedule ExchangeDone on sending, here */
- if (! DD_IS_MSBIT_SET (o6n->dbdesc_bits))
- {
- if (! DD_IS_MBIT_SET (o6n->dbdesc_bits) &&
- ! DD_IS_MBIT_SET (o6n->last_dd.bits))
- thread_add_event (master, exchange_done, o6n, 0);
- }
- }
- }
-
- /* if this is initial, set seqnum */
- if (DDBIT_IS_INITIAL (o6n->dbdesc_bits))
- ospf6_dbdesc_seqnum_init (o6n);
-
- /* set dbdesc */
- memcpy (dbdesc.options, o6n->ospf6_interface->area->options,
- sizeof (dbdesc.options));
- dbdesc.ifmtu = htons (o6n->ospf6_interface->interface->mtu);
- dbdesc.bits = o6n->dbdesc_bits;
- dbdesc.seqnum = htonl (o6n->dbdesc_seqnum);
-
- /* send dbdesc */
- ospf6_message_send (OSPF6_MESSAGE_TYPE_DBDESC, message, &o6n->hisaddr,
- o6n->ospf6_interface->interface->ifindex);
-
- /* if master, set retransmission */
- if (DD_IS_MSBIT_SET (o6n->dbdesc_bits))
- o6n->thread_rxmt_dbdesc =
- thread_add_timer (master, ospf6_send_dbdesc_rxmt,
- o6n, o6n->ospf6_interface->rxmt_interval);
-
- /* statistics */
- o6n->lsa_send[OSPF6_MESSAGE_TYPE_DBDESC] += o6n->dbdesc_list->count;
-
- return 0;
-}
-
-int
-ospf6_send_lsreq_rxmt (struct thread *thread)
-{
- struct ospf6_neighbor *o6n;
-
- o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
- assert (o6n);
-
- o6n->thread_rxmt_lsreq = (struct thread *) NULL;
- o6n->thread_send_lsreq = thread_add_event (master, ospf6_send_lsreq, o6n, 0);
- return 0;
-}
-
-int
-ospf6_send_lsreq (struct thread *thread)
-{
- struct ospf6_neighbor *o6n;
- struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
- struct ospf6_lsreq lsreq[OSPF6_MESSAGE_IOVEC_SIZE];
- struct ospf6_lsa *lsa;
- struct ospf6_lsdb_node node;
+ unsigned char level = 0;
+ int type = 0;
int i;
- o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
- assert (o6n);
+ assert (argc > 0);
- /* LSReq will be send only in ExStart or Loading */
- if (o6n->state != NBS_EXCHANGE && o6n->state != NBS_LOADING)
- return 0;
+ /* check type */
+ if (! strncmp (argv[0], "u", 1))
+ type = OSPF6_MESSAGE_TYPE_UNKNOWN;
+ else if (! strncmp (argv[0], "h", 1))
+ type = OSPF6_MESSAGE_TYPE_HELLO;
+ else if (! strncmp (argv[0], "d", 1))
+ type = OSPF6_MESSAGE_TYPE_DBDESC;
+ else if (! strncmp (argv[0], "lsr", 3))
+ type = OSPF6_MESSAGE_TYPE_LSREQ;
+ else if (! strncmp (argv[0], "lsu", 3))
+ type = OSPF6_MESSAGE_TYPE_LSUPDATE;
+ else if (! strncmp (argv[0], "lsa", 3))
+ type = OSPF6_MESSAGE_TYPE_LSACK;
+ else if (! strncmp (argv[0], "a", 1))
+ type = OSPF6_MESSAGE_TYPE_ALL;
- /* clear thread */
- o6n->thread_send_lsreq = (struct thread *) NULL;
- if (o6n->thread_rxmt_lsreq)
- thread_cancel (o6n->thread_rxmt_lsreq);
- o6n->thread_rxmt_lsreq = (struct thread *) NULL;
+ if (argc == 1)
+ level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
+ else if (! strncmp (argv[1], "s", 1))
+ level = OSPF6_DEBUG_MESSAGE_SEND;
+ else if (! strncmp (argv[1], "r", 1))
+ level = OSPF6_DEBUG_MESSAGE_RECV;
- /* schedule loading_done if request list is empty */
- if (o6n->request_list->count == 0)
+ if (type == OSPF6_MESSAGE_TYPE_ALL)
{
- thread_add_event (master, loading_done, o6n, 0);
+ for (i = 0; i < 6; i++)
+ OSPF6_DEBUG_MESSAGE_ON (i, level);
+ }
+ else
+ OSPF6_DEBUG_MESSAGE_ON (type, level);
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (debug_ospf6_message,
+ debug_ospf6_message_sendrecv_cmd,
+ "debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
+ DEBUG_STR
+ OSPF6_STR
+ "Debug OSPFv3 message\n"
+ "Debug Unknown message\n"
+ "Debug Hello message\n"
+ "Debug Database Description message\n"
+ "Debug Link State Request message\n"
+ "Debug Link State Update message\n"
+ "Debug Link State Acknowledgement message\n"
+ "Debug All message\n"
+ "Debug only sending message\n"
+ "Debug only receiving message\n"
+ );
+
+
+DEFUN (no_debug_ospf6_message,
+ no_debug_ospf6_message_cmd,
+ "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all)",
+ NO_STR
+ DEBUG_STR
+ OSPF6_STR
+ "Debug OSPFv3 message\n"
+ "Debug Unknown message\n"
+ "Debug Hello message\n"
+ "Debug Database Description message\n"
+ "Debug Link State Request message\n"
+ "Debug Link State Update message\n"
+ "Debug Link State Acknowledgement message\n"
+ "Debug All message\n"
+ )
+{
+ unsigned char level = 0;
+ int type = 0;
+ int i;
+
+ assert (argc > 0);
+
+ /* check type */
+ if (! strncmp (argv[0], "u", 1))
+ type = OSPF6_MESSAGE_TYPE_UNKNOWN;
+ else if (! strncmp (argv[0], "h", 1))
+ type = OSPF6_MESSAGE_TYPE_HELLO;
+ else if (! strncmp (argv[0], "d", 1))
+ type = OSPF6_MESSAGE_TYPE_DBDESC;
+ else if (! strncmp (argv[0], "lsr", 3))
+ type = OSPF6_MESSAGE_TYPE_LSREQ;
+ else if (! strncmp (argv[0], "lsu", 3))
+ type = OSPF6_MESSAGE_TYPE_LSUPDATE;
+ else if (! strncmp (argv[0], "lsa", 3))
+ type = OSPF6_MESSAGE_TYPE_LSACK;
+ else if (! strncmp (argv[0], "a", 1))
+ type = OSPF6_MESSAGE_TYPE_ALL;
+
+ if (argc == 1)
+ level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
+ else if (! strncmp (argv[1], "s", 1))
+ level = OSPF6_DEBUG_MESSAGE_SEND;
+ else if (! strncmp (argv[1], "r", 1))
+ level = OSPF6_DEBUG_MESSAGE_RECV;
+
+ if (type == OSPF6_MESSAGE_TYPE_ALL)
+ {
+ for (i = 0; i < 6; i++)
+ OSPF6_DEBUG_MESSAGE_OFF (i, level);
+ }
+ else
+ OSPF6_DEBUG_MESSAGE_OFF (type, level);
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_ospf6_message,
+ no_debug_ospf6_message_sendrecv_cmd,
+ "no debug ospf6 message (unknown|hello|dbdesc|lsreq|lsupdate|lsack|all) (send|recv)",
+ NO_STR
+ DEBUG_STR
+ OSPF6_STR
+ "Debug OSPFv3 message\n"
+ "Debug Unknown message\n"
+ "Debug Hello message\n"
+ "Debug Database Description message\n"
+ "Debug Link State Request message\n"
+ "Debug Link State Update message\n"
+ "Debug Link State Acknowledgement message\n"
+ "Debug All message\n"
+ "Debug only sending message\n"
+ "Debug only receiving message\n"
+ );
+
+int
+config_write_ospf6_debug_message (struct vty *vty)
+{
+ char *type_str[] = {"unknown", "hello", "dbdesc",
+ "lsreq", "lsupdate", "lsack"};
+ unsigned char s = 0, r = 0;
+ int i;
+
+ for (i = 0; i < 6; i++)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
+ s |= 1 << i;
+ if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
+ r |= 1 << i;
+ }
+
+ if (s == 0x3f && r == 0x3f)
+ {
+ vty_out (vty, "debug ospf6 message all%s", VTY_NEWLINE);
return 0;
}
- /* clear message buffer */
- OSPF6_MESSAGE_CLEAR (message);
-
- i = 0;
- for (ospf6_lsdb_head (&node, o6n->request_list);
- ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node))
+ if (s == 0x3f && r == 0)
{
- lsa = node.lsa;
-
- /* Buffer Overflow */
- if (i >= OSPF6_MESSAGE_IOVEC_SIZE)
- break;
-
- /* I/F MTU check */
- if (OSPF6_MESSAGE_LENGTH (message)
- + sizeof (struct ospf6_lsreq)
- + sizeof (struct ospf6_header)
- > o6n->ospf6_interface->ifmtu)
- break;
-
- lsreq[i].mbz = 0;
- lsreq[i].type = lsa->header->type;
- lsreq[i].id = lsa->header->id;
- lsreq[i].adv_router = lsa->header->adv_router;
-
- OSPF6_MESSAGE_ATTACH (message, &lsreq[i], sizeof (struct ospf6_lsreq));
- i++;
+ vty_out (vty, "debug ospf6 message all send%s", VTY_NEWLINE);
+ return 0;
+ }
+ else if (s == 0 && r == 0x3f)
+ {
+ vty_out (vty, "debug ospf6 message all recv%s", VTY_NEWLINE);
+ return 0;
}
- ospf6_message_send (OSPF6_MESSAGE_TYPE_LSREQ, message, &o6n->hisaddr,
- o6n->ospf6_interface->interface->ifindex);
+ /* Unknown message is logged by default */
+ if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND) &&
+ ! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ vty_out (vty, "no debug ospf6 message unknown%s", VTY_NEWLINE);
+ else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, SEND))
+ vty_out (vty, "no debug ospf6 message unknown send%s", VTY_NEWLINE);
+ else if (! IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+ vty_out (vty, "no debug ospf6 message unknown recv%s", VTY_NEWLINE);
- /* set retransmit thread */
- o6n->thread_rxmt_lsreq =
- thread_add_timer (master, ospf6_send_lsreq_rxmt,
- o6n, o6n->ospf6_interface->rxmt_interval);
-
- /* statistics */
- o6n->lsa_send[OSPF6_MESSAGE_TYPE_LSREQ] += i;
+ for (i = 1; i < 6; i++)
+ {
+ if (IS_OSPF6_DEBUG_MESSAGE (i, SEND) &&
+ IS_OSPF6_DEBUG_MESSAGE (i, RECV))
+ vty_out (vty, "debug ospf6 message %s%s", type_str[i], VTY_NEWLINE);
+ else if (IS_OSPF6_DEBUG_MESSAGE (i, SEND))
+ vty_out (vty, "debug ospf6 message %s send%s", type_str[i],
+ VTY_NEWLINE);
+ else if (IS_OSPF6_DEBUG_MESSAGE (i, RECV))
+ vty_out (vty, "debug ospf6 message %s recv%s", type_str[i],
+ VTY_NEWLINE);
+ }
return 0;
}
-/* Send LSUpdate directly to the neighbor, from his retransmission list */
-int
-ospf6_send_lsupdate_rxmt (struct thread *thread)
-{
- struct ospf6_neighbor *o6n;
- struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
- struct ospf6_lsupdate lsupdate;
- struct ospf6_lsa *lsa;
- struct ospf6_lsdb_node node;
-
- o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
- assert (o6n);
-
- o6n->send_update = (struct thread *) NULL;
-
- if (o6n->ospf6_interface->state <= IFS_WAITING)
- return -1;
-
- /* clear message buffer */
- OSPF6_MESSAGE_CLEAR (message);
-
- /* set lsupdate header */
- lsupdate.lsupdate_num = 0; /* set gradually */
- OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate));
-
- /* for each LSA listed on retransmission-list */
- for (ospf6_lsdb_head (&node, o6n->retrans_list);
- ! ospf6_lsdb_is_end (&node);
- ospf6_lsdb_next (&node))
- {
- lsa = node.lsa;
-
- /* I/F MTU check */
- if (OSPF6_MESSAGE_LENGTH (message)
- + sizeof (struct ospf6_lsupdate)
- + sizeof (struct ospf6_header)
- + ntohs (lsa->header->length)
- > o6n->ospf6_interface->ifmtu)
- break;
-
- ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay);
- OSPF6_MESSAGE_ATTACH (message, lsa->header, ntohs (lsa->header->length));
- lsupdate.lsupdate_num++;
- }
-
- /* check and correct lsupdate */
- if (lsupdate.lsupdate_num == 0)
- return 0;
- lsupdate.lsupdate_num = htonl (lsupdate.lsupdate_num);
-
- if (IS_OSPF6_DUMP_LSUPDATE)
- zlog_info ("MESSAGE: retrsnsmit LSUpdate to %s", o6n->str);
-
- /* statistics */
- o6n->ospf6_stat_retrans_lsupdate++;
-
- ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message,
- &o6n->hisaddr, o6n->ospf6_interface->if_id);
-
- o6n->send_update = thread_add_timer (master, ospf6_send_lsupdate_rxmt, o6n,
- o6n->ospf6_interface->rxmt_interval);
- return 0;
-}
-
-/* Send LSUpdate containing one LSA directly to the neighbor.
- This is "implied acknowledgement" */
void
-ospf6_send_lsupdate_direct (struct ospf6_lsa *lsa, struct ospf6_neighbor *o6n)
+install_element_ospf6_debug_message ()
{
- struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
- struct ospf6_lsupdate lsupdate;
- int lsa_len;
-
- /* clear message buffer */
- OSPF6_MESSAGE_CLEAR (message);
-
- /* set lsupdate header */
- lsupdate.lsupdate_num = ntohl (1);
- OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate));
-
- /* set one LSA */
- lsa_len = ntohs (lsa->lsa_hdr->lsh_len);
- ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay);
- OSPF6_MESSAGE_ATTACH (message, lsa->lsa_hdr, lsa_len);
-
- ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message, &o6n->hisaddr,
- o6n->ospf6_interface->if_id);
+ install_element (ENABLE_NODE, &debug_ospf6_message_cmd);
+ install_element (ENABLE_NODE, &no_debug_ospf6_message_cmd);
+ install_element (ENABLE_NODE, &debug_ospf6_message_sendrecv_cmd);
+ install_element (ENABLE_NODE, &no_debug_ospf6_message_sendrecv_cmd);
+ install_element (CONFIG_NODE, &debug_ospf6_message_cmd);
+ install_element (CONFIG_NODE, &no_debug_ospf6_message_cmd);
+ install_element (CONFIG_NODE, &debug_ospf6_message_sendrecv_cmd);
+ install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd);
}
-/* Send LSUpdate containing one LSA by multicast.
- On non-broadcast link, send it to each neighbor by unicast.
- This is ordinary flooding */
-void
-ospf6_send_lsupdate_flood (struct ospf6_lsa *lsa, struct ospf6_interface *o6i)
-{
- struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE];
- struct ospf6_lsupdate lsupdate;
- struct in6_addr dst;
- int lsa_len;
-
- /* clear message buffer */
- OSPF6_MESSAGE_CLEAR (message);
-
- /* set lsupdate header */
- lsupdate.lsupdate_num = ntohl (1);
- OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate));
-
- /* set one LSA */
- lsa_len = ntohs (lsa->lsa_hdr->lsh_len);
- ospf6_lsa_age_update_to_send (lsa, o6i->transdelay);
- OSPF6_MESSAGE_ATTACH (message, lsa->lsa_hdr, lsa_len);
-
- if (if_is_broadcast (o6i->interface))
- {
- /* set destination */
- if (o6i->state == IFS_DR || o6i->state == IFS_BDR)
- inet_pton (AF_INET6, ALLSPFROUTERS6, &dst);
- else
- inet_pton (AF_INET6, ALLDROUTERS6, &dst);
- }
- else
- {
- /* IPv6 relies on link local multicast */
- inet_pton (AF_INET6, ALLSPFROUTERS6, &dst);
- }
-
- ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message, &dst,
- o6i->if_id);
-}
-
-int
-ospf6_send_lsack_delayed (struct thread *thread)
-{
- struct ospf6_interface *o6i;
- struct iovec message[MAXIOVLIST];
- struct ospf6_lsa *lsa;
- struct ospf6_lsdb_node node;
-
- o6i = THREAD_ARG (thread);
- assert (o6i);
-
- if (IS_OSPF6_DUMP_LSACK)
- zlog_info ("LSACK: Delayed LSAck for %s\n", o6i->interface->name);
-
- o6i->thread_send_lsack_delayed = (struct thread *) NULL;
-
- if (o6i->state <= IFS_WAITING)
- return 0;
-
- if (o6i->ack_list->count == 0)
- return 0;
-
- iov_clear (message, MAXIOVLIST);
-
- for (ospf6_lsdb_head (&node, o6i->ack_list);
- ! ospf6_lsdb_is_end (&node);
- ospf6_lsdb_next (&node))
- {
- lsa = node.lsa;
- if (IS_OVER_MTU (message, o6i->ifmtu, sizeof (struct ospf6_lsa_hdr)))
- break;
-
- OSPF6_MESSAGE_ATTACH (message, lsa->header,
- sizeof (struct ospf6_lsa_header));
- ospf6_interface_delayed_ack_remove (lsa, o6i);
- }
-
- /* statistics */
- o6i->ospf6_stat_delayed_lsack++;
-
- switch (o6i->state)
- {
- case IFS_DR:
- case IFS_BDR:
- ospf6_message_send (OSPF6_MESSAGE_TYPE_LSACK, message,
- &allspfrouters6.sin6_addr, o6i->if_id);
- break;
- default:
- ospf6_message_send (OSPF6_MESSAGE_TYPE_LSACK, message,
- &alldrouters6.sin6_addr, o6i->if_id);
- break;
- }
-
- iov_clear (message, MAXIOVLIST);
- return 0;
-}
diff --git a/ospf6d/ospf6_message.h b/ospf6d/ospf6_message.h
index 105cb4f..f8be627 100644
--- a/ospf6d/ospf6_message.h
+++ b/ospf6d/ospf6_message.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 1999-2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -22,87 +22,84 @@
#ifndef OSPF6_MESSAGE_H
#define OSPF6_MESSAGE_H
-#include "ospf6_prefix.h"
-#include "ospf6_lsa.h"
+#define OSPF6_MESSAGE_BUFSIZ 4096
+
+/* Debug option */
+extern unsigned char conf_debug_ospf6_message[];
+#define OSPF6_DEBUG_MESSAGE_SEND 0x01
+#define OSPF6_DEBUG_MESSAGE_RECV 0x02
+#define OSPF6_DEBUG_MESSAGE_ON(type, level) \
+ (conf_debug_ospf6_message[type] |= (level))
+#define OSPF6_DEBUG_MESSAGE_OFF(type, level) \
+ (conf_debug_ospf6_message[type] &= ~(level))
+#define IS_OSPF6_DEBUG_MESSAGE(t, e) \
+ (conf_debug_ospf6_message[t] & OSPF6_DEBUG_MESSAGE_ ## e)
/* Type */
-#define OSPF6_MESSAGE_TYPE_NONE 0x0
#define OSPF6_MESSAGE_TYPE_UNKNOWN 0x0
#define OSPF6_MESSAGE_TYPE_HELLO 0x1 /* Discover/maintain neighbors */
#define OSPF6_MESSAGE_TYPE_DBDESC 0x2 /* Summarize database contents */
-#define OSPF6_MESSAGE_TYPE_LSREQ 0x3 /* Database download */
+#define OSPF6_MESSAGE_TYPE_LSREQ 0x3 /* Database download request */
#define OSPF6_MESSAGE_TYPE_LSUPDATE 0x4 /* Database update */
#define OSPF6_MESSAGE_TYPE_LSACK 0x5 /* Flooding acknowledgment */
-#define OSPF6_MESSAGE_TYPE_MAX 0x6
+#define OSPF6_MESSAGE_TYPE_ALL 0x6 /* For debug option */
+
+#define OSPF6_MESSAGE_TYPE_CANONICAL(T) \
+ ((T) > OSPF6_MESSAGE_TYPE_LSACK ? OSPF6_MESSAGE_TYPE_UNKNOWN : (T))
+
+extern char *ospf6_message_type_str[];
+#define OSPF6_MESSAGE_TYPE_NAME(T) \
+ (ospf6_message_type_str[ OSPF6_MESSAGE_TYPE_CANONICAL (T) ])
/* OSPFv3 packet header */
struct ospf6_header
{
u_char version;
u_char type;
- u_int16_t len;
+ u_int16_t length;
u_int32_t router_id;
u_int32_t area_id;
- u_int16_t cksum;
+ u_int16_t checksum;
u_char instance_id;
u_char reserved;
};
+#define OSPF6_MESSAGE_END(H) ((caddr_t) (H) + ntohs ((H)->length))
+
/* Hello */
-#define MAXLISTEDNBR 64
struct ospf6_hello
{
u_int32_t interface_id;
- u_char rtr_pri;
+ u_char priority;
u_char options[3];
u_int16_t hello_interval;
- u_int16_t router_dead_interval;
- u_int32_t dr;
- u_int32_t bdr;
+ u_int16_t dead_interval;
+ u_int32_t drouter;
+ u_int32_t bdrouter;
+ /* Followed by Router-IDs */
};
/* Database Description */
struct ospf6_dbdesc
{
- u_char mbz1;
+ u_char reserved1;
u_char options[3];
u_int16_t ifmtu;
- u_char mbz2;
+ u_char reserved2;
u_char bits;
u_int32_t seqnum;
- /* Followed by LSAs */
+ /* Followed by LSA Headers */
};
-#define DEFAULT_INTERFACE_MTU 1500
-#define DD_IS_MSBIT_SET(x) ((x) & (1 << 0))
-#define DD_MSBIT_SET(x) ((x) |= (1 << 0))
-#define DD_MSBIT_CLEAR(x) ((x) &= ~(1 << 0))
-#define DD_IS_MBIT_SET(x) ((x) & (1 << 1))
-#define DD_MBIT_SET(x) ((x) |= (1 << 1))
-#define DD_MBIT_CLEAR(x) ((x) &= ~(1 << 1))
-#define DD_IS_IBIT_SET(x) ((x) & (1 << 2))
-#define DD_IBIT_SET(x) ((x) |= (1 << 2))
-#define DD_IBIT_CLEAR(x) ((x) &= ~(1 << 2))
-
-#define DDBIT_IS_MASTER(x) ((x) & (1 << 0))
-#define DDBIT_IS_SLAVE(x) (!((x) & (1 << 0)))
-#define DDBIT_SET_MASTER(x) ((x) |= (1 << 0))
-#define DDBIT_SET_SLAVE(x) ((x) |= ~(1 << 0))
-#define DDBIT_IS_MORE(x) ((x) & (1 << 1))
-#define DDBIT_SET_MORE(x) ((x) |= (1 << 1))
-#define DDBIT_CLR_MORE(x) ((x) |= ~(1 << 1))
-#define DDBIT_IS_INITIAL(x) ((x) & (1 << 2))
-#define DDBIT_SET_INITIAL(x) ((x) |= (1 << 2))
-#define DDBIT_CLR_INITIAL(x) ((x) |= ~(1 << 2))
-
-#define OSPF6_DBDESC_BIT_MASTER 0x01
-#define OSPF6_DBDESC_BIT_MORE 0x02
-#define OSPF6_DBDESC_BIT_INITIAL 0x04
+#define OSPF6_DBDESC_MSBIT (0x01) /* master/slave bit */
+#define OSPF6_DBDESC_MBIT (0x02) /* more bit */
+#define OSPF6_DBDESC_IBIT (0x04) /* initial bit */
/* Link State Request */
-struct ospf6_lsreq
+/* It is just a sequence of entries below */
+struct ospf6_lsreq_entry
{
- u_int16_t mbz; /* Must Be Zero */
+ u_int16_t reserved; /* Must Be Zero */
u_int16_t type; /* LS type */
u_int32_t id; /* Link State ID */
u_int32_t adv_router; /* Advertising Router */
@@ -111,92 +108,33 @@
/* Link State Update */
struct ospf6_lsupdate
{
- u_int32_t lsupdate_num;
+ u_int32_t lsa_number;
+ /* Followed by LSAs */
};
/* Link State Acknowledgement */
- /* no need for structure,
- it will include only LSA header in the packet body.*/
+/* It is just a sequence of LSA Headers */
-/* definition for ospf6_message.c */
-#define OSPF6_MESSAGE_RECEIVE_BUFSIZE 5120
-#define OSPF6_MESSAGE_IOVEC_END 1024
+/* Function definition */
+void ospf6_hello_print (struct ospf6_header *);
+void ospf6_dbdesc_print (struct ospf6_header *);
+void ospf6_lsreq_print (struct ospf6_header *);
+void ospf6_lsupdate_print (struct ospf6_header *);
+void ospf6_lsack_print (struct ospf6_header *);
-#define IS_OVER_MTU(message,mtu,addsize) \
- (iov_totallen(message)+(addsize) >= \
- (mtu)-sizeof(struct ospf6_header))
+int ospf6_receive (struct thread *thread);
-#define OSPF6_MESSAGE_IOVEC_SIZE 1024
-#define OSPF6_MESSAGE_CLEAR(msg) \
-do { \
- int x; \
- for (x = 0; x < OSPF6_MESSAGE_IOVEC_SIZE; x++) \
- { \
- (msg)[x].iov_base = NULL; \
- (msg)[x].iov_len = 0; \
- } \
-} while (0)
+int ospf6_hello_send (struct thread *thread);
+int ospf6_dbdesc_send (struct thread *thread);
+int ospf6_dbdesc_send_newone (struct thread *thread);
+int ospf6_lsreq_send (struct thread *thread);
+int ospf6_lsupdate_send_interface (struct thread *thread);
+int ospf6_lsupdate_send_neighbor (struct thread *thread);
+int ospf6_lsack_send_interface (struct thread *thread);
+int ospf6_lsack_send_neighbor (struct thread *thread);
-#define OSPF6_MESSAGE_ATTACH(msg,buf,bufsize) \
-do { \
- int x; \
- for (x = 0; x < OSPF6_MESSAGE_IOVEC_SIZE; x++) \
- if ((msg)[x].iov_base == (void *)NULL && (msg)[x].iov_len == 0) \
- break; \
- if (x < OSPF6_MESSAGE_IOVEC_SIZE - 1) \
- { \
- (msg)[x].iov_base = (void *)(buf); \
- (msg)[x].iov_len = (bufsize); \
- } \
-} while (0)
-
-#define OSPF6_MESSAGE_JOIN(msg,join) \
-do { \
- int x,y; \
- for (x = 0; x < OSPF6_MESSAGE_IOVEC_SIZE; x++) \
- if ((msg)[x].iov_base == NULL && (msg)[x].iov_len == 0) \
- break; \
- for (y = x; y < OSPF6_MESSAGE_IOVEC_SIZE; y++) \
- { \
- (msg)[y].iov_base = (join)[y - x].iov_base; \
- (msg)[y].iov_len = (join)[y - x].iov_len; \
- } \
-} while (0)
-
-
-/* Statistics */
-struct ospf6_message_stat
-{
- u_int32_t send;
- u_int32_t send_octet;
- u_int32_t recv;
- u_int32_t recv_octet;
-};
-
-/* Type string */
-extern char *ospf6_message_type_string[];
-
-/* Function Prototypes */
-int ospf6_receive (struct thread *);
-
-int ospf6_send_hello (struct thread *);
-int ospf6_send_dbdesc_rxmt (struct thread *);
-int ospf6_send_dbdesc (struct thread *);
-int ospf6_send_lsreq (struct thread *);
-
-struct ospf6_neighbor;
-struct ospf6_interface;
-int
-ospf6_send_lsupdate_rxmt (struct thread *);
-void
-ospf6_send_lsupdate_direct (struct ospf6_lsa *, struct ospf6_neighbor *);
-void
-ospf6_send_lsupdate_flood (struct ospf6_lsa *, struct ospf6_interface *);
-
-int ospf6_send_lsack_delayed (struct thread *);
-int ospf6_send_lsack_direct (struct thread *);
-
-void ospf6_message_send (u_char, struct iovec *, struct in6_addr *, u_int);
+int config_write_ospf6_debug_message (struct vty *);
+void install_element_ospf6_debug_message ();
#endif /* OSPF6_MESSAGE_H */
diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c
index 72735d5..acfd1a4 100644
--- a/ospf6d/ospf6_neighbor.c
+++ b/ospf6d/ospf6_neighbor.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -19,321 +19,581 @@
* Boston, MA 02111-1307, USA.
*/
-#include "ospf6d.h"
-
#include <zebra.h>
#include "log.h"
+#include "memory.h"
#include "thread.h"
#include "linklist.h"
#include "vty.h"
#include "command.h"
-#include "ospf6_lsa.h"
-#include "ospf6_message.h"
-#include "ospf6_neighbor.h"
-#include "ospf6_nsm.h"
+#include "ospf6d.h"
+#include "ospf6_proto.h"
#include "ospf6_lsa.h"
#include "ospf6_lsdb.h"
+#include "ospf6_message.h"
+#include "ospf6_top.h"
+#include "ospf6_area.h"
+#include "ospf6_interface.h"
+#include "ospf6_neighbor.h"
+#include "ospf6_intra.h"
-char *ospf6_neighbor_state_string[] =
-{
- "None", "Down", "Attempt", "Init", "Twoway",
- "ExStart", "ExChange", "Loading", "Full", NULL
-};
+unsigned char conf_debug_ospf6_neighbor = 0;
+
+char *ospf6_neighbor_state_str[] =
+{ "None", "Down", "Attempt", "Init", "Twoway", "ExStart", "ExChange",
+ "Loading", "Full", NULL };
int
-ospf6_neighbor_last_dbdesc_release (struct thread *thread)
+ospf6_neighbor_cmp (void *va, void *vb)
{
- struct ospf6_neighbor *o6n;
-
- o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
- assert (o6n);
- memset (&o6n->last_dd, 0, sizeof (struct ospf6_dbdesc));
- return 0;
+ struct ospf6_neighbor *ona = (struct ospf6_neighbor *) va;
+ struct ospf6_neighbor *onb = (struct ospf6_neighbor *) vb;
+ return (ntohl (ona->router_id) - ntohl (onb->router_id));
}
-
-
-void
-ospf6_neighbor_thread_cancel_all (struct ospf6_neighbor *o6n)
+struct ospf6_neighbor *
+ospf6_neighbor_lookup (u_int32_t router_id,
+ struct ospf6_interface *oi)
{
- if (o6n->inactivity_timer)
- thread_cancel (o6n->inactivity_timer);
- o6n->inactivity_timer = (struct thread *) NULL;
+ listnode n;
+ struct ospf6_neighbor *on;
- if (o6n->send_update)
- thread_cancel (o6n->send_update);
- o6n->send_update = (struct thread *) NULL;
-
- if (o6n->thread_send_dbdesc)
- thread_cancel (o6n->thread_send_dbdesc);
- o6n->thread_send_dbdesc = (struct thread *) NULL;
- if (o6n->thread_rxmt_dbdesc)
- thread_cancel (o6n->thread_rxmt_dbdesc);
- o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
-
- if (o6n->thread_rxmt_lsreq)
- thread_cancel (o6n->thread_rxmt_lsreq);
- o6n->thread_rxmt_lsreq = (struct thread *) NULL;
-}
-
-void
-ospf6_neighbor_lslist_clear (struct ospf6_neighbor *nei)
-{
- ospf6_lsdb_remove_all (nei->summary_list);
- ospf6_lsdb_remove_all (nei->request_list);
- ospf6_lsdb_remove_all (nei->retrans_list);
- ospf6_lsdb_remove_all (nei->dbdesc_list);
-}
-
-void
-ospf6_neighbor_summary_add (struct ospf6_lsa *lsa,
- struct ospf6_neighbor *nei)
-{
- struct ospf6_lsa *summary;
-
- if (IS_OSPF6_DUMP_NEIGHBOR)
+ for (n = listhead (oi->neighbor_list); n; nextnode (n))
{
- zlog_info ("Neighbor %s summary-list:", nei->str);
- zlog_info (" Add %s", lsa->str);
+ on = (struct ospf6_neighbor *) getdata (n);
+ if (on->router_id == router_id)
+ return on;
}
-
- ospf6_lsa_age_current (lsa);
- summary = ospf6_lsa_summary_create (lsa->header);
- ospf6_lsdb_add (summary, nei->summary_list);
-}
-
-void
-ospf6_neighbor_summary_remove (struct ospf6_lsa *lsa,
- struct ospf6_neighbor *nei)
-{
- struct ospf6_lsa *summary;
-
- if (IS_OSPF6_DUMP_NEIGHBOR)
- {
- zlog_info ("Neighbor %s summary-list:", nei->str);
- zlog_info (" Remove %s", lsa->str);
- }
-
- summary = ospf6_lsdb_lookup_lsdb (lsa->header->type, lsa->header->id,
- lsa->header->adv_router, nei->summary_list);
- ospf6_lsdb_remove (summary, nei->summary_list);
-}
-
-void
-ospf6_neighbor_request_add (struct ospf6_lsa *lsa,
- struct ospf6_neighbor *nei)
-{
- struct ospf6_lsa *summary;
-
- if (IS_OSPF6_DUMP_NEIGHBOR)
- {
- zlog_info ("Neighbor %s request-list:", nei->str);
- zlog_info (" Add %s", lsa->str);
- }
-
- ospf6_lsa_age_current (lsa);
- summary = ospf6_lsa_summary_create (lsa->header);
- ospf6_lsdb_add (summary, nei->request_list);
-}
-
-void
-ospf6_neighbor_request_remove (struct ospf6_lsa *lsa,
- struct ospf6_neighbor *nei)
-{
- struct ospf6_lsa *summary;
-
- if (IS_OSPF6_DUMP_NEIGHBOR)
- {
- zlog_info ("Neighbor %s request-list:", nei->str);
- zlog_info (" Remove %s", lsa->str);
- }
-
- summary = ospf6_lsdb_lookup_lsdb (lsa->header->type, lsa->header->id,
- lsa->header->adv_router, nei->request_list);
- ospf6_lsdb_remove (summary, nei->request_list);
-}
-
-void
-ospf6_neighbor_retrans_add (struct ospf6_lsa *lsa,
- struct ospf6_neighbor *nei)
-{
- if (IS_OSPF6_DUMP_NEIGHBOR)
- {
- zlog_info ("Neighbor %s retrans-list:", nei->str);
- zlog_info (" Add %s", lsa->str);
- }
-
- ospf6_lsdb_add (lsa, nei->retrans_list);
-}
-
-void
-ospf6_neighbor_retrans_remove (struct ospf6_lsa *lsa,
- struct ospf6_neighbor *nei)
-{
- if (IS_OSPF6_DUMP_NEIGHBOR)
- {
- zlog_info ("Neighbor %s retrans-list:", nei->str);
- zlog_info (" Remove %s", lsa->str);
- }
-
- ospf6_lsdb_remove (lsa, nei->retrans_list);
-
- if (nei->retrans_list->count == 0)
- {
- if (nei->send_update)
- thread_cancel (nei->send_update);
- nei->send_update = NULL;
- }
-}
-
-void
-ospf6_neighbor_dbdesc_add (struct ospf6_lsa *lsa,
- struct ospf6_neighbor *nei)
-{
- if (IS_OSPF6_DUMP_NEIGHBOR)
- {
- zlog_info ("Neighbor %s dbdesc-list:", nei->str);
- zlog_info (" Add %s", lsa->str);
- }
-
- ospf6_lsdb_add (lsa, nei->dbdesc_list);
-}
-
-void
-ospf6_neighbor_dbdesc_remove (struct ospf6_lsa *lsa,
- struct ospf6_neighbor *nei)
-{
- if (IS_OSPF6_DUMP_NEIGHBOR)
- {
- zlog_info ("Neighbor %s dbdesc-list:", nei->str);
- zlog_info (" Remove %s", lsa->str);
- }
-
- ospf6_lsdb_remove (lsa, nei->dbdesc_list);
-}
-
-
-/* prepare summary-list of his neighbor structure */
-void
-ospf6_neighbor_dbex_init (struct ospf6_neighbor *nei)
-{
- struct ospf6_lsdb_node node;
-
- /* clear ls-list */
- ospf6_neighbor_lslist_clear (nei);
-
- /* AS scope LSAs */
- for (ospf6_lsdb_head (&node, nei->ospf6_interface->area->ospf6->lsdb);
- ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node))
- {
- if (IS_LSA_MAXAGE (node.lsa))
- ospf6_neighbor_retrans_add (node.lsa, nei);
- else
- ospf6_neighbor_summary_add (node.lsa, nei);
- }
-
- /* AREA scope LSAs */
- for (ospf6_lsdb_head (&node, nei->ospf6_interface->area->lsdb);
- ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node))
- {
- if (IS_LSA_MAXAGE (node.lsa))
- ospf6_neighbor_retrans_add (node.lsa, nei);
- else
- ospf6_neighbor_summary_add (node.lsa, nei);
- }
-
- /* INTERFACE scope LSAs */
- for (ospf6_lsdb_head (&node, nei->ospf6_interface->lsdb);
- ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node))
- {
- if (IS_LSA_MAXAGE (node.lsa))
- ospf6_neighbor_retrans_add (node.lsa, nei);
- else
- ospf6_neighbor_summary_add (node.lsa, nei);
- }
+ return (struct ospf6_neighbor *) NULL;
}
/* create ospf6_neighbor */
struct ospf6_neighbor *
-ospf6_neighbor_create (u_int32_t router_id, struct ospf6_interface *o6i)
+ospf6_neighbor_create (u_int32_t router_id, struct ospf6_interface *oi)
{
- struct ospf6_neighbor *new;
- char buf[32];
+ struct ospf6_neighbor *on;
+ char buf[16];
- new = (struct ospf6_neighbor *)
+ on = (struct ospf6_neighbor *)
XMALLOC (MTYPE_OSPF6_NEIGHBOR, sizeof (struct ospf6_neighbor));
- if (new == NULL)
+ if (on == NULL)
{
zlog_warn ("neighbor: malloc failed");
return NULL;
}
- memset (new, 0, sizeof (struct ospf6_neighbor));
-
- new->state = OSPF6_NEIGHBOR_STATE_DOWN;
-
- new->router_id = router_id;
+ memset (on, 0, sizeof (struct ospf6_neighbor));
inet_ntop (AF_INET, &router_id, buf, sizeof (buf));
- snprintf (new->str, sizeof (new->str), "%s%%%s", buf, o6i->interface->name);
- new->inactivity_timer = (struct thread *) NULL;
+ snprintf (on->name, sizeof (on->name), "%s%%%s",
+ buf, oi->interface->name);
+ on->ospf6_if = oi;
+ on->state = OSPF6_NEIGHBOR_DOWN;
+ gettimeofday (&on->last_changed, (struct timezone *) NULL);
+ on->router_id = router_id;
- new->summary_list = ospf6_lsdb_create ();
- new->request_list = ospf6_lsdb_create ();
- new->retrans_list = ospf6_lsdb_create ();
- new->dbdesc_list = ospf6_lsdb_create ();
+ on->summary_list = ospf6_lsdb_create ();
+ on->request_list = ospf6_lsdb_create ();
+ on->retrans_list = ospf6_lsdb_create ();
- listnode_add (o6i->neighbor_list, new);
- new->ospf6_interface = o6i;
+ on->dbdesc_list = ospf6_lsdb_create ();
+ on->lsreq_list = ospf6_lsdb_create ();
+ on->lsupdate_list = ospf6_lsdb_create ();
+ on->lsack_list = ospf6_lsdb_create ();
- CALL_ADD_HOOK (&neighbor_hook, new);
-
- return new;
+ listnode_add_sort (oi->neighbor_list, on);
+ return on;
}
void
-ospf6_neighbor_delete (struct ospf6_neighbor *o6n)
+ospf6_neighbor_delete (struct ospf6_neighbor *on)
{
- CALL_REMOVE_HOOK (&neighbor_hook, o6n);
+ ospf6_lsdb_remove_all (on->summary_list);
+ ospf6_lsdb_remove_all (on->request_list);
+ ospf6_lsdb_remove_all (on->retrans_list);
- ospf6_neighbor_thread_cancel_all (o6n);
- ospf6_neighbor_lslist_clear (o6n);
+ ospf6_lsdb_remove_all (on->dbdesc_list);
+ ospf6_lsdb_remove_all (on->lsreq_list);
+ ospf6_lsdb_remove_all (on->lsupdate_list);
+ ospf6_lsdb_remove_all (on->lsack_list);
- list_free (o6n->dbdesc_lsa);
+ ospf6_lsdb_delete (on->summary_list);
+ ospf6_lsdb_delete (on->request_list);
+ ospf6_lsdb_delete (on->retrans_list);
- ospf6_lsdb_delete (o6n->summary_list);
- ospf6_lsdb_delete (o6n->request_list);
- ospf6_lsdb_delete (o6n->retrans_list);
- ospf6_lsdb_delete (o6n->dbdesc_list);
+ ospf6_lsdb_delete (on->dbdesc_list);
+ ospf6_lsdb_delete (on->lsreq_list);
+ ospf6_lsdb_delete (on->lsupdate_list);
+ ospf6_lsdb_delete (on->lsack_list);
- XFREE (MTYPE_OSPF6_NEIGHBOR, o6n);
+ THREAD_OFF (on->inactivity_timer);
+
+ THREAD_OFF (on->thread_send_dbdesc);
+ THREAD_OFF (on->thread_send_lsreq);
+ THREAD_OFF (on->thread_send_lsupdate);
+ THREAD_OFF (on->thread_send_lsack);
+
+ XFREE (MTYPE_OSPF6_NEIGHBOR, on);
}
-struct ospf6_neighbor *
-ospf6_neighbor_lookup (u_int32_t router_id,
- struct ospf6_interface *o6i)
+static void
+ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on)
{
- listnode n;
- struct ospf6_neighbor *o6n;
+ u_char prev_state;
- for (n = listhead (o6i->neighbor_list); n; nextnode (n))
+ prev_state = on->state;
+ on->state = next_state;
+
+ if (prev_state == next_state)
+ return;
+
+ gettimeofday (&on->last_changed, (struct timezone *) NULL);
+
+ /* log */
+ if (IS_OSPF6_DEBUG_NEIGHBOR (STATE))
{
- o6n = (struct ospf6_neighbor *) getdata (n);
- if (o6n->router_id == router_id)
- return o6n;
+ zlog_info ("Neighbor state change %s: [%s]->[%s]", on->name,
+ ospf6_neighbor_state_str[prev_state],
+ ospf6_neighbor_state_str[next_state]);
}
- return (struct ospf6_neighbor *) NULL;
+
+ if (prev_state == OSPF6_NEIGHBOR_FULL || next_state == OSPF6_NEIGHBOR_FULL)
+ {
+ OSPF6_ROUTER_LSA_SCHEDULE (on->ospf6_if->area);
+ if (on->ospf6_if->state == OSPF6_INTERFACE_DR)
+ {
+ OSPF6_NETWORK_LSA_SCHEDULE (on->ospf6_if);
+ OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (on->ospf6_if);
+ OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (on->ospf6_if->area);
+ }
+ }
+
+#ifdef XXX
+ if (prev_state == NBS_FULL || next_state == NBS_FULL)
+ nbs_full_change (on->ospf6_interface);
+
+ /* check for LSAs that already reached MaxAge */
+ if ((prev_state == OSPF6_NEIGHBOR_EXCHANGE ||
+ prev_state == OSPF6_NEIGHBOR_LOADING) &&
+ (next_state != OSPF6_NEIGHBOR_EXCHANGE &&
+ next_state != OSPF6_NEIGHBOR_LOADING))
+ {
+ ospf6_maxage_remover ();
+ }
+#endif /*XXX*/
+
}
+/* RFC2328 section 10.4 */
+int
+need_adjacency (struct ospf6_neighbor *on)
+{
+ if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT ||
+ on->ospf6_if->state == OSPF6_INTERFACE_DR ||
+ on->ospf6_if->state == OSPF6_INTERFACE_BDR)
+ return 1;
+
+ if (on->ospf6_if->drouter == on->router_id ||
+ on->ospf6_if->bdrouter == on->router_id)
+ return 1;
+
+ return 0;
+}
+
+int
+hello_received (struct thread *thread)
+{
+ struct ospf6_neighbor *on;
+
+ on = (struct ospf6_neighbor *) THREAD_ARG (thread);
+ assert (on);
+
+ if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
+ zlog_info ("Neighbor Event %s: *HelloReceived*", on->name);
+
+ /* reset Inactivity Timer */
+ THREAD_OFF (on->inactivity_timer);
+ on->inactivity_timer = thread_add_timer (master, inactivity_timer, on,
+ on->ospf6_if->dead_interval);
+
+ if (on->state <= OSPF6_NEIGHBOR_DOWN)
+ ospf6_neighbor_state_change (OSPF6_NEIGHBOR_INIT, on);
+
+ return 0;
+}
+
+int
+twoway_received (struct thread *thread)
+{
+ struct ospf6_neighbor *on;
+
+ on = (struct ospf6_neighbor *) THREAD_ARG (thread);
+ assert (on);
+
+ if (on->state > OSPF6_NEIGHBOR_INIT)
+ return 0;
+
+ if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
+ zlog_info ("Neighbor Event %s: *2Way-Received*", on->name);
+
+ thread_add_event (master, neighbor_change, on->ospf6_if, 0);
+
+ if (! need_adjacency (on))
+ {
+ ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on);
+ return 0;
+ }
+
+ ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on);
+ SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
+ SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
+ SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
+
+ THREAD_OFF (on->thread_send_dbdesc);
+ on->thread_send_dbdesc =
+ thread_add_event (master, ospf6_dbdesc_send, on, 0);
+
+ return 0;
+}
+
+int
+negotiation_done (struct thread *thread)
+{
+ struct ospf6_neighbor *on;
+ struct ospf6_lsa *lsa;
+
+ on = (struct ospf6_neighbor *) THREAD_ARG (thread);
+ assert (on);
+
+ if (on->state != OSPF6_NEIGHBOR_EXSTART)
+ return 0;
+
+ if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
+ zlog_info ("Neighbor Event %s: *NegotiationDone*", on->name);
+
+ /* clear ls-list */
+ ospf6_lsdb_remove_all (on->summary_list);
+ ospf6_lsdb_remove_all (on->request_list);
+ ospf6_lsdb_remove_all (on->retrans_list);
+
+ /* Interface scoped LSAs */
+ for (lsa = ospf6_lsdb_head (on->ospf6_if->lsdb); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ {
+ if (IS_OSPF6_DEBUG_LSA (DATABASE))
+ zlog_info ("Add copy of %s to %s of %s", lsa->name,
+ (OSPF6_LSA_IS_MAXAGE (lsa) ? "retrans_list" :
+ "summary_list"), on->name);
+ if (OSPF6_LSA_IS_MAXAGE (lsa))
+ ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
+ else
+ ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->summary_list);
+ }
+
+ /* Area scoped LSAs */
+ for (lsa = ospf6_lsdb_head (on->ospf6_if->area->lsdb); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ {
+ if (IS_OSPF6_DEBUG_LSA (DATABASE))
+ zlog_info ("Add copy of %s to %s of %s", lsa->name,
+ (OSPF6_LSA_IS_MAXAGE (lsa) ? "retrans_list" :
+ "summary_list"), on->name);
+ if (OSPF6_LSA_IS_MAXAGE (lsa))
+ ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
+ else
+ ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->summary_list);
+ }
+
+ /* AS scoped LSAs */
+ for (lsa = ospf6_lsdb_head (on->ospf6_if->area->ospf6->lsdb); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ {
+ if (IS_OSPF6_DEBUG_LSA (DATABASE))
+ zlog_info ("Add copy of %s to %s of %s", lsa->name,
+ (OSPF6_LSA_IS_MAXAGE (lsa) ? "retrans_list" :
+ "summary_list"), on->name);
+ if (OSPF6_LSA_IS_MAXAGE (lsa))
+ ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list);
+ else
+ ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->summary_list);
+ }
+
+ UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
+ ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXCHANGE, on);
+
+ return 0;
+}
+
+int
+exchange_done (struct thread *thread)
+{
+ struct ospf6_neighbor *on;
+
+ on = (struct ospf6_neighbor *) THREAD_ARG (thread);
+ assert (on);
+
+ if (on->state != OSPF6_NEIGHBOR_EXCHANGE)
+ return 0;
+
+ if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
+ zlog_info ("Neighbor Event %s: *ExchangeDone*", on->name);
+
+ THREAD_OFF (on->thread_send_dbdesc);
+ ospf6_lsdb_remove_all (on->dbdesc_list);
+
+/* XXX
+ thread_add_timer (master, ospf6_neighbor_last_dbdesc_release, on,
+ on->ospf6_if->dead_interval);
+*/
+
+ if (on->request_list->count == 0)
+ ospf6_neighbor_state_change (OSPF6_NEIGHBOR_FULL, on);
+ else
+ ospf6_neighbor_state_change (OSPF6_NEIGHBOR_LOADING, on);
+
+ return 0;
+}
+
+int
+loading_done (struct thread *thread)
+{
+ struct ospf6_neighbor *on;
+
+ on = (struct ospf6_neighbor *) THREAD_ARG (thread);
+ assert (on);
+
+ if (on->state != OSPF6_NEIGHBOR_LOADING)
+ return 0;
+
+ if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
+ zlog_info ("Neighbor Event %s: *LoadingDone*", on->name);
+
+ assert (on->request_list->count == 0);
+
+ ospf6_neighbor_state_change (OSPF6_NEIGHBOR_FULL, on);
+
+ return 0;
+}
+
+int
+adj_ok (struct thread *thread)
+{
+ struct ospf6_neighbor *on;
+
+ on = (struct ospf6_neighbor *) THREAD_ARG (thread);
+ assert (on);
+
+ if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
+ zlog_info ("Neighbor Event %s: *AdjOK?*", on->name);
+
+ if (on->state == OSPF6_NEIGHBOR_TWOWAY && need_adjacency (on))
+ {
+ ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on);
+ SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
+ SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
+ SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
+
+ THREAD_OFF (on->thread_send_dbdesc);
+ on->thread_send_dbdesc =
+ thread_add_event (master, ospf6_dbdesc_send, on, 0);
+
+ }
+ else if (on->state >= OSPF6_NEIGHBOR_EXSTART &&
+ ! need_adjacency (on))
+ {
+ ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on);
+ ospf6_lsdb_remove_all (on->summary_list);
+ ospf6_lsdb_remove_all (on->request_list);
+ ospf6_lsdb_remove_all (on->retrans_list);
+ }
+
+ return 0;
+}
+
+int
+seqnumber_mismatch (struct thread *thread)
+{
+ struct ospf6_neighbor *on;
+
+ on = (struct ospf6_neighbor *) THREAD_ARG (thread);
+ assert (on);
+
+ if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
+ return 0;
+
+ if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
+ zlog_info ("Neighbor Event %s: *SeqNumberMismatch*", on->name);
+
+ ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on);
+ SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
+ SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
+ SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
+
+ ospf6_lsdb_remove_all (on->summary_list);
+ ospf6_lsdb_remove_all (on->request_list);
+ ospf6_lsdb_remove_all (on->retrans_list);
+
+ THREAD_OFF (on->thread_send_dbdesc);
+ on->thread_send_dbdesc =
+ thread_add_event (master, ospf6_dbdesc_send, on, 0);
+
+ return 0;
+}
+
+int
+bad_lsreq (struct thread *thread)
+{
+ struct ospf6_neighbor *on;
+
+ on = (struct ospf6_neighbor *) THREAD_ARG (thread);
+ assert (on);
+
+ if (on->state < OSPF6_NEIGHBOR_EXCHANGE)
+ return 0;
+
+ if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
+ zlog_info ("Neighbor Event %s: *BadLSReq*", on->name);
+
+ ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on);
+ SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
+ SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
+ SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
+
+ ospf6_lsdb_remove_all (on->summary_list);
+ ospf6_lsdb_remove_all (on->request_list);
+ ospf6_lsdb_remove_all (on->retrans_list);
+
+ THREAD_OFF (on->thread_send_dbdesc);
+ on->thread_send_dbdesc =
+ thread_add_event (master, ospf6_dbdesc_send, on, 0);
+
+ return 0;
+}
+
+int
+oneway_received (struct thread *thread)
+{
+ struct ospf6_neighbor *on;
+
+ on = (struct ospf6_neighbor *) THREAD_ARG (thread);
+ assert (on);
+
+ if (on->state < OSPF6_NEIGHBOR_TWOWAY)
+ return 0;
+
+ if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
+ zlog_info ("Neighbor Event %s: *1Way-Received*", on->name);
+
+ ospf6_neighbor_state_change (OSPF6_NEIGHBOR_INIT, on);
+ thread_add_event (master, neighbor_change, on->ospf6_if, 0);
+
+ ospf6_lsdb_remove_all (on->summary_list);
+ ospf6_lsdb_remove_all (on->request_list);
+ ospf6_lsdb_remove_all (on->retrans_list);
+
+ THREAD_OFF (on->thread_send_dbdesc);
+ THREAD_OFF (on->thread_send_lsreq);
+ THREAD_OFF (on->thread_send_lsupdate);
+ THREAD_OFF (on->thread_send_lsack);
+
+ return 0;
+}
+
+int
+inactivity_timer (struct thread *thread)
+{
+ struct ospf6_neighbor *on;
+
+ on = (struct ospf6_neighbor *) THREAD_ARG (thread);
+ assert (on);
+
+ if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
+ zlog_info ("Neighbor Event %s: *InactivityTimer*", on->name);
+
+ on->inactivity_timer = NULL;
+ on->drouter = on->prev_drouter = 0;
+ on->bdrouter = on->prev_bdrouter = 0;
+
+ ospf6_neighbor_state_change (OSPF6_NEIGHBOR_DOWN, on);
+ thread_add_event (master, neighbor_change, on->ospf6_if, 0);
+
+ listnode_delete (on->ospf6_if->neighbor_list, on);
+ ospf6_neighbor_delete (on);
+
+ return 0;
+}
+
+
/* vty functions */
/* show neighbor structure */
void
-ospf6_neighbor_show_summary (struct vty *vty, struct ospf6_neighbor *o6n)
+ospf6_neighbor_show (struct vty *vty, struct ospf6_neighbor *on)
{
char router_id[16];
- char dr[16], bdr[16];
+ char duration[16];
+ struct timeval now, res;
+ char nstate[16];
+ char deadtime[16];
+ long h, m, s;
+
+ /* Router-ID (Name) */
+ inet_ntop (AF_INET, &on->router_id, router_id, sizeof (router_id));
+#ifdef HAVE_GETNAMEINFO
+ {
+ }
+#endif /*HAVE_GETNAMEINFO*/
+
+ gettimeofday (&now, NULL);
+
+ /* Dead time */
+ h = m = s = 0;
+ if (on->inactivity_timer)
+ {
+ s = on->inactivity_timer->u.sands.tv_sec - now.tv_sec;
+ h = s / 3600;
+ s -= h * 3600;
+ m = s / 60;
+ s -= m * 60;
+ }
+ snprintf (deadtime, sizeof (deadtime), "%02ld:%02ld:%02ld", h, m, s);
+
+ /* Neighbor State */
+ if (if_is_pointopoint (on->ospf6_if->interface))
+ snprintf (nstate, sizeof (nstate), "PointToPoint");
+ else
+ {
+ if (on->router_id == on->drouter)
+ snprintf (nstate, sizeof (nstate), "DR");
+ else if (on->router_id == on->bdrouter)
+ snprintf (nstate, sizeof (nstate), "BDR");
+ else
+ snprintf (nstate, sizeof (nstate), "DROther");
+ }
+
+ /* Duration */
+ timersub (&now, &on->last_changed, &res);
+ timerstring (&res, duration, sizeof (duration));
+
+ /*
+ vty_out (vty, "%-15s %3d %11s %6s/%-12s %11s %s[%s]%s",
+ "Neighbor ID", "Pri", "DeadTime", "State", "", "Duration",
+ "I/F", "State", VTY_NEWLINE);
+ */
+
+ vty_out (vty, "%-15s %3d %11s %6s/%-12s %11s %s[%s]%s",
+ router_id, on->priority, deadtime,
+ ospf6_neighbor_state_str[on->state], nstate, duration,
+ on->ospf6_if->interface->name,
+ ospf6_interface_state_str[on->ospf6_if->state], VTY_NEWLINE);
+}
+
+void
+ospf6_neighbor_show_drchoice (struct vty *vty, struct ospf6_neighbor *on)
+{
+ char router_id[16];
+ char drouter[16], bdrouter[16];
char duration[16];
struct timeval now, res;
@@ -343,247 +603,232 @@
"State", VTY_NEWLINE);
*/
- inet_ntop (AF_INET, &o6n->router_id, router_id, sizeof (router_id));
- inet_ntop (AF_INET, &o6n->dr, dr, sizeof (dr));
- inet_ntop (AF_INET, &o6n->bdr, bdr, sizeof (bdr));
+ inet_ntop (AF_INET, &on->router_id, router_id, sizeof (router_id));
+ inet_ntop (AF_INET, &on->drouter, drouter, sizeof (drouter));
+ inet_ntop (AF_INET, &on->bdrouter, bdrouter, sizeof (bdrouter));
gettimeofday (&now, NULL);
- ospf6_timeval_sub (&now, &o6n->last_changed, &res);
- ospf6_timeval_string_summary (&res, duration, sizeof (duration));
+ timersub (&now, &on->last_changed, &res);
+ timerstring (&res, duration, sizeof (duration));
vty_out (vty, "%-15s %6s/%-11s %-15s %-15s %s[%s]%s",
- router_id, ospf6_neighbor_state_string[o6n->state],
- duration, dr, bdr, o6n->ospf6_interface->interface->name,
- ospf6_interface_state_string[o6n->ospf6_interface->state],
+ router_id, ospf6_neighbor_state_str[on->state],
+ duration, drouter, bdrouter, on->ospf6_if->interface->name,
+ ospf6_interface_state_str[on->ospf6_if->state],
VTY_NEWLINE);
}
void
-ospf6_neighbor_show (struct vty *vty, struct ospf6_neighbor *o6n)
+ospf6_neighbor_show_detail (struct vty *vty, struct ospf6_neighbor *on)
{
- char hisaddr[64], timestring[32];
+ char drouter[16], bdrouter[16];
+ char linklocal_addr[64], duration[32];
struct timeval now, res;
+ struct ospf6_lsa *lsa;
- inet_ntop (AF_INET6, &o6n->hisaddr, hisaddr, sizeof (hisaddr));
- vty_out (vty, " Neighbor %s, interface address %s%s",
- o6n->str, hisaddr, VTY_NEWLINE);
- vty_out (vty, " Area %s via interface %s (ifindex %d)%s",
- o6n->ospf6_interface->area->str,
- o6n->ospf6_interface->interface->name,
- o6n->ospf6_interface->interface->ifindex,
- VTY_NEWLINE);
- vty_out (vty, " Priority: %d, State: %s, %d state changes%s",
- o6n->priority, ospf6_neighbor_state_string[o6n->state],
- o6n->ospf6_stat_state_changed, VTY_NEWLINE);
+ inet_ntop (AF_INET6, &on->linklocal_addr, linklocal_addr,
+ sizeof (linklocal_addr));
+ inet_ntop (AF_INET, &on->drouter, drouter, sizeof (drouter));
+ inet_ntop (AF_INET, &on->bdrouter, bdrouter, sizeof (bdrouter));
gettimeofday (&now, NULL);
- ospf6_timeval_sub (&now, &o6n->last_changed, &res);
- ospf6_timeval_string_summary (&res, timestring, sizeof (timestring));
- vty_out (vty, " Last state changed: %s ago%s", timestring, VTY_NEWLINE);
-}
+ timersub (&now, &on->last_changed, &res);
+ timerstring (&res, duration, sizeof (duration));
-void
-ospf6_neighbor_show_detail (struct vty *vty, struct ospf6_neighbor *o6n)
-{
- char hisdr[16], hisbdr[16];
-
- ospf6_neighbor_show (vty, o6n);
-
- inet_ntop (AF_INET, &o6n->dr, hisdr, sizeof (hisdr));
- inet_ntop (AF_INET, &o6n->bdr, hisbdr, sizeof (hisbdr));
-
- vty_out (vty, " His Ifindex of myside: %d%s",
- o6n->ifid, VTY_NEWLINE);
- vty_out (vty, " His DR Election: DR %s, BDR %s%s",
- hisdr, hisbdr, VTY_NEWLINE);
-
- vty_out (vty, " Last received DbDesc: opt:%s"
- " ifmtu:%hu bit:%s%s%s seqnum:%ld%s",
- "xxx", ntohs (o6n->last_dd.ifmtu),
- (DD_IS_IBIT_SET (o6n->last_dd.bits) ? "I" : "-"),
- (DD_IS_MBIT_SET (o6n->last_dd.bits) ? "M" : "-"),
- (DD_IS_MSBIT_SET (o6n->last_dd.bits) ? "m" : "s"),
- (u_long)ntohl (o6n->last_dd.seqnum), VTY_NEWLINE);
- vty_out (vty, " My DbDesc bit for this neighbor: %s%s%s%s",
- (DD_IS_IBIT_SET (o6n->dbdesc_bits) ? "I" : "-"),
- (DD_IS_MBIT_SET (o6n->dbdesc_bits) ? "M" : "-"),
- (DD_IS_MSBIT_SET (o6n->dbdesc_bits) ? "m" : "s"),
+ vty_out (vty, " Neighbor %s%s", on->name,
+ VTY_NEWLINE);
+ vty_out (vty, " Area %s via interface %s (ifindex %d)%s",
+ on->ospf6_if->area->name,
+ on->ospf6_if->interface->name,
+ on->ospf6_if->interface->ifindex,
+ VTY_NEWLINE);
+ vty_out (vty, " His IfIndex: %d Link-local address: %s%s",
+ on->ifindex, linklocal_addr,
+ VTY_NEWLINE);
+ vty_out (vty, " State %s for a duration of %s%s",
+ ospf6_neighbor_state_str[on->state], duration,
+ VTY_NEWLINE);
+ vty_out (vty, " His choice of DR/BDR %s/%s, Priority %d%s",
+ drouter, bdrouter, on->priority,
+ VTY_NEWLINE);
+ vty_out (vty, " DbDesc status: %s%s%s SeqNum: %#lx%s",
+ (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT) ? "Initial " : ""),
+ (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT) ? "More " : ""),
+ (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT) ?
+ "Master" : "Slave"), (u_long) ntohl (on->dbdesc_seqnum),
VTY_NEWLINE);
- vty_out (vty, " %-16s %5d times, %-16s %5d times%s",
- "SeqnumMismatch", o6n->ospf6_stat_seqnum_mismatch,
- "BadLSReq", o6n->ospf6_stat_bad_lsreq, VTY_NEWLINE);
- vty_out (vty, " %-16s %5d times, %-16s %5d times%s",
- "OnewayReceived", o6n->ospf6_stat_oneway_received,
- "InactivityTimer", o6n->ospf6_stat_inactivity_timer,
- VTY_NEWLINE);
- vty_out (vty, " %-16s %5d times, %-16s %5d times%s",
- "DbDescRetrans", o6n->ospf6_stat_retrans_dbdesc,
- "LSReqRetrans", o6n->ospf6_stat_retrans_lsreq,
- VTY_NEWLINE);
- vty_out (vty, " %-16s %5d times%s",
- "LSUpdateRetrans", o6n->ospf6_stat_retrans_lsupdate,
- VTY_NEWLINE);
- vty_out (vty, " %-16s %5d times, %-16s %5d times%s",
- "LSAReceived", o6n->ospf6_stat_received_lsa,
- "LSUpdateReceived", o6n->ospf6_stat_received_lsupdate,
- VTY_NEWLINE);
+ vty_out (vty, " Summary-List: %d LSAs%s", on->summary_list->count,
+ VTY_NEWLINE);
+ for (lsa = ospf6_lsdb_head (on->summary_list); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ vty_out (vty, " %s%s", lsa->name, VTY_NEWLINE);
- vty_out (vty, " %-12s %-12s %-12s%s",
- "Message", "DbDesc", "LSReq", VTY_NEWLINE);
- vty_out (vty, " %-12s %12d %12d%s", "LSA Send",
- o6n->lsa_send[OSPF6_MESSAGE_TYPE_DBDESC],
- o6n->lsa_send[OSPF6_MESSAGE_TYPE_LSREQ], VTY_NEWLINE);
- vty_out (vty, " %-12s %12d %12d%s", "LSA Receive",
- o6n->lsa_receive[OSPF6_MESSAGE_TYPE_DBDESC],
- o6n->lsa_receive[OSPF6_MESSAGE_TYPE_LSREQ], VTY_NEWLINE);
- vty_out (vty, "%s", VTY_NEWLINE);
+ vty_out (vty, " Request-List: %d LSAs%s", on->request_list->count,
+ VTY_NEWLINE);
+ for (lsa = ospf6_lsdb_head (on->request_list); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ vty_out (vty, " %s%s", lsa->name, VTY_NEWLINE);
+
+ vty_out (vty, " Retrans-List: %d LSAs%s", on->retrans_list->count,
+ VTY_NEWLINE);
+ for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ vty_out (vty, " %s%s", lsa->name, VTY_NEWLINE);
+
+ timerclear (&res);
+ if (on->thread_send_dbdesc)
+ timersub (&on->thread_send_dbdesc->u.sands, &now, &res);
+ timerstring (&res, duration, sizeof (duration));
+ vty_out (vty, " %d Pending LSAs for DbDesc in Time %s [thread %s]%s",
+ on->dbdesc_list->count, duration,
+ (on->thread_send_dbdesc ? "on" : "off"),
+ VTY_NEWLINE);
+ for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ vty_out (vty, " %s%s", lsa->name, VTY_NEWLINE);
+
+ timerclear (&res);
+ if (on->thread_send_lsreq)
+ timersub (&on->thread_send_lsreq->u.sands, &now, &res);
+ timerstring (&res, duration, sizeof (duration));
+ vty_out (vty, " %d Pending LSAs for LSReq in Time %s [thread %s]%s",
+ on->lsreq_list->count, duration,
+ (on->thread_send_lsreq ? "on" : "off"),
+ VTY_NEWLINE);
+ for (lsa = ospf6_lsdb_head (on->lsreq_list); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ vty_out (vty, " %s%s", lsa->name, VTY_NEWLINE);
+
+ timerclear (&res);
+ if (on->thread_send_lsupdate)
+ timersub (&on->thread_send_lsupdate->u.sands, &now, &res);
+ timerstring (&res, duration, sizeof (duration));
+ vty_out (vty, " %d Pending LSAs for LSUpdate in Time %s [thread %s]%s",
+ on->lsupdate_list->count, duration,
+ (on->thread_send_lsupdate ? "on" : "off"),
+ VTY_NEWLINE);
+ for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ vty_out (vty, " %s%s", lsa->name, VTY_NEWLINE);
+
+ timerclear (&res);
+ if (on->thread_send_lsack)
+ timersub (&on->thread_send_lsack->u.sands, &now, &res);
+ timerstring (&res, duration, sizeof (duration));
+ vty_out (vty, " %d Pending LSAs for LSAck in Time %s [thread %s]%s",
+ on->lsack_list->count, duration,
+ (on->thread_send_lsack ? "on" : "off"),
+ VTY_NEWLINE);
+ for (lsa = ospf6_lsdb_head (on->lsack_list); lsa;
+ lsa = ospf6_lsdb_next (lsa))
+ vty_out (vty, " %s%s", lsa->name, VTY_NEWLINE);
+
}
-void
-ospf6_neighbor_timestamp_hello (struct ospf6_neighbor *o6n)
-{
- struct timeval now, interval;
- gettimeofday (&now, (struct timezone *) NULL);
- if (o6n->tv_last_hello_received.tv_sec)
- {
- ospf6_timeval_sub (&now, &o6n->tv_last_hello_received, &interval);
- zlog_info ("Hello Interval %s : %ld msec",
- o6n->str, interval.tv_sec * 1000 + interval.tv_usec % 1000);
- }
- o6n->tv_last_hello_received.tv_sec = now.tv_sec;
- o6n->tv_last_hello_received.tv_usec = now.tv_usec;
-}
-
-DEFUN (show_ipv6_ospf6_neighbor_routerid,
- show_ipv6_ospf6_neighbor_routerid_cmd,
- "show ipv6 ospf6 neighbor A.B.C.D",
- SHOW_STR
- IP6_STR
- OSPF6_STR
- "Neighbor list\n"
- "OSPF6 neighbor Router ID in IP address format\n"
- )
-{
- u_int32_t router_id;
- struct ospf6_neighbor *o6n;
- struct ospf6_interface *o6i;
- struct ospf6_area *o6a;
- listnode nodei, nodej, nodek;
-
- OSPF6_CMD_CHECK_RUNNING ();
-
- if (argc == 0)
- vty_out (vty, "%-15s %6s/%-11s %-15s %-15s %s[%s]%s",
- "RouterID", "State", "Duration", "DR", "BDR", "I/F",
- "State", VTY_NEWLINE);
- else if (inet_pton (AF_INET, argv[0], &router_id) != 1)
- {
- vty_out (vty, "Malformed Router-ID: %s%s", argv[0], VTY_NEWLINE);
- return CMD_SUCCESS;
- }
-
- for (nodei = listhead (ospf6->area_list); nodei; nextnode (nodei))
- {
- o6a = getdata (nodei);
- for (nodej = listhead (o6a->if_list); nodej; nextnode (nodej))
- {
- o6i = getdata (nodej);
- for (nodek = listhead (o6i->neighbor_list); nodek; nextnode (nodek))
- {
- o6n = getdata (nodek);
- if (argc == 0)
- ospf6_neighbor_show_summary (vty, o6n);
- else if (o6n->router_id == router_id)
- ospf6_neighbor_show_detail (vty, o6n);
- }
- }
- }
- return CMD_SUCCESS;
-}
-
-ALIAS (show_ipv6_ospf6_neighbor_routerid,
+DEFUN (show_ipv6_ospf6_neighbor,
show_ipv6_ospf6_neighbor_cmd,
"show ipv6 ospf6 neighbor",
SHOW_STR
IP6_STR
OSPF6_STR
"Neighbor list\n"
- )
-
-DEFUN (show_ipv6_ospf6_neighborlist,
- show_ipv6_ospf6_neighborlist_cmd,
- "show ipv6 ospf6 (summary-list|request-list|retrans-list|dbdesc-list)",
- SHOW_STR
- IP6_STR
- OSPF6_STR
- "Link State summary list\n"
- "Link State request list\n"
- "Link State retransmission list\n"
- "Link State Description list (Used to retrans DbDesc)\n"
- )
+ )
{
- struct ospf6_area *o6a;
- struct ospf6_interface *o6i;
- struct ospf6_neighbor *o6n;
- listnode i, j, k, l;
- struct ospf6_lsa *lsa;
- struct ospf6_lsdb *lsdb = NULL;
- char type[16], id[16], adv_router[16];
- struct ospf6_lsdb_node node;
- u_int16_t age, cksum, len;
- u_int32_t seqnum;
+ struct ospf6_neighbor *on;
+ struct ospf6_interface *oi;
+ struct ospf6_area *oa;
+ listnode i, j, k;
+ void (*showfunc) (struct vty *, struct ospf6_neighbor *);
OSPF6_CMD_CHECK_RUNNING ();
- i = j = k = l = NULL;
+ showfunc = ospf6_neighbor_show;
+
+ if (argc)
+ {
+ if (! strncmp (argv[0], "de", 2))
+ showfunc = ospf6_neighbor_show_detail;
+ else if (! strncmp (argv[0], "dr", 2))
+ showfunc = ospf6_neighbor_show_drchoice;
+ }
+
+ if (showfunc == ospf6_neighbor_show)
+ vty_out (vty, "%-15s %3s %11s %6s/%-12s %11s %s[%s]%s",
+ "Neighbor ID", "Pri", "DeadTime", "State", "IfState", "Duration",
+ "I/F", "State", VTY_NEWLINE);
+ else if (showfunc == ospf6_neighbor_show_drchoice)
+ vty_out (vty, "%-15s %6s/%-11s %-15s %-15s %s[%s]%s",
+ "RouterID", "State", "Duration", "DR", "BDR", "I/F",
+ "State", VTY_NEWLINE);
for (i = listhead (ospf6->area_list); i; nextnode (i))
{
- o6a = (struct ospf6_area *) getdata (i);
- for (j = listhead (o6a->if_list); j; nextnode (j))
+ oa = (struct ospf6_area *) getdata (i);
+ for (j = listhead (oa->if_list); j; nextnode (j))
{
- o6i = (struct ospf6_interface *) getdata (j);
- for (k = listhead (o6i->neighbor_list); k; nextnode (k))
+ oi = (struct ospf6_interface *) getdata (j);
+ for (k = listhead (oi->neighbor_list); k; nextnode (k))
{
- o6n = (struct ospf6_neighbor *) getdata (k);
-
- if (strncmp (argv[0], "sum", 3) == 0)
- lsdb = o6n->summary_list;
- else if (strncmp (argv[0], "req", 3) == 0)
- lsdb = o6n->request_list;
- else if (strncmp (argv[0], "ret", 3) == 0)
- lsdb = o6n->retrans_list;
- else if (strncmp (argv[0], "dbd", 3) == 0)
- lsdb = o6n->dbdesc_list;
-
- vty_out (vty, "neighbor %s on interface %s: %d%s", o6n->str,
- o6i->interface->name, lsdb->count,
- VTY_NEWLINE);
- for (ospf6_lsdb_head (&node, lsdb); ! ospf6_lsdb_is_end (&node);
- ospf6_lsdb_next (&node))
- {
- lsa = node.lsa;
- ospf6_lsa_age_current (lsa);
-
- ospf6_lsa_type_string (lsa->header->type, type,
- sizeof (type));
- inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
- inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
- sizeof (adv_router));
- age = ntohs (lsa->header->age);
- seqnum = ntohl (lsa->header->seqnum);
- cksum = ntohs (lsa->header->checksum);
- len = ntohs (lsa->header->length);
-
- vty_out (vty, " %s-LSA ID=%s Adv=%s%s",
- type, id, adv_router, VTY_NEWLINE);
- vty_out (vty, " Age: %hu SeqNum: %#x Cksum: %hx Len: %hu%s",
- age, seqnum, cksum, len, VTY_NEWLINE);
- }
+ on = (struct ospf6_neighbor *) getdata (k);
+ (*showfunc) (vty, on);
}
}
}
+ return CMD_SUCCESS;
+}
+ALIAS (show_ipv6_ospf6_neighbor,
+ show_ipv6_ospf6_neighbor_detail_cmd,
+ "show ipv6 ospf6 neighbor (detail|drchoice)",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ "Neighbor list\n"
+ "Display details\n"
+ "Display DR choices\n"
+ );
+
+DEFUN (show_ipv6_ospf6_neighbor_one,
+ show_ipv6_ospf6_neighbor_one_cmd,
+ "show ipv6 ospf6 neighbor A.B.C.D",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ "Neighbor list\n"
+ "Specify Router-ID as IPv4 address notation\n"
+ )
+{
+ struct ospf6_neighbor *on;
+ struct ospf6_interface *oi;
+ struct ospf6_area *oa;
+ listnode i, j, k;
+ void (*showfunc) (struct vty *, struct ospf6_neighbor *);
+ u_int32_t router_id;
+
+ OSPF6_CMD_CHECK_RUNNING ();
+ showfunc = ospf6_neighbor_show_detail;
+
+ if ((inet_pton (AF_INET, argv[0], &router_id)) != 1)
+ {
+ vty_out (vty, "Router-ID is not parsable: %s%s", argv[0],
+ VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ for (i = listhead (ospf6->area_list); i; nextnode (i))
+ {
+ oa = (struct ospf6_area *) getdata (i);
+ for (j = listhead (oa->if_list); j; nextnode (j))
+ {
+ oi = (struct ospf6_interface *) getdata (j);
+ for (k = listhead (oi->neighbor_list); k; nextnode (k))
+ {
+ on = (struct ospf6_neighbor *) getdata (k);
+ if (on->router_id == router_id)
+ (*showfunc) (vty, on);
+ }
+ }
+ }
return CMD_SUCCESS;
}
@@ -591,12 +836,104 @@
ospf6_neighbor_init ()
{
install_element (VIEW_NODE, &show_ipv6_ospf6_neighbor_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_neighbor_routerid_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_neighborlist_cmd);
-
+ install_element (VIEW_NODE, &show_ipv6_ospf6_neighbor_detail_cmd);
install_element (ENABLE_NODE, &show_ipv6_ospf6_neighbor_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_neighbor_routerid_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_neighborlist_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_neighbor_detail_cmd);
}
+DEFUN (debug_ospf6_neighbor,
+ debug_ospf6_neighbor_cmd,
+ "debug ospf6 neighbor",
+ DEBUG_STR
+ OSPF6_STR
+ "Debug OSPFv3 Neighbor\n"
+ )
+{
+ unsigned char level = 0;
+ if (argc)
+ {
+ if (! strncmp (argv[0], "s", 1))
+ level = OSPF6_DEBUG_NEIGHBOR_STATE;
+ if (! strncmp (argv[0], "e", 1))
+ level = OSPF6_DEBUG_NEIGHBOR_EVENT;
+ }
+ else
+ level = OSPF6_DEBUG_NEIGHBOR_STATE | OSPF6_DEBUG_NEIGHBOR_EVENT;
+
+ OSPF6_DEBUG_NEIGHBOR_ON (level);
+ return CMD_SUCCESS;
+}
+
+ALIAS (debug_ospf6_neighbor,
+ debug_ospf6_neighbor_detail_cmd,
+ "debug ospf6 neighbor (state|event)",
+ DEBUG_STR
+ OSPF6_STR
+ "Debug OSPFv3 Neighbor\n"
+ "Debug OSPFv3 Neighbor State Change\n"
+ "Debug OSPFv3 Neighbor Event\n"
+ );
+
+DEFUN (no_debug_ospf6_neighbor,
+ no_debug_ospf6_neighbor_cmd,
+ "no debug ospf6 neighbor",
+ NO_STR
+ DEBUG_STR
+ OSPF6_STR
+ "Debug OSPFv3 Neighbor\n"
+ )
+{
+ unsigned char level = 0;
+ if (argc)
+ {
+ if (! strncmp (argv[0], "s", 1))
+ level = OSPF6_DEBUG_NEIGHBOR_STATE;
+ if (! strncmp (argv[0], "e", 1))
+ level = OSPF6_DEBUG_NEIGHBOR_EVENT;
+ }
+ else
+ level = OSPF6_DEBUG_NEIGHBOR_STATE | OSPF6_DEBUG_NEIGHBOR_EVENT;
+
+ OSPF6_DEBUG_NEIGHBOR_OFF (level);
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_ospf6_neighbor,
+ no_debug_ospf6_neighbor_detail_cmd,
+ "no debug ospf6 neighbor (state|event)",
+ NO_STR
+ DEBUG_STR
+ OSPF6_STR
+ "Debug OSPFv3 Neighbor\n"
+ "Debug OSPFv3 Neighbor State Change\n"
+ "Debug OSPFv3 Neighbor Event\n"
+ );
+
+int
+config_write_ospf6_debug_neighbor (struct vty *vty)
+{
+ if (IS_OSPF6_DEBUG_NEIGHBOR (STATE) &&
+ IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
+ vty_out (vty, "debug ospf6 neighbor%s", VTY_NEWLINE);
+ else if (IS_OSPF6_DEBUG_NEIGHBOR (STATE))
+ vty_out (vty, "debug ospf6 neighbor state%s", VTY_NEWLINE);
+ else if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
+ vty_out (vty, "debug ospf6 neighbor event%s", VTY_NEWLINE);
+ return 0;
+}
+
+void
+install_element_ospf6_debug_neighbor ()
+{
+ install_element (ENABLE_NODE, &debug_ospf6_neighbor_cmd);
+ install_element (ENABLE_NODE, &debug_ospf6_neighbor_detail_cmd);
+ install_element (ENABLE_NODE, &no_debug_ospf6_neighbor_cmd);
+ install_element (ENABLE_NODE, &no_debug_ospf6_neighbor_detail_cmd);
+ install_element (CONFIG_NODE, &debug_ospf6_neighbor_cmd);
+ install_element (CONFIG_NODE, &debug_ospf6_neighbor_detail_cmd);
+ install_element (CONFIG_NODE, &no_debug_ospf6_neighbor_cmd);
+ install_element (CONFIG_NODE, &no_debug_ospf6_neighbor_detail_cmd);
+}
+
+
diff --git a/ospf6d/ospf6_neighbor.h b/ospf6d/ospf6_neighbor.h
index c3821c6..441ab81 100644
--- a/ospf6d/ospf6_neighbor.h
+++ b/ospf6d/ospf6_neighbor.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -22,140 +22,117 @@
#ifndef OSPF6_NEIGHBOR_H
#define OSPF6_NEIGHBOR_H
+/* Debug option */
+extern unsigned char conf_debug_ospf6_neighbor;
+#define OSPF6_DEBUG_NEIGHBOR_STATE 0x01
+#define OSPF6_DEBUG_NEIGHBOR_EVENT 0x02
+#define OSPF6_DEBUG_NEIGHBOR_ON(level) \
+ (conf_debug_ospf6_neighbor |= (level))
+#define OSPF6_DEBUG_NEIGHBOR_OFF(level) \
+ (conf_debug_ospf6_neighbor &= ~(level))
+#define IS_OSPF6_DEBUG_NEIGHBOR(level) \
+ (conf_debug_ospf6_neighbor & OSPF6_DEBUG_NEIGHBOR_ ## level)
+
/* Neighbor structure */
struct ospf6_neighbor
{
/* Neighbor Router ID String */
- char str[32];
+ char name[32];
/* OSPFv3 Interface this neighbor belongs to */
- struct ospf6_interface *ospf6_interface;
+ struct ospf6_interface *ospf6_if;
/* Neighbor state */
u_char state;
+
+ /* timestamp of last changing state */
struct timeval last_changed;
/* Neighbor Router ID */
u_int32_t router_id;
+ /* Neighbor Interface ID */
+ u_int32_t ifindex;
+
/* Router Priority of this neighbor */
u_char priority;
- u_int32_t ifid;
- u_int32_t dr;
- u_int32_t bdr;
- u_int32_t prevdr;
- u_int32_t prevbdr;
+ u_int32_t drouter;
+ u_int32_t bdrouter;
+ u_int32_t prev_drouter;
+ u_int32_t prev_bdrouter;
- /* Link-LSA's options field */
+ /* Options field (Capability) */
char options[3];
/* IPaddr of I/F on our side link */
- struct in6_addr hisaddr;
-
- /* new */
- struct ospf6_lsdb *summary_list;
- struct ospf6_lsdb *request_list;
- struct ospf6_lsdb *retrans_list;
+ struct in6_addr linklocal_addr;
/* For Database Exchange */
u_char dbdesc_bits;
u_int32_t dbdesc_seqnum;
- struct ospf6_dbdesc *dbdesc_previous;
+ /* Last received Database Description packet */
+ struct ospf6_dbdesc dbdesc_last;
- /* last received DD , including OSPF capability of this neighbor */
- struct ospf6_dbdesc last_dd;
+ /* LS-list */
+ struct ospf6_lsdb *summary_list;
+ struct ospf6_lsdb *request_list;
+ struct ospf6_lsdb *retrans_list;
- /* LSAs to retransmit to this neighbor */
- list dbdesc_lsa;
+ /* LSA list for message transmission */
+ struct ospf6_lsdb *dbdesc_list;
+ struct ospf6_lsdb *lsreq_list;
+ struct ospf6_lsdb *lsupdate_list;
+ struct ospf6_lsdb *lsack_list;
- /* placeholder for DbDesc */
- struct iovec dbdesc_last_send[1024];
-
+ /* Inactivity timer */
struct thread *inactivity_timer;
- /* DbDesc */
+ /* Thread for sending message */
struct thread *thread_send_dbdesc;
- struct thread *thread_rxmt_dbdesc;
- list dbdesclist;
- struct ospf6_lsdb *dbdesc_list;
-
- /* LSReq */
struct thread *thread_send_lsreq;
- struct thread *thread_rxmt_lsreq;
-
- /* LSUpdate */
- struct thread *send_update;
- struct thread *thread_send_update;
- struct thread *thread_rxmt_update;
-
- /* statistics */
- u_int message_send[OSPF6_MESSAGE_TYPE_MAX];
- u_int message_receive[OSPF6_MESSAGE_TYPE_MAX];
- u_int lsa_send[OSPF6_MESSAGE_TYPE_MAX];
- u_int lsa_receive[OSPF6_MESSAGE_TYPE_MAX];
-
- u_int ospf6_stat_state_changed;
- u_int ospf6_stat_seqnum_mismatch;
- u_int ospf6_stat_bad_lsreq;
- u_int ospf6_stat_oneway_received;
- u_int ospf6_stat_inactivity_timer;
- u_int ospf6_stat_dr_election;
- u_int ospf6_stat_retrans_dbdesc;
- u_int ospf6_stat_retrans_lsreq;
- u_int ospf6_stat_retrans_lsupdate;
- u_int ospf6_stat_received_lsa;
- u_int ospf6_stat_received_lsupdate;
-
- struct timeval tv_last_hello_received;
+ struct thread *thread_send_lsupdate;
+ struct thread *thread_send_lsack;
};
-extern char *ospf6_neighbor_state_string[];
+/* Neighbor state */
+#define OSPF6_NEIGHBOR_DOWN 1
+#define OSPF6_NEIGHBOR_ATTEMPT 2
+#define OSPF6_NEIGHBOR_INIT 3
+#define OSPF6_NEIGHBOR_TWOWAY 4
+#define OSPF6_NEIGHBOR_EXSTART 5
+#define OSPF6_NEIGHBOR_EXCHANGE 6
+#define OSPF6_NEIGHBOR_LOADING 7
+#define OSPF6_NEIGHBOR_FULL 8
+
+extern char *ospf6_neighbor_state_str[];
/* Function Prototypes */
-int
-ospf6_neighbor_last_dbdesc_release (struct thread *);
+int ospf6_neighbor_cmp (void *va, void *vb);
+void ospf6_neighbor_dbex_init (struct ospf6_neighbor *on);
-void
-ospf6_neighbor_lslist_clear (struct ospf6_neighbor *);
+struct ospf6_neighbor *ospf6_neighbor_lookup (u_int32_t,
+ struct ospf6_interface *);
+struct ospf6_neighbor *ospf6_neighbor_create (u_int32_t,
+ struct ospf6_interface *);
+void ospf6_neighbor_delete (struct ospf6_neighbor *);
-void
-ospf6_neighbor_summary_add (struct ospf6_lsa *, struct ospf6_neighbor *);
-void
-ospf6_neighbor_summary_remove (struct ospf6_lsa *, struct ospf6_neighbor *);
-
-void
-ospf6_neighbor_request_add (struct ospf6_lsa *, struct ospf6_neighbor *);
-void
-ospf6_neighbor_request_remove (struct ospf6_lsa *, struct ospf6_neighbor *);
-
-void
-ospf6_neighbor_retrans_add (struct ospf6_lsa *, struct ospf6_neighbor *);
-void
-ospf6_neighbor_retrans_remove (struct ospf6_lsa *, struct ospf6_neighbor *);
-
-void
-ospf6_neighbor_dbdesc_add (struct ospf6_lsa *lsa,
- struct ospf6_neighbor *nei);
-void
-ospf6_neighbor_dbdesc_remove (struct ospf6_lsa *lsa,
- struct ospf6_neighbor *nei);
-
-void
-ospf6_neighbor_dbex_init (struct ospf6_neighbor *nei);
-
-void
-ospf6_neighbor_thread_cancel_all (struct ospf6_neighbor *);
-
-struct ospf6_neighbor *
-ospf6_neighbor_create (u_int32_t, struct ospf6_interface *);
-void
-ospf6_neighbor_delete (struct ospf6_neighbor *);
-struct ospf6_neighbor *
-ospf6_neighbor_lookup (u_int32_t, struct ospf6_interface *);
+/* Neighbor event */
+int hello_received (struct thread *);
+int twoway_received (struct thread *);
+int negotiation_done (struct thread *);
+int exchange_done (struct thread *);
+int loading_done (struct thread *);
+int adj_ok (struct thread *);
+int seqnumber_mismatch (struct thread *);
+int bad_lsreq (struct thread *);
+int oneway_received (struct thread *);
+int inactivity_timer (struct thread *);
void ospf6_neighbor_init ();
+int config_write_ospf6_debug_neighbor (struct vty *vty);
+void install_element_ospf6_debug_neighbor ();
#endif /* OSPF6_NEIGHBOR_H */
diff --git a/ospf6d/ospf6_network.c b/ospf6d/ospf6_network.c
index ece3413..b4f37f6 100644
--- a/ospf6d/ospf6_network.c
+++ b/ospf6d/ospf6_network.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -20,288 +20,20 @@
*/
#include <zebra.h>
-#include "memory.h"
+
#include "log.h"
+#include "memory.h"
#include "sockunion.h"
#include "privs.h"
-#include "ospf6d.h"
#include "ospf6_proto.h"
+#include "ospf6_network.h"
-extern int errno;
-extern struct sockaddr_in6 allspfrouters6;
-extern struct sockaddr_in6 alldrouters6;
-extern int ospf6_sock;
-extern struct thread_master *master;
extern struct zebra_privs_t ospf6d_privs;
-/* iovec functions */
-void
-iov_clear (struct iovec *iov, size_t iovlen)
-{
- int i;
- for (i = 0; i < iovlen; i++)
- {
- iov[i].iov_base = NULL;
- iov[i].iov_len = 0;
- }
-}
-
-int
-iov_count (struct iovec *iov)
-{
- int i;
- for (i = 0; iov[i].iov_base; i++)
- ;
- return i;
-}
-
-int
-iov_totallen (struct iovec *iov)
-{
- int i;
- int totallen = 0;
- for (i = 0; iov[i].iov_base; i++)
- totallen += iov[i].iov_len;
- return totallen;
-}
-
-void *
-iov_prepend (int mtype, struct iovec *iov, size_t len)
-{
- int i, iovlen;
- void *base;
-
- base = (void *) XMALLOC (mtype, len);
- if (!base)
- {
- zlog_warn ("Network: iov_prepend failed");
- return NULL;
- }
- memset (base, 0, len);
-
- iovlen = iov_count (iov);
- for (i = iovlen; i; i--)
- {
- iov[i].iov_base = iov[i - 1].iov_base;
- iov[i].iov_len = iov[i - 1].iov_len;
- }
- iov[0].iov_base = (char *)base;
- iov[0].iov_len = len;
-
- return base;
-}
-
-void *
-iov_append (int mtype, struct iovec *iov, size_t len)
-{
- int i;
- void *base;
-
- base = (void *)XMALLOC (mtype, len);
- if (!base)
- {
- zlog_warn ("Network: iov_append failed");
- return NULL;
- }
- memset (base, 0, len);
-
- /* proceed to the end */
- i = iov_count (iov);
-
- iov[i].iov_base = (char *)base;
- iov[i].iov_len = len;
-
- return base;
-}
-
-void *
-iov_attach_last (struct iovec *iov, void *base, size_t len)
-{
- int i;
- i = iov_count (iov);
- iov[i].iov_base = (char *)base;
- iov[i].iov_len = len;
- return base;
-}
-
-void *
-iov_detach_first (struct iovec *iov)
-{
- int i, iovlen;
- void *base;
- size_t len;
-
- base = iov[0].iov_base;
- len = iov[0].iov_len;
- iovlen = iov_count (iov);
- for (i = 0; i < iovlen; i++)
- {
- iov[i].iov_base = iov[i + 1].iov_base;
- iov[i].iov_len = iov[i + 1].iov_len;
- }
- return base;
-}
-
-int
-iov_free (int mtype, struct iovec *iov, u_int begin, u_int end)
-{
- int i;
-
- for (i = begin; i < end; i++)
- {
- XFREE (mtype, iov[i].iov_base);
- iov[i].iov_base = NULL;
- iov[i].iov_len = 0;
- }
-
- return 0;
-}
-
-void
-iov_trim_head (int mtype, struct iovec *iov)
-{
- void *base;
-
- base = iov_detach_first (iov);
- XFREE (mtype, base);
- return;
-}
-
-void
-iov_free_all (int mtype, struct iovec *iov)
-{
- int i, end = iov_count (iov);
- for (i = 0; i < end; i++)
- {
- XFREE (mtype, iov[i].iov_base);
- iov[i].iov_base = NULL;
- iov[i].iov_len = 0;
- }
-}
-
-void
-iov_copy_all (struct iovec *dst, struct iovec *src, size_t size)
-{
- int i;
- for (i = 0; i < size; i++)
- {
- dst[i].iov_base = src[i].iov_base;
- dst[i].iov_len = src[i].iov_len;
- }
-}
-
-
-/* Make ospf6d's server socket. */
-int
-ospf6_serv_sock ()
-{
-
- if (ospf6d_privs.change (ZPRIVS_RAISE))
- zlog_err ("ospf6_serv_sock: could not raise privs");
-
- ospf6_sock = socket (AF_INET6, SOCK_RAW, IPPROTO_OSPFIGP);
- if (ospf6_sock < 0)
- {
- zlog_warn ("Network: can't create OSPF6 socket.");
- return -1;
- }
- sockopt_reuseaddr (ospf6_sock);
-
- if (ospf6d_privs.change (ZPRIVS_LOWER))
- zlog_err ("ospf_sock_init: could not lower privs");
-
- /* setup global sockaddr_in6, allspf6 & alldr6 for later use */
- allspfrouters6.sin6_family = AF_INET6;
- alldrouters6.sin6_family = AF_INET6;
-#ifdef SIN6_LEN
- allspfrouters6.sin6_len = sizeof (struct sockaddr_in6);
- alldrouters6.sin6_len = sizeof (struct sockaddr_in6);
-#endif /* SIN6_LEN */
- inet_pton (AF_INET6, ALLSPFROUTERS6, &allspfrouters6.sin6_addr);
- inet_pton (AF_INET6, ALLDROUTERS6, &alldrouters6.sin6_addr);
-
- return 0;
-}
-
-/* returns 0 if succeed, else returns -1 */
-int
-ospf6_join_allspfrouters (u_int ifindex)
-{
- struct ipv6_mreq mreq6;
- int retval;
-
- assert (ifindex);
- mreq6.ipv6mr_interface = ifindex;
- memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6.sin6_addr,
- sizeof (struct in6_addr));
-
- retval = setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
- &mreq6, sizeof (mreq6));
-
- if (retval < 0)
- zlog_err ("Network: Join AllSPFRouters on ifindex %d failed: %s",
- ifindex, strerror (errno));
-#if 0
- else
- zlog_info ("Network: Join AllSPFRouters on ifindex %d", ifindex);
-#endif
-
- return retval;
-}
-
-void
-ospf6_leave_allspfrouters (u_int ifindex)
-{
- struct ipv6_mreq mreq6;
-
- assert (ifindex);
- mreq6.ipv6mr_interface = ifindex;
- memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6.sin6_addr,
- sizeof (struct in6_addr));
-
- if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
- &mreq6, sizeof (mreq6)) < 0)
- zlog_warn ("Network: Leave AllSPFRouters on ifindex %d Failed: %s",
- ifindex, strerror (errno));
- else
- zlog_info ("Network: Leave AllSPFRouters on ifindex %d", ifindex);
-}
-
-void
-ospf6_join_alldrouters (u_int ifindex)
-{
- struct ipv6_mreq mreq6;
-
- assert (ifindex);
- mreq6.ipv6mr_interface = ifindex;
- memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6.sin6_addr,
- sizeof (struct in6_addr));
-
- if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
- &mreq6, sizeof (mreq6)) < 0)
- zlog_warn ("Network: Join AllDRouters on ifindex %d Failed: %s",
- ifindex, strerror (errno));
- else
- zlog_info ("Network: Join AllDRouters on ifindex %d", ifindex);
-}
-
-void
-ospf6_leave_alldrouters (u_int ifindex)
-{
- struct ipv6_mreq mreq6;
-
- assert (ifindex);
- mreq6.ipv6mr_interface = ifindex;
- memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6.sin6_addr,
- sizeof (struct in6_addr));
-
- if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
- &mreq6, sizeof (mreq6)) < 0)
- zlog_warn ("Network: Leave AllDRouters on ifindex %d Failed", ifindex);
- else
- zlog_info ("Network: Leave AllDRouters on ifindex %d", ifindex);
-}
+int ospf6_sock;
+struct in6_addr allspfrouters6;
+struct in6_addr alldrouters6;
/* setsockopt ReUseAddr to on */
void
@@ -343,7 +75,7 @@
ospf6_set_checksum ()
{
int offset = 12;
-#if !defined(DISABLE_IPV6_CHECKSUM)
+#ifndef DISABLE_IPV6_CHECKSUM
if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_CHECKSUM,
&offset, sizeof (offset)) < 0)
zlog_warn ("Network: set IPV6_CHECKSUM failed: %s", strerror (errno));
@@ -352,7 +84,143 @@
#endif /* DISABLE_IPV6_CHECKSUM */
}
+/* Make ospf6d's server socket. */
+int
+ospf6_serv_sock ()
+{
+ if (ospf6d_privs.change (ZPRIVS_RAISE))
+ zlog_err ("ospf6_serv_sock: could not raise privs");
+
+ ospf6_sock = socket (AF_INET6, SOCK_RAW, IPPROTO_OSPFIGP);
+ if (ospf6_sock < 0)
+ {
+ zlog_warn ("Network: can't create OSPF6 socket.");
+ if (ospf6d_privs.change (ZPRIVS_LOWER))
+ zlog_err ("ospf_sock_init: could not lower privs");
+ return -1;
+ }
+ if (ospf6d_privs.change (ZPRIVS_LOWER))
+ zlog_err ("ospf_sock_init: could not lower privs");
+
+ /* set socket options */
+#if 1
+ sockopt_reuseaddr (ospf6_sock);
+#else
+ ospf6_set_reuseaddr ();
+#endif /*1*/
+ ospf6_reset_mcastloop ();
+ ospf6_set_pktinfo ();
+ ospf6_set_checksum ();
+
+ /* setup global in6_addr, allspf6 and alldr6 for later use */
+ inet_pton (AF_INET6, ALLSPFROUTERS6, &allspfrouters6);
+ inet_pton (AF_INET6, ALLDROUTERS6, &alldrouters6);
+
+ return 0;
+}
+
void
+ospf6_join_allspfrouters (u_int ifindex)
+{
+ struct ipv6_mreq mreq6;
+ int retval;
+
+ assert (ifindex);
+ mreq6.ipv6mr_interface = ifindex;
+ memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6,
+ sizeof (struct in6_addr));
+
+ retval = setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+ &mreq6, sizeof (mreq6));
+
+ if (retval < 0)
+ zlog_err ("Network: Join AllSPFRouters on ifindex %d failed: %s",
+ ifindex, strerror (errno));
+#if 0
+ else
+ zlog_info ("Network: Join AllSPFRouters on ifindex %d", ifindex);
+#endif
+}
+
+void
+ospf6_leave_allspfrouters (u_int ifindex)
+{
+ struct ipv6_mreq mreq6;
+
+ assert (ifindex);
+ mreq6.ipv6mr_interface = ifindex;
+ memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6,
+ sizeof (struct in6_addr));
+
+ if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
+ &mreq6, sizeof (mreq6)) < 0)
+ zlog_warn ("Network: Leave AllSPFRouters on ifindex %d Failed: %s",
+ ifindex, strerror (errno));
+#if 0
+ else
+ zlog_info ("Network: Leave AllSPFRouters on ifindex %d", ifindex);
+#endif
+}
+
+void
+ospf6_join_alldrouters (u_int ifindex)
+{
+ struct ipv6_mreq mreq6;
+
+ assert (ifindex);
+ mreq6.ipv6mr_interface = ifindex;
+ memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6,
+ sizeof (struct in6_addr));
+
+ if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+ &mreq6, sizeof (mreq6)) < 0)
+ zlog_warn ("Network: Join AllDRouters on ifindex %d Failed: %s",
+ ifindex, strerror (errno));
+#if 0
+ else
+ zlog_info ("Network: Join AllDRouters on ifindex %d", ifindex);
+#endif
+}
+
+void
+ospf6_leave_alldrouters (u_int ifindex)
+{
+ struct ipv6_mreq mreq6;
+
+ assert (ifindex);
+ mreq6.ipv6mr_interface = ifindex;
+ memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6,
+ sizeof (struct in6_addr));
+
+ if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
+ &mreq6, sizeof (mreq6)) < 0)
+ zlog_warn ("Network: Leave AllDRouters on ifindex %d Failed", ifindex);
+#if 0
+ else
+ zlog_info ("Network: Leave AllDRouters on ifindex %d", ifindex);
+#endif
+}
+
+int
+iov_count (struct iovec *iov)
+{
+ int i;
+ for (i = 0; iov[i].iov_base; i++)
+ ;
+ return i;
+}
+
+int
+iov_totallen (struct iovec *iov)
+{
+ int i;
+ int totallen = 0;
+ for (i = 0; iov[i].iov_base; i++)
+ totallen += iov[i].iov_len;
+ return totallen;
+}
+
+int
ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst,
unsigned int *ifindex, struct iovec *message)
{
@@ -403,11 +271,13 @@
retval = sendmsg (ospf6_sock, &smsghdr, 0);
if (retval != iov_totallen (message))
- zlog_warn ("Network: sendmsg (ifindex: %d) failed: %s(%d)",
+ zlog_warn ("sendmsg failed: ifindex: %d: %s (%d)",
*ifindex, strerror (errno), errno);
+
+ return retval;
}
-void
+int
ospf6_recvmsg (struct in6_addr *src, struct in6_addr *dst,
unsigned int *ifindex, struct iovec *message)
{
@@ -438,14 +308,9 @@
retval = recvmsg (ospf6_sock, &rmsghdr, 0);
if (retval < 0)
- {
- zlog_warn ("Network: recvmsg failed: %s", strerror (errno));
- }
+ zlog_warn ("recvmsg failed: %s", strerror (errno));
else if (retval == iov_totallen (message))
- {
- zlog_warn ("Network: possibly buffer shortage: %d received, buffer size: %d",
- retval, iov_totallen (message));
- }
+ zlog_warn ("recvmsg read full buffer size: %d", retval);
/* source address */
assert (src);
@@ -456,49 +321,8 @@
*ifindex = pktinfo->ipi6_ifindex;
if (dst)
memcpy (dst, &pktinfo->ipi6_addr, sizeof (struct in6_addr));
+
+ return retval;
}
-void
-ospf6_recvmsg_peek (struct in6_addr *src, struct in6_addr *dst,
- unsigned int *ifindex, struct iovec *message)
-{
- int retval;
- struct msghdr rmsghdr;
- struct cmsghdr *rcmsgp;
- u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
- struct in6_pktinfo *pktinfo;
- struct sockaddr_in6 src_sin6;
-
- rcmsgp = (struct cmsghdr *)cmsgbuf;
- pktinfo = (struct in6_pktinfo *)(CMSG_DATA(rcmsgp));
- memset (&src_sin6, 0, sizeof (struct sockaddr_in6));
-
- /* receive control msg */
- rcmsgp->cmsg_level = IPPROTO_IPV6;
- rcmsgp->cmsg_type = IPV6_PKTINFO;
- rcmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));
- /* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */
-
- /* receive msg hdr */
- rmsghdr.msg_iov = message;
- rmsghdr.msg_iovlen = iov_count (message);
- rmsghdr.msg_name = (caddr_t) &src_sin6;
- rmsghdr.msg_namelen = sizeof (struct sockaddr_in6);
- rmsghdr.msg_control = (caddr_t) cmsgbuf;
- rmsghdr.msg_controllen = sizeof (cmsgbuf);
-
- retval = recvmsg (ospf6_sock, &rmsghdr, MSG_PEEK);
- if (retval != iov_totallen (message))
- zlog_warn ("Network: recvmsg failed: %s", strerror (errno));
-
- /* source address */
- assert (src);
- memcpy (src, &src_sin6.sin6_addr, sizeof (struct in6_addr));
-
- /* destination address */
- if (ifindex)
- *ifindex = pktinfo->ipi6_ifindex;
- if (dst)
- memcpy (dst, &pktinfo->ipi6_addr, sizeof (struct in6_addr));
-}
diff --git a/ospf6d/ospf6_network.h b/ospf6d/ospf6_network.h
index 934cce5..9a4d795 100644
--- a/ospf6d/ospf6_network.h
+++ b/ospf6d/ospf6_network.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -24,35 +24,27 @@
-/* Function Prototypes */
-void iov_clear (struct iovec *, size_t);
-int iov_count (struct iovec *);
-int iov_totallen (struct iovec *);
-void *iov_prepend (int, struct iovec *, size_t);
-void *iov_append (int, struct iovec *, size_t);
-void *iov_attach_last (struct iovec *, void *, size_t);
-void *iov_detach_first (struct iovec *);
-int iov_free (int, struct iovec *, u_int, u_int);
-void iov_trim_head (int, struct iovec *);
-void iov_free_all (int, struct iovec *);
-void iov_copy_all (struct iovec *, struct iovec *, size_t);
+extern int ospf6_sock;
+extern struct in6_addr allspfrouters6;
+extern struct in6_addr alldrouters6;
-int ospf6_serv_sock ();
-int ospf6_join_allspfrouters (u_int);
-void ospf6_leave_allspfrouters (u_int);
-void ospf6_join_alldrouters (u_int);
-void ospf6_leave_alldrouters (u_int);
+/* Function Prototypes */
void ospf6_set_reuseaddr ();
void ospf6_reset_mcastloop ();
void ospf6_set_pktinfo ();
void ospf6_set_checksum ();
-void ospf6_sendmsg (struct in6_addr *, struct in6_addr *,
- unsigned int *, struct iovec *);
-void ospf6_recvmsg (struct in6_addr *, struct in6_addr *,
- unsigned int *, struct iovec *);
-void ospf6_recvmsg_peek (struct in6_addr *, struct in6_addr *,
- unsigned int *, struct iovec *);
+int ospf6_serv_sock ();
+
+void ospf6_join_allspfrouters (u_int);
+void ospf6_leave_allspfrouters (u_int);
+void ospf6_join_alldrouters (u_int);
+void ospf6_leave_alldrouters (u_int);
+
+int ospf6_sendmsg (struct in6_addr *, struct in6_addr *,
+ unsigned int *, struct iovec *);
+int ospf6_recvmsg (struct in6_addr *, struct in6_addr *,
+ unsigned int *, struct iovec *);
#endif /* OSPF6_NETWORK_H */
diff --git a/ospf6d/ospf6_nsm.c b/ospf6d/ospf6_nsm.c
deleted file mode 100644
index aa08d40..0000000
--- a/ospf6d/ospf6_nsm.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * Copyright (C) 1999 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 "ospf6d.h"
-
-static int
-nbs_full_change (struct ospf6_interface *ospf6_interface)
-{
- CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, ospf6_interface);
- return 0;
-}
-
-static int
-nbs_change (state_t nbs_next, char *reason, struct ospf6_neighbor *o6n)
-{
- state_t nbs_previous;
-
- nbs_previous = o6n->state;
- o6n->state = nbs_next;
-
- if (nbs_previous == nbs_next)
- return 0;
-
- /* statistics */
- o6n->ospf6_stat_state_changed++;
- gettimeofday (&o6n->last_changed, NULL);
-
- /* log */
- if (IS_OSPF6_DUMP_NEIGHBOR)
- {
- if (reason)
- zlog_info ("Neighbor status change %s: [%s]->[%s](%s)",
- o6n->str,
- ospf6_neighbor_state_string[nbs_previous],
- ospf6_neighbor_state_string[nbs_next],
- reason);
- else
- zlog_info ("Neighbor status change %s: [%s]->[%s]",
- o6n->str,
- ospf6_neighbor_state_string[nbs_previous],
- ospf6_neighbor_state_string[nbs_next]);
- }
-
- if (nbs_previous == NBS_FULL || nbs_next == NBS_FULL)
- nbs_full_change (o6n->ospf6_interface);
-
- /* check for LSAs that already reached MaxAge */
- if ((nbs_previous == NBS_EXCHANGE || nbs_previous == NBS_LOADING) &&
- (nbs_next != NBS_EXCHANGE && nbs_next != NBS_LOADING))
- {
- ospf6_maxage_remover ();
- }
-
- CALL_CHANGE_HOOK (&neighbor_hook, o6n);
-
- return 0;
-}
-
-/* RFC2328 section 10.4 */
-int
-need_adjacency (struct ospf6_neighbor *o6n)
-{
-
- if (o6n->ospf6_interface->state == IFS_PTOP)
- return 1;
- if (o6n->ospf6_interface->state == IFS_DR)
- return 1;
- if (o6n->ospf6_interface->state == IFS_BDR)
- return 1;
- if (o6n->router_id == o6n->ospf6_interface->dr)
- return 1;
- if (o6n->router_id == o6n->ospf6_interface->bdr)
- return 1;
-
- return 0;
-}
-
-int
-hello_received (struct thread *thread)
-{
- struct ospf6_neighbor *o6n;
-
- o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
- assert (o6n);
-
- if (IS_OSPF6_DUMP_NEIGHBOR)
- zlog_info ("Neighbor Event %s: *HelloReceived*", o6n->str);
-
- if (o6n->inactivity_timer)
- thread_cancel (o6n->inactivity_timer);
-
- o6n->inactivity_timer = thread_add_timer (master, inactivity_timer, o6n,
- o6n->ospf6_interface->dead_interval);
- if (o6n->state <= NBS_DOWN)
- nbs_change (NBS_INIT, "HelloReceived", o6n);
- return 0;
-}
-
-int
-twoway_received (struct thread *thread)
-{
- struct ospf6_neighbor *o6n;
-
- o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
- assert (o6n);
-
- if (o6n->state > NBS_INIT)
- return 0;
-
- if (IS_OSPF6_DUMP_NEIGHBOR)
- zlog_info ("Neighbor Event %s: *2Way-Received*", o6n->str);
-
- thread_add_event (master, neighbor_change, o6n->ospf6_interface, 0);
-
- if (!need_adjacency (o6n))
- {
- nbs_change (NBS_TWOWAY, "No Need Adjacency", o6n);
- return 0;
- }
- else
- nbs_change (NBS_EXSTART, "Need Adjacency", o6n);
-
- DD_MSBIT_SET (o6n->dbdesc_bits);
- DD_MBIT_SET (o6n->dbdesc_bits);
- DD_IBIT_SET (o6n->dbdesc_bits);
-
- if (o6n->thread_send_dbdesc)
- thread_cancel (o6n->thread_send_dbdesc);
- o6n->thread_send_dbdesc =
- thread_add_event (master, ospf6_send_dbdesc, o6n, 0);
- if (o6n->thread_rxmt_dbdesc)
- thread_cancel (o6n->thread_rxmt_dbdesc);
- o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
-
- return 0;
-}
-
-int
-negotiation_done (struct thread *thread)
-{
- struct ospf6_neighbor *o6n;
-
- o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
- assert (o6n);
-
- if (o6n->state != NBS_EXSTART)
- return 0;
-
- if (IS_OSPF6_DUMP_NEIGHBOR)
- zlog_info ("Neighbor Event %s: *NegotiationDone*", o6n->str);
-
- nbs_change (NBS_EXCHANGE, "NegotiationDone", o6n);
- DD_IBIT_CLEAR (o6n->dbdesc_bits);
-
- return 0;
-}
-
-int
-exchange_done (struct thread *thread)
-{
- struct ospf6_neighbor *o6n;
-
- o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
- assert (o6n);
-
- if (o6n->state != NBS_EXCHANGE)
- return 0;
-
- if (o6n->thread_rxmt_dbdesc)
- thread_cancel (o6n->thread_rxmt_dbdesc);
- o6n->thread_rxmt_dbdesc = (struct thread *) NULL;
-
- if (IS_OSPF6_DUMP_NEIGHBOR)
- zlog_info ("Neighbor Event %s: *ExchangeDone*", o6n->str);
-
- ospf6_lsdb_remove_all (o6n->dbdesc_list);
-
- thread_add_timer (master, ospf6_neighbor_last_dbdesc_release, o6n,
- o6n->ospf6_interface->dead_interval);
-
- if (o6n->request_list->count == 0)
- nbs_change (NBS_FULL, "Requestlist Empty", o6n);
- else
- {
- thread_add_event (master, ospf6_send_lsreq, o6n, 0);
- nbs_change (NBS_LOADING, "Requestlist Not Empty", o6n);
- }
- return 0;
-}
-
-int
-loading_done (struct thread *thread)
-{
- struct ospf6_neighbor *o6n;
-
- o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
- assert (o6n);
-
- if (o6n->state != NBS_LOADING)
- return 0;
-
- if (IS_OSPF6_DUMP_NEIGHBOR)
- zlog_info ("Neighbor Event %s: *LoadingDone*", o6n->str);
-
- assert (o6n->request_list->count == 0);
-
- nbs_change (NBS_FULL, "LoadingDone", o6n);
-
- return 0;
-}
-
-int
-adj_ok (struct thread *thread)
-{
- struct ospf6_neighbor *o6n;
-
- o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
- assert (o6n);
-
- if (IS_OSPF6_DUMP_NEIGHBOR)
- zlog_info ("Neighbor Event %s: *AdjOK?*", o6n->str);
-
- if (o6n->state == NBS_TWOWAY)
- {
- if (!need_adjacency (o6n))
- {
- nbs_change (NBS_TWOWAY, "No Need Adjacency", o6n);
- return 0;
- }
- else
- nbs_change (NBS_EXSTART, "Need Adjacency", o6n);
-
- DD_MSBIT_SET (o6n->dbdesc_bits);
- DD_MBIT_SET (o6n->dbdesc_bits);
- DD_IBIT_SET (o6n->dbdesc_bits);
-
- if (o6n->thread_send_dbdesc)
- thread_cancel (o6n->thread_send_dbdesc);
- o6n->thread_send_dbdesc =
- thread_add_event (master, ospf6_send_dbdesc, o6n, 0);
-
- return 0;
- }
-
- if (o6n->state >= NBS_EXSTART)
- {
- if (need_adjacency (o6n))
- return 0;
- else
- {
- nbs_change (NBS_TWOWAY, "No Need Adjacency", o6n);
- ospf6_neighbor_lslist_clear (o6n);
- }
- }
- return 0;
-}
-
-int
-seqnumber_mismatch (struct thread *thread)
-{
- struct ospf6_neighbor *o6n;
-
- o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
- assert (o6n);
-
- if (o6n->state < NBS_EXCHANGE)
- return 0;
-
- /* statistics */
- o6n->ospf6_stat_seqnum_mismatch++;
-
- if (IS_OSPF6_DUMP_NEIGHBOR)
- zlog_info ("Neighbor Event %s: *SeqNumberMismatch*", o6n->str);
-
- nbs_change (NBS_EXSTART, "SeqNumberMismatch", o6n);
-
- DD_MSBIT_SET (o6n->dbdesc_bits);
- DD_MBIT_SET (o6n->dbdesc_bits);
- DD_IBIT_SET (o6n->dbdesc_bits);
- ospf6_neighbor_lslist_clear (o6n);
-
- if (o6n->thread_send_dbdesc)
- thread_cancel (o6n->thread_send_dbdesc);
- o6n->thread_send_dbdesc =
- thread_add_event (master, ospf6_send_dbdesc, o6n, 0);
-
- return 0;
-}
-
-int
-bad_lsreq (struct thread *thread)
-{
- struct ospf6_neighbor *o6n;
-
- o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
- assert (o6n);
-
- if (o6n->state < NBS_EXCHANGE)
- return 0;
-
- /* statistics */
- o6n->ospf6_stat_bad_lsreq++;
-
- if (IS_OSPF6_DUMP_NEIGHBOR)
- zlog_info ("Neighbor Event %s: *BadLSReq*", o6n->str);
-
- nbs_change (NBS_EXSTART, "BadLSReq", o6n);
-
- DD_MSBIT_SET (o6n->dbdesc_bits);
- DD_MBIT_SET (o6n->dbdesc_bits);
- DD_IBIT_SET (o6n->dbdesc_bits);
- ospf6_neighbor_lslist_clear (o6n);
-
- if (o6n->thread_send_dbdesc)
- thread_cancel (o6n->thread_send_dbdesc);
- o6n->thread_send_dbdesc =
- thread_add_event (master, ospf6_send_dbdesc, o6n, 0);
-
- return 0;
-}
-
-int
-oneway_received (struct thread *thread)
-{
- struct ospf6_neighbor *o6n;
-
- o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
- assert (o6n);
-
- if (o6n->state < NBS_TWOWAY)
- return 0;
-
- /* statistics */
- o6n->ospf6_stat_oneway_received++;
-
- if (IS_OSPF6_DUMP_NEIGHBOR)
- zlog_info ("Neighbor Event %s: *1Way-Received*", o6n->str);
-
- nbs_change (NBS_INIT, "1Way-Received", o6n);
-
- thread_add_event (master, neighbor_change, o6n->ospf6_interface, 0);
-
- ospf6_neighbor_thread_cancel_all (o6n);
- ospf6_neighbor_lslist_clear (o6n);
- return 0;
-}
-
-int
-inactivity_timer (struct thread *thread)
-{
- struct ospf6_neighbor *o6n;
-
- o6n = (struct ospf6_neighbor *) THREAD_ARG (thread);
- assert (o6n);
-
- /* statistics */
- o6n->ospf6_stat_inactivity_timer++;
-
- if (IS_OSPF6_DUMP_NEIGHBOR)
- zlog_info ("Neighbor Event %s: *InactivityTimer*", o6n->str);
-
- o6n->inactivity_timer = NULL;
- o6n->dr = o6n->bdr = o6n->prevdr = o6n->prevbdr = 0;
- nbs_change (NBS_DOWN, "InactivityTimer", o6n);
-
- thread_add_event (master, neighbor_change, o6n->ospf6_interface, 0);
-
- listnode_delete (o6n->ospf6_interface->neighbor_list, o6n);
- ospf6_neighbor_delete (o6n);
-
- return 0;
-}
-
diff --git a/ospf6d/ospf6_nsm.h b/ospf6d/ospf6_nsm.h
deleted file mode 100644
index d70f1e8..0000000
--- a/ospf6d/ospf6_nsm.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 1999 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.
- */
-
-#ifndef OSPF6_NSM_H
-#define OSPF6_NSM_H
-
-/* Neighbor state */
-#define NBS_DOWN 1
-#define OSPF6_NEIGHBOR_STATE_DOWN 1
-#define NBS_ATTEMPT 2
-#define OSPF6_NEIGHBOR_STATE_ATTEMPT 2
-#define NBS_INIT 3
-#define OSPF6_NEIGHBOR_STATE_INIT 3
-#define NBS_TWOWAY 4
-#define OSPF6_NEIGHBOR_STATE_TWOWAY 4
-#define NBS_EXSTART 5
-#define OSPF6_NEIGHBOR_STATE_EXSTART 5
-#define NBS_EXCHANGE 6
-#define OSPF6_NEIGHBOR_STATE_EXCHANGE 6
-#define NBS_LOADING 7
-#define OSPF6_NEIGHBOR_STATE_LOADING 7
-#define NBS_FULL 8
-#define OSPF6_NEIGHBOR_STATE_FULL 8
-
-
-
-/* Function Prototypes */
-
-#include "ospf6_types.h"
-
-int need_adjacency (struct ospf6_neighbor *);
-
-
-/* Neighbor event */
-int hello_received (struct thread *);
-int twoway_received (struct thread *);
-int negotiation_done (struct thread *);
-int exchange_done (struct thread *);
-int loading_done (struct thread *);
-int adj_ok (struct thread *);
-int seqnumber_mismatch (struct thread *);
-int bad_lsreq (struct thread *);
-int oneway_received (struct thread *);
-int inactivity_timer (struct thread *);
-
-int dr_election (struct ospf6_interface *);
-
-#endif /* OSPF6_NSM_H */
-
diff --git a/ospf6d/ospf6_prefix.c b/ospf6d/ospf6_prefix.c
deleted file mode 100644
index 1542200..0000000
--- a/ospf6d/ospf6_prefix.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright (C) 1999 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.
- */
-
-#if 0
-
-#include <zebra.h>
-
-#include "log.h"
-#include "prefix.h"
-#include "memory.h"
-#include "linklist.h"
-
-#include "ospf6_prefix.h"
-
-#else /*0*/
-
-#include "ospf6d.h"
-
-#endif /*0*/
-
-struct ospf6_prefix *
-ospf6_prefix_create (u_int8_t options, u_int16_t metric, struct prefix_ipv6 *p)
-{
- struct prefix_ipv6 prefix;
- struct ospf6_prefix *o6p;
- size_t size;
-
- /* copy prefix and apply mask */
- prefix_copy ((struct prefix *) &prefix, (struct prefix *) p);
- apply_mask_ipv6 (&prefix);
-
- size = OSPF6_PREFIX_SPACE (prefix.prefixlen) + sizeof (struct ospf6_prefix);
- o6p = (struct ospf6_prefix *) XMALLOC (MTYPE_OSPF6_PREFIX, size);
- if (! o6p)
- zlog_warn ("Can't allocate memory for ospf6 prefix: size: %d", size);
- else
- memset (o6p, 0, size);
-
- o6p->prefix_length = prefix.prefixlen;
- o6p->prefix_options = options;
- o6p->prefix_metric = htons (metric);
- memcpy (o6p + 1, &prefix.prefix, OSPF6_PREFIX_SPACE (prefix.prefixlen));
-
- return o6p;
-}
-
-void
-ospf6_prefix_delete (struct ospf6_prefix *p)
-{
- XFREE (MTYPE_OSPF6_PREFIX, p);
-}
-
-int
-ospf6_prefix_issame (struct ospf6_prefix *p1, struct ospf6_prefix *p2)
-{
- if (p1->prefix_length != p2->prefix_length)
- return 0;
- if (memcmp (&p1->u, &p2->u, sizeof (p1->u)))
- return 0;
- if (memcmp (p1 + 1, p2 + 1, OSPF6_PREFIX_SPACE (p1->prefix_length)))
- return 0;
- return 1;
-}
-
-struct ospf6_prefix *
-ospf6_prefix_lookup (list l, struct ospf6_prefix *p1)
-{
- listnode node;
- struct ospf6_prefix *p2;
- for (node = listhead (l); node; nextnode (node))
- {
- p2 = (struct ospf6_prefix *) getdata (node);
- if (ospf6_prefix_issame (p1, p2))
- return p2;
- }
- return NULL;
-}
-
-/* add a copy of given prefix to the list */
-void
-ospf6_prefix_add (list l, struct ospf6_prefix *p)
-{
- struct ospf6_prefix *add;
- add = (struct ospf6_prefix *) XMALLOC (MTYPE_OSPF6_PREFIX,
- OSPF6_PREFIX_SIZE (p));
- if (add == NULL)
- {
- zlog_warn ("Can't allocate memory for ospf6 prefix");
- return;
- }
- else
- memcpy (add, p, OSPF6_PREFIX_SIZE (p));
-
- if (ospf6_prefix_lookup (l, add))
- {
- ospf6_prefix_delete (add);
- return;
- }
- listnode_add (l, add);
-}
-
-void
-ospf6_prefix_remove (list l, struct ospf6_prefix *p)
-{
- struct ospf6_prefix *rem;
- rem = ospf6_prefix_lookup (l, p);
- if (rem)
- {
- listnode_delete (l, rem);
- ospf6_prefix_delete (rem);
- }
-}
-
-void
-ospf6_prefix_in6_addr (struct ospf6_prefix *o6p, struct in6_addr *in6)
-{
- memset (in6, 0, sizeof (struct in6_addr));
- memcpy (in6, o6p + 1, OSPF6_PREFIX_SPACE (o6p->prefix_length));
- return;
-}
-
-char *
-ospf6_prefix_options_str (u_int8_t opt, char *buf, size_t bufsize)
-{
- char *p, *mc, *la, *nu;
-
- p = (CHECK_FLAG (opt, OSPF6_PREFIX_OPTION_P) ? "P" : "-");
- mc = (CHECK_FLAG (opt, OSPF6_PREFIX_OPTION_MC) ? "MC" : "--");
- la = (CHECK_FLAG (opt, OSPF6_PREFIX_OPTION_LA) ? "LA" : "--");
- nu = (CHECK_FLAG (opt, OSPF6_PREFIX_OPTION_NU) ? "NU" : "--");
-
- snprintf (buf, bufsize, "%s|%s|%s|%s", p, mc, la, nu);
- return buf;
-}
-
-char *
-ospf6_prefix_string (struct ospf6_prefix *prefix, char *buf, size_t size)
-{
- struct in6_addr in6;
- char s[64];
-
- memset (&in6, 0, sizeof (in6));
- memcpy (&in6, prefix + 1, OSPF6_PREFIX_SPACE (prefix->prefix_length));
- inet_ntop (AF_INET6, &in6, s, sizeof (s));
-
- snprintf (buf, size, "%s/%d", s, prefix->prefix_length);
- return buf;
-}
-
-void
-ospf6_prefix_copy (struct ospf6_prefix *dst, struct ospf6_prefix *src,
- size_t dstsize)
-{
- size_t srcsize;
-
- memset (dst, 0, dstsize);
-
- srcsize = OSPF6_PREFIX_SIZE (src);
- if (dstsize < srcsize)
- memcpy (dst, src, dstsize);
- else
- memcpy (dst, src, srcsize);
-
- return;
-}
-
-void
-ospf6_prefix_apply_mask (struct ospf6_prefix *o6p)
-{
- u_char *pnt, mask;
- int index, offset;
-
- char buf[128];
- struct in6_addr in6;
- ospf6_prefix_in6_addr (o6p, &in6);
- inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
-
- pnt = (u_char *)(o6p + 1);
- index = o6p->prefix_length / 8;
- offset = o6p->prefix_length % 8;
- mask = 0xff << (8 - offset);
-
- if (index >= 16)
- return;
-
- pnt[index] &= mask;
- index ++;
-
- while (index < OSPF6_PREFIX_SPACE (o6p->prefix_length))
- pnt[index++] = 0;
-
- ospf6_prefix_in6_addr (o6p, &in6);
- inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
-}
-
diff --git a/ospf6d/ospf6_prefix.h b/ospf6d/ospf6_prefix.h
deleted file mode 100644
index 65a8cbc..0000000
--- a/ospf6d/ospf6_prefix.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 1999 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.
- */
-
-#ifndef OSPF6_PREFIX_H
-#define OSPF6_PREFIX_H
-
-#include "linklist.h"
-
-#define OSPF6_PREFIX_OPTION_NU (1 << 0) /* No Unicast */
-#define OSPF6_PREFIX_OPTION_LA (1 << 1) /* Local Address */
-#define OSPF6_PREFIX_OPTION_MC (1 << 2) /* MultiCast */
-#define OSPF6_PREFIX_OPTION_P (1 << 3) /* Propagate (NSSA) */
-
-struct ospf6_prefix
-{
- u_int8_t prefix_length;
- u_int8_t prefix_options;
- union {
- u_int16_t _prefix_metric;
- u_int16_t _prefix_referenced_lstype;
- } u;
-#define prefix_metric u._prefix_metric
-#define prefix_refer_lstype u._prefix_referenced_lstype
- /* followed by one address_prefix */
-};
-
-/* size_t OSPF6_PREFIX_SPACE (int prefixlength); */
-#define OSPF6_PREFIX_SPACE(x) ((((x) + 31) / 32) * 4)
-
-/* size_t OSPF6_PREFIX_SIZE (struct ospf6_prefix *); */
-#define OSPF6_PREFIX_SIZE(x) \
- (OSPF6_PREFIX_SPACE ((x)->prefix_length) + sizeof (struct ospf6_prefix))
-
-/* struct ospf6_prefix *OSPF6_NEXT_PREFIX (struct ospf6_prefix *); */
-#define OSPF6_NEXT_PREFIX(x) \
- ((struct ospf6_prefix *)((char *)(x) + OSPF6_PREFIX_SIZE (x)))
-
-
-
-/* Function Prototypes */
-struct ospf6_prefix *
- ospf6_prefix_make (u_int8_t, u_int16_t, struct prefix_ipv6 *);
-void ospf6_prefix_free (struct ospf6_prefix *);
-void ospf6_prefix_in6_addr (struct ospf6_prefix *, struct in6_addr *);
-void ospf6_prefix_copy (struct ospf6_prefix *, struct ospf6_prefix *,
- size_t);
-
-void ospf6_prefix_apply_mask (struct ospf6_prefix *);
-int ospf6_prefix_issame (struct ospf6_prefix *, struct ospf6_prefix *);
-
-char *ospf6_prefix_options_str (u_int8_t, char *, size_t);
-char *ospf6_prefix_string (struct ospf6_prefix *, char *, size_t);
-
-struct ospf6_prefix *
-ospf6_prefix_lookup (list l, struct ospf6_prefix *prefix);
-void ospf6_prefix_add (list, struct ospf6_prefix *);
-
-struct ospf6_prefix *
-ospf6_prefix_create (u_int8_t, u_int16_t, struct prefix_ipv6 *);
-void ospf6_prefix_delete (struct ospf6_prefix *);
-
-void ospf6_prefix_init ();
-
-#endif /* OSPF6_PREFIX_H */
-
diff --git a/ospf6d/ospf6_proto.c b/ospf6d/ospf6_proto.c
index 71e575f..7ee7e0a 100644
--- a/ospf6d/ospf6_proto.c
+++ b/ospf6d/ospf6_proto.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -21,20 +21,62 @@
#include <zebra.h>
+#include "log.h"
+
#include "ospf6_proto.h"
-char *
-ospf6_options_string (u_char opt_capability[3], char *buffer, int size)
+void
+ospf6_prefix_apply_mask (struct ospf6_prefix *op)
+{
+ u_char *pnt, mask;
+ int index, offset;
+
+ pnt = (u_char *)((caddr_t) op + sizeof (struct ospf6_prefix));
+ index = op->prefix_length / 8;
+ offset = op->prefix_length % 8;
+ mask = 0xff << (8 - offset);
+
+ if (index >= 16)
+ {
+ zlog_warn ("Apply mask to ospf6_prefix failed");
+ return;
+ }
+
+ pnt[index] &= mask;
+ index ++;
+
+ while (index < OSPF6_PREFIX_SPACE (op->prefix_length))
+ pnt[index++] = 0;
+}
+
+void
+ospf6_prefix_options_printbuf (u_int8_t prefix_options, char *buf, int size)
+{
+ snprintf (buf, size, "xxx");
+}
+
+void
+ospf6_capability_printbuf (char capability, char *buf, int size)
+{
+ char w, v, e, b;
+ w = (capability & OSPF6_ROUTER_BIT_W ? 'W' : '-');
+ v = (capability & OSPF6_ROUTER_BIT_V ? 'V' : '-');
+ e = (capability & OSPF6_ROUTER_BIT_E ? 'E' : '-');
+ b = (capability & OSPF6_ROUTER_BIT_B ? 'B' : '-');
+ snprintf (buf, size, "----%c%c%c%c", w, v, e, b);
+}
+
+void
+ospf6_options_printbuf (char *options, char *buf, int size)
{
char *dc, *r, *n, *mc, *e, *v6;
-
- dc = (OSPF6_OPT_ISSET (opt_capability, OSPF6_OPT_DC) ? "DC" : "--");
- r = (OSPF6_OPT_ISSET (opt_capability, OSPF6_OPT_R) ? "R" : "-");
- n = (OSPF6_OPT_ISSET (opt_capability, OSPF6_OPT_N) ? "N" : "-");
- mc = (OSPF6_OPT_ISSET (opt_capability, OSPF6_OPT_MC) ? "MC" : "--");
- e = (OSPF6_OPT_ISSET (opt_capability, OSPF6_OPT_E) ? "E" : "-");
- v6 = (OSPF6_OPT_ISSET (opt_capability, OSPF6_OPT_V6) ? "V6" : "--");
- snprintf (buffer, size, "%s|%s|%s|%s|%s|%s", dc, r, n, mc, e, v6);
- return buffer;
+ dc = (OSPF6_OPT_ISSET (options, OSPF6_OPT_DC) ? "DC" : "--");
+ r = (OSPF6_OPT_ISSET (options, OSPF6_OPT_R) ? "R" : "-" );
+ n = (OSPF6_OPT_ISSET (options, OSPF6_OPT_N) ? "N" : "-" );
+ mc = (OSPF6_OPT_ISSET (options, OSPF6_OPT_MC) ? "MC" : "--");
+ e = (OSPF6_OPT_ISSET (options, OSPF6_OPT_E) ? "E" : "-" );
+ v6 = (OSPF6_OPT_ISSET (options, OSPF6_OPT_V6) ? "V6" : "--");
+ snprintf (buf, size, "%s|%s|%s|%s|%s|%s", dc, r, n, mc, e, v6);
}
+
diff --git a/ospf6d/ospf6_proto.h b/ospf6d/ospf6_proto.h
index 9a95444..447513a 100644
--- a/ospf6d/ospf6_proto.h
+++ b/ospf6d/ospf6_proto.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -23,7 +23,7 @@
#define OSPF6_PROTO_H
/* OSPF protocol version */
-#define OSPF6_VERSION 3
+#define OSPFV3_VERSION 3
/* OSPF protocol number. */
#ifndef IPPROTO_OSPFIGP
@@ -31,28 +31,31 @@
#endif
/* TOS field normaly null */
-#define OSPF6_TOS_VALUE 0x0
+#define DEFAULT_TOS_VALUE 0x0
/* Architectural Constants */
-#define OSPF6_LS_REFRESH_TIME 1800 /* 30 min */
-#define OSPF6_MIN_LS_INTERVAL 5
-#define OSPF6_MIN_LS_ARRIVAL 1
-#define MAXAGE 3600 /* 1 hour */
-#define CHECK_AGE 300 /* 5 min */
-#define MAX_AGE_DIFF 900 /* 15 min */
-#define LS_INFINITY 0xffffff /* 24-bit binary value */
-#define INITIAL_SEQUENCE_NUMBER 0x80000001 /* signed 32-bit integer */
-#define MAX_SEQUENCE_NUMBER 0x7fffffff /* signed 32-bit integer */
-
-#define MAXOSPFMESSAGELEN 4096
+#define LS_REFRESH_TIME 1800 /* 30 min */
+#define MIN_LS_INTERVAL 5
+#define MIN_LS_ARRIVAL 1
+#define MAXAGE 3600 /* 1 hour */
+#define CHECK_AGE 300 /* 5 min */
+#define MAX_AGE_DIFF 900 /* 15 min */
+#define LS_INFINITY 0xffffff /* 24-bit binary value */
+#define INITIAL_SEQUENCE_NUMBER 0x80000001 /* signed 32-bit integer */
+#define MAX_SEQUENCE_NUMBER 0x7fffffff /* signed 32-bit integer */
#define ALLSPFROUTERS6 "ff02::5"
#define ALLDROUTERS6 "ff02::6"
/* Configurable Constants */
-#define DEFAULT_HELLO_INTERVAL 10
-#define DEFAULT_ROUTER_DEAD_TIMER 40
+#define DEFAULT_HELLO_INTERVAL 10
+#define DEFAULT_ROUTER_DEAD_INTERVAL 40
+
+#define OSPF6_ROUTER_BIT_W (1 << 3)
+#define OSPF6_ROUTER_BIT_V (1 << 2)
+#define OSPF6_ROUTER_BIT_E (1 << 1)
+#define OSPF6_ROUTER_BIT_B (1 << 0)
/* OSPF options */
/* present in HELLO, DD, LSA */
@@ -61,15 +64,58 @@
#define OSPF6_OPT_CLEAR(x,opt) ((x)[2] &= ~(opt))
#define OSPF6_OPT_CLEAR_ALL(x) ((x)[0] = (x)[1] = (x)[2] = 0)
-#define OSPF6_OPT_V6 (1 << 0) /* IPv6 forwarding Capability */
-#define OSPF6_OPT_E (1 << 1) /* AS External Capability */
-#define OSPF6_OPT_MC (1 << 2) /* Multicasting Capability */
-#define OSPF6_OPT_N (1 << 3) /* Handling Type-7 LSA Capability */
-#define OSPF6_OPT_R (1 << 4) /* Forwarding Capability (Any Protocol) */
#define OSPF6_OPT_DC (1 << 5) /* Demand Circuit handling Capability */
+#define OSPF6_OPT_R (1 << 4) /* Forwarding Capability (Any Protocol) */
+#define OSPF6_OPT_N (1 << 3) /* Handling Type-7 LSA Capability */
+#define OSPF6_OPT_MC (1 << 2) /* Multicasting Capability */
+#define OSPF6_OPT_E (1 << 1) /* AS External Capability */
+#define OSPF6_OPT_V6 (1 << 0) /* IPv6 forwarding Capability */
-char *
-ospf6_options_string (u_char opt_capability[3], char *buffer, int size);
+/* OSPF6 Prefix */
+struct ospf6_prefix
+{
+ u_int8_t prefix_length;
+ u_int8_t prefix_options;
+ union {
+ u_int16_t _prefix_metric;
+ u_int16_t _prefix_referenced_lstype;
+ } u;
+#define prefix_metric u._prefix_metric
+#define prefix_refer_lstype u._prefix_referenced_lstype
+ /* followed by one address_prefix */
+};
+
+#define OSPF6_PREFIX_OPTION_NU (1 << 0) /* No Unicast */
+#define OSPF6_PREFIX_OPTION_LA (1 << 1) /* Local Address */
+#define OSPF6_PREFIX_OPTION_MC (1 << 2) /* MultiCast */
+#define OSPF6_PREFIX_OPTION_P (1 << 3) /* Propagate (NSSA) */
+
+/* caddr_t OSPF6_PREFIX_BODY (struct ospf6_prefix *); */
+#define OSPF6_PREFIX_BODY(x) ((caddr_t)(x) + sizeof (struct ospf6_prefix))
+
+/* size_t OSPF6_PREFIX_SPACE (int prefixlength); */
+#define OSPF6_PREFIX_SPACE(x) ((((x) + 31) / 32) * 4)
+
+/* size_t OSPF6_PREFIX_SIZE (struct ospf6_prefix *); */
+#define OSPF6_PREFIX_SIZE(x) \
+ (OSPF6_PREFIX_SPACE ((x)->prefix_length) + sizeof (struct ospf6_prefix))
+
+/* struct ospf6_prefix *OSPF6_PREFIX_NEXT (struct ospf6_prefix *); */
+#define OSPF6_PREFIX_NEXT(x) \
+ ((struct ospf6_prefix *)((caddr_t)(x) + OSPF6_PREFIX_SIZE (x)))
+
+#define ospf6_prefix_in6_addr(in6, op) \
+do { \
+ memset (in6, 0, sizeof (struct in6_addr)); \
+ memcpy (in6, (caddr_t) (op) + sizeof (struct ospf6_prefix), \
+ OSPF6_PREFIX_SPACE ((op)->prefix_length)); \
+} while (0)
+
+void ospf6_prefix_apply_mask (struct ospf6_prefix *op);
+void ospf6_prefix_options_printbuf (u_int8_t prefix_options,
+ char *buf, int size);
+void ospf6_capability_printbuf (char capability, char *buf, int size);
+void ospf6_options_printbuf (char *options, char *buf, int size);
#endif /* OSPF6_PROTO_H */
diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c
index b3abedc..73bdac2 100644
--- a/ospf6d/ospf6_route.c
+++ b/ospf6d/ospf6_route.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -19,1118 +19,1119 @@
* Boston, MA 02111-1307, USA.
*/
+#include <zebra.h>
+
+#include "log.h"
+#include "memory.h"
+#include "prefix.h"
+#include "table.h"
+#include "vty.h"
+#include "command.h"
+
#include "ospf6d.h"
+#include "ospf6_proto.h"
+#include "ospf6_lsa.h"
+#include "ospf6_route.h"
-char *
-dtype_name[OSPF6_DEST_TYPE_MAX] =
+unsigned char conf_debug_ospf6_route = 0;
+
+void
+ospf6_linkstate_prefix (u_int32_t adv_router, u_int32_t id,
+ struct prefix *prefix)
{
- "Unknown", "Router", "Network", "Discard"
-};
-#define DTYPE_NAME(x) \
- (0 < (x) && (x) < sizeof (dtype_name) ? \
- dtype_name[(x)] : dtype_name[0])
-
-char *
-dtype_abname[OSPF6_DEST_TYPE_MAX] =
-{
- "?", "R", "N", "D"
-};
-#define DTYPE_ABNAME(x) \
- (0 < (x) && (x) < sizeof (dtype_abname) ? \
- dtype_abname[(x)] : dtype_abname[0])
-
-char *
-ptype_name[OSPF6_PATH_TYPE_MAX] =
-{
- "Unknown", "Intra", "Inter", "External-1", "External-2",
- "System", "Kernel", "Connect", "Static", "RIP", "RIPng",
- "OSPF", "OSPF6", "BGP"
-};
-#define PTYPE_NAME(x) \
- (0 < (x) && (x) < sizeof (ptype_name) ? \
- ptype_name[(x)] : ptype_name[0])
-
-char *
-ptype_abname[OSPF6_PATH_TYPE_MAX] =
-{
- "??", "Ia", "Ie", "E1", "E2",
- "-X", "-K", "-C", "-S", "-R", "-R",
- "-O", "-O", "-B"
-};
-#define PTYPE_ABNAME(x) \
- (0 < (x) && (x) < sizeof (ptype_abname) ? \
- ptype_abname[(x)] : ptype_abname[0])
-
-
-
-int
-ospf6_path_cmp (void *arg1, void *arg2)
-{
- struct ospf6_path_node *pn1 = arg1;
- struct ospf6_path_node *pn2 = arg2;
- struct ospf6_path *p1 = &pn1->path;
- struct ospf6_path *p2 = &pn2->path;
-
- if (p1->type < p2->type)
- return -1;
- else if (p1->type > p2->type)
- return 1;
-
- if (p1->type == OSPF6_PATH_TYPE_EXTERNAL2)
- {
- if (p1->cost_e2 < p2->cost_e2)
- return -1;
- else if (p1->cost_e2 > p2->cost_e2)
- return 1;
- }
-
- if (p1->cost < p2->cost)
- return -1;
- else if (p1->cost > p2->cost)
- return 1;
-
- /* if from the same source, recognize as identical
- (and treat this as update) */
- if (! memcmp (&p1->origin, &p2->origin, sizeof (struct ls_origin)) &&
- p1->area_id == p2->area_id)
- return 0;
-
- /* else, always prefer left */
- return -1;
+ memset (prefix, 0, sizeof (struct prefix));
+ prefix->family = AF_INET6;
+ prefix->prefixlen = 64;
+ memcpy (&prefix->u.prefix6.s6_addr[0], &adv_router, 4);
+ memcpy (&prefix->u.prefix6.s6_addr[4], &id, 4);
}
-int
-ospf6_nexthop_cmp (void *arg1, void *arg2)
+void
+ospf6_linkstate_prefix2str (struct prefix *prefix, char *buf, int size)
{
- int i, ret = 0;
- struct ospf6_nexthop_node *nn1 = arg1;
- struct ospf6_nexthop_node *nn2 = arg2;
- struct ospf6_nexthop *n1 = &nn1->nexthop;
- struct ospf6_nexthop *n2 = &nn2->nexthop;
-
- if (memcmp (n1, n2, sizeof (struct ospf6_nexthop)) == 0)
- return 0;
-
- for (i = 0; i < sizeof (struct in6_addr); i++)
- {
- if (nn1->nexthop.address.s6_addr[i] != nn2->nexthop.address.s6_addr[i])
- {
- ret = nn1->nexthop.address.s6_addr[i] -
- nn2->nexthop.address.s6_addr[i];
- break;
- }
- }
-
- if (ret == 0)
- ret = -1;
-
- return ret;
+ u_int32_t adv_router, id;
+ char adv_router_str[16];
+ memcpy (&adv_router, &prefix->u.prefix6.s6_addr[0], 4);
+ memcpy (&id, &prefix->u.prefix6.s6_addr[4], 4);
+ inet_ntop (AF_INET, &adv_router, adv_router_str, sizeof (adv_router_str));
+ snprintf (buf, size, "%s(%lu)", adv_router_str, (u_long) ntohl (id));
}
-static void
-ospf6_route_request (struct ospf6_route_req *request,
- struct ospf6_route_node *rn,
- struct ospf6_path_node *pn,
- struct ospf6_nexthop_node *nn)
+/* Global strings for logging */
+char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX] =
+{ "Unknown", "Router", "Network", "Discard", "Linkstate", };
+
+char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX] =
+{ "?", "R", "N", "D", "L", };
+
+char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX] =
+{ "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", };
+
+char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] =
+{ "??", "Ia", "Ie", "E1", "E2", };
+
+
+struct ospf6_route *
+ospf6_route_create ()
{
- assert (request);
- assert (rn && pn && nn);
-
- request->route_node = rn->route_node;
-
- linklist_head (rn->path_list, &request->path_lnode);
- while (request->path_lnode.data != pn)
- {
- //assert (! linklist_end (&request->path_lnode));
- if (linklist_end (&request->path_lnode))
- {
- struct linklist_node node;
-
- zlog_info ("rn: %p, pn: %p", rn, pn);
- zlog_info ("origin: %hx %x %x bits: %x opt: %x%x%x popt: %x area: %x type: %d cost %d %d %d",
- pn->path.origin.type, pn->path.origin.id, pn->path.origin.adv_router, (int)pn->path.router_bits, (int)pn->path.capability[0],
- (int)pn->path.capability[1], (int)pn->path.capability[2],
- (int)pn->path.prefix_options, pn->path.area_id,
- pn->path.type, pn->path.metric_type, pn->path.cost, pn->path.cost_e2);
-
- for (linklist_head (rn->path_list, &node); ! linklist_end (&node);
- linklist_next (&node))
- {
- struct ospf6_path_node *pn2 = node.data;
-
- zlog_info (" %p: path data with pn(%p): %s", pn2, pn,
- (memcmp (&pn->path, &pn2->path,
- sizeof (struct ospf6_path)) ?
- "different" : "same"));
-
- zlog_info (" origin: %hx %x %x bits: %x opt: %x%x%x popt: %x area: %x type: %d cost %d %d %d",
- pn2->path.origin.type, pn2->path.origin.id, pn2->path.origin.adv_router, (int)pn2->path.router_bits, (int)pn2->path.capability[0],
- (int)pn2->path.capability[1], (int)pn2->path.capability[2],
- (int)pn2->path.prefix_options, pn2->path.area_id,
- pn2->path.type, pn2->path.metric_type, pn2->path.cost, pn2->path.cost_e2);
-
- if (! memcmp (&pn->path, &pn2->path, sizeof (struct ospf6_path)))
- {
- pn = pn2;
- request->nexthop_lnode.data = pn2;
- }
- }
- break;
- }
- linklist_next (&request->path_lnode);
- }
- assert (request->path_lnode.data == pn);
-
- linklist_head (pn->nexthop_list, &request->nexthop_lnode);
- while (request->nexthop_lnode.data != nn)
- {
- assert (! linklist_end (&request->nexthop_lnode));
- linklist_next (&request->nexthop_lnode);
- }
- assert (request->nexthop_lnode.data == nn);
-
- request->table = rn->table;
- request->count = rn->count;
- request->route_id = rn->route_id;
- memcpy (&request->route, &rn->route, sizeof (struct ospf6_route));
- memcpy (&request->path, &pn->path, sizeof (struct ospf6_path));
- memcpy (&request->nexthop, &nn->nexthop, sizeof (struct ospf6_nexthop));
+ struct ospf6_route *route;
+ route = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route));
+ return route;
}
-int
-ospf6_route_count (struct ospf6_route_req *request)
+void
+ospf6_route_delete (struct ospf6_route *route)
{
- return request->count;
+ XFREE (MTYPE_OSPF6_ROUTE, route);
}
-int
-ospf6_route_lookup (struct ospf6_route_req *request,
- struct prefix *prefix,
+struct ospf6_route *
+ospf6_route_copy (struct ospf6_route *route)
+{
+ struct ospf6_route *new;
+
+ new = ospf6_route_create ();
+ memcpy (new, route, sizeof (struct ospf6_route));
+ new->rnode = NULL;
+ new->prev = NULL;
+ new->next = NULL;
+ new->lock = 0;
+ return new;
+}
+
+void
+ospf6_route_lock (struct ospf6_route *route)
+{
+ route->lock++;
+}
+
+void
+ospf6_route_unlock (struct ospf6_route *route)
+{
+ assert (route->lock > 0);
+ route->lock--;
+ if (route->lock == 0)
+ ospf6_route_delete (route);
+}
+
+/* Route compare function. If ra is more preferred, it returns
+ less than 0. If rb is more preferred returns greater than 0.
+ Otherwise (neither one is preferred), returns 0 */
+static int
+ospf6_route_cmp (struct ospf6_route *ra, struct ospf6_route *rb)
+{
+ assert (ospf6_route_is_same (ra, rb));
+ assert (OSPF6_PATH_TYPE_NONE < ra->path.type &&
+ ra->path.type < OSPF6_PATH_TYPE_MAX);
+ assert (OSPF6_PATH_TYPE_NONE < rb->path.type &&
+ rb->path.type < OSPF6_PATH_TYPE_MAX);
+
+ if (ra->type != rb->type)
+ return (ra->type - rb->type);
+
+ if (ra->path.area_id != rb->path.area_id)
+ return (ntohl (ra->path.area_id) - ntohl (rb->path.area_id));
+
+ if (ra->path.type != rb->path.type)
+ return (ra->path.type - rb->path.type);
+
+ if (ra->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
+ {
+ if (ra->path.cost_e2 != rb->path.cost_e2)
+ return (ra->path.cost_e2 - rb->path.cost_e2);
+ }
+ else
+ {
+ if (ra->path.cost != rb->path.cost)
+ return (ra->path.cost - rb->path.cost);
+ }
+
+ return 0;
+}
+
+struct ospf6_route *
+ospf6_route_lookup (struct prefix *prefix,
struct ospf6_route_table *table)
{
struct route_node *node;
- struct ospf6_route_node *rn = NULL;
- struct ospf6_path_node *pn = NULL;
- struct ospf6_nexthop_node *nn = NULL;
- struct linklist_node lnode;
-
- if (request)
- memset ((void *) request, 0, sizeof (struct ospf6_route_req));
+ struct ospf6_route *route;
node = route_node_lookup (table->table, prefix);
- if (! node)
- return 0;
+ if (node == NULL)
+ return NULL;
- rn = (struct ospf6_route_node *) node->info;
- if (! rn)
- return 0;
-
- if (request)
- {
- linklist_head (rn->path_list, &lnode);
- pn = lnode.data;
- linklist_head (pn->nexthop_list, &lnode);
- nn = lnode.data;
-
- ospf6_route_request (request, rn, pn, nn);
- }
-
- return 1;
+ route = (struct ospf6_route *) node->info;
+ return route;
}
-void
-ospf6_route_head (struct ospf6_route_req *request,
- struct ospf6_route_table *table)
+struct ospf6_route *
+ospf6_route_lookup_identical (struct ospf6_route *route,
+ struct ospf6_route_table *table)
+{
+ struct ospf6_route *target;
+
+ for (target = ospf6_route_lookup (&route->prefix, table);
+ target; target = target->next)
+ {
+ if (ospf6_route_is_identical (target, route))
+ return target;
+ }
+ return NULL;
+}
+
+struct ospf6_route *
+ospf6_route_lookup_bestmatch (struct prefix *prefix,
+ struct ospf6_route_table *table)
{
struct route_node *node;
- struct ospf6_route_node *rn = NULL;
- struct ospf6_path_node *pn = NULL;
- struct ospf6_nexthop_node *nn = NULL;
- struct linklist_node lnode;
+ struct ospf6_route *route;
- if (request)
- memset (request, 0, sizeof (struct ospf6_route_req));
+ node = route_node_match (table->table, prefix);
+ if (node == NULL)
+ return NULL;
+ route_unlock_node (node);
- node = route_top (table->table);
- if (! node)
- return;
-
- while (node && node->info == NULL)
- node = route_next (node);
- if (! node)
- return;
-
- rn = (struct ospf6_route_node *) node->info;
- linklist_head (rn->path_list, &lnode);
- pn = lnode.data;
- linklist_head (pn->nexthop_list, &lnode);
- nn = lnode.data;
-
- ospf6_route_request (request, rn, pn, nn);
+ route = (struct ospf6_route *) node->info;
+ return route;
}
-int
-ospf6_route_end (struct ospf6_route_req *request)
+#ifndef NDEBUG
+static void
+_route_count_assert (struct ospf6_route_table *table)
{
- if (request->route_node == NULL &&
- linklist_end (&request->path_lnode) &&
- linklist_end (&request->nexthop_lnode) &&
- request->nexthop.ifindex == 0 &&
- IN6_IS_ADDR_UNSPECIFIED (&request->nexthop.address))
- return 1;
- return 0;
+ struct ospf6_route *debug;
+ int num = 0;
+ for (debug = ospf6_route_head (table); debug;
+ debug = ospf6_route_next (debug))
+ num++;
+ assert (num == table->count);
}
+#define ospf6_route_count_assert(t) (_route_count_assert (t))
+#else
+#define ospf6_route_count_assert(t) ((void) 0)
+#endif /*NDEBUG*/
-void
-ospf6_route_next (struct ospf6_route_req *request)
-{
- struct ospf6_route_node *route_node = NULL;
- struct ospf6_path_node *path_node = NULL;
- struct ospf6_nexthop_node *nexthop_node = NULL;
-
- linklist_next (&request->nexthop_lnode);
- if (linklist_end (&request->nexthop_lnode))
- {
- linklist_next (&request->path_lnode);
- if (linklist_end (&request->path_lnode))
- {
- request->route_node = route_next (request->route_node);
- while (request->route_node && request->route_node->info == NULL)
- request->route_node = route_next (request->route_node);
- if (request->route_node)
- {
- route_node = request->route_node->info;
- if (route_node)
- linklist_head (route_node->path_list, &request->path_lnode);
- }
- }
-
- path_node = request->path_lnode.data;
- if (path_node)
- linklist_head (path_node->nexthop_list, &request->nexthop_lnode);
- }
-
- nexthop_node = request->nexthop_lnode.data;
-
- if (nexthop_node == NULL)
- {
- assert (path_node == NULL);
- assert (route_node == NULL);
-
- memset (&request->route, 0, sizeof (struct ospf6_route));
- memset (&request->path, 0, sizeof (struct ospf6_path));
- memset (&request->nexthop, 0, sizeof (struct ospf6_nexthop));
- }
- else
- {
- path_node = request->path_lnode.data;
- route_node = request->route_node->info;
-
- assert (path_node != NULL);
- assert (route_node != NULL);
-
- memcpy (&request->route, &route_node->route,
- sizeof (struct ospf6_route));
- memcpy (&request->path, &path_node->path,
- sizeof (struct ospf6_path));
- memcpy (&request->nexthop, &nexthop_node->nexthop,
- sizeof (struct ospf6_nexthop));
- }
-}
-
-#define ADD 0
-#define CHANGE 1
-#define REMOVE 2
-
-void
-ospf6_route_hook_call (int type,
- struct ospf6_route_req *request,
- struct ospf6_route_table *table)
-{
- struct linklist_node node;
- void (*func) (struct ospf6_route_req *);
-
- for (linklist_head (table->hook_list[type], &node);
- ! linklist_end (&node);
- linklist_next (&node))
- {
- func = node.data;
- (*func) (request);
- }
-}
-
-void
-ospf6_route_hook_register (void (*add) (struct ospf6_route_req *),
- void (*change) (struct ospf6_route_req *),
- void (*remove) (struct ospf6_route_req *),
- struct ospf6_route_table *table)
-{
- linklist_add (add, table->hook_list[ADD]);
- linklist_add (change, table->hook_list[CHANGE]);
- linklist_add (remove, table->hook_list[REMOVE]);
-}
-
-void
-ospf6_route_hook_unregister (void (*add) (struct ospf6_route_req *),
- void (*change) (struct ospf6_route_req *),
- void (*remove) (struct ospf6_route_req *),
- struct ospf6_route_table *table)
-{
- linklist_remove (add, table->hook_list[ADD]);
- linklist_remove (change, table->hook_list[CHANGE]);
- linklist_remove (remove, table->hook_list[REMOVE]);
-}
-
-
-int
-prefix_ls2str (struct prefix *p, char *str, int size)
-{
- char id[BUFSIZ], adv_router[BUFSIZ];
- struct prefix_ls *pl = (struct prefix_ls *) p;
-
- inet_ntop (AF_INET, &pl->id, id, BUFSIZ);
- inet_ntop (AF_INET, &pl->adv_router, adv_router, BUFSIZ);
- snprintf (str, size, "%s-%s", adv_router, id);
- return 0;
-}
-
-void
-ospf6_route_log_request (char *what, char *where,
- struct ospf6_route_req *request)
-{
- char prefix[64];
- char area_id[16];
- char type[16], id[16], adv[16];
- char address[64], ifname[IFNAMSIZ];
-
- if (request->route.prefix.family != AF_INET &&
- request->route.prefix.family != AF_INET6)
- prefix_ls2str (&request->route.prefix, prefix, sizeof (prefix));
- else
- prefix2str (&request->route.prefix, prefix, sizeof (prefix));
-
- inet_ntop (AF_INET, &request->path.area_id, area_id, sizeof (area_id));
-
- ospf6_lsa_type_string (request->path.origin.type, type, sizeof (type));
- inet_ntop (AF_INET, &request->path.origin.id, id, sizeof (id));
- inet_ntop (AF_INET, &request->path.origin.adv_router, adv, sizeof (adv));
-
- inet_ntop (AF_INET6, &request->nexthop.address, address, sizeof (address));
-
- zlog_info ("ROUTE: %s %s %s %s %s",
- what, DTYPE_ABNAME (request->route.type), prefix,
- ((strcmp ("Add", what) == 0) ? "to" : "from"), where);
- zlog_info ("ROUTE: Area: %s type: %s cost: %lu (E2: %lu)",
- area_id, PTYPE_NAME (request->path.type),
- (u_long) request->path.cost, (u_long) request->path.cost_e2);
- zlog_info ("ROUTE: Origin: Type: %s", type);
- zlog_info ("ROUTE: Origin: Id: %s Adv: %s", id, adv);
- zlog_info ("ROUTE: Nexthop: %s", address);
- zlog_info ("ROUTE: Nexthop: Ifindex: %u (%s)",
- request->nexthop.ifindex,
- if_indextoname (request->nexthop.ifindex, ifname));
-}
-
-struct ospf6_path_node *
-ospf6_route_find_path_node (struct ospf6_route_req *request,
- struct ospf6_route_node *rn)
-{
- struct linklist_node node;
-
- for (linklist_head (rn->path_list, &node); ! linklist_end (&node);
- linklist_next (&node))
- {
- struct ospf6_path_node *path_node = node.data;
-
- if (path_node->path.area_id == request->path.area_id &&
- path_node->path.origin.type == request->path.origin.type &&
- path_node->path.origin.id == request->path.origin.id &&
- path_node->path.origin.adv_router == request->path.origin.adv_router)
- return path_node;
- }
-
-#if 0
- zlog_info ("req path : area: %#x origin: type: %d, id: %d, adv_router: %#x",
- request->path.area_id, request->path.origin.type,
- request->path.origin.id, request->path.origin.adv_router);
- for (linklist_head (rn->path_list, &node); ! linklist_end (&node);
- linklist_next (&node))
- {
- struct ospf6_path_node *path_node = node.data;
- zlog_info (" path : area: %#x origin: type: %d, id: %d, adv_router: %#x",
- path_node->path.area_id, path_node->path.origin.type,
- path_node->path.origin.id, path_node->path.origin.adv_router);
- }
-#endif
-
- return NULL;
-}
-
-struct ospf6_nexthop_node *
-ospf6_route_find_nexthop_node (struct ospf6_route_req *request,
- struct ospf6_path_node *pn)
-{
- struct linklist_node node;
- for (linklist_head (pn->nexthop_list, &node); ! linklist_end (&node);
- linklist_next (&node))
- {
- struct ospf6_nexthop_node *nexthop_node = node.data;
-
- if (! memcmp (&nexthop_node->nexthop, &request->nexthop,
- sizeof (struct ospf6_nexthop)))
- return nexthop_node;
- }
- return NULL;
-}
-
-void
-ospf6_route_add (struct ospf6_route_req *request,
+struct ospf6_route *
+ospf6_route_add (struct ospf6_route *route,
struct ospf6_route_table *table)
{
- struct ospf6_route_node *rn;
- struct ospf6_path_node *pn;
- struct ospf6_nexthop_node *nn;
- struct route_node *route_node;
+ struct route_node *node, *nextnode, *prevnode;
+ struct ospf6_route *current = NULL;
+ struct ospf6_route *prev = NULL, *old = NULL, *next = NULL;
+ char buf[64];
+ struct timeval now;
- struct ospf6_route_req route;
+ assert (route->rnode == NULL);
+ assert (route->lock == 0);
+ assert (route->next == NULL);
+ assert (route->prev == NULL);
- int route_change = 0;
- int path_change = 0;
- int nexthop_change = 0;
+ if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
+ ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
+ else
+ prefix2str (&route->prefix, buf, sizeof (buf));
- /* find the requested route */
- route_node = route_node_get (table->table, &request->route.prefix);
- rn = (struct ospf6_route_node *) route_node->info;
+ if (IS_OSPF6_DEBUG_ROUTE (TABLE))
+ zlog_info ("route add %s", buf);
- if (rn)
+ gettimeofday (&now, NULL);
+
+ node = route_node_get (table->table, &route->prefix);
+ route->rnode = node;
+
+ /* find place to insert */
+ for (current = node->info; current; current = current->next)
{
- if (memcmp (&rn->route, &request->route, sizeof (struct ospf6_route)))
- {
- memcpy (&rn->route, &request->route, sizeof (struct ospf6_route));
- route_change++;
- }
+ if (! ospf6_route_is_same (current, route))
+ next = current;
+ else if (current->type != route->type)
+ prev = current;
+ else if (ospf6_route_is_same_origin (current, route))
+ old = current;
+ else if (ospf6_route_cmp (current, route) > 0)
+ next = current;
+ else
+ prev = current;
+
+ if (old || next)
+ break;
}
+
+ if (old)
+ {
+ /* if route does not actually change, return unchanged */
+ if (ospf6_route_is_identical (old, route))
+ {
+ if (IS_OSPF6_DEBUG_ROUTE (TABLE))
+ zlog_info (" identical route found, ignore");
+
+ ospf6_route_delete (route);
+ SET_FLAG (old->flag, OSPF6_ROUTE_ADD);
+ ospf6_route_count_assert (table);
+ return old;
+ }
+
+ if (IS_OSPF6_DEBUG_ROUTE (TABLE))
+ zlog_info (" old route found, replace");
+
+ /* replace old one if exists */
+ if (node->info == old)
+ {
+ node->info = route;
+ SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
+ }
+
+ if (old->prev)
+ old->prev->next = route;
+ route->prev = old->prev;
+ if (old->next)
+ old->next->prev = route;
+ route->next = old->next;
+
+ route->installed = old->installed;
+ route->changed = now;
+
+ ospf6_route_unlock (old); /* will be deleted later */
+ ospf6_route_lock (route);
+
+ SET_FLAG (route->flag, OSPF6_ROUTE_CHANGE);
+ if (table->hook_add)
+ (*table->hook_add) (route);
+
+ ospf6_route_count_assert (table);
+ return route;
+ }
+
+ /* insert if previous or next node found */
+ if (prev || next)
+ {
+ if (IS_OSPF6_DEBUG_ROUTE (TABLE))
+ zlog_info (" another path found, insert");
+
+ if (prev == NULL)
+ prev = next->prev;
+ if (next == NULL)
+ next = prev->next;
+
+ if (prev)
+ prev->next = route;
+ route->prev = prev;
+ if (next)
+ next->prev = route;
+ route->next = next;
+
+ if (node->info == next)
+ {
+ assert (next->rnode == node);
+ node->info = route;
+ UNSET_FLAG (next->flag, OSPF6_ROUTE_BEST);
+ SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
+ }
+
+ route->installed = now;
+ route->changed = now;
+
+ ospf6_route_lock (route);
+ table->count++;
+
+ SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
+ if (table->hook_add)
+ (*table->hook_add) (route);
+
+ ospf6_route_count_assert (table);
+ return route;
+ }
+
+ /* Else, this is the brand new route regarding to the prefix */
+ if (IS_OSPF6_DEBUG_ROUTE (TABLE))
+ zlog_info (" brand new route, add");
+
+ assert (node->info == NULL);
+ node->info = route;
+ SET_FLAG (route->flag, OSPF6_ROUTE_BEST);
+ ospf6_route_lock (route);
+ route->installed = now;
+ route->changed = now;
+
+ /* lookup real existing next route */
+ nextnode = node;
+ route_lock_node (nextnode);
+ do {
+ nextnode = route_next (nextnode);
+ } while (nextnode && nextnode->info == NULL);
+
+ /* set next link */
+ if (nextnode == NULL)
+ route->next = NULL;
else
{
- rn = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_node));
- rn->table = table;
- rn->route_node = route_node;
- rn->route_id = table->route_id++;
- rn->path_list = linklist_create ();
- rn->path_list->cmp = ospf6_path_cmp;
- memcpy (&rn->route, &request->route, sizeof (struct ospf6_route));
- route_node->info = rn;
+ route_unlock_node (nextnode);
+
+ next = nextnode->info;
+ route->next = next;
+ next->prev = route;
}
- /* find the same path */
- pn = ospf6_route_find_path_node (request, rn);
+ /* lookup real existing prev route */
+ prevnode = node;
+ route_lock_node (prevnode);
+ do {
+ prevnode = route_prev (prevnode);
+ } while (prevnode && prevnode->info == NULL);
- if (pn)
- {
- if (memcmp (&pn->path, &request->path, sizeof (struct ospf6_path)))
- {
- memcpy (&pn->path, &request->path, sizeof (struct ospf6_path));
- path_change++;
- }
- }
+ /* set prev link */
+ if (prevnode == NULL)
+ route->prev = NULL;
else
{
- pn = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_path_node));
- pn->route_node = rn;
- pn->nexthop_list = linklist_create ();
- pn->nexthop_list->cmp = ospf6_nexthop_cmp;
- memcpy (&pn->path, &request->path, sizeof (struct ospf6_path));
- linklist_add (pn, rn->path_list);
+ route_unlock_node (prevnode);
+
+ prev = prevnode->info;
+ while (prev->next && ospf6_route_is_same (prev, prev->next))
+ prev = prev->next;
+ route->prev = prev;
+ prev->next = route;
}
- /* find the same nexthop */
- nn = ospf6_route_find_nexthop_node (request, pn);
+ table->count++;
- if (nn)
- {
- if (memcmp (&nn->nexthop, &request->nexthop,
- sizeof (struct ospf6_nexthop)))
- {
- memcpy (&nn->nexthop, &request->nexthop,
- sizeof (struct ospf6_nexthop));
- nexthop_change++;
- gettimeofday (&nn->installed, (struct timezone *) NULL);
- }
- }
- else
- {
- nn = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_nexthop_node));
- nn->path_node = pn;
- memcpy (&nn->nexthop, &request->nexthop, sizeof (struct ospf6_nexthop));
- linklist_add (nn, pn->nexthop_list);
- rn->count++;
- gettimeofday (&nn->installed, (struct timezone *) NULL);
- }
+ SET_FLAG (route->flag, OSPF6_ROUTE_ADD);
+ if (table->hook_add)
+ (*table->hook_add) (route);
- SET_FLAG (nn->flag, OSPF6_ROUTE_FLAG_ADD);
- if (route_change)
- SET_FLAG (nn->flag, OSPF6_ROUTE_FLAG_ROUTE_CHANGE);
- if (path_change)
- SET_FLAG (nn->flag, OSPF6_ROUTE_FLAG_PATH_CHANGE);
- if (nexthop_change)
- SET_FLAG (nn->flag, OSPF6_ROUTE_FLAG_CHANGE);
-
- if (table->freeze)
- return;
-
- if (IS_OSPF6_DUMP_ROUTE)
- {
- ospf6_route_log_request ("Add", table->name, request);
-
- if (CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_ROUTE_CHANGE))
- zlog_info ("ROUTE: route attribute change");
- if (CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_PATH_CHANGE))
- zlog_info ("ROUTE: path attribute change");
- if (CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_CHANGE))
- zlog_info ("ROUTE: nexthop attribute change");
- }
-
- if (CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_ROUTE_CHANGE) ||
- CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_PATH_CHANGE))
- SET_FLAG (nn->flag, OSPF6_ROUTE_FLAG_CHANGE);
-
- /* Call hooks */
- ospf6_route_request (&route, rn, pn, nn);
- if (CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_ADD))
- ospf6_route_hook_call (ADD, &route, table);
- else if (CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_CHANGE))
- ospf6_route_hook_call (CHANGE, &route, table);
-
- if (table->hook_add &&
- CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_ADD))
- (*table->hook_add) (&route);
- else if (table->hook_change &&
- CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_CHANGE))
- (*table->hook_change) (&route);
-
- /* clear flag */
- nn->flag = 0;
+ ospf6_route_count_assert (table);
+ return route;
}
void
-ospf6_route_remove (struct ospf6_route_req *request,
+ospf6_route_remove (struct ospf6_route *route,
struct ospf6_route_table *table)
{
- struct ospf6_route_node *rn;
- struct ospf6_path_node *pn;
- struct ospf6_nexthop_node *nn;
- struct route_node *route_node;
- struct ospf6_route_req route;
+ struct route_node *node;
+ struct ospf6_route *current;
+ char buf[64];
- /* find the requested route */
- route_node = route_node_get (table->table, &request->route.prefix);
- rn = (struct ospf6_route_node *) route_node->info;
+ if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
+ ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf));
+ else
+ prefix2str (&route->prefix, buf, sizeof (buf));
- if (! rn)
+ if (IS_OSPF6_DEBUG_ROUTE (TABLE))
+ zlog_info ("route remove: %s", buf);
+
+ node = route_node_lookup (table->table, &route->prefix);
+ assert (node);
+
+ /* find the route to remove, making sure that the route pointer
+ is from the route table. */
+ current = node->info;
+ while (current && ospf6_route_is_same (current, route))
{
- if (IS_OSPF6_DUMP_ROUTE)
+ if (current == route)
+ break;
+ current = current->next;
+ }
+ assert (current == route);
+
+ /* adjust doubly linked list */
+ if (route->prev)
+ route->prev->next = route->next;
+ if (route->next)
+ route->next->prev = route->prev;
+
+ if (node->info == route)
+ {
+ if (route->next && ospf6_route_is_same (route->next, route))
{
- ospf6_route_log_request ("Remove", table->name, request);
- zlog_info ("ROUTE: Can't remove: No such route");
+ node->info = route->next;
+ SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST);
}
- return;
+ else
+ node->info = NULL; /* should unlock route_node here ? */
}
- pn = ospf6_route_find_path_node (request, rn);
- if (! pn)
- {
- if (IS_OSPF6_DUMP_ROUTE)
- {
- ospf6_route_log_request ("Remove", table->name, request);
- zlog_info ("ROUTE: Can't remove: No such path");
- }
- return;
- }
-
- if (pn->path.area_id != request->path.area_id ||
- pn->path.origin.type != request->path.origin.type ||
- pn->path.origin.id != request->path.origin.id ||
- pn->path.origin.adv_router != request->path.origin.adv_router)
- {
- if (IS_OSPF6_DUMP_ROUTE)
- {
- ospf6_route_log_request ("Remove", table->name, request);
- zlog_info ("ROUTE: Can't remove: Path differ");
- {
- char *s, *e, *c;
- char line[512], *p;
-
- p = line;
- s = (char *) &pn->path;
- e = s + sizeof (struct ospf6_path);
- for (c = s; c < e; c++)
- {
- if ((c - s) % 4 == 0)
- {
- snprintf (p, line + sizeof (line) - p, " ");
- p++;
- }
- snprintf (p, line + sizeof (line) - p, "%02x", *c);
- p += 2;
- }
- zlog_info ("ROUTE: path: %s", line);
-
- p = line;
- s = (char *) &request->path;
- e = s + sizeof (struct ospf6_path);
- for (c = s; c < e; c++)
- {
- if ((c - s) % 4 == 0)
- {
- snprintf (p, line + sizeof (line) - p, " ");
- p++;
- }
- snprintf (p, line + sizeof (line) - p, "%02x", *c);
- p += 2;
- }
- zlog_info ("ROUTE: req : %s", line);
-
- }
- }
- return;
- }
-
- nn = ospf6_route_find_nexthop_node (request, pn);
- if (! nn)
- {
- if (IS_OSPF6_DUMP_ROUTE)
- {
- ospf6_route_log_request ("Remove", table->name, request);
- zlog_info ("ROUTE: Can't remove: No such nexthop");
- }
- return;
- }
-
- if (memcmp (&nn->nexthop, &request->nexthop, sizeof (struct ospf6_nexthop)))
- {
- if (IS_OSPF6_DUMP_ROUTE)
- {
- ospf6_route_log_request ("Remove", table->name, request);
- zlog_info ("ROUTE: Can't remove: Nexthop differ");
- }
- return;
- }
-
- SET_FLAG (nn->flag, OSPF6_ROUTE_FLAG_REMOVE);
-
- if (table->freeze)
- return;
-
- if (IS_OSPF6_DUMP_ROUTE)
- ospf6_route_log_request ("Remove", table->name, request);
-
- ospf6_route_request (&route, rn, pn, nn);
- ospf6_route_hook_call (REMOVE, &route, table);
if (table->hook_remove)
- (*table->hook_remove) (&route);
+ (*table->hook_remove) (route);
- /* clear flag */
- nn->flag = 0;
+ ospf6_route_unlock (route);
+ table->count--;
- /* remove nexthop */
- linklist_remove (nn, pn->nexthop_list);
- rn->count--;
- XFREE (MTYPE_OSPF6_ROUTE, nn);
+ ospf6_route_count_assert (table);
+}
- /* remove path if there's no nexthop for the path */
- if (pn->nexthop_list->count != 0)
- return;
- linklist_remove (pn, rn->path_list);
- linklist_delete (pn->nexthop_list);
- XFREE (MTYPE_OSPF6_ROUTE, pn);
+struct ospf6_route *
+ospf6_route_head (struct ospf6_route_table *table)
+{
+ struct route_node *node;
+ struct ospf6_route *route;
- /* remove route if there's no path for the route */
- if (rn->path_list->count != 0)
- return;
- route_node->info = NULL;
- linklist_delete (rn->path_list);
- XFREE (MTYPE_OSPF6_ROUTE, rn);
+ node = route_top (table->table);
+ if (node == NULL)
+ return NULL;
+
+ /* skip to the real existing entry */
+ while (node && node->info == NULL)
+ node = route_next (node);
+ if (node == NULL)
+ return NULL;
+
+ route_unlock_node (node);
+ assert (node->info);
+
+ route = (struct ospf6_route *) node->info;
+ assert (route->prev == NULL);
+ ospf6_route_lock (route);
+ return route;
+}
+
+struct ospf6_route *
+ospf6_route_next (struct ospf6_route *route)
+{
+ struct ospf6_route *next = route->next;
+
+ ospf6_route_unlock (route);
+ if (next)
+ ospf6_route_lock (next);
+
+ return next;
+}
+
+struct ospf6_route *
+ospf6_route_best_next (struct ospf6_route *route)
+{
+ struct route_node *rnode;
+ struct ospf6_route *next;
+
+ rnode = route->rnode;
+ route_lock_node (rnode);
+ rnode = route_next (rnode);
+ while (rnode && rnode->info == NULL)
+ rnode = route_next (rnode);
+ if (rnode == NULL)
+ return NULL;
+ route_unlock_node (rnode);
+
+ assert (rnode->info);
+ next = (struct ospf6_route *) rnode->info;
+ ospf6_route_unlock (route);
+ ospf6_route_lock (next);
+ return next;
+}
+
+/* Macro version of check_bit (). */
+#define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1)
+
+struct ospf6_route *
+ospf6_route_match_head (struct prefix *prefix,
+ struct ospf6_route_table *table)
+{
+ struct route_node *node;
+ struct ospf6_route *route;
+
+ /* Walk down tree. */
+ node = table->table->top;
+ while (node && node->p.prefixlen < prefix->prefixlen &&
+ prefix_match (&node->p, prefix))
+ node = node->link[CHECK_BIT(&prefix->u.prefix, node->p.prefixlen)];
+
+ if (node)
+ route_lock_node (node);
+ while (node && node->info == NULL)
+ node = route_next (node);
+ if (node == NULL)
+ return NULL;
+ route_unlock_node (node);
+
+ if (! prefix_match (prefix, &node->p))
+ return NULL;
+
+ route = node->info;
+ ospf6_route_lock (route);
+ return route;
+}
+
+struct ospf6_route *
+ospf6_route_match_next (struct prefix *prefix,
+ struct ospf6_route *route)
+{
+ struct ospf6_route *next;
+
+ next = ospf6_route_next (route);
+ if (next && ! prefix_match (prefix, &next->prefix))
+ {
+ ospf6_route_unlock (next);
+ next = NULL;
+ }
+
+ return next;
}
void
ospf6_route_remove_all (struct ospf6_route_table *table)
{
- struct ospf6_route_req request;
-
- for (ospf6_route_head (&request, table); ! ospf6_route_end (&request);
- ospf6_route_next (&request))
- ospf6_route_remove (&request, table);
+ struct ospf6_route *route;
+ for (route = ospf6_route_head (table); route;
+ route = ospf6_route_next (route))
+ ospf6_route_remove (route, table);
}
-
struct ospf6_route_table *
-ospf6_route_table_create (char *name)
+ospf6_route_table_create ()
{
- int i;
struct ospf6_route_table *new;
-
new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table));
- snprintf (new->name, sizeof (new->name), "%s", name);
-
new->table = route_table_init ();
- for (i = 0; i < 3; i++)
- new->hook_list[i] = linklist_create ();
-
return new;
}
void
ospf6_route_table_delete (struct ospf6_route_table *table)
{
- int i;
-
ospf6_route_remove_all (table);
route_table_finish (table->table);
- for (i = 0; i < 3; i++)
- linklist_delete (table->hook_list[i]);
XFREE (MTYPE_OSPF6_ROUTE, table);
}
-void
-ospf6_route_table_freeze (struct ospf6_route_table *route_table)
-{
- if (IS_OSPF6_DUMP_ROUTE)
- zlog_info ("ROUTE: Table freeze: %s", route_table->name);
- assert (route_table->freeze == 0);
- route_table->freeze = 1;
-}
-
-void
-ospf6_route_table_thaw (struct ospf6_route_table *route_table)
-{
- struct route_node *node;
- struct linklist_node pnode;
- struct linklist_node nnode;
-
- struct ospf6_route_node *rn;
- struct ospf6_path_node *pn;
- struct ospf6_nexthop_node *nn;
-
- struct ospf6_route_req request;
-
- if (IS_OSPF6_DUMP_ROUTE)
- zlog_info ("ROUTE: Table thaw: %s", route_table->name);
-
- assert (route_table->freeze == 1);
- route_table->freeze = 0;
-
- for (node = route_top (route_table->table); node;
- node = route_next (node))
- {
- rn = node->info;
- if (! rn)
- continue;
-
- for (linklist_head (rn->path_list, &pnode);
- ! linklist_end (&pnode);
- linklist_next (&pnode))
- {
- pn = pnode.data;
-
- for (linklist_head (pn->nexthop_list, &nnode);
- ! linklist_end (&nnode);
- linklist_next (&nnode))
- {
- nn = nnode.data;
-
- /* if the add and remove flag set without change flag,
- do nothing with this route */
- if (! CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_CHANGE) &&
- CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_ADD) &&
- CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_REMOVE))
- {
- nn->flag = 0;
- continue;
- }
-
- memset (&request, 0, sizeof (request));
- memcpy (&request.route, &rn->route, sizeof (rn->route));
- memcpy (&request.path, &pn->path, sizeof (pn->path));
- memcpy (&request.nexthop, &nn->nexthop, sizeof (nn->nexthop));
-
- if (CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_ADD) ||
- CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_CHANGE))
- ospf6_route_add (&request, route_table);
- else if (CHECK_FLAG (nn->flag, OSPF6_ROUTE_FLAG_REMOVE))
- ospf6_route_remove (&request, route_table);
- }
- }
- }
-}
/* VTY commands */
+void
+ospf6_route_show (struct vty *vty, struct ospf6_route *route)
+{
+ int i;
+ char destination[64], nexthop[64];
+ char duration[16], ifname[IFNAMSIZ];
+ struct timeval now, res;
+
+ gettimeofday (&now, (struct timezone *) NULL);
+ timersub (&now, &route->changed, &res);
+ timerstring (&res, duration, sizeof (duration));
+
+ /* destination */
+ if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
+ ospf6_linkstate_prefix2str (&route->prefix, destination,
+ sizeof (destination));
+ else if (route->type == OSPF6_DEST_TYPE_ROUTER)
+ inet_ntop (route->prefix.family, &route->prefix.u.prefix,
+ destination, sizeof (destination));
+ else
+ prefix2str (&route->prefix, destination, sizeof (destination));
+
+ /* nexthop */
+ inet_ntop (AF_INET6, &route->nexthop[0].address, nexthop,
+ sizeof (nexthop));
+ if (! if_indextoname (route->nexthop[0].ifindex, ifname))
+ snprintf (ifname, sizeof (ifname), "%d", route->nexthop[0].ifindex);
+
+ vty_out (vty, "%c%1s %2s %-30s %-25s %6s %s%s",
+ (ospf6_route_is_best (route) ? '*' : ' '),
+ OSPF6_DEST_TYPE_SUBSTR (route->type),
+ OSPF6_PATH_TYPE_SUBSTR (route->path.type),
+ destination, nexthop, ifname, duration, VTY_NEWLINE);
+
+ for (i = 1; ospf6_nexthop_is_set (&route->nexthop[i]) &&
+ i < OSPF6_MULTI_PATH_LIMIT; i++)
+ {
+ /* nexthop */
+ inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
+ sizeof (nexthop));
+ if (! if_indextoname (route->nexthop[i].ifindex, ifname))
+ snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
+
+ vty_out (vty, "%c%1s %2s %-30s %-25s %6s %s%s",
+ ' ', "", "", "", nexthop, ifname, "", VTY_NEWLINE);
+ }
+}
void
-ospf6_route_show (struct vty *vty, struct ospf6_route_node *rn)
+ospf6_route_show_detail (struct vty *vty, struct ospf6_route *route)
{
- struct linklist_node pnode;
- struct linklist_node nnode;
- struct ospf6_path_node *pn;
- struct ospf6_nexthop_node *nn;
-
+ char destination[64], nexthop[64], ifname[IFNAMSIZ];
+ char area_id[16], id[16], adv_router[16], capa[16], options[16];
struct timeval now, res;
char duration[16];
-
- u_int pc = 0;
- u_int nc = 0;
-#define HEAD (pc == 0 && nc == 0)
-
- char prefix[64], nexthop[64], ifname[IFNAMSIZ];
+ int i;
gettimeofday (&now, (struct timezone *) NULL);
/* destination */
- if (rn->route.prefix.family == AF_INET ||
- rn->route.prefix.family == AF_INET6)
- prefix2str (&rn->route.prefix, prefix, sizeof (prefix));
+ if (route->type == OSPF6_DEST_TYPE_LINKSTATE)
+ ospf6_linkstate_prefix2str (&route->prefix, destination,
+ sizeof (destination));
+ else if (route->type == OSPF6_DEST_TYPE_ROUTER)
+ inet_ntop (route->prefix.family, &route->prefix.u.prefix,
+ destination, sizeof (destination));
else
- prefix_ls2str (&rn->route.prefix, prefix, sizeof (prefix));
+ prefix2str (&route->prefix, destination, sizeof (destination));
+ vty_out (vty, "Destination: %s%s", destination, VTY_NEWLINE);
- for (linklist_head (rn->path_list, &pnode); ! linklist_end (&pnode);
- linklist_next (&pnode))
+ /* destination type */
+ vty_out (vty, "Destination type: %s%s",
+ OSPF6_DEST_TYPE_NAME (route->type),
+ VTY_NEWLINE);
+
+ /* Time */
+ timersub (&now, &route->installed, &res);
+ timerstring (&res, duration, sizeof (duration));
+ vty_out (vty, "Installed Time: %s ago%s", duration, VTY_NEWLINE);
+
+ timersub (&now, &route->changed, &res);
+ timerstring (&res, duration, sizeof (duration));
+ vty_out (vty, " Changed Time: %s ago%s", duration, VTY_NEWLINE);
+
+ /* Debugging info */
+ vty_out (vty, "Lock: %d Flags: %s%s%s%s%s", route->lock,
+ (CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
+ (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
+ (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
+ (CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"),
+ VTY_NEWLINE);
+ vty_out (vty, "Memory: prev: %p this: %p next: %p%s",
+ route->prev, route, route->next, VTY_NEWLINE);
+
+ /* Path section */
+
+ /* Area-ID */
+ inet_ntop (AF_INET, &route->path.area_id, area_id, sizeof (area_id));
+ vty_out (vty, "Associated Area: %s%s", area_id, VTY_NEWLINE);
+
+ /* Path type */
+ vty_out (vty, "Path Type: %s%s",
+ OSPF6_PATH_TYPE_NAME (route->path.type), VTY_NEWLINE);
+
+ /* LS Origin */
+ inet_ntop (AF_INET, &route->path.origin.id, id, sizeof (id));
+ inet_ntop (AF_INET, &route->path.origin.adv_router, adv_router,
+ sizeof (adv_router));
+ vty_out (vty, "LS Origin: %s Id: %s Adv: %s%s",
+ OSPF6_LSTYPE_NAME (route->path.origin.type),
+ id, adv_router, VTY_NEWLINE);
+
+ /* Options */
+ ospf6_options_printbuf (route->path.options, options, sizeof (options));
+ vty_out (vty, "Options: %s%s", options, VTY_NEWLINE);
+
+ /* Router Bits */
+ ospf6_capability_printbuf (route->path.router_bits, capa, sizeof (capa));
+ vty_out (vty, "Router Bits: %s%s", capa, VTY_NEWLINE);
+
+ /* Prefix Options */
+ vty_out (vty, "Prefix Options: xxx%s", VTY_NEWLINE);
+
+ /* Metrics */
+ vty_out (vty, "Metric Type: %d%s", route->path.metric_type,
+ VTY_NEWLINE);
+ vty_out (vty, "Metric: %d (%d)%s",
+ route->path.cost, route->path.cost_e2, VTY_NEWLINE);
+
+ /* Nexthops */
+ vty_out (vty, "Nexthop:%s", VTY_NEWLINE);
+ for (i = 0; ospf6_nexthop_is_set (&route->nexthop[i]) &&
+ i < OSPF6_MULTI_PATH_LIMIT; i++)
{
- pn = pnode.data;
-
- for (linklist_head (pn->nexthop_list, &nnode); ! linklist_end (&nnode);
- linklist_next (&nnode))
- {
- nn = nnode.data;
-
- inet_ntop (AF_INET6, &nn->nexthop.address, nexthop,
- sizeof (nexthop));
- if (! if_indextoname (nn->nexthop.ifindex, ifname))
- snprintf (ifname, sizeof (ifname), "%d", nn->nexthop.ifindex);
-
- ospf6_timeval_sub (&now, &nn->installed, &res);
- ospf6_timeval_string_summary (&res, duration, sizeof (duration));
-
- vty_out (vty, "%c%1s %2s %-30s %-25s %6s %s%s",
- (HEAD ? '*' : ' '),
- DTYPE_ABNAME (rn->route.type),
- PTYPE_ABNAME (pn->path.type),
- prefix, nexthop, ifname, duration, VTY_NEWLINE);
-
- nc++;
- }
- pc++;
+ /* nexthop */
+ inet_ntop (AF_INET6, &route->nexthop[i].address, nexthop,
+ sizeof (nexthop));
+ if (! if_indextoname (route->nexthop[i].ifindex, ifname))
+ snprintf (ifname, sizeof (ifname), "%d", route->nexthop[i].ifindex);
+ vty_out (vty, " %s %s%s", nexthop, ifname, VTY_NEWLINE);
}
+ vty_out (vty, "%s", VTY_NEWLINE);
}
void
-ospf6_route_show_detail (struct vty *vty, struct ospf6_route_node *rn)
+ospf6_route_show_table_summary (struct vty *vty,
+ struct ospf6_route_table *table)
{
- struct linklist_node pnode;
- struct linklist_node nnode;
- struct ospf6_path_node *pn;
- struct ospf6_nexthop_node *nn;
+ struct ospf6_route *route, *prev = NULL;
+ int i, pathtype[OSPF6_PATH_TYPE_MAX];
+ int number = 0;
+ int nhinval = 0, ecmp = 0;
+ int multipath = 0, destination = 0;
+ int desttype = 0, desttype_mismatch = 0;
- u_int pc = 0;
- u_int nc = 0;
+ for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
+ pathtype[i] = 0;
- char prefix[64], nexthop[64], ifname[IFNAMSIZ];
- char area_id[16], type[16], id[16], adv[16];
- char capa[64];
-
- /* destination */
- if (rn->route.prefix.family == AF_INET ||
- rn->route.prefix.family == AF_INET6)
- prefix2str (&rn->route.prefix, prefix, sizeof (prefix));
- else
- prefix_ls2str (&rn->route.prefix, prefix, sizeof (prefix));
-
- vty_out (vty, "%s%s%s", VTY_NEWLINE, prefix, VTY_NEWLINE);
- vty_out (vty, " Destination Type: %s%s",
- DTYPE_NAME (rn->route.type), VTY_NEWLINE);
-
- for (linklist_head (rn->path_list, &pnode); ! linklist_end (&pnode);
- linklist_next (&pnode))
+ for (route = ospf6_route_head (table); route;
+ route = ospf6_route_next (route))
{
- pn = pnode.data;
+ if (desttype == 0)
+ desttype = route->type;
+ else if (desttype != route->type)
+ desttype_mismatch++;
- inet_ntop (AF_INET, &pn->path.area_id, area_id, sizeof (area_id));
- ospf6_lsa_type_string (pn->path.origin.type, type, sizeof (type));
- inet_ntop (AF_INET, &pn->path.origin.id, id, sizeof (id));
- inet_ntop (AF_INET, &pn->path.origin.adv_router, adv, sizeof (adv));
- ospf6_options_string (pn->path.capability, capa, sizeof (capa));
+ if (prev == NULL || ! ospf6_route_is_same (prev, route))
+ destination++;
+ else
+ multipath++;
- vty_out (vty, " Path:%s", VTY_NEWLINE);
- vty_out (vty, " Associated Area: %s%s", area_id, VTY_NEWLINE);
- vty_out (vty, " LS Origin: %s ID: %s Adv: %s%s",
- type, id, adv, VTY_NEWLINE);
- vty_out (vty, " Path Type: %s%s",
- PTYPE_NAME (pn->path.type), VTY_NEWLINE);
- vty_out (vty, " Metric Type: %d%s",
- pn->path.metric_type, VTY_NEWLINE);
- vty_out (vty, " Cost: Type-1: %lu Type-2: %lu%s",
- (u_long) pn->path.cost, (u_long) pn->path.cost_e2,
- VTY_NEWLINE);
- vty_out (vty, " Router Bits: %s|%s|%s|%s%s",
- (CHECK_FLAG (pn->path.router_bits, OSPF6_ROUTER_LSA_BIT_W) ?
- "W" : "-"),
- (CHECK_FLAG (pn->path.router_bits, OSPF6_ROUTER_LSA_BIT_V) ?
- "V" : "-"),
- (CHECK_FLAG (pn->path.router_bits, OSPF6_ROUTER_LSA_BIT_E) ?
- "E" : "-"),
- (CHECK_FLAG (pn->path.router_bits, OSPF6_ROUTER_LSA_BIT_B) ?
- "B" : "-"), VTY_NEWLINE);
- vty_out (vty, " Optional Capabilities: %s%s", capa, VTY_NEWLINE);
- vty_out (vty, " Prefix Options: %s%s", "xxx", VTY_NEWLINE);
- vty_out (vty, " Next Hops:%s", VTY_NEWLINE);
+ if (! ospf6_nexthop_is_set (&route->nexthop[0]))
+ nhinval++;
+ else if (ospf6_nexthop_is_set (&route->nexthop[1]))
+ ecmp++;
- for (linklist_head (pn->nexthop_list, &nnode); ! linklist_end (&nnode);
- linklist_next (&nnode))
- {
- nn = nnode.data;
+ if (prev == NULL || ! ospf6_route_is_same (prev, route))
+ pathtype[route->path.type]++;
- inet_ntop (AF_INET6, &nn->nexthop.address, nexthop,
- sizeof (nexthop));
- if (! if_indextoname (nn->nexthop.ifindex, ifname))
- snprintf (ifname, sizeof (ifname), "%d", nn->nexthop.ifindex);
-
- vty_out (vty, " %c%s%%%s%s",
- (HEAD ? '*' : ' '), nexthop, ifname, VTY_NEWLINE);
-
- nc++;
- }
- pc++;
+ number++;
+ prev = route;
}
- vty_out (vty, "%s", VTY_NEWLINE);
+
+ assert (number == table->count);
+ vty_out (vty, "Number of Destination: %d (%d routes)%s",
+ destination, number, VTY_NEWLINE);
+ if (multipath)
+ vty_out (vty, " Number of Multi-path: %d%s", multipath, VTY_NEWLINE);
+ if (desttype_mismatch)
+ vty_out (vty, " Number of Different Dest-type: %d%s",
+ desttype_mismatch, VTY_NEWLINE);
+ if (ecmp)
+ vty_out (vty, " Number of Equal Cost Multi Path: %d%s",
+ ecmp, VTY_NEWLINE);
+ if (ecmp)
+ vty_out (vty, " Number of Invalid Nexthop: %d%s",
+ nhinval, VTY_NEWLINE);
+
+ for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++)
+ {
+ if (pathtype[i])
+ vty_out (vty, " Number of %s routes: %d%s",
+ OSPF6_PATH_TYPE_NAME (i), pathtype[i], VTY_NEWLINE);
+ }
}
int
ospf6_route_table_show (struct vty *vty, int argc, char **argv,
struct ospf6_route_table *table)
{
+ unsigned char flag = 0;
+#define MATCH 0x01
+#define DETAIL 0x02
+#define PREFIX 0x04
+#define SUMMARY 0x08
int i, ret;
- unsigned long ret_ul;
- char *endptr;
- struct prefix prefix;
- int detail = 0;
- int arg_ipv6 = 0;
- int arg_ipv4 = 0;
- int arg_digit = 0;
- struct prefix_ipv6 *p6 = (struct prefix_ipv6 *) &prefix;
- struct prefix_ls *pl = (struct prefix_ls *) &prefix;
- struct route_node *node;
-
- u_int route_count = 0;
- u_int path_count = 0;
- u_int route_redundant = 0;
+ struct prefix prefix, *p;
+ struct ospf6_route *route;
memset (&prefix, 0, sizeof (struct prefix));
for (i = 0; i < argc; i++)
{
+ /* set "detail" */
+ if (! strcmp (argv[i], "summary"))
+ {
+ SET_FLAG (flag, SUMMARY);
+ continue;
+ }
+
+ /* set "detail" */
if (! strcmp (argv[i], "detail"))
{
- detail++;
- break;
+ SET_FLAG (flag, DETAIL);
+ continue;
}
- if (! arg_ipv6 && ! arg_ipv4 && ! arg_digit)
+ /* set "match" */
+ if (! strcmp (argv[i], "match"))
{
-
- if ((ret = inet_pton (AF_INET6, argv[i], &p6->prefix)) == 1)
- {
- p6->family = AF_INET6;
- p6->prefixlen = 128;
- arg_ipv6++;
- continue;
- }
- else if ((ret = inet_pton (AF_INET, argv[i], &pl->adv_router)) == 1)
- {
- pl->family = AF_UNSPEC;
- pl->prefixlen = 64; /* xxx */
- arg_ipv4++;
- continue;
- }
- else
- {
- ret_ul = strtoul (argv[i], &endptr, 10);
- if (*endptr == '\0')
- {
- pl->adv_router.s_addr = htonl (ret_ul);
- pl->family = AF_UNSPEC;
- pl->prefixlen = 64; /* xxx */
- arg_digit++;
- continue;
- }
- else
- {
- vty_out (vty, "Malformed argument: %s%s",
- argv[i], VTY_NEWLINE);
- return CMD_SUCCESS;
- }
- }
+ SET_FLAG (flag, MATCH);
+ continue;
}
- if (arg_ipv4 || arg_digit)
+ if (prefix.family)
{
- if ((ret = inet_pton (AF_INET, argv[i], &pl->id)) == 1)
- {
- arg_ipv4++;
- }
- else
- {
- ret_ul = strtoul (argv[i], &endptr, 10);
- if (*endptr == '\0')
- {
- pl->id.s_addr = htonl (ret_ul);
- arg_digit++;
- }
- else
- {
- vty_out (vty, "Malformed argument: %s%s",
- argv[i], VTY_NEWLINE);
- return CMD_SUCCESS;
- }
- }
+ vty_out (vty, "Invalid argument: %s%s", argv[i], VTY_NEWLINE);
+ return CMD_SUCCESS;
}
+
+ ret = str2prefix (argv[i], &prefix);
+ if (ret != 1 || prefix.family != AF_INET6)
+ {
+ vty_out (vty, "Malformed argument: %s%s", argv[i], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ if (strchr (argv[i], '/'))
+ SET_FLAG (flag, PREFIX);
}
- if (arg_ipv4 || arg_ipv6 || arg_digit)
+ /* Give summary of this route table */
+ if (CHECK_FLAG (flag, SUMMARY))
{
- node = route_node_match (table->table, &prefix);
- if (node && node->info)
- ospf6_route_show_detail (vty, node->info);
+ ospf6_route_show_table_summary (vty, table);
return CMD_SUCCESS;
}
- if (! detail)
+ /* Give exact prefix-match route */
+ if (prefix.family && ! CHECK_FLAG (flag, MATCH))
{
- vty_out (vty, "%s%c%1s %2s %-30s %-25s %6s%s", VTY_NEWLINE,
- ' ', " ", " ", "Destination", "Gateway", "I/F", VTY_NEWLINE);
- vty_out (vty, "---------------------------%s", VTY_NEWLINE);
+ /* If exact address, give best matching route */
+ if (! CHECK_FLAG (flag, PREFIX))
+ route = ospf6_route_lookup_bestmatch (&prefix, table);
+ else
+ route = ospf6_route_lookup (&prefix, table);
+
+ if (route)
+ {
+ ospf6_route_lock (route);
+ p = &route->prefix;
+ }
+
+ while (route && ospf6_route_is_prefix (p, route))
+ {
+ /* Seaching an entry will always display details */
+ if (route)
+ ospf6_route_show_detail (vty, route);
+
+ route = ospf6_route_next (route);
+ }
+
+ return CMD_SUCCESS;
}
- for (node = route_top (table->table); node; node = route_next (node))
+ if (prefix.family == 0)
+ route = ospf6_route_head (table);
+ else
+ route = ospf6_route_match_head (&prefix, table);
+
+ while (route)
{
- struct ospf6_route_node *route = node->info;
-
- if (! route)
- continue;
-
- if (detail)
+ if (CHECK_FLAG (flag, DETAIL))
ospf6_route_show_detail (vty, route);
else
ospf6_route_show (vty, route);
- route_count++;
- path_count += route->path_list->count;
- if (route->path_list->count > 1)
- route_redundant++;
+ if (prefix.family == 0)
+ route = ospf6_route_next (route);
+ else
+ route = ospf6_route_match_next (&prefix, route);
}
- vty_out (vty, "===========%s", VTY_NEWLINE);
- vty_out (vty, "Route: %d Path: %d Redundant: %d%s",
- route_count, path_count, route_redundant, VTY_NEWLINE);
-
return CMD_SUCCESS;
}
+
+int
+ospf6_lsentry_table_show (struct vty *vty, int argc, char **argv,
+ struct ospf6_route_table *table)
+{
+ unsigned char flag = 0;
+#define MATCH 0x01
+#define DETAIL 0x02
+ int i, ret;
+ struct prefix adv_router, id, prefix;
+ struct ospf6_route *route;
+
+ memset (&adv_router, 0, sizeof (struct prefix));
+ memset (&id, 0, sizeof (struct prefix));
+
+ for (i = 0; i < argc; i++)
+ {
+ /* set "detail" */
+ if (! strcmp (argv[i], "detail"))
+ {
+ SET_FLAG (flag, DETAIL);
+ continue;
+ }
+
+ /* set "match" */
+ if (! strcmp (argv[i], "match"))
+ {
+ SET_FLAG (flag, MATCH);
+ continue;
+ }
+
+ if (adv_router.family && id.family)
+ {
+ vty_out (vty, "Invalid argument: %s%s", argv[i], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ if (adv_router.family == 0)
+ {
+ ret = str2prefix (argv[i], &adv_router);
+ if (ret != 1)
+ {
+ if (! strcmp (argv[i], "*"))
+ {
+ adv_router.family = AF_INET;
+ adv_router.prefixlen = 0;
+ ret = 1;
+ }
+ }
+ if (ret != 1)
+ {
+ vty_out (vty, "Invalid Router-ID: %s%s", argv[i], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+ }
+ else if (id.family == 0)
+ {
+ unsigned long val;
+ char *endptr;
+
+ ret = str2prefix (argv[i], &id);
+ if (ret != 1)
+ {
+ val = strtoul (argv[i], &endptr, 0);
+ if (val != ULONG_MAX && *endptr == '\0')
+ {
+ id.u.prefix4.s_addr = val;
+ ret = 1;
+ }
+ }
+
+ if (ret != 1)
+ {
+ vty_out (vty, "Invalid Link state ID: %s%s", argv[i],
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ }
+ }
+
+ /* Encode to linkstate prefix */
+ if (adv_router.family)
+ {
+ if (adv_router.prefixlen == 0 &&
+ id.family && id.prefixlen != IPV4_MAX_BITLEN)
+ {
+ vty_out (vty, "Specifying Link State ID by prefix is not allowed%s"
+ "when specifying Router-ID as wildcard%s",
+ VTY_NEWLINE, VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+ else if (adv_router.prefixlen != 0 &&
+ adv_router.prefixlen != IPV4_MAX_BITLEN && id.family)
+ {
+ vty_out (vty, "Specifying Link State ID is not allowed%s"
+ "when specifying Router-ID by prefix%s",
+ VTY_NEWLINE, VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ if (adv_router.prefixlen == 0)
+ ospf6_linkstate_prefix (0, id.u.prefix4.s_addr, &prefix);
+ else if (adv_router.prefixlen != IPV4_MAX_BITLEN)
+ {
+ ospf6_linkstate_prefix (adv_router.u.prefix4.s_addr, 0, &prefix);
+ prefix.prefixlen = adv_router.prefixlen;
+ SET_FLAG (flag, MATCH);
+ }
+ else
+ {
+ ospf6_linkstate_prefix (adv_router.u.prefix4.s_addr,
+ id.u.prefix4.s_addr, &prefix);
+ prefix.prefixlen = adv_router.prefixlen + id.prefixlen;
+ if (prefix.prefixlen != 64)
+ SET_FLAG (flag, MATCH);
+ }
+ }
+
+ /* give exact match entry */
+ if (adv_router.family && adv_router.prefixlen == IPV4_MAX_BITLEN &&
+ id.family && id.prefixlen == IPV4_MAX_BITLEN)
+ {
+ route = ospf6_route_lookup (&prefix, table);
+ if (route)
+ ospf6_route_show_detail (vty, route);
+ return CMD_SUCCESS;
+ }
+
+ if (CHECK_FLAG (flag, MATCH))
+ route = ospf6_route_match_head (&prefix, table);
+ else
+ route = ospf6_route_head (table);
+
+ while (route)
+ {
+ if (! adv_router.family ||
+ (CHECK_FLAG (flag, MATCH) &&
+ prefix_match (&prefix, &route->prefix)) ||
+ (adv_router.prefixlen == 0 && id.family &&
+ ospf6_linkstate_prefix_id (&prefix) ==
+ ospf6_linkstate_prefix_id (&route->prefix)))
+ {
+ if (CHECK_FLAG (flag, DETAIL))
+ ospf6_route_show_detail (vty, route);
+ else
+ ospf6_route_show (vty, route);
+ }
+
+ if (CHECK_FLAG (flag, MATCH))
+ route = ospf6_route_match_next (&prefix, route);
+ else
+ route = ospf6_route_next (route);
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (debug_ospf6_route,
+ debug_ospf6_route_cmd,
+ "debug ospf6 route (table|intra-area|inter-area)",
+ DEBUG_STR
+ OSPF6_STR
+ "Debug route table calculation\n"
+ "Debug detail\n"
+ "Debug intra-area route calculation\n"
+ "Debug inter-area route calculation\n"
+ )
+{
+ unsigned char level = 0;
+
+ if (! strncmp (argv[0], "table", 5))
+ level = OSPF6_DEBUG_ROUTE_TABLE;
+ else if (! strncmp (argv[0], "intra", 5))
+ level = OSPF6_DEBUG_ROUTE_INTRA;
+ else if (! strncmp (argv[0], "inter", 5))
+ level = OSPF6_DEBUG_ROUTE_INTER;
+ OSPF6_DEBUG_ROUTE_ON (level);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_ospf6_route,
+ no_debug_ospf6_route_cmd,
+ "no debug ospf6 route (table|intra-area|inter-area)",
+ NO_STR
+ DEBUG_STR
+ OSPF6_STR
+ "Debug route table calculation\n"
+ "Debug intra-area route calculation\n")
+{
+ unsigned char level = 0;
+
+ if (! strncmp (argv[0], "table", 5))
+ level = OSPF6_DEBUG_ROUTE_TABLE;
+ else if (! strncmp (argv[0], "intra", 5))
+ level = OSPF6_DEBUG_ROUTE_INTRA;
+ else if (! strncmp (argv[0], "inter", 5))
+ level = OSPF6_DEBUG_ROUTE_INTER;
+ OSPF6_DEBUG_ROUTE_OFF (level);
+ return CMD_SUCCESS;
+}
+
+int
+config_write_ospf6_debug_route (struct vty *vty)
+{
+ if (IS_OSPF6_DEBUG_ROUTE (TABLE))
+ vty_out (vty, "debug ospf6 route table%s", VTY_NEWLINE);
+ if (IS_OSPF6_DEBUG_ROUTE (INTRA))
+ vty_out (vty, "debug ospf6 route intra-area%s", VTY_NEWLINE);
+ if (IS_OSPF6_DEBUG_ROUTE (INTER))
+ vty_out (vty, "debug ospf6 route inter-area%s", VTY_NEWLINE);
+ return 0;
+}
+
+void
+install_element_ospf6_debug_route ()
+{
+ install_element (ENABLE_NODE, &debug_ospf6_route_cmd);
+ install_element (ENABLE_NODE, &no_debug_ospf6_route_cmd);
+ install_element (CONFIG_NODE, &debug_ospf6_route_cmd);
+ install_element (CONFIG_NODE, &no_debug_ospf6_route_cmd);
+}
+
+
+
diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h
index 71b2562..834774c 100644
--- a/ospf6d/ospf6_route.h
+++ b/ospf6d/ospf6_route.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -22,40 +22,49 @@
#ifndef OSPF6_ROUTE_H
#define OSPF6_ROUTE_H
-#include "ospf6_hook.h"
-#include "ospf6_linklist.h"
+#define OSPF6_MULTI_PATH_LIMIT 4
-struct ospf6_route_table
+/* Debug option */
+extern unsigned char conf_debug_ospf6_route;
+#define OSPF6_DEBUG_ROUTE_TABLE 0x01
+#define OSPF6_DEBUG_ROUTE_INTRA 0x02
+#define OSPF6_DEBUG_ROUTE_INTER 0x04
+#define OSPF6_DEBUG_ROUTE_ON(level) \
+ (conf_debug_ospf6_route |= (level))
+#define OSPF6_DEBUG_ROUTE_OFF(level) \
+ (conf_debug_ospf6_route &= ~(level))
+#define IS_OSPF6_DEBUG_ROUTE(e) \
+ (conf_debug_ospf6_route & OSPF6_DEBUG_ROUTE_ ## e)
+
+/* Nexthop */
+struct ospf6_nexthop
{
- char name[128];
+ /* Interface index */
+ unsigned int ifindex;
- int freeze;
-
- /* radix tree */
- struct route_table *table;
-
- /* list of hooks */
- struct linklist *hook_list[3];
- void (*hook_add) (void *);
- void (*hook_change) (void *);
- void (*hook_remove) (void *);
-
- u_int32_t route_id;
+ /* IP address, if any */
+ struct in6_addr address;
};
-
-
-struct ospf6_route
-{
- /* Destination ID */
- struct prefix prefix;
-
- /* Destination Type */
- u_char type;
-};
+#define ospf6_nexthop_is_set(x) \
+ ((x)->ifindex || ! IN6_IS_ADDR_UNSPECIFIED (&(x)->address))
+#define ospf6_nexthop_is_same(a,b) \
+ ((a)->ifindex == (b)->ifindex && \
+ IN6_ARE_ADDR_EQUAL (&(a)->address, &(b)->address))
+#define ospf6_nexthop_clear(x) \
+ do { \
+ (x)->ifindex = 0; \
+ memset (&(x)->address, 0, sizeof (struct in6_addr)); \
+ } while (0)
+#define ospf6_nexthop_copy(a, b) \
+ do { \
+ (a)->ifindex = (b)->ifindex; \
+ memcpy (&(a)->address, &(b)->address, \
+ sizeof (struct in6_addr)); \
+ } while (0)
/* Path */
-struct ls_origin
+struct ospf6_ls_origin
{
u_int16_t type;
u_int32_t id;
@@ -65,13 +74,13 @@
struct ospf6_path
{
/* Link State Origin */
- struct ls_origin origin;
+ struct ospf6_ls_origin origin;
/* Router bits */
u_char router_bits;
/* Optional Capabilities */
- u_char capability[3];
+ u_char options[3];
/* Prefix Options */
u_char prefix_options;
@@ -88,122 +97,165 @@
u_int32_t cost_e2;
};
-/* Nexthop */
-struct ospf6_nexthop
+#define OSPF6_PATH_TYPE_NONE 0
+#define OSPF6_PATH_TYPE_INTRA 1
+#define OSPF6_PATH_TYPE_INTER 2
+#define OSPF6_PATH_TYPE_EXTERNAL1 3
+#define OSPF6_PATH_TYPE_EXTERNAL2 4
+#define OSPF6_PATH_TYPE_MAX 5
+
+#include "prefix.h"
+#include "table.h"
+
+struct ospf6_route
{
- /* Interface index */
- unsigned int ifindex;
+ struct route_node *rnode;
- /* IP address, if any */
- struct in6_addr address;
-};
+ struct ospf6_route *prev;
+ struct ospf6_route *next;
-struct ospf6_route_node
-{
- struct ospf6_route_table *table;
- int count;
- u_int32_t route_id;
+ unsigned int lock;
- struct route_node *route_node;
- struct ospf6_route route;
- struct linklist *path_list;
-};
+ /* Destination Type */
+ u_char type;
-struct ospf6_path_node
-{
- struct ospf6_route_node *route_node;
- struct ospf6_path path;
- struct linklist *nexthop_list;
-};
+ /* Destination ID */
+ struct prefix prefix;
-struct ospf6_nexthop_node
-{
- int flag;
+ /* Time */
struct timeval installed;
+ struct timeval changed;
- struct ospf6_path_node *path_node;
- struct ospf6_nexthop nexthop;
-};
+ /* flag */
+ u_char flag;
-struct ospf6_route_req
-{
- struct ospf6_route_table *table;
- struct route_node *route_node;
- struct linklist_node path_lnode;
- struct linklist_node nexthop_lnode;
- u_int32_t route_id;
+ /* path */
+ struct ospf6_path path;
- int count;
- struct ospf6_route route;
- struct ospf6_path path;
- struct ospf6_nexthop nexthop;
+ /* nexthop */
+ struct ospf6_nexthop nexthop[OSPF6_MULTI_PATH_LIMIT];
+
+ /* route option */
+ void *route_option;
};
#define OSPF6_DEST_TYPE_NONE 0
#define OSPF6_DEST_TYPE_ROUTER 1
#define OSPF6_DEST_TYPE_NETWORK 2
#define OSPF6_DEST_TYPE_DISCARD 3
-#define OSPF6_DEST_TYPE_MAX 4
+#define OSPF6_DEST_TYPE_LINKSTATE 4
+#define OSPF6_DEST_TYPE_MAX 5
-#define OSPF6_PATH_TYPE_NONE 0
-#define OSPF6_PATH_TYPE_INTRA 1
-#define OSPF6_PATH_TYPE_INTER 2
-#define OSPF6_PATH_TYPE_EXTERNAL1 3
-#define OSPF6_PATH_TYPE_EXTERNAL2 4
-#define OSPF6_PATH_TYPE_ZOFFSET 5
-#define OSPF6_PATH_TYPE_ZSYSTEM (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_SYSTEM)
-#define OSPF6_PATH_TYPE_ZKERNEL (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_KERNEL)
-#define OSPF6_PATH_TYPE_ZCONNECT (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_CONNECT)
-#define OSPF6_PATH_TYPE_ZSTATIC (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_STATIC)
-#define OSPF6_PATH_TYPE_ZRIP (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_RIP)
-#define OSPF6_PATH_TYPE_ZRIPNG (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_RIPNG)
-#define OSPF6_PATH_TYPE_ZOSPF (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_OSPF)
-#define OSPF6_PATH_TYPE_ZOSPF6 (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_OSPF6)
-#define OSPF6_PATH_TYPE_ZBGP (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_BGP)
-#define OSPF6_PATH_TYPE_MAX (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_MAX)
+#define OSPF6_ROUTE_CHANGE 0x01
+#define OSPF6_ROUTE_ADD 0x02
+#define OSPF6_ROUTE_REMOVE 0x04
+#define OSPF6_ROUTE_BEST 0x08
-#define OSPF6_ROUTE_FLAG_ROUTE_CHANGE 0x01
-#define OSPF6_ROUTE_FLAG_PATH_CHANGE 0x02
-#define OSPF6_ROUTE_FLAG_ADD 0x04
-#define OSPF6_ROUTE_FLAG_REMOVE 0x08
-#define OSPF6_ROUTE_FLAG_CHANGE 0x10
+struct ospf6_route_table
+{
+ /* patricia tree */
+ struct route_table *table;
-int ospf6_route_lookup (struct ospf6_route_req *request,
- struct prefix *prefix,
- struct ospf6_route_table *table);
-void ospf6_route_head (struct ospf6_route_req *request,
- struct ospf6_route_table *table);
-int ospf6_route_end (struct ospf6_route_req *request);
-void ospf6_route_next (struct ospf6_route_req *request);
+ u_int32_t count;
-void ospf6_route_add (struct ospf6_route_req *, struct ospf6_route_table *);
-void ospf6_route_remove (struct ospf6_route_req *, struct ospf6_route_table *);
+ /* hooks */
+ void (*hook_add) (struct ospf6_route *);
+ void (*hook_change) (struct ospf6_route *);
+ void (*hook_remove) (struct ospf6_route *);
+};
+
+extern char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX];
+extern char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX];
+#define OSPF6_DEST_TYPE_NAME(x) \
+ (0 < (x) && (x) < OSPF6_DEST_TYPE_MAX ? \
+ ospf6_dest_type_str[(x)] : ospf6_dest_type_str[0])
+#define OSPF6_DEST_TYPE_SUBSTR(x) \
+ (0 < (x) && (x) < OSPF6_DEST_TYPE_MAX ? \
+ ospf6_dest_type_substr[(x)] : ospf6_dest_type_substr[0])
+
+extern char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX];
+extern char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX];
+#define OSPF6_PATH_TYPE_NAME(x) \
+ (0 < (x) && (x) < OSPF6_PATH_TYPE_MAX ? \
+ ospf6_path_type_str[(x)] : ospf6_path_type_str[0])
+#define OSPF6_PATH_TYPE_SUBSTR(x) \
+ (0 < (x) && (x) < OSPF6_PATH_TYPE_MAX ? \
+ ospf6_path_type_substr[(x)] : ospf6_path_type_substr[0])
+
+#define OSPF6_ROUTE_ADDRESS_STR "Display the route bestmatches the address\n"
+#define OSPF6_ROUTE_PREFIX_STR "Display the route\n"
+#define OSPF6_ROUTE_MATCH_STR "Display the route matches the prefix\n"
+
+#define ospf6_route_is_prefix(p, r) \
+ (memcmp (p, &(r)->prefix, sizeof (struct prefix)) == 0)
+#define ospf6_route_is_same(ra, rb) \
+ (prefix_same (&(ra)->prefix, &(rb)->prefix))
+#define ospf6_route_is_same_origin(ra, rb) \
+ ((ra)->path.area_id == (rb)->path.area_id && \
+ memcmp (&(ra)->path.origin, &(rb)->path.origin, \
+ sizeof (struct ospf6_ls_origin)) == 0)
+#define ospf6_route_is_identical(ra, rb) \
+ ((ra)->type == (rb)->type && \
+ memcmp (&(ra)->prefix, &(rb)->prefix, sizeof (struct prefix)) == 0 && \
+ memcmp (&(ra)->path, &(rb)->path, sizeof (struct ospf6_path)) == 0 && \
+ memcmp (&(ra)->nexthop, &(rb)->nexthop, \
+ sizeof (struct ospf6_nexthop) * OSPF6_MULTI_PATH_LIMIT) == 0)
+#define ospf6_route_is_best(r) (CHECK_FLAG ((r)->flag, OSPF6_ROUTE_BEST))
+
+#define ospf6_linkstate_prefix_adv_router(x) \
+ (*(u_int32_t *)(&(x)->u.prefix6.s6_addr[0]))
+#define ospf6_linkstate_prefix_id(x) \
+ (*(u_int32_t *)(&(x)->u.prefix6.s6_addr[4]))
+
+/* Function prototype */
+void ospf6_linkstate_prefix (u_int32_t adv_router, u_int32_t id,
+ struct prefix *prefix);
+void ospf6_linkstate_prefix2str (struct prefix *prefix, char *buf, int size);
+
+struct ospf6_route *ospf6_route_create ();
+void ospf6_route_delete (struct ospf6_route *);
+struct ospf6_route *ospf6_route_copy (struct ospf6_route *route);
+
+void ospf6_route_lock (struct ospf6_route *route);
+void ospf6_route_unlock (struct ospf6_route *route);
+
+struct ospf6_route *
+ospf6_route_lookup (struct prefix *prefix,
+ struct ospf6_route_table *table);
+struct ospf6_route *
+ospf6_route_lookup_identical (struct ospf6_route *route,
+ struct ospf6_route_table *table);
+struct ospf6_route *
+ospf6_route_lookup_bestmatch (struct prefix *prefix,
+ struct ospf6_route_table *table);
+
+struct ospf6_route *
+ospf6_route_add (struct ospf6_route *route, struct ospf6_route_table *table);
+void
+ospf6_route_remove (struct ospf6_route *route, struct ospf6_route_table *table);
+
+struct ospf6_route *ospf6_route_head (struct ospf6_route_table *table);
+struct ospf6_route *ospf6_route_next (struct ospf6_route *route);
+struct ospf6_route *ospf6_route_best_next (struct ospf6_route *route);
+
+struct ospf6_route *ospf6_route_match_head (struct prefix *prefix,
+ struct ospf6_route_table *table);
+struct ospf6_route *ospf6_route_match_next (struct prefix *prefix,
+ struct ospf6_route *route);
+
void ospf6_route_remove_all (struct ospf6_route_table *);
-
struct ospf6_route_table *ospf6_route_table_create ();
void ospf6_route_table_delete (struct ospf6_route_table *);
-
-void ospf6_route_table_freeze (struct ospf6_route_table *);
-void ospf6_route_table_thaw (struct ospf6_route_table *);
-
-void ospf6_route_log_request (char *what, char *where,
- struct ospf6_route_req *request);
-
-void
-ospf6_route_hook_register (void (*add) (struct ospf6_route_req *),
- void (*change) (struct ospf6_route_req *),
- void (*remove) (struct ospf6_route_req *),
- struct ospf6_route_table *table);
-void
-ospf6_route_hook_unregister (void (*add) (struct ospf6_route_req *),
- void (*change) (struct ospf6_route_req *),
- void (*remove) (struct ospf6_route_req *),
- struct ospf6_route_table *table);
-
-void ospf6_route_init ();
+void ospf6_route_dump (struct ospf6_route_table *table);
int ospf6_route_table_show (struct vty *, int, char **,
struct ospf6_route_table *);
+int ospf6_lsentry_table_show (struct vty *, int, char **,
+ struct ospf6_route_table *);
+
+int config_write_ospf6_debug_route (struct vty *vty);
+void install_element_ospf6_debug_route ();
+void ospf6_route_init ();
#endif /* OSPF6_ROUTE_H */
diff --git a/ospf6d/ospf6_routemap.c b/ospf6d/ospf6_routemap.c
deleted file mode 100644
index f617e91..0000000
--- a/ospf6d/ospf6_routemap.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- * OSPFv3 Route-Map
- * Copyright (C) 1999 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 "log.h"
-#include "memory.h"
-#include "linklist.h"
-#include "prefix.h"
-#include "command.h"
-#include "vty.h"
-#include "routemap.h"
-#include "table.h"
-#include "plist.h"
-
-#include "ospf6_route.h"
-#include "ospf6_prefix.h"
-#include "ospf6_lsa.h"
-#include "ospf6_asbr.h"
-
-route_map_result_t
-ospf6_routemap_rule_match_address_prefixlist (void *rule,
- struct prefix *prefix,
- route_map_object_t type,
- void *object)
-{
- struct prefix_list *plist;
-
- if (type != RMAP_OSPF6)
- return RMAP_NOMATCH;
-
- plist = prefix_list_lookup (AFI_IP6, (char *) rule);
-
- if (plist == NULL)
- return RMAP_NOMATCH;
-
- return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
- RMAP_NOMATCH : RMAP_MATCH);
-}
-
-void *
-ospf6_routemap_rule_match_address_prefixlist_compile (char *arg)
-{
- return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
-}
-
-void
-ospf6_routemap_rule_match_address_prefixlist_free (void *rule)
-{
- XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
-}
-
-struct route_map_rule_cmd
-ospf6_routemap_rule_match_address_prefixlist_cmd =
-{
- "ipv6 address prefix-list",
- ospf6_routemap_rule_match_address_prefixlist,
- ospf6_routemap_rule_match_address_prefixlist_compile,
- ospf6_routemap_rule_match_address_prefixlist_free,
-};
-
-route_map_result_t
-ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
- route_map_object_t type, void *object)
-{
- char *metric_type = rule;
- struct ospf6_external_info *info = object;
-
- if (type != RMAP_OSPF6)
- return RMAP_OKAY;
-
- if (strcmp (metric_type, "type-2") == 0)
- info->metric_type = 2;
- else
- info->metric_type = 1;
-
- return RMAP_OKAY;
-}
-
-void *
-ospf6_routemap_rule_set_metric_type_compile (char *arg)
-{
- return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
-}
-
-void
-ospf6_routemap_rule_set_metric_type_free (void *rule)
-{
- XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
-}
-
-struct route_map_rule_cmd
-ospf6_routemap_rule_set_metric_type_cmd =
-{
- "metric-type",
- ospf6_routemap_rule_set_metric_type,
- ospf6_routemap_rule_set_metric_type_compile,
- ospf6_routemap_rule_set_metric_type_free,
-};
-
-route_map_result_t
-ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix,
- route_map_object_t type, void *object)
-{
- char *metric = rule;
- struct ospf6_external_info *info = object;
-
- if (type != RMAP_OSPF6)
- return RMAP_OKAY;
-
- info->metric = atoi (metric);
- return RMAP_OKAY;
-}
-
-void *
-ospf6_routemap_rule_set_metric_compile (char *arg)
-{
- return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
-}
-
-void
-ospf6_routemap_rule_set_metric_free (void *rule)
-{
- XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
-}
-
-struct route_map_rule_cmd
-ospf6_routemap_rule_set_metric_cmd =
-{
- "metric",
- ospf6_routemap_rule_set_metric,
- ospf6_routemap_rule_set_metric_compile,
- ospf6_routemap_rule_set_metric_free,
-};
-
-route_map_result_t
-ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix,
- route_map_object_t type, void *object)
-{
- char *forwarding = rule;
- struct ospf6_external_info *info = object;
-
- if (type != RMAP_OSPF6)
- return RMAP_OKAY;
-
- if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1)
- {
- memset (&info->forwarding, 0, sizeof (struct in6_addr));
- return RMAP_ERROR;
- }
-
- return RMAP_OKAY;
-}
-
-void *
-ospf6_routemap_rule_set_forwarding_compile (char *arg)
-{
- return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
-}
-
-void
-ospf6_routemap_rule_set_forwarding_free (void *rule)
-{
- XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
-}
-
-struct route_map_rule_cmd
-ospf6_routemap_rule_set_forwarding_cmd =
-{
- "forwarding-address",
- ospf6_routemap_rule_set_forwarding,
- ospf6_routemap_rule_set_forwarding_compile,
- ospf6_routemap_rule_set_forwarding_free,
-};
-
-int
-route_map_command_status (struct vty *vty, int ret)
-{
- if (! ret)
- return CMD_SUCCESS;
-
- switch (ret)
- {
- case RMAP_RULE_MISSING:
- vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
- break;
- case RMAP_COMPILE_ERROR:
- vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
- break;
- default:
- vty_out (vty, "route-map add set failed.%s", VTY_NEWLINE);
- break;
- }
- return CMD_WARNING;
-}
-
-/* add "match address" */
-DEFUN (match_ipv6_address_prefix_list,
- match_ipv6_address_prefix_list_cmd,
- "match ipv6 address prefix-list WORD",
- MATCH_STR
- IPV6_STR
- "Match address of route\n"
- "Match entries of prefix-lists\n"
- "IP prefix-list name\n")
-{
- int ret = route_map_add_match ((struct route_map_index *) vty->index,
- "ipv6 address prefix-list", argv[0]);
- return route_map_command_status (vty, ret);
-}
-
-/* delete "match address" */
-DEFUN (no_match_ipv6_address_prefix_list,
- no_match_ipv6_address_prefix_list_cmd,
- "no match ipv6 address prefix-list WORD",
- NO_STR
- MATCH_STR
- IPV6_STR
- "Match address of route\n"
- "Match entries of prefix-lists\n"
- "IP prefix-list name\n")
-{
- int ret = route_map_delete_match ((struct route_map_index *) vty->index,
- "ipv6 address prefix-list", argv[0]);
- return route_map_command_status (vty, ret);
-}
-
-/* add "set metric-type" */
-DEFUN (set_metric_type,
- set_metric_type_cmd,
- "set metric-type (type-1|type-2)",
- SET_STR
- "Type of metric for destination routing protocol\n"
- "OSPF[6] external type 1 metric\n"
- "OSPF[6] external type 2 metric\n")
-{
- int ret = route_map_add_set ((struct route_map_index *) vty->index,
- "metric-type", argv[0]);
- return route_map_command_status (vty, ret);
-}
-
-/* delete "set metric-type" */
-DEFUN (no_set_metric_type,
- no_set_metric_type_cmd,
- "no set metric-type",
- NO_STR
- SET_STR
- "Type of metric for destination routing protocol\n")
-{
- int ret;
- if (argc == 0)
- ret = route_map_delete_set ((struct route_map_index *) vty->index,
- "metric-type", NULL);
- else
- ret = route_map_delete_set ((struct route_map_index *) vty->index,
- "metric-type", argv[0]);
- return route_map_command_status (vty, ret);
-}
-
-ALIAS (no_set_metric_type,
- no_set_metric_type_val_cmd,
- "no set metric-type (type-1|type-2)",
- NO_STR
- SET_STR
- "Type of metric for destination routing protocol\n"
- "OSPF[6] external type 1 metric\n"
- "OSPF[6] external type 2 metric\n")
-
-/* add "set metric" */
-DEFUN (set_metric,
- set_metric_cmd,
- "set metric <0-4294967295>",
- SET_STR
- "Metric value for destination routing protocol\n"
- "Metric value\n")
-{
- int ret = route_map_add_set ((struct route_map_index *) vty->index,
- "metric", argv[0]);
- return route_map_command_status (vty, ret);
-}
-
-/* delete "set metric" */
-DEFUN (no_set_metric,
- no_set_metric_cmd,
- "no set metric",
- NO_STR
- SET_STR
- "Metric value for destination routing protocol\n")
-{
- int ret;
- if (argc == 0)
- ret = route_map_delete_set ((struct route_map_index *) vty->index,
- "metric", NULL);
- else
- ret = route_map_delete_set ((struct route_map_index *) vty->index,
- "metric", argv[0]);
- return route_map_command_status (vty, ret);
-}
-
-ALIAS (no_set_metric,
- no_set_metric_val_cmd,
- "no set metric <0-4294967295>",
- NO_STR
- SET_STR
- "Metric value for destination routing protocol\n"
- "Metric value\n")
-
-/* add "set forwarding-address" */
-DEFUN (ospf6_routemap_set_forwarding,
- ospf6_routemap_set_forwarding_cmd,
- "set forwarding-address X:X::X:X",
- "Set value\n"
- "Forwarding Address\n"
- "IPv6 Address\n")
-{
- int ret = route_map_add_set ((struct route_map_index *) vty->index,
- "forwarding-address", argv[0]);
- return route_map_command_status (vty, ret);
-}
-
-/* delete "set forwarding-address" */
-DEFUN (ospf6_routemap_no_set_forwarding,
- ospf6_routemap_no_set_forwarding_cmd,
- "no set forwarding-address X:X::X:X",
- NO_STR
- "Set value\n"
- "Forwarding Address\n"
- "IPv6 Address\n")
-{
- int ret = route_map_delete_set ((struct route_map_index *) vty->index,
- "forwarding-address", argv[0]);
- return route_map_command_status (vty, ret);
-}
-
-void
-ospf6_routemap_init ()
-{
- route_map_init ();
- route_map_init_vty ();
- route_map_add_hook (ospf6_asbr_routemap_update);
- route_map_delete_hook (ospf6_asbr_routemap_update);
-
- route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
- route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
- route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
- route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
-
- /* Match address prefix-list */
- install_element (RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
- install_element (RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
-
- /* ASE Metric Type (e.g. Type-1/Type-2) */
- install_element (RMAP_NODE, &set_metric_type_cmd);
- install_element (RMAP_NODE, &no_set_metric_type_cmd);
- install_element (RMAP_NODE, &no_set_metric_type_val_cmd);
-
- /* ASE Metric */
- install_element (RMAP_NODE, &set_metric_cmd);
- install_element (RMAP_NODE, &no_set_metric_cmd);
- install_element (RMAP_NODE, &no_set_metric_val_cmd);
-
- /* ASE Metric */
- install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
- install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
-}
-
diff --git a/ospf6d/ospf6_routemap.h b/ospf6d/ospf6_routemap.h
deleted file mode 100644
index c68e0ff..0000000
--- a/ospf6d/ospf6_routemap.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * OSPFv3 Route-Map
- * Copyright (C) 2000 Kunihiro Ishiguro
- *
- * 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.
- */
-
-#ifndef OSPF6_ROUTEMAP_H
-
-void ospf6_routemap_init ();
-
-#endif /* OSPF6_ROUTEMAP_H */
diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c
index fd7fc77..10b73b8 100644
--- a/ospf6d/ospf6_spf.c
+++ b/ospf6d/ospf6_spf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -18,1437 +18,627 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
/* Shortest Path First calculation for OSPFv3 */
-#include "ospf6d.h"
+#include <zebra.h>
-#include "linklist.h"
+#include "log.h"
+#include "memory.h"
+#include "command.h"
+#include "vty.h"
#include "prefix.h"
-#include "table.h"
+#include "pqueue.h"
+#include "linklist.h"
+#include "thread.h"
-#include "ospf6_proto.h"
+#include "ospf6d.h"
#include "ospf6_lsa.h"
#include "ospf6_lsdb.h"
#include "ospf6_route.h"
-#include "ospf6_spf.h"
-#include "ospf6_neighbor.h"
-#include "ospf6_interface.h"
#include "ospf6_area.h"
+#include "ospf6_spf.h"
+#include "ospf6_intra.h"
+#include "ospf6_interface.h"
-#include "ospf6_bintree.h"
-#include "ospf6_linklist.h"
-
-struct bintree *_candidate_list;
-struct linklist *nexthop_list;
-
-struct ospf6_spf_candidate_node
-{
- u_int32_t cost;
- struct linklist *list;
-};
+unsigned char conf_debug_ospf6_spf = 0;
int
-ospf6_spf_candidate_node_cmp (void *a, void *b)
+ospf6_vertex_cmp (void *a, void *b)
{
- struct ospf6_spf_candidate_node *ca = a;
- struct ospf6_spf_candidate_node *cb = b;
- return ca->cost - cb->cost;
+ struct ospf6_vertex *va = (struct ospf6_vertex *) a;
+ struct ospf6_vertex *vb = (struct ospf6_vertex *) b;
+
+ /* ascending order */
+ return (va->cost - vb->cost);
}
int
-ospf6_spf_vertex_cmp (void *a, void *b)
+ospf6_vertex_id_cmp (void *a, void *b)
{
- return 1;
-}
+ struct ospf6_vertex *va = (struct ospf6_vertex *) a;
+ struct ospf6_vertex *vb = (struct ospf6_vertex *) b;
+ int ret = 0;
-void
-ospf6_spf_candidate_node_print (int indent_num, void *node)
-{
- struct ospf6_spf_candidate_node *cn = node;
- char format[256];
+ ret = ntohl (ospf6_linkstate_prefix_adv_router (&va->vertex_id)) -
+ ntohl (ospf6_linkstate_prefix_adv_router (&vb->vertex_id));
+ if (ret)
+ return ret;
- snprintf (format, sizeof (format), "%%%ds %%d (num: %%d)",
- indent_num * 2 + 1);
- zlog_info (format, " ", cn->cost, cn->list->count);
-}
-
-void
-ospf6_spf_candidate_init ()
-{
- _candidate_list = bintree_create ();
- _candidate_list->cmp = ospf6_spf_candidate_node_cmp;
-}
-
-u_int32_t
-ospf6_spf_candidate_count ()
-{
- u_int32_t count = 0;
- struct bintree_node node;
- struct ospf6_spf_candidate_node *cnode;
-
- for (bintree_head (_candidate_list, &node); ! bintree_end (&node);
- bintree_next (&node))
- {
- cnode = node.data;
- count += cnode->list->count;
- }
-
- return count;
-}
-
-void
-ospf6_spf_candidate_print ()
-{
- zlog_info ("---------------------------");
- bintree_print (ospf6_spf_candidate_node_print, _candidate_list);
- zlog_info ("---------------------------");
-}
-
-void
-ospf6_spf_candidate_enqueue (struct ospf6_vertex *v)
-{
- struct ospf6_spf_candidate_node req, *node;
-
- memset (&req, 0, sizeof (req));
- req.cost = v->distance;
- node = bintree_lookup (&req, _candidate_list);
-
- if (node == NULL)
- {
- node = malloc (sizeof (struct ospf6_spf_candidate_node));
- node->cost = v->distance;
- node->list = linklist_create ();
- node->list->cmp = ospf6_spf_vertex_cmp;
- bintree_add (node, _candidate_list);
- }
-
- linklist_add (v, node->list);
-
-#if 0
- if (IS_OSPF6_DUMP_SPF)
- ospf6_spf_candidate_print ();
-#endif
-}
-
-struct ospf6_vertex *
-ospf6_spf_candidate_dequeue ()
-{
- struct ospf6_spf_candidate_node *node;
- struct linklist_node lnode;
- struct ospf6_vertex *ret;
-
- node = bintree_lookup_min (_candidate_list);
- if (node == NULL)
- return NULL;
-
- linklist_head (node->list, &lnode);
- ret = lnode.data;
-
- linklist_remove (ret, node->list);
- if (node->list->count == 0)
- {
- linklist_delete (node->list);
- bintree_remove (node, _candidate_list);
- }
-
-#if 0
- if (IS_OSPF6_DUMP_SPF)
- ospf6_spf_candidate_print ();
-#endif
-
+ ret = ntohl (ospf6_linkstate_prefix_id (&va->vertex_id)) -
+ ntohl (ospf6_linkstate_prefix_id (&vb->vertex_id));
return ret;
}
+struct ospf6_vertex *
+ospf6_vertex_create (struct ospf6_lsa *lsa)
+{
+ struct ospf6_vertex *v;
+ int i;
+
+ v = (struct ospf6_vertex *)
+ XMALLOC (MTYPE_OSPF6_VERTEX, sizeof (struct ospf6_vertex));
+
+ /* type */
+ if (ntohs (lsa->header->type) == OSPF6_LSTYPE_ROUTER)
+ v->type = OSPF6_VERTEX_TYPE_ROUTER;
+ else if (ntohs (lsa->header->type) == OSPF6_LSTYPE_NETWORK)
+ v->type = OSPF6_VERTEX_TYPE_NETWORK;
+ else
+ assert (0);
+
+ /* vertex_id */
+ ospf6_linkstate_prefix (lsa->header->adv_router, lsa->header->id,
+ &v->vertex_id);
+
+ /* name */
+ ospf6_linkstate_prefix2str (&v->vertex_id, v->name, sizeof (v->name));
+
+ /* Associated LSA */
+ v->lsa = lsa;
+
+ /* capability bits + options */
+ v->capability = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header));
+ v->options[0] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 1);
+ v->options[1] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 2);
+ v->options[2] = *(u_char *)(OSPF6_LSA_HEADER_END (lsa->header) + 3);
+
+ for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
+ ospf6_nexthop_clear (&v->nexthop[i]);
+
+ v->parent = NULL;
+ v->child_list = list_new ();
+ v->child_list->cmp = ospf6_vertex_id_cmp;
+
+ return v;
+}
+
void
-ospf6_spf_candidate_remove (struct ospf6_vertex *v)
+ospf6_vertex_delete (struct ospf6_vertex *v)
{
- struct bintree_node node;
- struct ospf6_spf_candidate_node *cnode = NULL;
-
- for (bintree_head (_candidate_list, &node); ! bintree_end (&node);
- bintree_next (&node))
- {
- cnode = node.data;
- if (linklist_lookup (v, cnode->list))
- {
- linklist_remove (v, cnode->list);
- break;
- }
- }
-
- if (cnode->list->count == 0)
- {
- linklist_delete (cnode->list);
- bintree_remove (cnode, _candidate_list);
- }
-}
-
-
-#define TIMER_SEC_MICRO 1000000
-
-/* timeval calculation */
-static void
-ospf6_timeval_add (const struct timeval *t1, const struct timeval *t2,
- struct timeval *result)
-{
- long moveup = 0;
-
- result->tv_usec = t1->tv_usec + t2->tv_usec;
- while (result->tv_usec > TIMER_SEC_MICRO)
- {
- result->tv_usec -= TIMER_SEC_MICRO;
- moveup ++;
- }
-
- result->tv_sec = t1->tv_sec + t2->tv_sec + moveup;
-}
-
-static void
-ospf6_timeval_add_equal (const struct timeval *t, struct timeval *result)
-{
- struct timeval tmp;
- ospf6_timeval_add (t, result, &tmp);
- result->tv_sec = tmp.tv_sec;
- result->tv_usec = tmp.tv_usec;
-}
-
-/* Compare timeval a and b. It returns an integer less than, equal
- to, or great than zero if a is found, respectively, to be less
- than, to match, or be greater than b. */
-static int
-ospf6_timeval_cmp (const struct timeval t1, const struct timeval t2)
-{
- return (t1.tv_sec == t2.tv_sec
- ? t1.tv_usec - t2.tv_usec : t1.tv_sec - t2.tv_sec);
-}
-
-
-static int
-ospf6_spf_lsd_num (struct ospf6_vertex *V, struct ospf6_area *o6a)
-{
- u_int16_t type;
- u_int32_t id, adv_router;
- struct ospf6_lsa *lsa;
-
- if (V->vertex_id.id.s_addr)
- type = htons (OSPF6_LSA_TYPE_NETWORK);
- else
- type = htons (OSPF6_LSA_TYPE_ROUTER);
- id = V->vertex_id.id.s_addr;
- adv_router = V->vertex_id.adv_router.s_addr;
-
- lsa = ospf6_lsdb_lookup_lsdb (type, id, adv_router, o6a->lsdb);
- if (! lsa)
- {
- zlog_err ("SPF: Can't find associated LSA for %s", V->string);
- return 0;
- }
-
- return ospf6_lsa_lsd_num ((struct ospf6_lsa_header *) lsa->header);
-}
-
-/* RFC2328 section 16.1.1:
- Check if there is at least one router in the path
- from the root to this vertex. */
-static int
-ospf6_spf_is_router_to_root (struct ospf6_vertex *c,
- struct ospf6_spftree *spf_tree)
-{
- listnode node;
- struct ospf6_vertex *p;
-
- if (spf_tree->root == c)
- return 0;
-
- for (node = listhead (c->parent_list); node; nextnode (node))
- {
- p = (struct ospf6_vertex *) getdata (node);
-
- if (p == spf_tree->root)
- return 0;
-
- if (p->vertex_id.id.s_addr == 0) /* this is router */
- continue;
- else if (ospf6_spf_is_router_to_root (p, spf_tree))
- continue;
-
- return 0;
- }
-
- return 1;
-}
-
-static struct in6_addr *
-ospf6_spf_get_ipaddr (u_int32_t id, u_int32_t adv_router, u_int32_t ifindex)
-{
- char buf[64], nhbuf[64];
- struct ospf6_interface *o6i;
- struct ospf6_neighbor *o6n;
- struct ospf6_lsa *lsa;
- struct ospf6_lsdb_node node;
-
- o6i = ospf6_interface_lookup_by_index (ifindex);
- if (! o6i)
- {
- zlog_err ("SPF: Can't find interface: index %d", ifindex);
- return (struct in6_addr *) NULL;
- }
-
- /* Find Link-LSA of the vertex in question */
- lsa = NULL;
- for (ospf6_lsdb_type_router (&node, htons (OSPF6_LSA_TYPE_LINK),
- adv_router, o6i->lsdb);
- ! ospf6_lsdb_is_end (&node);
- ospf6_lsdb_next (&node))
- lsa = node.lsa;
-
- /* return Linklocal Address field if the Link-LSA exists */
- if (lsa && lsa->header->adv_router == adv_router)
- {
- struct ospf6_link_lsa *link_lsa;
- link_lsa = (struct ospf6_link_lsa *) (lsa->header + 1);
- return &link_lsa->llsa_linklocal;
- }
-
- zlog_warn ("SPF: Can't find Link-LSA for %s",
- inet_ntop (AF_INET, &adv_router, buf, sizeof (buf)));
-
- o6n = ospf6_neighbor_lookup (adv_router, o6i);
- if (! o6n)
- {
- inet_ntop (AF_INET, &adv_router, buf, sizeof (buf));
- zlog_err ("SPF: Can't find neighbor %s in %s, "
- "unable to find his linklocal address",
- buf, o6i->interface->name);
- return (struct in6_addr *) NULL;
- }
-
- zlog_warn ("SPF: use packet's source address for %s's nexthop: %s",
- inet_ntop (AF_INET, &adv_router, buf, sizeof (buf)),
- inet_ntop (AF_INET6, &o6n->hisaddr, nhbuf, sizeof (nhbuf)));
-
- return &o6n->hisaddr;
-}
-
-static int
-ospf6_spf_nexthop_calculation (struct ospf6_vertex *W,
- u_int32_t ifindex,
- struct ospf6_vertex *V,
- struct ospf6_spftree *spf_tree)
-{
- struct ospf6_nexthop *nexthop, *n;
- u_int32_t adv_router, id;
- struct in6_addr nexthop_ipaddr, *ipaddr;
- unsigned int nexthop_ifindex;
- struct linklist_node node;
-
- /* until this, nexthop_list should be untouched */
- assert (list_isempty (W->nexthop_list));
-
- /* If ther is at least one intervening router from root to W */
- if (ospf6_spf_is_router_to_root (W, spf_tree))
- {
- /* Create no new nexthop, Inherit from the intervening router */
- for (linklist_head (V->nexthop_list, &node); ! linklist_end (&node);
- linklist_next (&node))
- linklist_add (node.data, W->nexthop_list);
- return 0;
- }
-
- /* Create new nexthop */
-
- adv_router = W->vertex_id.adv_router.s_addr;
- id = W->vertex_id.id.s_addr;
-
- nexthop_ifindex = 0;
- memset (&nexthop_ipaddr, 0, sizeof (struct in6_addr));
- if (spf_tree->root && V == spf_tree->root)
- {
- nexthop_ifindex = ifindex;
- if (! id) /* xxx, if V is router */
- {
- ipaddr = ospf6_spf_get_ipaddr (id, adv_router, ifindex);
- if (! ipaddr)
- {
- /* xxx, should trigger error and quit SPF calculation... */
- memset (&nexthop_ipaddr, 0xff, sizeof (struct in6_addr));
- return -1;
- }
- else
- memcpy (&nexthop_ipaddr, ipaddr, sizeof (struct in6_addr));
- }
- }
- else
- {
- /* V is broadcast network, W is router */
- assert (V->vertex_id.id.s_addr != 0);
- assert (W->vertex_id.id.s_addr == 0);
-
- linklist_head (V->nexthop_list, &node);
- n = (struct ospf6_nexthop *) node.data;
- nexthop_ifindex = n->ifindex;
- ipaddr = ospf6_spf_get_ipaddr (id, adv_router, n->ifindex);
- if (! ipaddr)
- {
- /* xxx, should trigger error and quit SPF calculation... */
- memset (&nexthop_ipaddr, 0xff, sizeof (struct in6_addr));
- return -1;
- }
- else
- memcpy (&nexthop_ipaddr, ipaddr, sizeof (struct in6_addr));
- }
-
- nexthop = XCALLOC (MTYPE_OSPF6_VERTEX, sizeof (struct ospf6_nexthop));
- nexthop->ifindex = nexthop_ifindex;
- memcpy (&nexthop->address, &nexthop_ipaddr, sizeof (nexthop->address));
-
- linklist_add (nexthop, W->nexthop_list);
-
- /* to hold malloced memory */
- linklist_add (nexthop, nexthop_list);
-
- return 0;
-}
-
-static struct ospf6_vertex *
-ospf6_spf_vertex_create (int index, struct ospf6_vertex *V,
- struct ospf6_area *o6a)
-{
- struct ospf6_lsa *lsa;
- struct ospf6_router_lsa *router_lsa;
- struct ospf6_router_lsd *router_lsd;
- struct ospf6_network_lsa *network_lsa;
- struct ospf6_network_lsd *network_lsd;
- u_int32_t id, adv_router;
- u_int16_t type;
- void *lsd;
- struct ospf6_vertex *W;
- u_int16_t distance;
- u_int32_t ifindex;
- int backreference, lsdnum, i;
- char buf_router[16], buf_id[16];
-
- type = id = adv_router = 0;
-
- /* Get Linkstate description */
- lsd = ospf6_lsa_lsd_get (index, (struct ospf6_lsa_header *) V->lsa->header);
- if (! lsd)
- {
- zlog_err ("SPF: Can't find %dth Link description from %s",
- index, V->lsa->str);
- return (struct ospf6_vertex *) NULL;
- }
-
- /* Check Link state description */
- distance = 0;
- ifindex = 0;
- if (V->lsa->header->type == htons (OSPF6_LSA_TYPE_ROUTER))
- {
- router_lsd = lsd;
- if (router_lsd->type == OSPF6_ROUTER_LSD_TYPE_POINTTOPOINT)
- {
- type = htons (OSPF6_LSA_TYPE_ROUTER);
- id = htonl (0);
- }
- else if (router_lsd->type == OSPF6_ROUTER_LSD_TYPE_TRANSIT_NETWORK)
- {
- type = htons (OSPF6_LSA_TYPE_NETWORK);
- id = router_lsd->neighbor_interface_id;
- }
- adv_router = router_lsd->neighbor_router_id;
- distance = ntohs (router_lsd->metric);
- ifindex = ntohl (router_lsd->interface_id);
- }
- else if (V->lsa->header->type == htons (OSPF6_LSA_TYPE_NETWORK))
- {
- network_lsd = lsd;
- type = htons (OSPF6_LSA_TYPE_ROUTER);
- id = htonl (0);
- adv_router = network_lsd->adv_router;
- }
-
- /* Avoid creating candidate of myself */
- if (adv_router == o6a->ospf6->router_id &&
- type == htons (OSPF6_LSA_TYPE_ROUTER))
- {
- return (struct ospf6_vertex *) NULL;
- }
-
- /* Find Associated LSA for W */
- lsa = ospf6_lsdb_lookup_lsdb (type, id, adv_router, o6a->lsdb);
-
- if (! lsa)
- {
- inet_ntop (AF_INET, &adv_router, buf_router, sizeof (buf_router));
- inet_ntop (AF_INET, &id, buf_id, sizeof (buf_id));
-
- if (IS_OSPF6_DUMP_SPF)
- {
- if (type == htons (OSPF6_LSA_TYPE_ROUTER))
- zlog_info ("SPF: Can't find LSA for W (%s *): not found",
- buf_router);
- else
- zlog_info ("SPF: Can't find LSA for W (%s %s): not found",
- buf_router, buf_id);
- }
- return (struct ospf6_vertex *) NULL;
- }
-
- if (IS_LSA_MAXAGE (lsa))
- {
- if (IS_OSPF6_DUMP_SPF)
- zlog_info ("SPF: Associated LSA for W is MaxAge: %s", lsa->str);
- return (struct ospf6_vertex *) NULL;
- }
-
- /* Check back reference from W's lsa to V's lsa */
- backreference = 0;
- lsdnum = ospf6_lsa_lsd_num ((struct ospf6_lsa_header *) lsa->header);
- for (i = 0; i < lsdnum; i++)
- {
- if (ospf6_lsa_lsd_is_refer_ok (i, (struct ospf6_lsa_header *) lsa->header,
- index, (struct ospf6_lsa_header *) V->lsa->header))
- backreference++;
- }
- if (! backreference)
- {
- if (IS_OSPF6_DUMP_SPF)
- zlog_info ("SPF: Back reference failed: V: %s, W: %s",
- V->lsa->str, lsa->str);
- return (struct ospf6_vertex *) NULL;
- }
-
- /* Allocate new ospf6_vertex for W */
- W = (struct ospf6_vertex *) XMALLOC (MTYPE_OSPF6_VERTEX,
- sizeof (struct ospf6_vertex));
- if (! W)
- {
- zlog_err ("SPF: Can't allocate memory for Vertex");
- return (struct ospf6_vertex *) NULL;
- }
- memset (W, 0, sizeof (struct ospf6_vertex));
-
- /* Initialize */
- W->vertex_id.family = AF_UNSPEC;
- W->vertex_id.prefixlen = 64; /* xxx */
- W->lsa = lsa;
- if (type == htons (OSPF6_LSA_TYPE_ROUTER))
- W->vertex_id.id.s_addr = htonl (0); /* XXX */
- else
- W->vertex_id.id.s_addr = W->lsa->header->id;
- W->vertex_id.adv_router.s_addr = W->lsa->header->adv_router;
- W->nexthop_list = linklist_create ();
- W->path_list = list_new ();
- W->parent_list = list_new ();
- W->distance = V->distance + distance;
- W->depth = V->depth + 1;
-
- inet_ntop (AF_INET, &W->vertex_id.adv_router.s_addr,
- buf_router, sizeof (buf_router));
- inet_ntop (AF_INET, &W->vertex_id.id.s_addr, buf_id, sizeof (buf_id));
- snprintf (W->string, sizeof (W->string), "[%s-%s (%d)]",
- buf_router, buf_id, W->distance);
-
- /* capability bits and optional capabilities */
- if (W->vertex_id.id.s_addr == 0)
- {
- router_lsa = (struct ospf6_router_lsa *) (W->lsa->header + 1);
- W->capability_bits = router_lsa->bits;
- memcpy (W->opt_capability, router_lsa->options,
- sizeof (W->opt_capability));
- }
- else
- {
- network_lsa = (struct ospf6_network_lsa *) (W->lsa->header + 1);
- W->capability_bits = network_lsa->reserved;
- memcpy (W->opt_capability, network_lsa->options,
- sizeof (W->opt_capability));
- }
-
- /* Link to Parent node */
- listnode_add (W->parent_list, V);
-
- /* Nexthop Calculation */
- if (ospf6_spf_nexthop_calculation (W, ifindex, V, o6a->spf_tree) < 0)
- return NULL;
-
- return W;
-}
-
-static void
-ospf6_spf_vertex_delete (struct ospf6_vertex *v)
-{
- linklist_delete (v->nexthop_list);
- list_delete (v->path_list);
- list_delete (v->parent_list);
+ list_delete (v->child_list);
XFREE (MTYPE_OSPF6_VERTEX, v);
}
-static void
-ospf6_spf_vertex_merge (struct ospf6_vertex *w, struct ospf6_vertex *x)
+struct ospf6_lsa *
+ospf6_lsdesc_lsa (caddr_t lsdesc, struct ospf6_vertex *v)
{
- listnode node;
- struct linklist_node lnode;
-
- /* merge should be done on two nodes which are
- almost the same */
-
- /* these w and x should be both candidate.
- candidate should not have any children */
- assert (list_isempty (w->path_list));
- assert (list_isempty (x->path_list));
-
- /* merge parent list */
- for (node = listhead (w->parent_list); node; nextnode (node))
- {
- if (listnode_lookup (x->parent_list, getdata (node)))
- continue;
- listnode_add (x->parent_list, getdata (node));
- }
-
- /* merge nexthop list */
- for (linklist_head (w->nexthop_list, &lnode); ! linklist_end (&lnode);
- linklist_next (&lnode))
- linklist_add (lnode.data, x->nexthop_list);
-}
-
-static void
-ospf6_spf_initialize (list candidate_list, struct ospf6_area *o6a)
-{
- listnode node;
- struct ospf6_vertex *v;
struct ospf6_lsa *lsa;
- u_int16_t type;
- u_int32_t id, adv_router;
- struct linklist_node lnode;
+ u_int16_t type = 0;
+ u_int32_t id = 0, adv_router = 0;
- struct ospf6_nexthop *nexthop;
- struct interface *ifp;
- char buf_router[64], buf_id[64];
-
- /* delete topology routing table for this area */
- ospf6_route_remove_all (o6a->table_topology);
-
- /* Delete previous spf tree */
- for (node = listhead (o6a->spf_tree->list); node; nextnode (node))
+ if (VERTEX_IS_TYPE (NETWORK, v))
{
- v = (struct ospf6_vertex *) getdata (node);
- ospf6_spf_vertex_delete (v);
+ type = htons (OSPF6_LSTYPE_ROUTER);
+ id = htonl (0);
+ adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc);
}
- list_delete_all_node (o6a->spf_tree->list);
-
- for (linklist_head (nexthop_list, &lnode); ! linklist_end (&lnode);
- linklist_next (&lnode))
- XFREE (MTYPE_OSPF6_VERTEX, lnode.data);
- linklist_remove_all (nexthop_list);
-
- /* Find self originated Router-LSA */
- type = htons (OSPF6_LSA_TYPE_ROUTER);
- id = htonl (0);
- adv_router = ospf6->router_id;
-
- lsa = ospf6_lsdb_lookup_lsdb (type, id, adv_router, o6a->lsdb);
-
- if (! lsa)
- {
- if (IS_OSPF6_DUMP_SPF)
- zlog_info ("SPF: Can't find self originated Router-LSA");
- return;
- }
- if (IS_LSA_MAXAGE (lsa))
- {
- zlog_err ("SPF: MaxAge self originated Router-LSA");
- return;
- }
-
- /* Create root vertex */
- v = (struct ospf6_vertex *) XMALLOC (MTYPE_OSPF6_VERTEX,
- sizeof (struct ospf6_vertex));
- if (! v)
- {
- zlog_err ("SPF: Can't allocate memory for root vertex");
- return;
- }
- memset (v, 0, sizeof (struct ospf6_vertex));
-
- v->vertex_id.family = AF_UNSPEC; /* XXX */
- v->vertex_id.prefixlen = 64; /* XXX */
- v->vertex_id.id.s_addr = htonl (0);
- v->vertex_id.adv_router.s_addr = ospf6->router_id;
- if (ospf6_is_asbr (ospf6))
- OSPF6_OPT_SET (v->opt_capability, OSPF6_OPT_E);
- OSPF6_OPT_SET (v->opt_capability, OSPF6_OPT_V6);
- OSPF6_OPT_SET (v->opt_capability, OSPF6_OPT_R);
- v->nexthop_list = linklist_create ();
- v->path_list = list_new ();
- v->parent_list = list_new ();
- v->distance = 0;
- v->depth = 0;
- v->lsa = lsa;
-
- inet_ntop (AF_INET, &v->vertex_id.adv_router.s_addr,
- buf_router, sizeof (buf_router));
- inet_ntop (AF_INET, &v->vertex_id.id.s_addr, buf_id, sizeof (buf_id));
- snprintf (v->string, sizeof (v->string), "[%s-%s (%d)]",
- buf_router, buf_id, v->distance);
-
- nexthop = XCALLOC (MTYPE_OSPF6_VERTEX, sizeof (struct ospf6_nexthop));
- ifp = if_lookup_by_name ("lo0");
- if (ifp)
- nexthop->ifindex = ifp->ifindex;
- inet_pton (AF_INET6, "::1", &nexthop->address);
- linklist_add (nexthop, v->nexthop_list);
- linklist_add (nexthop, nexthop_list);
-
- o6a->spf_tree->root = v;
- listnode_add (candidate_list, v);
-
- ospf6_spf_candidate_enqueue (v);
-}
-
-static struct ospf6_vertex *
-ospf6_spf_get_closest_candidate (list candidate_list)
-{
- listnode node;
- struct ospf6_vertex *candidate, *closest;
-
- closest = (struct ospf6_vertex *) NULL;
- for (node = listhead (candidate_list); node; nextnode (node))
- {
- candidate = (struct ospf6_vertex *) getdata (node);
-
- if (closest && candidate->distance > closest->distance)
- continue;
-
- /* always choose network vertices if those're the same cost */
- if (closest && candidate->distance == closest->distance
- && closest->vertex_id.id.s_addr != 0)
- continue;
-
- closest = candidate;
- }
-
- return closest;
-}
-
-static struct ospf6_vertex *
-ospf6_spf_get_same_candidate (struct ospf6_vertex *w, list candidate_list)
-{
- listnode node;
- struct ospf6_vertex *c, *same;
-
- same = (struct ospf6_vertex *) NULL;
- for (node = listhead (candidate_list); node; nextnode (node))
- {
- c = (struct ospf6_vertex *) getdata (node);
- if (w->vertex_id.adv_router.s_addr != c->vertex_id.adv_router.s_addr)
- continue;
- if (w->vertex_id.id.s_addr != c->vertex_id.id.s_addr)
- continue;
-
- if (same)
- zlog_warn ("SPF: duplicate candidates in candidate_list");
-
- same = c;
- }
-
- return same;
-}
-
-static void
-ospf6_spf_install (struct ospf6_vertex *vertex, struct ospf6_area *o6a)
-{
- listnode node;
- struct ospf6_vertex *parent;
- struct ospf6_nexthop *nexthop;
- struct ospf6_route_req request;
- struct linklist_node lnode;
-
- struct ospf6_router_lsa *router_lsa;
- struct ospf6_network_lsa *network_lsa;
-
- router_lsa = OSPF6_LSA_HEADER_END (vertex->lsa->header);
- network_lsa = OSPF6_LSA_HEADER_END (vertex->lsa->header);
-
- if (IS_OSPF6_DUMP_SPF)
- {
- zlog_info ("SPF: Install: %s", vertex->string);
- }
-
- listnode_add (o6a->spf_tree->list, vertex);
-
- for (node = listhead (vertex->parent_list); node; nextnode (node))
- {
- parent = (struct ospf6_vertex *) getdata (node);
- listnode_add (parent->path_list, vertex);
- vertex->depth = parent->depth + 1;
- }
-
-#if 0
- if (vertex == o6a->spf_tree->root)
- return;
-#endif /*0*/
-
- /* install route to topology table */
- memset (&request, 0, sizeof (request));
- if (vertex->vertex_id.id.s_addr) /* xxx */
- request.route.type = OSPF6_DEST_TYPE_NETWORK;
else
- request.route.type = OSPF6_DEST_TYPE_ROUTER;
- memcpy (&request.route.prefix, &vertex->vertex_id,
- sizeof (struct prefix));
-
- request.path.area_id = o6a->area_id;
- request.path.type = OSPF6_PATH_TYPE_INTRA;
- request.path.cost = vertex->distance;
- request.path.cost_e2 = 0;
- request.path.origin.type = vertex->lsa->header->type;
- request.path.origin.id = vertex->lsa->header->id;
- request.path.origin.adv_router = vertex->lsa->header->adv_router;
- if (vertex->lsa->header->type == htons (OSPF6_LSA_TYPE_ROUTER))
- request.path.router_bits = router_lsa->bits;
- memcpy (&request.path.capability, vertex->opt_capability,
- sizeof (request.path.capability));
-
-#if 0
- if (IS_OSPF6_DUMP_SPF)
- zlog_info ("SPF: install %d nexthops for %s",
- listcount (vertex->nexthop_list), vertex->string);
-#endif
-
- for (linklist_head (vertex->nexthop_list, &lnode); ! linklist_end (&lnode);
- linklist_next (&lnode))
{
- nexthop = lnode.data;
-
- request.nexthop.ifindex = nexthop->ifindex;
- memcpy (&request.nexthop.address, &nexthop->address,
- sizeof (request.nexthop.address));
-
- ospf6_route_add (&request, o6a->table_topology);
- }
-}
-
-struct ospf6_vertex *
-ospf6_spf_lookup (struct ospf6_vertex *w, struct ospf6_area *o6a)
-{
- listnode node;
- struct ospf6_vertex *v;
-
- for (node = listhead (o6a->spf_tree->list); node; nextnode (node))
- {
- v = (struct ospf6_vertex *) getdata (node);
-
- if (w->vertex_id.adv_router.s_addr != v->vertex_id.adv_router.s_addr)
- continue;
- if (w->vertex_id.id.s_addr != v->vertex_id.id.s_addr)
- continue;
-
- return v;
- }
-
- return (struct ospf6_vertex *) NULL;
-}
-
-u_int32_t stat_node = 0;
-u_int32_t stat_candidate = 0;
-u_int32_t stat_candidate_max = 0;
-u_int32_t stat_spf = 0;
-
-
-/* RFC2328 section 16.1 , RFC2740 section 3.8.1 */
-static int
-ospf6_spf_calculation (struct ospf6_area *o6a)
-{
- list candidate_list;
- struct ospf6_vertex *V, *W, *X;
- int ldnum, i;
-
- if (! o6a || ! o6a->spf_tree)
- {
- zlog_err ("SPF: Can't calculate SPF tree: malformed area");
- return -1;
- }
-
- stat_spf ++;
- stat_node = 0;
- stat_candidate = 0;
- stat_candidate_max = 0;
-
- if (IS_OSPF6_DUMP_SPF)
- zlog_info ("SPF: Calculation for area %s", o6a->str);
-
- ospf6_route_table_freeze (o6a->table_topology);
- ospf6_route_remove_all (o6a->table_topology);
-
- /* (1): Initialize the algorithm's data structures */
- candidate_list = list_new ();
- ospf6_spf_initialize (candidate_list, o6a);
- stat_candidate ++;
-
- /* (3): Install closest from candidate list; if empty, break */
- while (listcount (candidate_list))
- {
- V = ospf6_spf_get_closest_candidate (candidate_list);
- listnode_delete (candidate_list, V);
-
- {
- struct ospf6_vertex *V_;
-
- if (stat_candidate_max < ospf6_spf_candidate_count ())
- stat_candidate_max = ospf6_spf_candidate_count ();
-
- V_ = ospf6_spf_candidate_dequeue ();
-
-#if 0
- if (IS_OSPF6_DUMP_SPF)
- {
- zlog_info ("Candidate list count: %lu",
- (u_long)ospf6_spf_candidate_count ());
- zlog_info ("*** Candidate %s: %p <-> %p",
- (V == V_ ? "same" : "*** differ ***"), V, V_);
- zlog_info (" %p: %s", V, V->string);
- zlog_info (" %p: %s", V_, V_->string);
- }
-#endif
-
- }
-
- stat_node++;
- ospf6_spf_install (V, o6a);
-
- /* (2): Examin LSA of just added vertex */
- ldnum = ospf6_spf_lsd_num (V, o6a);
- for (i = 0; i < ldnum; i++)
+ if (ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc))
{
- /* (b): If no LSA, or MaxAge, or LinkBack fail, examin next */
- W = ospf6_spf_vertex_create (i, V, o6a);
- if (! W)
- continue;
-
- stat_candidate ++;
-
- /* (c) */
- if (ospf6_spf_lookup (W, o6a))
- {
- if (IS_OSPF6_DUMP_SPF)
- zlog_info ("SPF: %s: Already in SPF tree", W->string);
- ospf6_spf_vertex_delete (W);
- continue;
- }
-
- /* (d) */
- X = ospf6_spf_get_same_candidate (W, candidate_list);
- if (X && X->distance < W->distance)
- {
- if (IS_OSPF6_DUMP_SPF)
- zlog_info ("SPF: %s: More closer found", W->string);
- ospf6_spf_vertex_delete (W);
- continue;
- }
- if (X && X->distance == W->distance)
- {
- if (IS_OSPF6_DUMP_SPF)
- zlog_info ("SPF: %s: new ECMP candidate", W->string);
- ospf6_spf_vertex_merge (W, X);
- ospf6_spf_vertex_delete (W);
- continue;
- }
-
- if (X)
- {
- if (IS_OSPF6_DUMP_SPF)
- zlog_info ("SPF: %s: Swap with old candidate", W->string);
- listnode_delete (candidate_list, X);
- ospf6_spf_candidate_remove (X);
- ospf6_spf_vertex_delete (X);
- }
- else
- {
- if (IS_OSPF6_DUMP_SPF)
- zlog_info ("SPF: %s: New Candidate", W->string);
- }
-
- if (stat_candidate_max < ospf6_spf_candidate_count ())
- stat_candidate_max = ospf6_spf_candidate_count ();
-
- listnode_add (candidate_list, W);
- ospf6_spf_candidate_enqueue (W);
+ type = htons (OSPF6_LSTYPE_ROUTER);
+ id = htonl (0);
+ adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc);
+ }
+ else if (ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK, lsdesc))
+ {
+ type = htons (OSPF6_LSTYPE_NETWORK);
+ id = htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc));
+ adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc);
}
}
- assert (listcount (candidate_list) == 0);
- list_free (candidate_list);
- assert (ospf6_spf_candidate_count () == 0);
+ lsa = ospf6_lsdb_lookup (type, id, adv_router, v->area->lsdb);
- /* Clear thread timer */
- o6a->spf_tree->t_spf_calculation = (struct thread *) NULL;
-
- if (IS_OSPF6_DUMP_SPF)
+ if (IS_OSPF6_DEBUG_SPF (DETAIL))
{
- zlog_info ("SPF: Calculation for area %s done", o6a->str);
- zlog_info ("SPF: Statistics: %luth", (u_long)stat_spf);
- zlog_info ("SPF: Node Number: %lu", (u_long)stat_node);
- zlog_info ("SPF: Candidate Number: %lu Max: %lu",
- (u_long) stat_candidate, (u_long) stat_candidate_max);
+ char ibuf[16], abuf[16];
+ inet_ntop (AF_INET, &id, ibuf, sizeof (ibuf));
+ inet_ntop (AF_INET, &adv_router, abuf, sizeof (abuf));
+ if (lsa)
+ zlog_info (" Link to: %s", lsa->name);
+ else
+ zlog_info (" Link to: [%s Id:%s Adv:%s] No LSA",
+ OSPF6_LSTYPE_NAME (type), ibuf, abuf);
}
- ospf6_route_table_thaw (o6a->table_topology);
+ return lsa;
+}
+
+char *
+ospf6_lsdesc_backlink (struct ospf6_lsa *lsa,
+ caddr_t lsdesc, struct ospf6_vertex *v)
+{
+ caddr_t backlink, found = NULL;
+ int size;
+
+ size = (OSPF6_LSA_IS_TYPE (ROUTER, lsa) ?
+ sizeof (struct ospf6_router_lsdesc) :
+ sizeof (struct ospf6_network_lsdesc));
+ for (backlink = OSPF6_LSA_HEADER_END (lsa->header) + 4;
+ backlink + size <= OSPF6_LSA_END (lsa->header); backlink += size)
+ {
+ assert (! (OSPF6_LSA_IS_TYPE (NETWORK, lsa) &&
+ VERTEX_IS_TYPE (NETWORK, v)));
+
+ if (OSPF6_LSA_IS_TYPE (NETWORK, lsa) &&
+ NETWORK_LSDESC_GET_NBR_ROUTERID (backlink)
+ == v->lsa->header->adv_router)
+ found = backlink;
+ else if (VERTEX_IS_TYPE (NETWORK, v) &&
+ ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK, backlink) &&
+ ROUTER_LSDESC_GET_NBR_ROUTERID (backlink)
+ == v->lsa->header->adv_router &&
+ ROUTER_LSDESC_GET_NBR_IFID (backlink)
+ == ntohl (v->lsa->header->id))
+ found = backlink;
+ else
+ {
+ if (! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, backlink) ||
+ ! ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc))
+ continue;
+ if (ROUTER_LSDESC_GET_NBR_IFID (backlink) !=
+ ROUTER_LSDESC_GET_IFID (lsdesc) ||
+ ROUTER_LSDESC_GET_NBR_IFID (lsdesc) !=
+ ROUTER_LSDESC_GET_IFID (backlink))
+ continue;
+ if (ROUTER_LSDESC_GET_NBR_ROUTERID (backlink) !=
+ v->lsa->header->adv_router ||
+ ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc) !=
+ lsa->header->adv_router)
+ continue;
+ found = backlink;
+ }
+ }
+
+ if (IS_OSPF6_DEBUG_SPF (DETAIL))
+ zlog_info (" Backlink %s", (found ? "OK" : "FAIL"));
+
+ return found;
+}
+
+void
+ospf6_nexthop_calc (struct ospf6_vertex *w, struct ospf6_vertex *v,
+ caddr_t lsdesc)
+{
+ int i, ifindex;
+ struct ospf6_interface *oi;
+ u_int16_t type;
+ u_int32_t adv_router;
+ struct ospf6_lsa *lsa;
+ struct ospf6_link_lsa *link_lsa;
+ char buf[64];
+
+ assert (VERTEX_IS_TYPE (ROUTER, w));
+ ifindex = (VERTEX_IS_TYPE (NETWORK, v) ? v->nexthop[0].ifindex :
+ ROUTER_LSDESC_GET_IFID (lsdesc));
+ oi = ospf6_interface_lookup_by_ifindex (ifindex);
+ if (oi == NULL)
+ {
+ if (IS_OSPF6_DEBUG_SPF (SUMMARY))
+ zlog_warn ("Can't find interface in SPF: ifindex %d", ifindex);
+ return;
+ }
+
+ type = htons (OSPF6_LSTYPE_LINK);
+ adv_router = (VERTEX_IS_TYPE (NETWORK, v) ?
+ NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc) :
+ ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc));
+
+ i = 0;
+ for (lsa = ospf6_lsdb_type_router_head (type, adv_router, oi->lsdb); lsa;
+ lsa = ospf6_lsdb_type_router_next (type, adv_router, lsa))
+ {
+ if (VERTEX_IS_TYPE (ROUTER, v) &&
+ htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc)) != lsa->header->id)
+ continue;
+
+ link_lsa = (struct ospf6_link_lsa *) OSPF6_LSA_HEADER_END (lsa->header);
+ if (IS_OSPF6_DEBUG_SPF (DETAIL))
+ {
+ inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));
+ zlog_info (" nexthop %s from %s", buf, lsa->name);
+ }
+
+ if (i < OSPF6_MULTI_PATH_LIMIT)
+ {
+ memcpy (&w->nexthop[i].address, &link_lsa->linklocal_addr,
+ sizeof (struct in6_addr));
+ w->nexthop[i].ifindex = ifindex;
+ i++;
+ }
+ }
+
+ if (i == 0 && IS_OSPF6_DEBUG_SPF (SUMMARY))
+ zlog_info ("No nexthop for %s found", w->name);
+}
+
+int
+ospf6_spf_install (struct ospf6_vertex *v,
+ struct ospf6_route_table *result_table)
+{
+ struct ospf6_route *route;
+ int i, j;
+ struct ospf6_vertex *prev, *w;
+ listnode node;
+
+ if (IS_OSPF6_DEBUG_SPF (SUMMARY))
+ zlog_info ("SPF install %s hops %d cost %d",
+ v->name, v->hops, v->cost);
+
+ route = ospf6_route_lookup (&v->vertex_id, result_table);
+ if (route && route->path.cost < v->cost)
+ {
+ if (IS_OSPF6_DEBUG_SPF (SUMMARY))
+ zlog_info (" already installed with lower cost (%d), ignore",
+ route->path.cost);
+ ospf6_vertex_delete (v);
+ return -1;
+ }
+ else if (route && route->path.cost == v->cost)
+ {
+ if (IS_OSPF6_DEBUG_SPF (SUMMARY))
+ zlog_info (" another path found, merge");
+
+ for (i = 0; ospf6_nexthop_is_set (&v->nexthop[i]) &&
+ i < OSPF6_MULTI_PATH_LIMIT; i++)
+ {
+ for (j = 0; j < OSPF6_MULTI_PATH_LIMIT; j++)
+ {
+ if (ospf6_nexthop_is_set (&route->nexthop[j]))
+ {
+ if (ospf6_nexthop_is_same (&route->nexthop[j],
+ &v->nexthop[i]))
+ break;
+ else
+ continue;
+ }
+ ospf6_nexthop_copy (&route->nexthop[j], &v->nexthop[i]);
+ break;
+ }
+ }
+
+ prev = (struct ospf6_vertex *) route->route_option;
+ if (prev->hops > v->hops)
+ {
+ LIST_LOOP (prev->child_list, w, node)
+ {
+ assert (w->parent == prev);
+ w->parent = v;
+ listnode_add_sort (v->child_list, w);
+ }
+ listnode_delete (prev->parent->child_list, prev);
+ listnode_add_sort (v->parent->child_list, v);
+
+ ospf6_vertex_delete (prev);
+ route->route_option = v;
+ }
+ else
+ ospf6_vertex_delete (v);
+
+ return -1;
+ }
+
+ /* There should be no case where candidate being installed (variable
+ "v") is closer than the one in the SPF tree (variable "route").
+ In the case something's gone wrong with the behavior of
+ Priority-Queue. */
+ assert (route == NULL);
+
+ route = ospf6_route_create ();
+ memcpy (&route->prefix, &v->vertex_id, sizeof (struct prefix));
+ route->type = OSPF6_DEST_TYPE_LINKSTATE;
+ route->path.type = OSPF6_PATH_TYPE_INTRA;
+ route->path.origin.type = v->lsa->header->type;
+ route->path.origin.id = v->lsa->header->id;
+ route->path.origin.adv_router = v->lsa->header->adv_router;
+ route->path.metric_type = 1;
+ route->path.cost = v->cost;
+ route->path.cost_e2 = v->hops;
+ route->path.router_bits = v->capability;
+ route->path.options[0] = v->options[0];
+ route->path.options[1] = v->options[1];
+ route->path.options[2] = v->options[2];
+
+ for (i = 0; ospf6_nexthop_is_set (&v->nexthop[i]) &&
+ i < OSPF6_MULTI_PATH_LIMIT; i++)
+ ospf6_nexthop_copy (&route->nexthop[i], &v->nexthop[i]);
+
+ if (v->parent)
+ listnode_add_sort (v->parent->child_list, v);
+ route->route_option = v;
+
+ ospf6_route_add (route, result_table);
return 0;
}
+void
+ospf6_spf_table_finish (struct ospf6_route_table *result_table)
+{
+ struct ospf6_route *route;
+ struct ospf6_vertex *v;
+ for (route = ospf6_route_head (result_table); route;
+ route = ospf6_route_next (route))
+ {
+ v = (struct ospf6_vertex *) route->route_option;
+ ospf6_vertex_delete (v);
+ ospf6_route_remove (route, result_table);
+ }
+}
+
+void
+ospf6_spf_calculation (u_int32_t router_id,
+ struct ospf6_route_table *result_table,
+ struct ospf6_area *oa)
+{
+ struct pqueue *candidate_list;
+ struct ospf6_vertex *root, *v, *w;
+ int i;
+ int size;
+ caddr_t lsdesc;
+ struct ospf6_lsa *lsa;
+
+ /* initialize */
+ candidate_list = pqueue_create ();
+ candidate_list->cmp = ospf6_vertex_cmp;
+
+ ospf6_spf_table_finish (result_table);
+
+ /* Install the calculating router itself as the root of the SPF tree */
+ /* construct root vertex */
+ lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_ROUTER), htonl (0),
+ router_id, oa->lsdb);
+ if (lsa == NULL)
+ return;
+ root = ospf6_vertex_create (lsa);
+ root->area = oa;
+ root->cost = 0;
+ root->hops = 0;
+ root->nexthop[0].ifindex = 0; /* should have been loopbak I/F ... */
+ inet_pton (AF_INET6, "::1", &root->nexthop[0].address);
+
+ /* Actually insert root to the candidate-list as the only candidate */
+ pqueue_enqueue (root, candidate_list);
+
+ /* Iterate until candidate-list becomes empty */
+ while (candidate_list->size)
+ {
+ /* get closest candidate from priority queue */
+ v = pqueue_dequeue (candidate_list);
+
+ /* install may result in merging and rejecting of the vertex */
+ if (ospf6_spf_install (v, result_table) < 0)
+ continue;
+
+ /* For each LS description in the just-added vertex V's LSA */
+ size = (VERTEX_IS_TYPE (ROUTER, v) ?
+ sizeof (struct ospf6_router_lsdesc) :
+ sizeof (struct ospf6_network_lsdesc));
+ for (lsdesc = OSPF6_LSA_HEADER_END (v->lsa->header) + 4;
+ lsdesc + size <= OSPF6_LSA_END (v->lsa->header); lsdesc += size)
+ {
+ lsa = ospf6_lsdesc_lsa (lsdesc, v);
+ if (lsa == NULL)
+ continue;
+
+ if (! ospf6_lsdesc_backlink (lsa, lsdesc, v))
+ continue;
+
+ w = ospf6_vertex_create (lsa);
+ w->area = oa;
+ w->parent = v;
+ if (VERTEX_IS_TYPE (ROUTER, v))
+ {
+ w->cost = v->cost + ROUTER_LSDESC_GET_METRIC (lsdesc);
+ w->hops = v->hops + (VERTEX_IS_TYPE (NETWORK, w) ? 0 : 1);
+ }
+ else /* NETWORK */
+ {
+ w->cost = v->cost;
+ w->hops = v->hops + 1;
+ }
+
+ /* nexthop calculation */
+ if (w->hops == 0)
+ w->nexthop[0].ifindex = ROUTER_LSDESC_GET_IFID (lsdesc);
+ else if (w->hops == 1 && v->hops == 0)
+ ospf6_nexthop_calc (w, v, lsdesc);
+ else
+ {
+ for (i = 0; ospf6_nexthop_is_set (&v->nexthop[i]) &&
+ i < OSPF6_MULTI_PATH_LIMIT; i++)
+ ospf6_nexthop_copy (&w->nexthop[i], &v->nexthop[i]);
+ }
+
+ /* add new candidate to the candidate_list */
+ if (IS_OSPF6_DEBUG_SPF (SUMMARY))
+ zlog_info (" New candidate: %s hops %d cost %d",
+ w->name, w->hops, w->cost);
+ pqueue_enqueue (w, candidate_list);
+ }
+ }
+
+ pqueue_delete (candidate_list);
+}
+
int
ospf6_spf_calculation_thread (struct thread *t)
{
- struct ospf6_area *o6a;
- struct timeval start, end, runtime, interval;
+ struct ospf6_area *oa;
+ struct timeval start, end, runtime;
- o6a = (struct ospf6_area *) THREAD_ARG (t);
- if (! o6a)
- {
- zlog_err ("SPF: Thread error");
- return -1;
- }
+ oa = (struct ospf6_area *) THREAD_ARG (t);
+ oa->thread_spf_calculation = NULL;
- if (! o6a->spf_tree)
- {
- zlog_err ("SPF: Can't find SPF Tree for area: %s", o6a->str);
- return -1;
- }
+ if (IS_OSPF6_DEBUG_SPF (SUMMARY))
+ zlog_info ("SPF calculation for area %s", oa->name);
/* execute SPF calculation */
gettimeofday (&start, (struct timezone *) NULL);
- ospf6_spf_calculation (o6a);
+ ospf6_spf_calculation (oa->ospf6->router_id, oa->spf_table, oa);
gettimeofday (&end, (struct timezone *) NULL);
- /* update statistics */
- o6a->spf_tree->timerun ++;
- ospf6_timeval_sub (&end, &start, &runtime);
- ospf6_timeval_add_equal (&runtime, &o6a->spf_tree->runtime_total);
-
- if (o6a->spf_tree->timerun == 1)
+ if (IS_OSPF6_DEBUG_SPF (SUMMARY))
{
- o6a->spf_tree->runtime_min.tv_sec = runtime.tv_sec;
- o6a->spf_tree->runtime_min.tv_usec = runtime.tv_usec;
- o6a->spf_tree->runtime_max.tv_sec = runtime.tv_sec;
- o6a->spf_tree->runtime_max.tv_usec = runtime.tv_usec;
- }
- if (ospf6_timeval_cmp (o6a->spf_tree->runtime_min, runtime) > 0)
- {
- o6a->spf_tree->runtime_min.tv_sec = runtime.tv_sec;
- o6a->spf_tree->runtime_min.tv_usec = runtime.tv_usec;
- }
- if (ospf6_timeval_cmp (runtime, o6a->spf_tree->runtime_max) > 0)
- {
- o6a->spf_tree->runtime_max.tv_sec = runtime.tv_sec;
- o6a->spf_tree->runtime_max.tv_usec = runtime.tv_usec;
+ timersub (&end, &start, &runtime);
+ zlog_info ("SPF calculation for area %s: runtime %ld sec %ld usec",
+ oa->name, runtime.tv_sec, runtime.tv_usec);
}
- if (o6a->spf_tree->timerun == 1)
- {
- ospf6_timeval_sub (&start, &ospf6->starttime, &interval);
- ospf6_timeval_add_equal (&interval, &o6a->spf_tree->interval_total);
- o6a->spf_tree->interval_min.tv_sec = interval.tv_sec;
- o6a->spf_tree->interval_min.tv_usec = interval.tv_usec;
- o6a->spf_tree->interval_max.tv_sec = interval.tv_sec;
- o6a->spf_tree->interval_max.tv_usec = interval.tv_usec;
- }
- else
- {
- ospf6_timeval_sub (&start, &o6a->spf_tree->updated_time, &interval);
- ospf6_timeval_add_equal (&interval, &o6a->spf_tree->interval_total);
- if (ospf6_timeval_cmp (o6a->spf_tree->interval_min, interval) > 0)
- {
- o6a->spf_tree->interval_min.tv_sec = interval.tv_sec;
- o6a->spf_tree->interval_min.tv_usec = interval.tv_usec;
- }
- if (ospf6_timeval_cmp (interval, o6a->spf_tree->interval_max) > 0)
- {
- o6a->spf_tree->interval_max.tv_sec = interval.tv_sec;
- o6a->spf_tree->interval_max.tv_usec = interval.tv_usec;
- }
- }
- o6a->spf_tree->updated_time.tv_sec = end.tv_sec;
- o6a->spf_tree->updated_time.tv_usec = end.tv_usec;
-
- /* clear thread */
- o6a->spf_tree->t_spf_calculation = (struct thread *) NULL;
+ ospf6_intra_route_calculation (oa);
+ ospf6_intra_asbr_calculation (oa);
return 0;
}
void
-ospf6_spf_database_hook (struct ospf6_lsa *old, struct ospf6_lsa *new)
+ospf6_spf_schedule (struct ospf6_area *oa)
{
- struct ospf6_area *o6a = NULL;
- struct ospf6_interface *o6i = NULL;
-
- if (new->header->type == htons (OSPF6_LSA_TYPE_ROUTER) ||
- new->header->type == htons (OSPF6_LSA_TYPE_NETWORK))
- o6a = new->scope;
- else if (new->header->type == htons (OSPF6_LSA_TYPE_LINK))
- {
- o6i = new->scope;
- o6a = o6i->area;
- }
-
- if (o6a)
- ospf6_spf_calculation_schedule (o6a->area_id);
-}
-
-void
-ospf6_spf_calculation_schedule (u_int32_t area_id)
-{
- struct ospf6_area *o6a;
- char buf[64];
-
- o6a = ospf6_area_lookup (area_id, ospf6);
- if (! o6a)
- {
- inet_ntop (AF_INET, &area_id, buf, sizeof (buf));
- zlog_err ("SPF: Can't find area: %s", buf);
- return;
- }
-
- if (! o6a->spf_tree)
- {
- zlog_err ("SPF: Can't find SPF Tree for area: %s", o6a->str);
- return;
- }
-
- if (o6a->spf_tree->t_spf_calculation)
+ if (oa->thread_spf_calculation)
return;
-
- o6a->spf_tree->t_spf_calculation =
- thread_add_event (master, ospf6_spf_calculation_thread, o6a, 0);
-}
-
-struct ospf6_spftree *
-ospf6_spftree_create ()
-{
- struct ospf6_spftree *spf_tree;
- spf_tree = (struct ospf6_spftree *) XMALLOC (MTYPE_OSPF6_SPFTREE,
- sizeof (struct ospf6_spftree));
- if (! spf_tree)
- {
- zlog_err ("SPF: Can't allocate memory for SPF tree");
- return (struct ospf6_spftree *) NULL;
- }
- memset (spf_tree, 0, sizeof (spf_tree));
-
- spf_tree->list = list_new ();
-
- return spf_tree;
+ oa->thread_spf_calculation =
+ thread_add_event (master, ospf6_spf_calculation_thread, oa, 0);
}
void
-ospf6_spftree_delete (struct ospf6_spftree *spf_tree)
+ospf6_spf_display_subtree (struct vty *vty, char *prefix, int rest,
+ struct ospf6_vertex *v)
{
listnode node;
- struct ospf6_vertex *v;
-
- /* Delete spf tree */
- for (node = listhead (spf_tree->list); node; nextnode (node))
- {
- v = (struct ospf6_vertex *) getdata (node);
- ospf6_spf_vertex_delete (v);
- }
- list_delete_all_node (spf_tree->list);
-
- XFREE (MTYPE_OSPF6_SPFTREE, spf_tree);
-}
-
-void
-ospf6_nexthop_show (struct vty *vty, struct ospf6_nexthop *nexthop)
-{
- char buf[128], *ifname;
- struct ospf6_interface *o6i;
-
- ifname = NULL;
-
- o6i = ospf6_interface_lookup_by_index (nexthop->ifindex);
- if (! o6i)
- {
- zlog_err ("Spf: invalid ifindex %d in nexthop", nexthop->ifindex);
- }
- else
- ifname = o6i->interface->name;
-
- inet_ntop (AF_INET6, &nexthop->address, buf, sizeof (buf));
- vty_out (vty, " %s%%%s(%d)%s", buf, ifname,
- nexthop->ifindex, VTY_NEWLINE);
-}
-
-void
-ospf6_vertex_show (struct vty *vty, struct ospf6_vertex *vertex)
-{
- listnode node;
- struct ospf6_vertex *v;
- struct linklist_node lnode;
-
- vty_out (vty, "SPF node %s%s", vertex->string, VTY_NEWLINE);
- vty_out (vty, " cost to this node: %d%s", vertex->distance, VTY_NEWLINE);
- vty_out (vty, " hops to this node: %d%s", vertex->depth, VTY_NEWLINE);
-
- vty_out (vty, " nexthops reachable to this node:%s", VTY_NEWLINE);
- for (linklist_head (vertex->nexthop_list, &lnode);
- ! linklist_end (&lnode);
- linklist_next (&lnode))
- ospf6_nexthop_show (vty, (struct ospf6_nexthop *) lnode.data);
-
- vty_out (vty, " parent nodes to this node:%s", VTY_NEWLINE);
- if (! list_isempty (vertex->parent_list))
- vty_out (vty, " ");
- for (node = listhead (vertex->parent_list); node; nextnode (node))
- {
- v = (struct ospf6_vertex *) getdata (node);
- vty_out (vty, "%s ", v->string);
- }
- if (! list_isempty (vertex->parent_list))
- vty_out (vty, "%s", VTY_NEWLINE);
-
- vty_out (vty, " child nodes to this node:%s", VTY_NEWLINE);
- if (! list_isempty (vertex->path_list))
- vty_out (vty, " ");
- for (node = listhead (vertex->path_list); node; nextnode (node))
- {
- v = (struct ospf6_vertex *) getdata (node);
- vty_out (vty, "%s ", v->string);
- }
- if (! list_isempty (vertex->path_list))
- vty_out (vty, "%s", VTY_NEWLINE);
-
- vty_out (vty, "%s", VTY_NEWLINE);
-}
-
-void
-ospf6_spf_statistics_show (struct vty *vty, struct ospf6_spftree *spf_tree)
-{
- listnode node;
- struct ospf6_vertex *vertex;
- u_int router_count, network_count, maxdepth;
- struct timeval runtime_avg, interval_avg, last_updated, now;
- char rmin[64], rmax[64], ravg[64];
- char imin[64], imax[64], iavg[64];
- char last_updated_string[64];
-
- maxdepth = router_count = network_count = 0;
- for (node = listhead (spf_tree->list); node; nextnode (node))
- {
- vertex = (struct ospf6_vertex *) getdata (node);
- if (vertex->vertex_id.id.s_addr)
- network_count++;
- else
- router_count++;
- if (maxdepth < vertex->depth)
- maxdepth = vertex->depth;
- }
-
- ospf6_timeval_div (&spf_tree->runtime_total, spf_tree->timerun,
- &runtime_avg);
- ospf6_timeval_string (&spf_tree->runtime_min, rmin, sizeof (rmin));
- ospf6_timeval_string (&spf_tree->runtime_max, rmax, sizeof (rmax));
- ospf6_timeval_string (&runtime_avg, ravg, sizeof (ravg));
-
- ospf6_timeval_div (&spf_tree->interval_total, spf_tree->timerun,
- &interval_avg);
- ospf6_timeval_string (&spf_tree->interval_min, imin, sizeof (imin));
- ospf6_timeval_string (&spf_tree->interval_max, imax, sizeof (imax));
- ospf6_timeval_string (&interval_avg, iavg, sizeof (iavg));
-
- gettimeofday (&now, (struct timezone *) NULL);
- ospf6_timeval_sub (&now, &spf_tree->updated_time, &last_updated);
- ospf6_timeval_string (&last_updated, last_updated_string,
- sizeof (last_updated_string));
-
- vty_out (vty, " SPF algorithm executed %d times%s",
- spf_tree->timerun, VTY_NEWLINE);
- vty_out (vty, " Average time to run SPF: %s%s",
- ravg, VTY_NEWLINE);
- vty_out (vty, " Maximum time to run SPF: %s%s",
- rmax, VTY_NEWLINE);
- vty_out (vty, " Average interval of SPF: %s%s",
- iavg, VTY_NEWLINE);
- vty_out (vty, " SPF last updated: %s ago%s",
- last_updated_string, VTY_NEWLINE);
- vty_out (vty, " Current SPF node count: %d%s",
- listcount (spf_tree->list), VTY_NEWLINE);
- vty_out (vty, " Router: %d Network: %d%s",
- router_count, network_count, VTY_NEWLINE);
- vty_out (vty, " Maximum of Hop count to nodes: %d%s",
- maxdepth, VTY_NEWLINE);
-}
-
-DEFUN (show_ipv6_ospf6_area_spf_node,
- show_ipv6_ospf6_area_spf_node_cmd,
- "show ipv6 ospf6 area A.B.C.D spf node",
- SHOW_STR
- IP6_STR
- OSPF6_STR
- OSPF6_AREA_STR
- OSPF6_AREA_ID_STR
- "Shortest Path First caculation\n"
- "vertex infomation\n"
- )
-{
- listnode i;
- u_int32_t area_id;
- struct ospf6_area *o6a;
- struct ospf6_vertex *vertex;
-
- OSPF6_CMD_CHECK_RUNNING ();
-
- inet_pton (AF_INET, argv[0], &area_id);
- o6a = ospf6_area_lookup (area_id, ospf6);
- if (! o6a)
- return CMD_SUCCESS;
-
- for (i = listhead (o6a->spf_tree->list); i; nextnode (i))
- {
- vertex = (struct ospf6_vertex *) getdata (i);
- ospf6_vertex_show (vty, vertex);
- }
-
- return CMD_SUCCESS;
-}
-
-static void
-ospf6_spftree_show (struct vty *vty, char *prefix, int current_rest,
- struct ospf6_vertex *v)
-{
- char *p;
- int psize;
+ struct ospf6_vertex *c;
+ char *next_prefix;
+ int len;
int restnum;
- listnode node;
- vty_out (vty, "%s+-%s%s", prefix, v->string, VTY_NEWLINE);
+ /* "prefix" is the space prefix of the display line */
+ vty_out (vty, "%s+-%s [%d]%s", prefix, v->name, v->cost, VTY_NEWLINE);
- if (listcount (v->path_list) == 0)
- return;
-
- psize = strlen (prefix) + 3;
- p = malloc (psize);
- if (!p)
+ len = strlen (prefix) + 4;
+ next_prefix = (char *) malloc (len);
+ if (next_prefix == NULL)
{
- vty_out (vty, "depth too long ...%s", VTY_NEWLINE);
+ vty_out (vty, "malloc failed%s", VTY_NEWLINE);
return;
}
+ snprintf (next_prefix, len, "%s%s", prefix, (rest ? "| " : " "));
- restnum = listcount (v->path_list);
- for (node = listhead (v->path_list); node; nextnode (node))
+ restnum = listcount (v->child_list);
+ LIST_LOOP (v->child_list, c, node)
{
- --restnum;
- snprintf (p, psize, "%s%s", prefix, (current_rest ? "| " : " "));
- ospf6_spftree_show (vty, p, restnum,
- (struct ospf6_vertex *) getdata (node));
+ restnum--;
+ ospf6_spf_display_subtree (vty, next_prefix, restnum, c);
}
- free (p);
+ free (next_prefix);
}
-DEFUN (show_ipv6_ospf6_area_spf_tree,
- show_ipv6_ospf6_area_spf_tree_cmd,
- "show ipv6 ospf6 area A.B.C.D spf tree",
- SHOW_STR
- IP6_STR
+DEFUN (debug_ospf6_spf_detail,
+ debug_ospf6_spf_detail_cmd,
+ "debug ospf6 spf detail",
+ DEBUG_STR
OSPF6_STR
- OSPF6_AREA_STR
- OSPF6_AREA_ID_STR
- "Shortest Path First caculation\n"
- "Displays spf tree\n")
+ "Debug SPF Calculation\n"
+ "Debug Detailed SPF\n"
+ )
{
- u_int32_t area_id;
- struct ospf6_area *o6a;
-
- OSPF6_CMD_CHECK_RUNNING ();
-
- inet_pton (AF_INET, argv[0], &area_id);
- o6a = ospf6_area_lookup (area_id, ospf6);
- if (! o6a)
- return CMD_SUCCESS;
-
- vty_out (vty, "%s SPF tree for Area %s%s%s",
- VTY_NEWLINE, o6a->str, VTY_NEWLINE, VTY_NEWLINE);
-
- if (! o6a->spf_tree->root)
- return CMD_SUCCESS;
-
- ospf6_spftree_show (vty, "", 0, o6a->spf_tree->root);
+ unsigned char level = 0;
+ level = OSPF6_DEBUG_SPF_SUMMARY | OSPF6_DEBUG_SPF_DETAIL;
+ OSPF6_DEBUG_SPF_ON (level);
return CMD_SUCCESS;
}
-DEFUN (show_ipv6_ospf6_area_topology,
- show_ipv6_ospf6_area_topology_cmd,
- "show ipv6 ospf6 area A.B.C.D topology",
- SHOW_STR
- IP6_STR
+DEFUN (debug_ospf6_spf,
+ debug_ospf6_spf_cmd,
+ "debug ospf6 spf",
+ DEBUG_STR
OSPF6_STR
- OSPF6_AREA_STR
- OSPF6_AREA_ID_STR
- OSPF6_SPF_STR
- "Displays SPF topology table\n")
+ "Debug SPF Calculation\n"
+ )
{
- struct ospf6_area *o6a;
- u_int32_t area_id;
-
- OSPF6_CMD_CHECK_RUNNING ();
-
- inet_pton (AF_INET, argv[0], &area_id);
- o6a = ospf6_area_lookup (area_id, ospf6);
-
- if (! o6a)
- return CMD_SUCCESS;
-
- argc -= 1;
- argv += 1;
-
- return ospf6_route_table_show (vty, argc, argv, o6a->table_topology);
+ unsigned char level = 0;
+ level = OSPF6_DEBUG_SPF_SUMMARY;
+ OSPF6_DEBUG_SPF_ON (level);
+ return CMD_SUCCESS;
}
-ALIAS (show_ipv6_ospf6_area_topology,
- show_ipv6_ospf6_area_topology_router_cmd,
- "show ipv6 ospf6 area A.B.C.D topology (A.B.C.D|<0-4294967295>|detail)",
- SHOW_STR
- IP6_STR
+DEFUN (no_debug_ospf6_spf_detail,
+ no_debug_ospf6_spf_detail_cmd,
+ "no debug ospf6 spf detail",
+ NO_STR
+ DEBUG_STR
OSPF6_STR
- OSPF6_AREA_STR
- OSPF6_AREA_ID_STR
- OSPF6_SPF_STR
- "Displays SPF topology table\n"
- OSPF6_ROUTER_ID_STR
- OSPF6_ROUTER_ID_STR
- )
+ "Quit Debugging SPF Calculation\n"
+ "Quit Debugging Detailed SPF (change to debug summary)\n"
+ )
+{
+ unsigned char level = 0;
+ level = OSPF6_DEBUG_SPF_DETAIL;
+ OSPF6_DEBUG_SPF_OFF (level);
+ return CMD_SUCCESS;
+}
-ALIAS (show_ipv6_ospf6_area_topology,
- show_ipv6_ospf6_area_topology_router_lsid_cmd,
- "show ipv6 ospf6 area A.B.C.D topology (A.B.C.D|<0-4294967295>) (A.B.C.D|<0-4294967295>)",
- SHOW_STR
- IP6_STR
+DEFUN (no_debug_ospf6_spf,
+ no_debug_ospf6_spf_cmd,
+ "no debug ospf6 spf",
+ NO_STR
+ DEBUG_STR
OSPF6_STR
- OSPF6_AREA_STR
- OSPF6_AREA_ID_STR
- OSPF6_SPF_STR
- "Displays SPF topology table\n"
- OSPF6_ROUTER_ID_STR
- OSPF6_ROUTER_ID_STR
- OSPF6_LS_ID_STR
- OSPF6_LS_ID_STR
- )
+ "Quit Debugging SPF Calculation\n"
+ )
+{
+ unsigned char level = 0;
+ level = OSPF6_DEBUG_SPF_SUMMARY | OSPF6_DEBUG_SPF_DETAIL;
+ OSPF6_DEBUG_SPF_OFF (level);
+ return CMD_SUCCESS;
+}
+
+int
+config_write_ospf6_debug_spf (struct vty *vty)
+{
+ if (IS_OSPF6_DEBUG_SPF (DETAIL))
+ vty_out (vty, "debug ospf6 spf detail%s", VTY_NEWLINE);
+ else if (IS_OSPF6_DEBUG_SPF (SUMMARY))
+ vty_out (vty, "debug ospf6 spf%s", VTY_NEWLINE);
+ return 0;
+}
+
+void
+install_element_ospf6_debug_spf ()
+{
+ install_element (ENABLE_NODE, &debug_ospf6_spf_cmd);
+ install_element (ENABLE_NODE, &debug_ospf6_spf_detail_cmd);
+ install_element (ENABLE_NODE, &no_debug_ospf6_spf_cmd);
+ install_element (ENABLE_NODE, &no_debug_ospf6_spf_detail_cmd);
+ install_element (CONFIG_NODE, &debug_ospf6_spf_cmd);
+ install_element (CONFIG_NODE, &debug_ospf6_spf_detail_cmd);
+ install_element (CONFIG_NODE, &no_debug_ospf6_spf_cmd);
+ install_element (CONFIG_NODE, &no_debug_ospf6_spf_detail_cmd);
+}
void
ospf6_spf_init ()
{
- nexthop_list = linklist_create ();
- ospf6_spf_candidate_init ();
- install_element (VIEW_NODE, &show_ipv6_ospf6_area_spf_node_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_area_topology_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_area_topology_router_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_area_topology_router_lsid_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_area_spf_node_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_area_spf_tree_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_area_topology_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_area_topology_router_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_area_topology_router_lsid_cmd);
}
+
diff --git a/ospf6d/ospf6_spf.h b/ospf6d/ospf6_spf.h
index de50e94..1c04afb 100644
--- a/ospf6d/ospf6_spf.h
+++ b/ospf6d/ospf6_spf.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -22,7 +22,16 @@
#ifndef OSPF6_SPF_H
#define OSPF6_SPF_H
-#include "prefix.h"
+/* Debug option */
+extern unsigned char conf_debug_ospf6_spf;
+#define OSPF6_DEBUG_SPF_SUMMARY 0x01
+#define OSPF6_DEBUG_SPF_DETAIL 0x02
+#define OSPF6_DEBUG_SPF_ON(level) \
+ (conf_debug_ospf6_spf |= (level))
+#define OSPF6_DEBUG_SPF_OFF(level) \
+ (conf_debug_ospf6_spf &= ~(level))
+#define IS_OSPF6_DEBUG_SPF(level) \
+ (conf_debug_ospf6_spf & OSPF6_DEBUG_SPF_ ## level)
/* Transit Vertex */
struct ospf6_vertex
@@ -31,74 +40,53 @@
u_int8_t type;
/* Vertex Identifier */
- struct prefix_ls vertex_id;
+ struct prefix vertex_id;
/* Identifier String */
- char string[128];
+ char name[128];
+
+ /* Associated Area */
+ struct ospf6_area *area;
/* Associated LSA */
struct ospf6_lsa *lsa;
- /* Distance from Root (Cost) */
- u_int16_t distance;
+ /* Distance from Root (i.e. Cost) */
+ u_int32_t cost;
- /* Depth of this node */
- u_char depth;
+ /* Router hops to this node */
+ u_char hops;
/* nexthops to this node */
- struct linklist *nexthop_list;
-
- /* upper nodes in spf tree */
- list parent_list;
-
- /* lower nodes in spf tree */
- list path_list;
+ struct ospf6_nexthop nexthop[OSPF6_MULTI_PATH_LIMIT];
/* capability bits */
- u_char capability_bits;
+ u_char capability;
/* Optional capabilities */
- u_char opt_capability[3];
+ u_char options[3];
+
+ /* For tree display */
+ struct ospf6_vertex *parent;
+ list child_list;
};
#define OSPF6_VERTEX_TYPE_ROUTER 0x01
#define OSPF6_VERTEX_TYPE_NETWORK 0x02
+#define VERTEX_IS_TYPE(t, v) \
+ ((v)->type == OSPF6_VERTEX_TYPE_ ## t ? 1 : 0)
-struct ospf6_spftree
-{
- /* calculation thread */
- struct thread *t_spf_calculation;
+void ospf6_spf_table_finish (struct ospf6_route_table *result_table);
+void ospf6_spf_calculation (u_int32_t router_id,
+ struct ospf6_route_table *result_table,
+ struct ospf6_area *oa);
+void ospf6_spf_schedule (struct ospf6_area *oa);
- /* root of this tree */
- struct ospf6_vertex *root;
+void ospf6_spf_display_subtree (struct vty *vty, char *prefix,
+ int rest, struct ospf6_vertex *v);
- /* list for search */
- list list;
-
- /* statistics */
- u_int32_t timerun;
-
- struct timeval runtime_total;
- struct timeval runtime_min;
- struct timeval runtime_max;
-
- struct timeval updated_time;
- struct timeval interval_total;
- struct timeval interval_min;
- struct timeval interval_max;
-};
-
-int ospf6_spf_calculate_route (void *);
-
-void
-ospf6_spf_calculation_schedule (u_int32_t area_id);
-struct ospf6_spftree *ospf6_spftree_create ();
-void
-ospf6_spf_statistics_show (struct vty *vty, struct ospf6_spftree *spf_tree);
-void ospf6_spftree_delete (struct ospf6_spftree *spf_tree);
-
-void ospf6_spf_database_hook (struct ospf6_lsa *old, struct ospf6_lsa *new);
-
+int config_write_ospf6_debug_spf (struct vty *vty);
+void install_element_ospf6_debug_spf ();
void ospf6_spf_init ();
#endif /* OSPF6_SPF_H */
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index f9cc329..b1c1644 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -1,6 +1,5 @@
/*
- * OSPFv3 Top Level Data Structure
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -31,299 +30,419 @@
#include "thread.h"
#include "command.h"
-#include "ospf6_hook.h"
+#include "ospf6d.h"
#include "ospf6_proto.h"
-#include "ospf6_prefix.h"
+#include "ospf6_message.h"
#include "ospf6_lsa.h"
#include "ospf6_lsdb.h"
-
-#include "ospf6_message.h"
-#include "ospf6_neighbor.h"
-#include "ospf6_interface.h"
-#include "ospf6_area.h"
-#include "ospf6_top.h"
-
#include "ospf6_route.h"
#include "ospf6_zebra.h"
-#include "ospf6_nsm.h"
-#include "ospf6_asbr.h"
-#include "ospf6_abr.h"
+#include "ospf6_top.h"
+#include "ospf6_area.h"
+#include "ospf6_interface.h"
+#include "ospf6_neighbor.h"
-#define HEADER_DEPENDENCY
-#include "ospf6d.h"
-#undef HEADER_DEPENDENCY
+#include "ospf6_asbr.h"
/* global ospf6d variable */
struct ospf6 *ospf6;
-static void
-ospf6_top_foreach_area (struct ospf6 *o6, void *arg, int val,
- void (*func) (void *, int, void *))
+void
+ospf6_top_lsdb_hook_add (struct ospf6_lsa *lsa)
{
- listnode node;
- struct ospf6_area *o6a;
-
- for (node = listhead (o6->area_list); node; nextnode (node))
+ switch (ntohs (lsa->header->type))
{
- o6a = (struct ospf6_area *) getdata (node);
- (*func) (arg, val, o6a);
+ case OSPF6_LSTYPE_AS_EXTERNAL:
+ ospf6_asbr_lsa_add (lsa);
+ break;
+
+ default:
+ if (IS_OSPF6_DEBUG_LSA (RECV))
+ zlog_info ("Unknown LSA in AS-scoped lsdb");
+ break;
}
}
-static void
-ospf6_top_foreach_interface (struct ospf6 *o6, void *arg, int val,
- void (*func) (void *, int, void *))
+void
+ospf6_top_lsdb_hook_remove (struct ospf6_lsa *lsa)
{
- listnode node;
- struct ospf6_area *o6a;
-
- for (node = listhead (o6->area_list); node; nextnode (node))
+ switch (ntohs (lsa->header->type))
{
- o6a = (struct ospf6_area *) getdata (node);
- (*o6a->foreach_if) (o6a, arg, val, func);
+ case OSPF6_LSTYPE_AS_EXTERNAL:
+ ospf6_asbr_lsa_remove (lsa);
+ break;
+
+ default:
+ if (IS_OSPF6_DEBUG_LSA (RECV))
+ zlog_info ("Unknown LSA in AS-scoped lsdb");
+ break;
}
}
-static void
-ospf6_top_foreach_neighbor (struct ospf6 *o6, void *arg, int val,
- void (*func) (void *, int, void *))
+struct ospf6 *
+ospf6_create ()
{
- listnode node;
- struct ospf6_area *o6a;
+ struct ospf6 *o;
- for (node = listhead (o6->area_list); node; nextnode (node))
+ o = XMALLOC (MTYPE_OSPF6_TOP, sizeof (struct ospf6));
+ memset (o, 0, sizeof (struct ospf6));
+
+ /* initialize */
+ gettimeofday (&o->starttime, (struct timezone *) NULL);
+ o->area_list = list_new ();
+ o->area_list->cmp = ospf6_area_cmp;
+ o->lsdb = ospf6_lsdb_create ();
+ o->lsdb->hook_add = ospf6_top_lsdb_hook_add;
+ o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove;
+
+ o->route_table = ospf6_route_table_create ();
+ o->route_table->hook_add = ospf6_zebra_route_update_add;
+ o->route_table->hook_remove = ospf6_zebra_route_update_remove;
+
+ o->asbr_table = ospf6_route_table_create ();
+ o->asbr_table->hook_add = ospf6_asbr_lsentry_add;
+ o->asbr_table->hook_remove = ospf6_asbr_lsentry_remove;
+
+ o->external_table = ospf6_route_table_create ();
+ o->external_id_table = route_table_init ();
+
+ return o;
+}
+
+void
+ospf6_delete (struct ospf6 *o)
+{
+ listnode i;
+ struct ospf6_area *oa;
+
+ for (i = listhead (o->area_list); i; nextnode (i))
{
- o6a = (struct ospf6_area *) getdata (node);
- (*o6a->foreach_nei) (o6a, arg, val, func);
+ oa = (struct ospf6_area *) getdata (i);
+ ospf6_area_delete (oa);
+ }
+
+ ospf6_lsdb_delete (o->lsdb);
+
+ ospf6_route_table_delete (o->route_table);
+ ospf6_route_table_delete (o->asbr_table);
+
+ ospf6_route_table_delete (o->external_table);
+ route_table_finish (o->external_id_table);
+
+ XFREE (MTYPE_OSPF6_TOP, o);
+}
+
+void
+ospf6_enable (struct ospf6 *o)
+{
+ listnode i;
+ struct ospf6_area *oa;
+
+ if (CHECK_FLAG (o->flag, OSPF6_DISABLED))
+ {
+ UNSET_FLAG (o->flag, OSPF6_DISABLED);
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ oa = (struct ospf6_area *) getdata (i);
+ ospf6_area_enable (oa);
+ }
}
}
-static int
-ospf6_top_maxage_remover (struct thread *t)
+void
+ospf6_disable (struct ospf6 *o)
{
- int count;
- struct ospf6 *o6 = (struct ospf6 *) THREAD_ARG (t);
+ listnode i;
+ struct ospf6_area *oa;
- o6->maxage_remover = (struct thread *) NULL;
+ if (! CHECK_FLAG (o->flag, OSPF6_DISABLED))
+ {
+ SET_FLAG (o->flag, OSPF6_DISABLED);
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ oa = (struct ospf6_area *) getdata (i);
+ ospf6_area_disable (oa);
+ }
- count = 0;
- o6->foreach_nei (o6, &count, NBS_EXCHANGE, ospf6_count_state);
- o6->foreach_nei (o6, &count, NBS_LOADING, ospf6_count_state);
- if (count != 0)
- return 0;
+ ospf6_lsdb_remove_all (o->lsdb);
+ ospf6_route_remove_all (o->route_table);
+ ospf6_route_remove_all (o->asbr_table);
+ }
+}
- ospf6_lsdb_remove_maxage (o6->lsdb);
+int
+ospf6_maxage_remover (struct thread *thread)
+{
+ struct ospf6 *o = (struct ospf6 *) THREAD_ARG (thread);
+ struct ospf6_area *oa;
+ struct ospf6_interface *oi;
+ struct ospf6_neighbor *on;
+ listnode i, j, k;
+
+ o->maxage_remover = (struct thread *) NULL;
+ if (IS_OSPF6_DEBUG_LSA (TIMER))
+ zlog_info ("Maxage Remover");
+
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ oa = (struct ospf6_area *) getdata (i);
+ for (j = listhead (oa->if_list); j; nextnode (j))
+ {
+ oi = (struct ospf6_interface *) getdata (j);
+ for (k = listhead (oi->neighbor_list); k; nextnode (k))
+ {
+ on = (struct ospf6_neighbor *) getdata (k);
+ if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
+ on->state != OSPF6_NEIGHBOR_LOADING)
+ continue;
+
+ if (IS_OSPF6_DEBUG_LSA (TIMER))
+ zlog_info ("Maxage Remover End: %s exchange or loading",
+ on->name);
+ return 0;
+ }
+ }
+ }
+
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ oa = (struct ospf6_area *) getdata (i);
+ for (j = listhead (oa->if_list); j; nextnode (j))
+ {
+ oi = (struct ospf6_interface *) getdata (j);
+ OSPF6_LSDB_MAXAGE_REMOVER (oi->lsdb);
+ }
+ OSPF6_LSDB_MAXAGE_REMOVER (oa->lsdb);
+ }
+ OSPF6_LSDB_MAXAGE_REMOVER (o->lsdb);
+
+ if (IS_OSPF6_DEBUG_LSA (TIMER))
+ zlog_info ("Maxage Remover End");
+
return 0;
}
void
-ospf6_top_schedule_maxage_remover (void *arg, int val, struct ospf6 *o6)
+ospf6_maxage_remove (struct ospf6 *o)
{
- if (o6->maxage_remover != NULL)
- return;
+ if (o && ! o->maxage_remover)
+ o->maxage_remover = thread_add_event (master, ospf6_maxage_remover, o, 0);
+}
- o6->maxage_remover =
- thread_add_event (master, ospf6_top_maxage_remover, o6, 0);
+/* start ospf6 */
+DEFUN (router_ospf6,
+ router_ospf6_cmd,
+ "router ospf6",
+ ROUTER_STR
+ OSPF6_STR)
+{
+ if (ospf6 == NULL)
+ ospf6 = ospf6_create ();
+ if (CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
+ ospf6_enable (ospf6);
+
+ /* set current ospf point. */
+ vty->node = OSPF6_NODE;
+ vty->index = ospf6;
+
+ return CMD_SUCCESS;
+}
+
+/* stop ospf6 */
+DEFUN (no_router_ospf6,
+ no_router_ospf6_cmd,
+ "no router ospf6",
+ NO_STR
+ OSPF6_ROUTER_STR)
+{
+ if (ospf6 == NULL || CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
+ vty_out (vty, "OSPFv3 is not running%s", VTY_NEWLINE);
+ else
+ ospf6_disable (ospf6);
+
+ /* return to config node . */
+ vty->node = CONFIG_NODE;
+ vty->index = NULL;
+
+ return CMD_SUCCESS;
+}
+
+/* change Router_ID commands. */
+DEFUN (ospf6_router_id,
+ ospf6_router_id_cmd,
+ "router-id A.B.C.D",
+ "Configure OSPF Router-ID\n"
+ V4NOTATION_STR)
+{
+ int ret;
+ u_int32_t router_id;
+ struct ospf6 *o;
+
+ o = (struct ospf6 *) vty->index;
+
+ ret = inet_pton (AF_INET, argv[0], &router_id);
+ if (ret == 0)
+ {
+ vty_out (vty, "malformed OSPF Router-ID: %s%s", argv[0], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ o->router_id = router_id;
+ return CMD_SUCCESS;
+}
+
+DEFUN (ospf6_interface_area,
+ ospf6_interface_area_cmd,
+ "interface IFNAME area A.B.C.D",
+ "Enable routing on an IPv6 interface\n"
+ IFNAME_STR
+ "Specify the OSPF6 area ID\n"
+ "OSPF6 area ID in IPv4 address notation\n"
+ )
+{
+ struct ospf6 *o;
+ struct ospf6_area *oa;
+ struct ospf6_interface *oi;
+ struct interface *ifp;
+ u_int32_t area_id;
+
+ o = (struct ospf6 *) vty->index;
+
+ /* find/create ospf6 interface */
+ ifp = if_get_by_name (argv[0]);
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
+ oi = ospf6_interface_create (ifp);
+ if (oi->area)
+ {
+ vty_out (vty, "%s already attached to Area %s%s",
+ oi->interface->name, oi->area->name, VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ /* parse Area-ID */
+ if (inet_pton (AF_INET, argv[1], &area_id) != 1)
+ {
+ vty_out (vty, "Invalid Area-ID: %s%s", argv[1], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ /* find/create ospf6 area */
+ oa = ospf6_area_lookup (area_id, o);
+ if (oa == NULL)
+ oa = ospf6_area_create (area_id, o);
+
+ /* attach interface to area */
+ listnode_add (oa->if_list, oi); /* sort ?? */
+ oi->area = oa;
+
+ /* start up */
+ thread_add_event (master, interface_up, oi, 0);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf6_interface_area,
+ no_ospf6_interface_area_cmd,
+ "no interface IFNAME area A.B.C.D",
+ NO_STR
+ "Disable routing on an IPv6 interface\n"
+ IFNAME_STR
+ "Specify the OSPF6 area ID\n"
+ "OSPF6 area ID in IPv4 address notation\n"
+ )
+{
+ struct ospf6 *o;
+ struct ospf6_interface *oi;
+ struct interface *ifp;
+ u_int32_t area_id;
+
+ o = (struct ospf6 *) vty->index;
+
+ ifp = if_lookup_by_name (argv[0]);
+ if (ifp == NULL)
+ {
+ vty_out (vty, "No such interface %s%s", argv[0], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ oi = (struct ospf6_interface *) ifp->info;
+ if (oi == NULL)
+ {
+ vty_out (vty, "Interface %s not enabled%s", ifp->name, VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ /* parse Area-ID */
+ if (inet_pton (AF_INET, argv[1], &area_id) != 1)
+ {
+ vty_out (vty, "Invalid Area-ID: %s%s", argv[1], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ if (oi->area->area_id != area_id)
+ {
+ vty_out (vty, "Wrong Area-ID: %s is attached to area %s%s",
+ oi->interface->name, oi->area->name, VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ thread_execute (master, interface_down, oi, 0);
+
+ listnode_delete (oi->area->if_list, oi);
+ oi->area = (struct ospf6_area *) NULL;
+
+ return CMD_SUCCESS;
}
void
-ospf6_show (struct vty *vty)
+ospf6_show (struct vty *vty, struct ospf6 *o)
{
listnode n;
- struct ospf6_area *area;
- char id_string[32];
- unsigned long day, hour, min, sec;
+ struct ospf6_area *oa;
+ char router_id[16], duration[32];
struct timeval now, running;
/* process id, router id */
- inet_ntop (AF_INET, &ospf6->router_id, id_string, sizeof (id_string));
- vty_out (vty, " Routing Process (%lu) with ID %s%s",
- ospf6->process_id, id_string, VTY_NEWLINE);
+ inet_ntop (AF_INET, &o->router_id, router_id, sizeof (router_id));
+ vty_out (vty, " OSPFv3 Routing Process (0) with Router-ID %s%s",
+ router_id, VTY_NEWLINE);
/* running time */
gettimeofday (&now, (struct timezone *)NULL);
- ospf6_timeval_sub (&now, &ospf6->starttime, &running);
- ospf6_timeval_decode (&running, &day, &hour, &min, &sec, NULL, NULL);
- vty_out (vty, " Running %ld days %ld hours %ld minutes %ld seconds%s",
- day, hour, min, sec, VTY_NEWLINE);
+ timersub (&now, &o->starttime, &running);
+ timerstring (&running, duration, sizeof (duration));
+ vty_out (vty, " Running %s%s", duration, VTY_NEWLINE);
- vty_out (vty, " Supports only single TOS(TOS0) routes%s", VTY_NEWLINE);
-
- /* Redistribute config */
- ospf6_redistribute_show_config (vty);
+ /* Redistribute configuration */
+ /* XXX */
/* LSAs */
vty_out (vty, " Number of AS scoped LSAs is %u%s",
- ospf6->lsdb->count, VTY_NEWLINE);
- vty_out (vty, " Route calculation executed %d times%s",
- ospf6->stat_route_calculation_execed, VTY_NEWLINE);
-
- /* Route Statistics */
-#if 0
- ospf6_route_statistics_show (vty, ospf6->route_table);
-#endif
+ o->lsdb->count, VTY_NEWLINE);
/* Areas */
vty_out (vty, " Number of areas in this router is %u%s",
- listcount (ospf6->area_list), VTY_NEWLINE);
- for (n = listhead (ospf6->area_list); n; nextnode (n))
+ listcount (o->area_list), VTY_NEWLINE);
+ for (n = listhead (o->area_list); n; nextnode (n))
{
- area = (struct ospf6_area *) getdata (n);
- ospf6_area_show (vty, area);
+ oa = (struct ospf6_area *) getdata (n);
+ ospf6_area_show (vty, oa);
}
}
-void
-ospf6_statistics_show (struct vty *vty, struct ospf6 *o6)
+/* show top level structures */
+DEFUN (show_ipv6_ospf6,
+ show_ipv6_ospf6_cmd,
+ "show ipv6 ospf6",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR)
{
- listnode node;
- struct ospf6_area *o6a;
- char running_time[128];
- struct timeval now, running;
+ OSPF6_CMD_CHECK_RUNNING ();
- gettimeofday (&now, (struct timezone *) NULL);
- ospf6_timeval_sub (&now, &o6->starttime, &running);
- ospf6_timeval_string (&running, running_time, sizeof (running_time));
-
- vty_out (vty, "Statistics of OSPF process %ld%s",
- o6->process_id, VTY_NEWLINE);
- vty_out (vty, " Running: %s%s", running_time, VTY_NEWLINE);
-
-#if 0
- ospf6_route_statistics_show (vty, o6->route_table);
-#endif
-
- for (node = listhead (o6->area_list); node; nextnode (node))
- {
- o6a = (struct ospf6_area *) getdata (node);
- ospf6_area_statistics_show (vty, o6a);
- }
-}
-
-static struct ospf6 *
-ospf6_new ()
-{
- struct ospf6 *new;
- new = XMALLOC (MTYPE_OSPF6_TOP, sizeof (struct ospf6));
- if (new)
- memset (new, 0, sizeof (struct ospf6));
- return new;
-}
-
-void
-ospf6_free (struct ospf6 *ospf6)
-{
- XFREE (MTYPE_OSPF6_TOP, ospf6);
-}
-
-void
-ospf6_top_topology_add (struct ospf6_route_req *request)
-{
- assert (request->route.type == OSPF6_DEST_TYPE_ROUTER);
- if (CHECK_FLAG (request->path.router_bits, OSPF6_ROUTER_LSA_BIT_E))
- ospf6_asbr_asbr_entry_add (request);
-}
-
-void
-ospf6_top_topology_remove (struct ospf6_route_req *request)
-{
- assert (request->route.type == OSPF6_DEST_TYPE_ROUTER);
- if (CHECK_FLAG (request->path.router_bits, OSPF6_ROUTER_LSA_BIT_E))
- ospf6_asbr_asbr_entry_remove (request);
-}
-
-struct ospf6 *
-ospf6_create (unsigned long process_id)
-{
- struct ospf6 *o6;
- char namebuf[64];
-
- o6 = ospf6_new ();
-
- /* initialize */
- gettimeofday (&o6->starttime, (struct timezone *)NULL);
- o6->process_id = process_id;
- o6->version = OSPF6_VERSION;
- o6->area_list = list_new ();
-
- o6->lsdb = ospf6_lsdb_create ();
-
- o6->foreach_area = ospf6_top_foreach_area;
- o6->foreach_if = ospf6_top_foreach_interface;
- o6->foreach_nei = ospf6_top_foreach_neighbor;
-
- snprintf (namebuf, sizeof (namebuf), "InterTopology table");
- o6->topology_table = ospf6_route_table_create (namebuf);
- ospf6_route_hook_register (ospf6_top_topology_add,
- ospf6_top_topology_add,
- ospf6_top_topology_remove,
- o6->topology_table);
-
-#if 0
- snprintf (namebuf, sizeof (namebuf), "External table");
- o6->external_table = ospf6_route_table_create (namebuf);
- ospf6_route_hook_register (ospf6_asbr_external_route_add,
- ospf6_asbr_external_route_add,
- ospf6_asbr_external_route_remove,
- o6->external_table);
-#endif /*0*/
-
- snprintf (namebuf, sizeof (namebuf), "Top route table");
- o6->route_table = ospf6_route_table_create (namebuf);
- ospf6_route_hook_register (ospf6_zebra_route_update_add,
- ospf6_zebra_route_update_add,
- ospf6_zebra_route_update_remove,
- o6->route_table);
- ospf6_route_hook_register (ospf6_abr_route_add,
- ospf6_abr_route_add,
- ospf6_abr_route_remove,
- o6->route_table);
-
- return o6;
-}
-
-void
-ospf6_delete (struct ospf6 *ospf6)
-{
- if (!ospf6)
- return;
-
- ospf6_route_remove_all (ospf6->route_table);
- ospf6_free (ospf6);
-}
-
-struct ospf6 *
-ospf6_start ()
-{
- if (ospf6)
- return ospf6;
-
- ospf6 = ospf6_create (0);
- return ospf6;
-}
-
-void
-ospf6_stop ()
-{
- if (!ospf6)
- return;
-
- ospf6_delete (ospf6);
- ospf6 = NULL;
-}
-
-int
-ospf6_is_asbr (struct ospf6 *o6)
-{
- int i = 0;
- i |= ospf6_zebra_is_redistribute (ZEBRA_ROUTE_SYSTEM);
- i |= ospf6_zebra_is_redistribute (ZEBRA_ROUTE_CONNECT);
- i |= ospf6_zebra_is_redistribute (ZEBRA_ROUTE_STATIC);
- i |= ospf6_zebra_is_redistribute (ZEBRA_ROUTE_KERNEL);
- i |= ospf6_zebra_is_redistribute (ZEBRA_ROUTE_RIPNG);
- i |= ospf6_zebra_is_redistribute (ZEBRA_ROUTE_BGP);
- return (i);
+ ospf6_show (vty, ospf6);
+ return CMD_SUCCESS;
}
DEFUN (show_ipv6_ospf6_route,
@@ -332,73 +451,146 @@
SHOW_STR
IP6_STR
OSPF6_STR
- "Routing table\n"
+ ROUTE_STR
)
{
- OSPF6_CMD_CHECK_RUNNING ();
- return ospf6_route_table_show (vty, argc, argv, ospf6->route_table);
+ ospf6_route_table_show (vty, argc, argv, ospf6->route_table);
+ return CMD_SUCCESS;
}
ALIAS (show_ipv6_ospf6_route,
- show_ipv6_ospf6_route_prefix_cmd,
- "show ipv6 ospf6 route (X::X|detail)",
+ show_ipv6_ospf6_route_detail_cmd,
+ "show ipv6 ospf6 route (X::X|X::X/M|detail|summary)",
SHOW_STR
IP6_STR
OSPF6_STR
- "Routing table\n"
- "match IPv6 prefix\n"
- )
+ ROUTE_STR
+ "Specify IPv6 address\n"
+ "Specify IPv6 prefix\n"
+ "Detailed information\n"
+ "Summary of route table\n"
+ );
-DEFUN (show_ipv6_ospf6_topology,
- show_ipv6_ospf6_topology_cmd,
- "show ipv6 ospf6 topology",
+DEFUN (show_ipv6_ospf6_route_match,
+ show_ipv6_ospf6_route_match_cmd,
+ "show ipv6 ospf6 route X::X/M match",
SHOW_STR
IP6_STR
OSPF6_STR
- "Inter Area topology information\n"
+ ROUTE_STR
+ "Specify IPv6 prefix\n"
+ "Display routes which match the specified route\n"
)
{
- OSPF6_CMD_CHECK_RUNNING ();
- return ospf6_route_table_show (vty, argc, argv, ospf6->topology_table);
+ char *sargv[CMD_ARGC_MAX];
+ int i, sargc;
+
+ /* copy argv to sargv and then append "match" */
+ for (i = 0; i < argc; i++)
+ sargv[i] = argv[i];
+ sargc = argc;
+ sargv[sargc++] = "match";
+ sargv[sargc] = NULL;
+
+ ospf6_route_table_show (vty, sargc, sargv, ospf6->route_table);
+ return CMD_SUCCESS;
}
-ALIAS (show_ipv6_ospf6_topology,
- show_ipv6_ospf6_topology_router_cmd,
- "show ipv6 ospf6 topology (A.B.C.D|<0-4294967295>|detail)",
+DEFUN (show_ipv6_ospf6_route_match_detail,
+ show_ipv6_ospf6_route_match_detail_cmd,
+ "show ipv6 ospf6 route X::X/M match detail",
SHOW_STR
IP6_STR
OSPF6_STR
- "Inter Area topology information\n"
- OSPF6_ROUTER_ID_STR
- OSPF6_ROUTER_ID_STR
+ ROUTE_STR
+ "Specify IPv6 prefix\n"
+ "Display routes which match the specified route\n"
"Detailed information\n"
)
+{
+ char *sargv[CMD_ARGC_MAX];
+ int i, sargc;
-ALIAS (show_ipv6_ospf6_topology,
- show_ipv6_ospf6_topology_router_lsid_cmd,
- "show ipv6 ospf6 topology (A.B.C.D|<0-4294967295>) (A.B.C.D|<0-4294967295>)",
- SHOW_STR
- IP6_STR
- OSPF6_STR
- "Inter Area topology information\n"
- OSPF6_ROUTER_ID_STR
- OSPF6_ROUTER_ID_STR
- OSPF6_LS_ID_STR
- OSPF6_LS_ID_STR
- )
+ /* copy argv to sargv and then append "match" and "detail" */
+ for (i = 0; i < argc; i++)
+ sargv[i] = argv[i];
+ sargc = argc;
+ sargv[sargc++] = "match";
+ sargv[sargc++] = "detail";
+ sargv[sargc] = NULL;
+ ospf6_route_table_show (vty, sargc, sargv, ospf6->route_table);
+ return CMD_SUCCESS;
+}
+
+
+/* OSPF configuration write function. */
+int
+config_write_ospf6 (struct vty *vty)
+{
+ char router_id[16];
+ listnode j, k;
+ struct ospf6_area *oa;
+ struct ospf6_interface *oi;
+
+ /* OSPFv6 configuration. */
+ if (ospf6 == NULL)
+ return CMD_SUCCESS;
+ if (CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
+ return CMD_SUCCESS;
+
+ inet_ntop (AF_INET, &ospf6->router_id, router_id, sizeof (router_id));
+ vty_out (vty, "router ospf6%s", VTY_NEWLINE);
+ vty_out (vty, " router-id %s%s", router_id, VTY_NEWLINE);
+
+ ospf6_redistribute_config_write (vty);
+
+ for (j = listhead (ospf6->area_list); j; nextnode (j))
+ {
+ oa = (struct ospf6_area *) getdata (j);
+ for (k = listhead (oa->if_list); k; nextnode (k))
+ {
+ oi = (struct ospf6_interface *) getdata (k);
+ vty_out (vty, " interface %s area %s%s",
+ oi->interface->name, oa->name, VTY_NEWLINE);
+ }
+ }
+ vty_out (vty, "!%s", VTY_NEWLINE);
+ return 0;
+}
+
+/* OSPF6 node structure. */
+struct cmd_node ospf6_node =
+{
+ OSPF6_NODE,
+ "%s(config-ospf6)# ",
+};
+
+/* Install ospf related commands. */
void
ospf6_top_init ()
{
+ /* Install ospf6 top node. */
+ install_node (&ospf6_node, config_write_ospf6);
+
+ install_element (VIEW_NODE, &show_ipv6_ospf6_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_cmd);
+ install_element (CONFIG_NODE, &router_ospf6_cmd);
+
install_element (VIEW_NODE, &show_ipv6_ospf6_route_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_route_prefix_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_topology_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_topology_router_cmd);
- install_element (VIEW_NODE, &show_ipv6_ospf6_topology_router_lsid_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_route_detail_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_route_match_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_route_match_detail_cmd);
install_element (ENABLE_NODE, &show_ipv6_ospf6_route_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_route_prefix_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_topology_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_topology_router_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_topology_router_lsid_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_route_detail_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_route_match_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_route_match_detail_cmd);
+
+ install_default (OSPF6_NODE);
+ install_element (OSPF6_NODE, &ospf6_router_id_cmd);
+ install_element (OSPF6_NODE, &ospf6_interface_area_cmd);
+ install_element (OSPF6_NODE, &no_ospf6_interface_area_cmd);
+ install_element (OSPF6_NODE, &no_router_ospf6_cmd);
}
+
diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h
index 4c68756..bd1336f 100644
--- a/ospf6d/ospf6_top.h
+++ b/ospf6d/ospf6_top.h
@@ -1,6 +1,5 @@
/*
- * OSPFv3 Top Level Data Structure
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -25,27 +24,28 @@
#include "routemap.h"
-/* ospfv3 top level data structure */
+/* OSPFv3 top level data structure */
struct ospf6
{
- /* process id */
- u_long process_id;
+ /* my router id */
+ u_int32_t router_id;
/* start time */
struct timeval starttime;
- /* ospf version must be 3 */
- unsigned char version;
-
- /* my router id */
- u_int32_t router_id;
-
/* list of areas */
list area_list;
/* AS scope link state database */
struct ospf6_lsdb *lsdb;
+ struct ospf6_route_table *route_table;
+ struct ospf6_route_table *asbr_table;
+
+ struct ospf6_route_table *external_table;
+ struct route_table *external_id_table;
+ u_int32_t external_id;
+
/* redistribute route-map */
struct
{
@@ -53,44 +53,21 @@
struct route_map *map;
} rmap[ZEBRA_ROUTE_MAX];
- struct thread *t_route_calculation;
- u_int stat_route_calculation_execed;
-
- struct ospf6_route_table *route_table;
- struct ospf6_route_table *topology_table;
- struct ospf6_route_table *external_table;
-
- void (*foreach_area) (struct ospf6 *, void *arg, int val,
- void (*func) (void *, int, void *));
- void (*foreach_if) (struct ospf6 *, void *arg, int val,
- void (*func) (void *, int, void *));
- void (*foreach_nei) (struct ospf6 *, void *arg, int val,
- void (*func) (void *, int, void *));
+ u_char flag;
struct thread *maxage_remover;
-
- list nexthop_list;
};
-
+
+#define OSPF6_DISABLED 0x01
+
+/* global pointer for OSPF top data structure */
extern struct ospf6 *ospf6;
/* prototypes */
-int
-ospf6_top_count_neighbor_in_state (u_char state, struct ospf6 *o6);
-
-void
-ospf6_top_schedule_maxage_remover (void *arg, int val, struct ospf6 *o6);
-
-void ospf6_show (struct vty *);
-void ospf6_statistics_show (struct vty *vty, struct ospf6 *o6);
-
-struct ospf6 *ospf6_start ();
-void ospf6_stop ();
-
-void ospf6_delete (struct ospf6 *);
-int ospf6_is_asbr (struct ospf6 *);
-
void ospf6_top_init ();
+void ospf6_maxage_remove (struct ospf6 *o);
+
#endif /* OSPF6_TOP_H */
+
diff --git a/ospf6d/ospf6_types.h b/ospf6d/ospf6_types.h
deleted file mode 100644
index 574e2f3..0000000
--- a/ospf6d/ospf6_types.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 1999 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.
- */
-
-#ifndef OSPF6_TYPES_H
-#define OSPF6_TYPES_H
-
-typedef unsigned char msgtype_t;
-typedef unsigned char instance_id_t;
-typedef unsigned char state_t;
-typedef unsigned char vers_t;
-typedef unsigned char opt_t;
-typedef unsigned char rtr_pri_t;
-typedef unsigned char prefixlen_t;
-typedef unsigned char ddbits_t;
-typedef unsigned long ddseqnum_t;
-typedef unsigned long rtr_id_t;
-typedef unsigned long ifid_t;
-typedef unsigned long cost_t;
-typedef unsigned long rxmt_int_t;
-typedef unsigned short hello_int_t;
-typedef unsigned short rtr_dead_int_t;
-typedef unsigned long area_id_t;
-
-#endif /* OSPF6_TYPES_H */
-
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index 4e8815f..b622086 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -19,12 +19,26 @@
* Boston, MA 02111-1307, USA.
*/
+#include <zebra.h>
+
+#include "log.h"
+#include "vty.h"
+#include "command.h"
+#include "prefix.h"
+#include "stream.h"
+#include "zclient.h"
+#include "memory.h"
+
#include "ospf6d.h"
-
+#include "ospf6_proto.h"
+#include "ospf6_top.h"
#include "ospf6_interface.h"
+#include "ospf6_route.h"
+#include "ospf6_lsa.h"
#include "ospf6_asbr.h"
+#include "ospf6_zebra.h"
-#include "ospf6_linklist.h"
+unsigned char conf_debug_ospf6_zebra = 0;
/* information about zebra. */
struct zclient *zclient = NULL;
@@ -33,50 +47,23 @@
void
ospf6_zebra_redistribute (int type)
{
- int top_change = 0;
-
if (zclient->redist[type])
return;
-
- if (! ospf6_is_asbr (ospf6))
- top_change = 1;
-
zclient->redist[type] = 1;
-
if (zclient->sock > 0)
zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient->sock, type);
-
- if (top_change)
- CALL_CHANGE_HOOK (&top_hook, ospf6);
}
void
ospf6_zebra_no_redistribute (int type)
{
- int top_change = 0;
-
- if (!zclient->redist[type])
+ if (! zclient->redist[type])
return;
-
- if (ospf6_is_asbr (ospf6))
- top_change = 1;
-
zclient->redist[type] = 0;
-
if (zclient->sock > 0)
zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient->sock, type);
-
- if (top_change)
- CALL_CHANGE_HOOK (&top_hook, ospf6);
}
-int
-ospf6_zebra_is_redistribute (int type)
-{
- return zclient->redist[type];
-}
-
-
/* Inteface addition message from zebra. */
int
ospf6_zebra_if_add (int command, struct zclient *zclient, zebra_size_t length)
@@ -84,14 +71,10 @@
struct interface *ifp;
ifp = zebra_interface_add_read (zclient->ibuf);
-
- /* log */
- if (IS_OSPF6_DUMP_ZEBRA)
- zlog_info ("ZEBRA: I/F add: %s index %d mtu %d",
+ if (IS_OSPF6_DEBUG_ZEBRA (RECV))
+ zlog_info ("Zebra Interface add: %s index %d mtu %d",
ifp->name, ifp->ifindex, ifp->mtu);
-
ospf6_interface_if_add (ifp);
-
return 0;
}
@@ -99,18 +82,15 @@
ospf6_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length)
{
#if 0
- struct interface *ifp = NULL;
+ struct interface *ifp;
ifp = zebra_interface_delete_read (zclient->ibuf);
-
- /* log */
- if (IS_OSPF6_DUMP_ZEBRA)
- zlog_info ("ZEBRA: I/F delete: %s index %d mtu %d",
+ if (IS_OSPF6_DEBUG_ZEBRA (RECV))
+ zlog_info ("Zebra Interface delete: %s index %d mtu %d",
ifp->name, ifp->ifindex, ifp->mtu);
ospf6_interface_if_del (ifp);
-#endif
-
+#endif /*0*/
return 0;
}
@@ -121,10 +101,9 @@
struct interface *ifp;
ifp = zebra_interface_state_read (zclient->ibuf);
-
- /* log */
- if (IS_OSPF6_DUMP_ZEBRA)
- zlog_info ("ZEBRA: I/F %s state change: index %d flags %ld metric %d mtu %d",
+ if (IS_OSPF6_DEBUG_ZEBRA (RECV))
+ zlog_info ("Zebra Interface state change: "
+ "%s index %d flags %ld metric %d mtu %d",
ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
ospf6_interface_state_update (ifp);
@@ -133,7 +112,7 @@
int
ospf6_zebra_if_address_update_add (int command, struct zclient *zclient,
- zebra_size_t length)
+ zebra_size_t length)
{
struct connected *c;
char buf[128];
@@ -142,14 +121,14 @@
if (c == NULL)
return 0;
- if (IS_OSPF6_DUMP_ZEBRA)
- zlog_info ("ZEBRA: I/F %s address add: %5s %s/%d",
+ if (IS_OSPF6_DEBUG_ZEBRA (RECV))
+ zlog_info ("Zebra Interface address add: %s %5s %s/%d",
c->ifp->name, prefix_family_str (c->address),
inet_ntop (c->address->family, &c->address->u.prefix,
buf, sizeof (buf)), c->address->prefixlen);
if (c->address->family == AF_INET6)
- ospf6_interface_address_update (c->ifp);
+ ospf6_interface_connected_route_update (c->ifp);
return 0;
}
@@ -165,14 +144,14 @@
if (c == NULL)
return 0;
- if (IS_OSPF6_DUMP_ZEBRA)
- zlog_info ("ZEBRA: I/F %s address del: %5s %s/%d",
+ if (IS_OSPF6_DEBUG_ZEBRA (RECV))
+ zlog_info ("Zebra Interface address delete: %s %5s %s/%d",
c->ifp->name, prefix_family_str (c->address),
inet_ntop (c->address->family, &c->address->u.prefix,
buf, sizeof (buf)), c->address->prefixlen);
if (c->address->family == AF_INET6)
- ospf6_interface_address_update (c->ifp);
+ ospf6_interface_connected_route_update (c->ifp);
return 0;
}
@@ -180,17 +159,8 @@
const char *zebra_route_name[ZEBRA_ROUTE_MAX] =
-{
- "System",
- "Kernel",
- "Connect",
- "Static",
- "RIP",
- "RIPng",
- "OSPF",
- "OSPF6",
- "BGP",
-};
+ { "System", "Kernel", "Connect", "Static", "RIP", "RIPng", "OSPF",
+ "OSPF6", "BGP" };
const char *zebra_route_abname[ZEBRA_ROUTE_MAX] =
{ "X", "K", "C", "S", "r", "R", "o", "O", "B" };
@@ -204,7 +174,6 @@
unsigned long ifindex;
struct prefix_ipv6 p;
struct in6_addr *nexthop;
- char prefixstr[128], nexthopstr[128];
s = zclient->ibuf;
ifindex = 0;
@@ -244,27 +213,25 @@
else
api.metric = 0;
- /* log */
- if (IS_OSPF6_DUMP_ZEBRA)
+ if (IS_OSPF6_DEBUG_ZEBRA (RECV))
{
+ char prefixstr[128], nexthopstr[128];
prefix2str ((struct prefix *)&p, prefixstr, sizeof (prefixstr));
- inet_ntop (AF_INET6, &nexthop, nexthopstr, sizeof (nexthopstr));
-
- if (command == ZEBRA_IPV6_ROUTE_ADD)
- zlog_info ("ZEBRA: Receive add %s route: %s nexthop:%s ifindex:%ld",
- zebra_route_name [api.type], prefixstr,
- nexthopstr, ifindex);
+ if (nexthop)
+ inet_ntop (AF_INET6, nexthop, nexthopstr, sizeof (nexthopstr));
else
- zlog_info ("ZEBRA: Receive remove %s route: %s nexthop:%s ifindex:%ld",
- zebra_route_name [api.type], prefixstr,
- nexthopstr, ifindex);
+ snprintf (nexthopstr, sizeof (nexthopstr), "::");
+
+ zlog_info ("Zebra Receive route %s: %s %s nexthop %s ifindex %ld",
+ (command == ZEBRA_IPV6_ROUTE_ADD ? "add" : "delete"),
+ zebra_route_name[api.type], prefixstr, nexthopstr, ifindex);
}
if (command == ZEBRA_IPV6_ROUTE_ADD)
- ospf6_asbr_route_add (api.type, ifindex, (struct prefix *) &p,
- api.nexthop_num, nexthop);
+ ospf6_asbr_redistribute_add (api.type, ifindex, (struct prefix *) &p,
+ api.nexthop_num, nexthop);
else
- ospf6_asbr_route_remove (api.type, ifindex, (struct prefix *) &p);
+ ospf6_asbr_redistribute_remove (api.type, ifindex, (struct prefix *) &p);
if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
free (nexthop);
@@ -272,6 +239,8 @@
return 0;
}
+
+
DEFUN (show_zebra,
show_zebra_cmd,
@@ -280,18 +249,24 @@
"Zebra information\n")
{
int i;
- if (!zclient)
- vty_out (vty, "Not connected to zebra%s", VTY_NEWLINE);
+ if (zclient == NULL)
+ {
+ vty_out (vty, "Not connected to zebra%s", VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
vty_out (vty, "Zebra Infomation%s", VTY_NEWLINE);
- vty_out (vty, " enable: %d%s", zclient->enable, VTY_NEWLINE);
- vty_out (vty, " fail: %d%s", zclient->fail, VTY_NEWLINE);
+ vty_out (vty, " enable: %d fail: %d%s",
+ zclient->enable, zclient->fail, VTY_NEWLINE);
vty_out (vty, " redistribute default: %d%s", zclient->redist_default,
VTY_NEWLINE);
+ vty_out (vty, " redistribute:");
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
- vty_out (vty, " RouteType: %s - %s%s", zebra_route_name[i],
- zclient->redist[i] ? "redistributed" : "not redistributed",
- VTY_NEWLINE);
+ {
+ if (zclient->redist[i])
+ vty_out (vty, " %s", zebra_route_name[i]);
+ }
+ vty_out (vty, "%s", VTY_NEWLINE);
return CMD_SUCCESS;
}
@@ -301,9 +276,6 @@
"Enable a routing process\n"
"Make connection to zebra daemon\n")
{
- if (IS_OSPF6_DUMP_CONFIG)
- zlog_info ("Config: router zebra");
-
vty->node = ZEBRA_NODE;
zclient->enable = 1;
zclient_start (zclient);
@@ -317,9 +289,6 @@
"Configure routing process\n"
"Disable connection to zebra daemon\n")
{
- if (IS_OSPF6_DUMP_CONFIG)
- zlog_info ("no router zebra");
-
zclient->enable = 0;
zclient_stop (zclient);
return CMD_SUCCESS;
@@ -327,18 +296,18 @@
/* Zebra configuration write function. */
int
-ospf6_zebra_config_write (struct vty *vty)
+config_write_ospf6_zebra (struct vty *vty)
{
if (! zclient->enable)
{
vty_out (vty, "no router zebra%s", VTY_NEWLINE);
- return 1;
+ vty_out (vty, "!%s", VTY_NEWLINE);
}
else if (! zclient->redist[ZEBRA_ROUTE_OSPF6])
{
vty_out (vty, "router zebra%s", VTY_NEWLINE);
vty_out (vty, " no redistribute ospf6%s", VTY_NEWLINE);
- return 1;
+ vty_out (vty, "!%s", VTY_NEWLINE);
}
return 0;
}
@@ -348,41 +317,32 @@
{
ZEBRA_NODE,
"%s(config-zebra)# ",
- vtysh: 0
};
#define ADD 0
-#define CHANGE 1
-#define REMOVE 2
-
+#define REM 1
static void
-ospf6_zebra_route_update (int type, struct ospf6_route_req *request)
+ospf6_zebra_route_update (int type, struct ospf6_route *request)
{
- char buf[96], ifname[IFNAMSIZ];
-
struct zapi_ipv6 api;
- struct ospf6_route_req route;
- struct linklist *nexthop_list;
- struct linklist_node node;
- struct ospf6_nexthop *nexthop = NULL;
+ char buf[64], ifname[IFNAMSIZ];
+ int nhcount;
struct in6_addr **nexthops;
unsigned int *ifindexes;
- struct prefix_ipv6 *p;
int i, ret = 0;
+ struct prefix_ipv6 *dest;
- if (IS_OSPF6_DUMP_ZEBRA)
+ if (IS_OSPF6_DEBUG_ZEBRA (SEND))
{
- prefix2str (&request->route.prefix, buf, sizeof (buf));
- if (type == REMOVE)
- zlog_info ("ZEBRA: Send remove route: %s", buf);
- else
- zlog_info ("ZEBRA: Send add route: %s", buf);
+ prefix2str (&request->prefix, buf, sizeof (buf));
+ zlog_info ("Send %s route: %s",
+ (type == REM ? "remove" : "add"), buf);
}
if (zclient->sock < 0)
{
- if (IS_OSPF6_DUMP_ZEBRA)
- zlog_info ("ZEBRA: failed: not connected to zebra");
+ if (IS_OSPF6_DEBUG_ZEBRA (SEND))
+ zlog_info (" Not connected to Zebra");
return;
}
@@ -390,195 +350,99 @@
(request->path.type == OSPF6_PATH_TYPE_EXTERNAL1 ||
request->path.type == OSPF6_PATH_TYPE_EXTERNAL2))
{
- if (IS_OSPF6_DUMP_ZEBRA)
- zlog_info ("ZEBRA: self originated external route, ignore");
+ if (IS_OSPF6_DEBUG_ZEBRA (SEND))
+ zlog_info (" Ignore self-originated external route");
return;
}
- /* Only the best path (i.e. the first path of the path-list
- in 'struct ospf6_route') will be sent to zebra. */
- ospf6_route_lookup (&route, &request->route.prefix, request->table);
- if (memcmp (&route.path, &request->path, sizeof (route.path)))
+ /* If removing is the best path and if there's another path,
+ treat this request as add the secondary path */
+ if (type == REM && ospf6_route_is_best (request) &&
+ request->next && ospf6_route_is_same (request, request->next))
+ {
+ if (IS_OSPF6_DEBUG_ZEBRA (SEND))
+ zlog_info (" Best-path removal resulted Sencondary addition");
+ type = ADD;
+ request = request->next;
+ }
+
+ /* Only the best path will be sent to zebra. */
+ if (! ospf6_route_is_best (request))
{
/* this is not preferred best route, ignore */
- if (IS_OSPF6_DUMP_ZEBRA)
- zlog_info ("ZEBRA: not best path, ignore");
+ if (IS_OSPF6_DEBUG_ZEBRA (SEND))
+ zlog_info (" Ignore non-best route");
return;
}
- nexthop_list = linklist_create ();
+ nhcount = 0;
+ for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
+ if (ospf6_nexthop_is_set (&request->nexthop[i]))
+ nhcount++;
- /* for each nexthop */
- for (ospf6_route_lookup (&route, &request->route.prefix, request->table);
- ! ospf6_route_end (&route); ospf6_route_next (&route))
+ if (nhcount == 0)
{
- if (memcmp (&route.path, &request->path, sizeof (route.path)))
- break;
-
- #define IN6_IS_ILLEGAL_NEXTHOP(a)\
- ((*(u_int32_t *)(void *)(&(a)->s6_addr[0]) == 0xffffffff) &&\
- (*(u_int32_t *)(void *)(&(a)->s6_addr[4]) == 0xffffffff) &&\
- (*(u_int32_t *)(void *)(&(a)->s6_addr[8]) == 0xffffffff) &&\
- (*(u_int32_t *)(void *)(&(a)->s6_addr[12]) == 0xffffffff))
- if (IN6_IS_ILLEGAL_NEXTHOP (&route.nexthop.address))
- {
- zlog_warn ("ZEBRA: Illegal nexthop");
- continue;
- }
-
- if (type == REMOVE && ! memcmp (&route.nexthop, &request->nexthop,
- sizeof (struct ospf6_nexthop)))
- continue;
-
- nexthop = XCALLOC (MTYPE_OSPF6_OTHER, sizeof (struct ospf6_nexthop));
- if (! nexthop)
- {
- zlog_warn ("ZEBRA: Can't update nexthop: malloc failed");
- continue;
- }
-
- memcpy (nexthop, &route.nexthop, sizeof (struct ospf6_nexthop));
- linklist_add (nexthop, nexthop_list);
- }
-
- if (type == REMOVE && nexthop_list->count != 0)
- type = ADD;
- else if (type == REMOVE && nexthop_list->count == 0)
- {
- if (IS_OSPF6_DUMP_ZEBRA)
- zlog_info ("ZEBRA: all nexthop with the selected path has gone");
-
- if (! memcmp (&request->route, &route.route,
- sizeof (struct ospf6_route)))
- {
- /* send 'add' of alternative route */
- struct ospf6_path seconde_path;
-
- if (IS_OSPF6_DUMP_ZEBRA)
- zlog_info ("ZEBRA: found alternative path to add");
-
- memcpy (&seconde_path, &route.path, sizeof (struct ospf6_path));
- type = ADD;
-
- while (! memcmp (&seconde_path, &route.path,
- sizeof (struct ospf6_path)))
- {
- nexthop = XCALLOC (MTYPE_OSPF6_OTHER,
- sizeof (struct ospf6_nexthop));
- if (! nexthop)
- zlog_warn ("ZEBRA: Can't update nexthop: malloc failed");
- else
- {
- memcpy (nexthop, &route.nexthop,
- sizeof (struct ospf6_nexthop));
- linklist_add (nexthop, nexthop_list);
- }
-
- ospf6_route_next (&route);
- }
- }
- else
- {
- /* there is no alternative route. send 'remove' to zebra for
- requested route */
- if (IS_OSPF6_DUMP_ZEBRA)
- zlog_info ("ZEBRA: can't find alternative path, remove");
-
- if (IS_OSPF6_DUMP_ZEBRA)
- {
- zlog_info ("ZEBRA: Debug: walk over the route ?");
- ospf6_route_log_request ("Debug route", "***", &route);
- ospf6_route_log_request ("Debug request", "***", request);
- }
-
- nexthop = XCALLOC (MTYPE_OSPF6_OTHER,
- sizeof (struct ospf6_nexthop));
- if (! nexthop)
- zlog_warn ("ZEBRA: Can't update nexthop: malloc failed");
- else
- {
- memcpy (nexthop, &request->nexthop,
- sizeof (struct ospf6_nexthop));
- linklist_add (nexthop, nexthop_list);
- }
- }
- }
-
- if (nexthop_list->count == 0)
- {
- if (IS_OSPF6_DUMP_ZEBRA)
- zlog_info ("ZEBRA: no nexthop, ignore");
- linklist_delete (nexthop_list);
+ if (IS_OSPF6_DEBUG_ZEBRA (SEND))
+ zlog_info (" No nexthop, ignore");
return;
}
/* allocate memory for nexthop_list */
nexthops = XCALLOC (MTYPE_OSPF6_OTHER,
- nexthop_list->count * sizeof (struct in6_addr *));
- if (! nexthops)
+ nhcount * sizeof (struct in6_addr *));
+ if (nexthops == NULL)
{
- zlog_warn ("ZEBRA: Can't update zebra route: malloc failed");
- for (linklist_head (nexthop_list, &node); !linklist_end (&node);
- linklist_next (&node))
- XFREE (MTYPE_OSPF6_OTHER, node.data);
- linklist_delete (nexthop_list);
+ zlog_warn ("Can't send route to zebra: malloc failed");
return;
}
/* allocate memory for ifindex_list */
ifindexes = XCALLOC (MTYPE_OSPF6_OTHER,
- nexthop_list->count * sizeof (unsigned int));
- if (! ifindexes)
+ nhcount * sizeof (unsigned int));
+ if (ifindexes == NULL)
{
- zlog_warn ("ZEBRA: Can't update zebra route: malloc failed");
- for (linklist_head (nexthop_list, &node); !linklist_end (&node);
- linklist_next (&node))
- XFREE (MTYPE_OSPF6_OTHER, node.data);
- linklist_delete (nexthop_list);
+ zlog_warn ("Can't send route to zebra: malloc failed");
XFREE (MTYPE_OSPF6_OTHER, nexthops);
return;
}
- i = 0;
- for (linklist_head (nexthop_list, &node); ! linklist_end (&node);
- linklist_next (&node))
+ for (i = 0; i < nhcount; i++)
{
- nexthop = node.data;
- if (IS_OSPF6_DUMP_ZEBRA)
+ if (IS_OSPF6_DEBUG_ZEBRA (SEND))
{
- inet_ntop (AF_INET6, &nexthop->address, buf, sizeof (buf));
- if_indextoname (nexthop->ifindex, ifname);
- zlog_info ("ZEBRA: nexthop: %s%%%s(%d)",
- buf, ifname, nexthop->ifindex);
+ inet_ntop (AF_INET6, &request->nexthop[i].address,
+ buf, sizeof (buf));
+ if_indextoname (request->nexthop[i].ifindex, ifname);
+ zlog_info (" nexthop: %s%%%s(%d)", buf, ifname,
+ request->nexthop[i].ifindex);
}
- nexthops[i] = &nexthop->address;
- ifindexes[i] = nexthop->ifindex;
- i++;
+ nexthops[i] = &request->nexthop[i].address;
+ ifindexes[i] = request->nexthop[i].ifindex;
}
api.type = ZEBRA_ROUTE_OSPF6;
api.flags = 0;
api.message = 0;
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
- SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
- api.nexthop_num = nexthop_list->count;
+ api.nexthop_num = nhcount;
api.nexthop = nexthops;
- api.ifindex_num = nexthop_list->count;
+ SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
+ api.ifindex_num = nhcount;
api.ifindex = ifindexes;
+ SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
+ api.metric = (request->path.metric_type == 2 ?
+ request->path.cost_e2 : request->path.cost);
- p = (struct prefix_ipv6 *) &request->route.prefix;
- if (type == REMOVE && nexthop_list->count == 1)
- ret = zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, p, &api);
+ dest = (struct prefix_ipv6 *) &request->prefix;
+ if (type == REM)
+ ret = zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, dest, &api);
else
- ret = zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, p, &api);
+ ret = zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, dest, &api);
if (ret < 0)
- zlog_err ("ZEBRA: zapi_ipv6_route () failed: %s", strerror (errno));
+ zlog_err ("zapi_ipv6_route() %s failed: %s",
+ (type == REM ? "delete" : "add"), strerror (errno));
- for (linklist_head (nexthop_list, &node); !linklist_end (&node);
- linklist_next (&node))
- XFREE (MTYPE_OSPF6_OTHER, node.data);
- linklist_delete (nexthop_list);
XFREE (MTYPE_OSPF6_OTHER, nexthops);
XFREE (MTYPE_OSPF6_OTHER, ifindexes);
@@ -586,64 +450,52 @@
}
void
-ospf6_zebra_route_update_add (struct ospf6_route_req *request)
+ospf6_zebra_route_update_add (struct ospf6_route *request)
{
+ if (! zclient->redist[ZEBRA_ROUTE_OSPF6])
+ {
+ ospf6->route_table->hook_add = NULL;
+ ospf6->route_table->hook_remove = NULL;
+ return;
+ }
ospf6_zebra_route_update (ADD, request);
}
void
-ospf6_zebra_route_update_remove (struct ospf6_route_req *request)
+ospf6_zebra_route_update_remove (struct ospf6_route *request)
{
- ospf6_zebra_route_update (REMOVE, request);
-}
-
-static void
-ospf6_zebra_redistribute_ospf6 ()
-{
- struct route_node *node;
-
- for (node = route_top (ospf6->route_table->table); node;
- node = route_next (node))
+ if (! zclient->redist[ZEBRA_ROUTE_OSPF6])
{
- if (! node || ! node->info)
- continue;
- ospf6_zebra_route_update_add (node->info);
+ ospf6->route_table->hook_add = NULL;
+ ospf6->route_table->hook_remove = NULL;
+ return;
}
+ ospf6_zebra_route_update (REM, request);
}
-static void
-ospf6_zebra_no_redistribute_ospf6 ()
-{
- struct route_node *node;
-
- if (! ospf6)
- return;
-
- for (node = route_top (ospf6->route_table->table); node;
- node = route_next (node))
- {
- if (! node || ! node->info)
- continue;
-
- ospf6_zebra_route_update_remove (node->info);
- }
-}
-
-
DEFUN (redistribute_ospf6,
redistribute_ospf6_cmd,
"redistribute ospf6",
"Redistribute control\n"
"OSPF6 route\n")
{
- /* log */
- if (IS_OSPF6_DUMP_CONFIG)
- zlog_info ("Config: redistribute ospf6");
+ struct ospf6_route *route;
+
+ if (zclient->redist[ZEBRA_ROUTE_OSPF6])
+ return CMD_SUCCESS;
zclient->redist[ZEBRA_ROUTE_OSPF6] = 1;
- /* set zebra route table */
- ospf6_zebra_redistribute_ospf6 ();
+ if (ospf6 == NULL)
+ return CMD_SUCCESS;
+
+ /* send ospf6 route to zebra route table */
+ for (route = ospf6_route_head (ospf6->route_table); route;
+ route = ospf6_route_next (route))
+ ospf6_zebra_route_update_add (route);
+
+ ospf6->route_table->hook_add = ospf6_zebra_route_update_add;
+ ospf6->route_table->hook_remove = ospf6_zebra_route_update_remove;
return CMD_SUCCESS;
}
@@ -655,22 +507,23 @@
"Redistribute control\n"
"OSPF6 route\n")
{
- /* log */
- if (IS_OSPF6_DUMP_CONFIG)
- zlog_info ("Config: no redistribute ospf6");
+ struct ospf6_route *route;
+
+ if (! zclient->redist[ZEBRA_ROUTE_OSPF6])
+ return CMD_SUCCESS;
zclient->redist[ZEBRA_ROUTE_OSPF6] = 0;
- if (! ospf6)
+ if (ospf6 == NULL)
return CMD_SUCCESS;
- /* clean up zebra route table */
- ospf6_zebra_no_redistribute_ospf6 ();
+ ospf6->route_table->hook_add = NULL;
+ ospf6->route_table->hook_remove = NULL;
- ospf6_route_hook_unregister (ospf6_zebra_route_update_add,
- ospf6_zebra_route_update_add,
- ospf6_zebra_route_update_remove,
- ospf6->route_table);
+ /* withdraw ospf6 route from zebra route table */
+ for (route = ospf6_route_head (ospf6->route_table); route;
+ route = ospf6_route_next (route))
+ ospf6_zebra_route_update_remove (route);
return CMD_SUCCESS;
}
@@ -696,33 +549,120 @@
/* ospf6_zebra_redistribute (ZEBRA_ROUTE_CONNECT); */
/* Install zebra node. */
- install_node (&zebra_node, ospf6_zebra_config_write);
+ install_node (&zebra_node, config_write_ospf6_zebra);
/* Install command element for zebra node. */
install_element (VIEW_NODE, &show_zebra_cmd);
install_element (ENABLE_NODE, &show_zebra_cmd);
install_element (CONFIG_NODE, &router_zebra_cmd);
install_element (CONFIG_NODE, &no_router_zebra_cmd);
+
install_default (ZEBRA_NODE);
install_element (ZEBRA_NODE, &redistribute_ospf6_cmd);
install_element (ZEBRA_NODE, &no_redistribute_ospf6_cmd);
-#if 0
- hook.name = "ZebraRouteUpdate";
- hook.hook_add = ospf6_zebra_route_update_add;
- hook.hook_change = ospf6_zebra_route_update_add;
- hook.hook_remove = ospf6_zebra_route_update_remove;
- ospf6_hook_register (&hook, &route_hook);
-#endif
-
return;
}
-void
-ospf6_zebra_finish ()
+/* Debug */
+
+DEFUN (debug_ospf6_zebra_sendrecv,
+ debug_ospf6_zebra_sendrecv_cmd,
+ "debug ospf6 zebra (send|recv)",
+ DEBUG_STR
+ OSPF6_STR
+ "Debug connection between zebra\n"
+ "Debug Sending zebra\n"
+ "Debug Receiving zebra\n"
+ )
{
- zclient_stop (zclient);
- zclient_free (zclient);
- zclient = (struct zclient *) NULL;
+ unsigned char level = 0;
+
+ if (argc)
+ {
+ if (! strncmp (argv[0], "s", 1))
+ level = OSPF6_DEBUG_ZEBRA_SEND;
+ else if (! strncmp (argv[0], "r", 1))
+ level = OSPF6_DEBUG_ZEBRA_RECV;
+ }
+ else
+ level = OSPF6_DEBUG_ZEBRA_SEND | OSPF6_DEBUG_ZEBRA_RECV;
+
+ OSPF6_DEBUG_ZEBRA_ON (level);
+ return CMD_SUCCESS;
}
+ALIAS (debug_ospf6_zebra_sendrecv,
+ debug_ospf6_zebra_cmd,
+ "debug ospf6 zebra",
+ DEBUG_STR
+ OSPF6_STR
+ "Debug connection between zebra\n"
+ );
+
+
+DEFUN (no_debug_ospf6_zebra_sendrecv,
+ no_debug_ospf6_zebra_sendrecv_cmd,
+ "no debug ospf6 zebra (send|recv)",
+ NO_STR
+ DEBUG_STR
+ OSPF6_STR
+ "Debug connection between zebra\n"
+ "Debug Sending zebra\n"
+ "Debug Receiving zebra\n"
+ )
+{
+ unsigned char level = 0;
+
+ if (argc)
+ {
+ if (! strncmp (argv[0], "s", 1))
+ level = OSPF6_DEBUG_ZEBRA_SEND;
+ else if (! strncmp (argv[0], "r", 1))
+ level = OSPF6_DEBUG_ZEBRA_RECV;
+ }
+ else
+ level = OSPF6_DEBUG_ZEBRA_SEND | OSPF6_DEBUG_ZEBRA_RECV;
+
+ OSPF6_DEBUG_ZEBRA_OFF (level);
+ return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_ospf6_zebra_sendrecv,
+ no_debug_ospf6_zebra_cmd,
+ "no debug ospf6 zebra",
+ NO_STR
+ DEBUG_STR
+ OSPF6_STR
+ "Debug connection between zebra\n"
+ );
+
+int
+config_write_ospf6_debug_zebra (struct vty *vty)
+{
+ if (IS_OSPF6_DEBUG_ZEBRA (SEND) && IS_OSPF6_DEBUG_ZEBRA (RECV))
+ vty_out (vty, "debug ospf6 zebra%s", VTY_NEWLINE);
+ else
+ {
+ if (IS_OSPF6_DEBUG_ZEBRA (SEND))
+ vty_out (vty, "debug ospf6 zebra send%s", VTY_NEWLINE);
+ if (IS_OSPF6_DEBUG_ZEBRA (RECV))
+ vty_out (vty, "debug ospf6 zebra recv%s", VTY_NEWLINE);
+ }
+ return 0;
+}
+
+void
+install_element_ospf6_debug_zebra ()
+{
+ install_element (ENABLE_NODE, &debug_ospf6_zebra_cmd);
+ install_element (ENABLE_NODE, &no_debug_ospf6_zebra_cmd);
+ install_element (ENABLE_NODE, &debug_ospf6_zebra_sendrecv_cmd);
+ install_element (ENABLE_NODE, &no_debug_ospf6_zebra_sendrecv_cmd);
+ install_element (CONFIG_NODE, &debug_ospf6_zebra_cmd);
+ install_element (CONFIG_NODE, &no_debug_ospf6_zebra_cmd);
+ install_element (CONFIG_NODE, &debug_ospf6_zebra_sendrecv_cmd);
+ install_element (CONFIG_NODE, &no_debug_ospf6_zebra_sendrecv_cmd);
+}
+
+
diff --git a/ospf6d/ospf6_zebra.h b/ospf6d/ospf6_zebra.h
index d86b2db..fb9877b 100644
--- a/ospf6d/ospf6_zebra.h
+++ b/ospf6d/ospf6_zebra.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -22,25 +22,32 @@
#ifndef OSPF6_ZEBRA_H
#define OSPF6_ZEBRA_H
+#include "zclient.h"
+
+/* Debug option */
+extern unsigned char conf_debug_ospf6_zebra;
+#define OSPF6_DEBUG_ZEBRA_SEND 0x01
+#define OSPF6_DEBUG_ZEBRA_RECV 0x02
+#define OSPF6_DEBUG_ZEBRA_ON(level) \
+ (conf_debug_ospf6_zebra |= level)
+#define OSPF6_DEBUG_ZEBRA_OFF(level) \
+ (conf_debug_ospf6_zebra &= ~(level))
+#define IS_OSPF6_DEBUG_ZEBRA(e) \
+ (conf_debug_ospf6_zebra & OSPF6_DEBUG_ZEBRA_ ## e)
+
extern struct zclient *zclient;
+void ospf6_zebra_route_update_add (struct ospf6_route *request);
+void ospf6_zebra_route_update_remove (struct ospf6_route *request);
+
void ospf6_zebra_redistribute (int);
void ospf6_zebra_no_redistribute (int);
-int ospf6_zebra_is_redistribute (int);
-
-int ospf6_zebra_get_interface (int, struct zclient *, zebra_size_t);
-int ospf6_zebra_read (struct thread *);
+#define ospf6_zebra_is_redistribute(type) \
+ (zclient->redist[type])
void ospf6_zebra_init ();
-void ospf6_zebra_finish ();
-void ospf6_zebra_start ();
-int ospf6_zebra_read_ipv6 (int, struct zclient *, zebra_size_t);
-
-extern const char *zebra_route_name[ZEBRA_ROUTE_MAX];
-extern const char *zebra_route_abname[ZEBRA_ROUTE_MAX];
-
-void ospf6_zebra_route_update_add (struct ospf6_route_req *request);
-void ospf6_zebra_route_update_remove (struct ospf6_route_req *request);
+int config_write_ospf6_debug_zebra (struct vty *vty);
+void install_element_ospf6_debug_zebra ();
#endif /*OSPF6_ZEBRA_H*/
diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c
index e83e1ea..362d679 100644
--- a/ospf6d/ospf6d.c
+++ b/ospf6d/ospf6d.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -19,173 +19,132 @@
* Boston, MA 02111-1307, USA.
*/
+#include <zebra.h>
+
+#include "thread.h"
+#include "linklist.h"
+#include "vty.h"
+#include "command.h"
+
#include "ospf6d.h"
-
-#include "ospf6_damp.h"
-
-/* global ospf6d variable */
-int ospf6_sock;
-list iflist;
-list nexthoplist = NULL;
-struct sockaddr_in6 allspfrouters6;
-struct sockaddr_in6 alldrouters6;
-char *recent_reason; /* set by ospf6_lsa_check_recent () */
-int proctitle_mode = 0;
+#include "ospf6_proto.h"
+#include "ospf6_network.h"
+#include "ospf6_lsa.h"
+#include "ospf6_lsdb.h"
+#include "ospf6_message.h"
+#include "ospf6_route.h"
+#include "ospf6_zebra.h"
+#include "ospf6_spf.h"
+#include "ospf6_top.h"
+#include "ospf6_area.h"
+#include "ospf6_interface.h"
+#include "ospf6_neighbor.h"
+#include "ospf6_intra.h"
+#include "ospf6_asbr.h"
char ospf6_daemon_version[] = OSPF6_DAEMON_VERSION;
-
-#define TIMER_SEC_MICRO 1000000
-
void
-ospf6_timeval_sub (const struct timeval *t1, const struct timeval *t2,
- struct timeval *result)
+ospf6_debug ()
{
- long usec, movedown = 0;
+}
- if (t1->tv_sec < t2->tv_sec ||
- (t1->tv_sec == t2->tv_sec && t1->tv_usec < t2->tv_usec))
+static struct route_node *
+_route_next_until (struct route_node *node, struct route_node *limit)
+{
+ struct route_node *next;
+ struct route_node *start;
+
+ /* Node may be deleted from route_unlock_node so we have to preserve
+ next node's pointer. */
+
+ if (node->l_left)
{
- result->tv_sec = 0;
- result->tv_usec = 0;
- return;
+ next = node->l_left;
+ if (next == limit)
+ {
+ route_unlock_node (node);
+ return NULL;
+ }
+ route_lock_node (next);
+ route_unlock_node (node);
+ return next;
+ }
+ if (node->l_right)
+ {
+ next = node->l_right;
+ if (next == limit)
+ {
+ route_unlock_node (node);
+ return NULL;
+ }
+ route_lock_node (next);
+ route_unlock_node (node);
+ return next;
}
- if (t1->tv_usec < t2->tv_usec)
+ start = node;
+ while (node->parent)
{
- usec = t1->tv_usec + TIMER_SEC_MICRO;
- movedown++;
- }
- else
- usec = t1->tv_usec;
- result->tv_usec = usec - t2->tv_usec;
-
- result->tv_sec = t1->tv_sec - t2->tv_sec - movedown;
-}
-
-void
-ospf6_timeval_div (const struct timeval *t1, u_int by,
- struct timeval *result)
-{
- long movedown;
-
- if (by == 0)
- {
- result->tv_sec = 0;
- result->tv_usec = 0;
- return;
+ if (node->parent->l_left == node && node->parent->l_right)
+ {
+ next = node->parent->l_right;
+ if (next == limit)
+ {
+ route_unlock_node (start);
+ return NULL;
+ }
+ route_lock_node (next);
+ route_unlock_node (start);
+ return next;
+ }
+ node = node->parent;
}
- movedown = t1->tv_sec % by;
- result->tv_sec = t1->tv_sec / by;
- result->tv_usec = (t1->tv_usec + movedown * TIMER_SEC_MICRO) / by;
+ route_unlock_node (start);
+ return NULL;
}
-void
-ospf6_timeval_decode (const struct timeval *t, long *dayp, long *hourp,
- long *minp, long *secp, long *msecp, long *usecp)
+struct route_node *
+route_prev (struct route_node *node)
{
- long day, hour, min, sec, msec, usec, left;
+ struct route_node *end;
+ struct route_node *prev = NULL;
- left = t->tv_sec;
- day = left / 86400; left -= day * 86400;
- hour = left / 3600; left -= hour * 3600;
- min = left / 60; left -= min * 60;
- sec = left;
- left = t->tv_usec;
- msec = left / 1000; left -= msec * 1000;
- usec = left;
+ if (node->parent == NULL)
+ {
+ route_unlock_node (node);
+ return NULL;
+ }
- if (dayp) *dayp = day;
- if (hourp) *hourp = hour;
- if (minp) *minp = min;
- if (secp) *secp = sec;
- if (msecp) *msecp = msec;
- if (usecp) *usecp = usec;
+ if (node->parent->l_left == node)
+ {
+ prev = node->parent;
+ route_lock_node (prev);
+ route_unlock_node (node);
+ return prev;
+ }
+
+ end = node;
+ node = node->parent;
+ route_lock_node (node);
+ while (node)
+ {
+ prev = node;
+ node = _route_next_until (node, end);
+ }
+ route_unlock_node (end);
+ route_lock_node (prev);
+
+ return prev;
}
-void
-ospf6_timeval_string (struct timeval *tv, char *buf, int size)
-{
- char days[16], hours[16], mins[16], secs[16], msecs[16], usecs[16];
- long day, hour, min, sec, msec, usec;
-
- ospf6_timeval_decode (tv, &day, &hour, &min, &sec, &msec, &usec);
- snprintf (days, sizeof (days), "%ld days ", day);
- snprintf (hours, sizeof (hours), "%ld hours ", hour);
- snprintf (mins, sizeof (mins), "%ld mins ", min);
- snprintf (secs, sizeof (secs), "%ld secs ", sec);
- snprintf (msecs, sizeof (msecs), "%ld msecs ", msec);
- snprintf (usecs, sizeof (usecs), "%ld usecs ", usec);
-
- snprintf (buf, size, "%s%s%s%s%s%s",
- (day ? days : ""), (hour ? hours : ""),
- (min ? mins : ""), (sec ? secs : ""),
- (msec ? msecs : ""), (usec ? usecs : ""));
-}
-
-void
-ospf6_timeval_string_summary (struct timeval *tv, char *buf, int size)
-{
- char days[16], hours[16], mins[16], secs[16], msecs[16], usecs[16];
- long day, hour, min, sec, msec, usec;
-
- ospf6_timeval_decode (tv, &day, &hour, &min, &sec, &msec, &usec);
- snprintf (days, sizeof (days), "%02ldd", day);
- snprintf (hours, sizeof (hours), "%ldh", hour);
- snprintf (mins, sizeof (mins), "%ldm", min);
- snprintf (secs, sizeof (secs), "%lds", sec);
- snprintf (msecs, sizeof (msecs), "%ldms", msec);
- snprintf (usecs, sizeof (usecs), "%ldus", usec);
-
- snprintf (buf, size, "%s%02ld:%02ld:%02ld",
- (day ? days : ""), hour, min, sec);
-}
-
-/* foreach function */
-void
-ospf6_count_state (void *arg, int val, void *obj)
-{
- int *count = (int *) arg;
- u_char state = val;
- struct ospf6_neighbor *nei = (struct ospf6_neighbor *) obj;
-
- if (nei->state == state)
- (*count)++;
-}
-
-/* VTY commands. */
-DEFUN (reload,
- reload_cmd,
- "reload",
- "Reloads\n")
-{
- extern void _reload ();
- _reload ();
- return CMD_SUCCESS;
-}
-
-DEFUN (garbage_collection,
- garbage_collection_cmd,
- "ipv6 ospf6 garbage collect",
- IPV6_STR
- OSPF6_STR
- "garbage collection by hand\n"
- "Remove Maxages if possible and recalculate routes\n")
-{
- ospf6_maxage_remover ();
-#if 0
- ospf6_route_calculation_schedule ();
-#endif
- return CMD_SUCCESS;
-}
-
-/* Show version. */
DEFUN (show_version_ospf6,
show_version_ospf6_cmd,
"show version ospf6",
SHOW_STR
- "Displays ospf6d version\n")
+ "Displays ospf6d version\n"
+ )
{
vty_out (vty, "Zebra OSPF6d Version: %s%s",
ospf6_daemon_version, VTY_NEWLINE);
@@ -193,582 +152,1103 @@
return CMD_SUCCESS;
}
-/* start ospf6 */
-DEFUN (router_ospf6,
- router_ospf6_cmd,
- "router ospf6",
- OSPF6_ROUTER_STR
- OSPF6_STR)
+struct cmd_node debug_node =
{
- if (ospf6 == NULL)
- ospf6_start ();
-
- /* set current ospf point. */
- vty->node = OSPF6_NODE;
- vty->index = ospf6;
-
- return CMD_SUCCESS;
-}
-
-/* stop ospf6 */
-DEFUN (no_router_ospf6,
- no_router_ospf6_cmd,
- "no router ospf6",
- NO_STR
- OSPF6_ROUTER_STR)
-{
- if (!ospf6)
- vty_out (vty, "OSPFv3 is not running%s", VTY_NEWLINE);
- else
- ospf6_stop ();
-
- /* return to config node . */
- vty->node = CONFIG_NODE;
- vty->index = NULL;
-
- return CMD_SUCCESS;
-}
-
-/* show top level structures */
-DEFUN (show_ipv6_ospf6,
- show_ipv6_ospf6_cmd,
- "show ipv6 ospf6",
- SHOW_STR
- IP6_STR
- OSPF6_STR)
-{
- OSPF6_CMD_CHECK_RUNNING ();
-
- ospf6_show (vty);
- return CMD_SUCCESS;
-}
-
-DEFUN (show_ipv6_ospf6_nexthoplist,
- show_ipv6_ospf6_nexthoplist_cmd,
- "show ipv6 ospf6 nexthop-list",
- SHOW_STR
- IP6_STR
- OSPF6_STR
- "List of nexthop\n")
-{
-#if 0
- listnode i;
- struct ospf6_nexthop *nh;
- char buf[128];
- for (i = listhead (nexthoplist); i; nextnode (i))
- {
- nh = (struct ospf6_nexthop *) getdata (i);
- nexthop_str (nh, buf, sizeof (buf));
- vty_out (vty, "%s%s", buf,
- VTY_NEWLINE);
- }
-#endif
- return CMD_SUCCESS;
-}
-
-DEFUN (show_ipv6_ospf6_statistics,
- show_ipv6_ospf6_statistics_cmd,
- "show ipv6 ospf6 statistics",
- SHOW_STR
- IP6_STR
- OSPF6_STR
- "Statistics\n")
-{
- OSPF6_CMD_CHECK_RUNNING ();
-
- ospf6_statistics_show (vty, ospf6);
- return CMD_SUCCESS;
-}
-
-/* change Router_ID commands. */
-DEFUN (ospf6_router_id,
- ospf6_router_id_cmd,
- "router-id ROUTER_ID",
- "Configure ospf Router-ID.\n"
- V4NOTATION_STR)
-{
- int ret;
- u_int32_t router_id;
-
- ret = inet_pton (AF_INET, argv[0], &router_id);
- if (!ret)
- {
- vty_out (vty, "malformed ospf router identifier%s", VTY_NEWLINE);
- vty_out (vty, "%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- if (IS_OSPF6_DUMP_CONFIG)
- zlog_info ("CONFIG: router-id %s", argv[0]);
- ospf6->router_id = router_id;
-
- return CMD_SUCCESS;
-}
+ DEBUG_NODE,
+ ""
+};
int
-ospf6_interface_bind_area (struct vty *vty,
- char *if_name, char *area_name,
- char *plist_name, int passive)
+config_write_ospf6_debug (struct vty *vty)
{
- struct interface *ifp;
- struct ospf6_interface *o6i;
- struct ospf6_area *o6a;
- u_int32_t area_id;
-
- /* find/create ospf6 interface */
- ifp = if_get_by_name (if_name);
- o6i = (struct ospf6_interface *) ifp->info;
- if (! o6i)
- o6i = ospf6_interface_create (ifp);
-
- /* parse Area-ID */
- if (inet_pton (AF_INET, area_name, &area_id) != 1)
- {
- vty_out (vty, "Invalid Area-ID: %s%s", area_name, VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- /* find/create ospf6 area */
- o6a = ospf6_area_lookup (area_id, ospf6);
- if (!o6a)
- {
- o6a = ospf6_area_create (area_id);
- o6a->ospf6 = ospf6;
- listnode_add (ospf6->area_list, o6a);
- }
-
- if (o6i->area)
- {
- if (o6i->area != o6a)
- {
- vty_out (vty, "Aready attached to area %s%s",
- o6i->area->str, VTY_NEWLINE);
- return CMD_ERR_NOTHING_TODO;
- }
- }
- else
- {
- listnode_add (o6a->if_list, o6i);
- o6i->area = o6a;
- }
-
- /* prefix-list name */
- if (plist_name)
- {
- if (o6i->plist_name)
- XFREE (MTYPE_PREFIX_LIST_STR, o6i->plist_name);
- o6i->plist_name = XSTRDUP (MTYPE_PREFIX_LIST_STR, plist_name);
- }
- else
- {
- if (o6i->plist_name)
- XFREE (MTYPE_PREFIX_LIST_STR, o6i->plist_name);
- o6i->plist_name = NULL;
- }
-
- if (passive)
- {
- listnode node;
- struct ospf6_neighbor *o6n;
-
- SET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE);
- if (o6i->thread_send_hello)
- {
- thread_cancel (o6i->thread_send_hello);
- o6i->thread_send_hello = (struct thread *) NULL;
- }
-
- for (node = listhead (o6i->neighbor_list); node; nextnode (node))
- {
- o6n = getdata (node);
- if (o6n->inactivity_timer)
- thread_cancel (o6n->inactivity_timer);
- thread_execute (master, inactivity_timer, o6n, 0);
- }
- }
- else
- {
- UNSET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE);
- if (o6i->thread_send_hello == NULL)
- thread_add_event (master, ospf6_send_hello, o6i, 0);
- }
-
- /* enable I/F if it's not enabled still */
- if (! ospf6_interface_is_enabled (o6i->interface->ifindex))
- thread_add_event (master, interface_up, o6i, 0);
- else
- CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, o6i);
-
- CALL_CHANGE_HOOK (&interface_hook, o6i);
- return CMD_SUCCESS;
-}
-
-DEFUN (ospf6_interface_area_plist,
- ospf6_interface_area_plist_cmd,
- "interface IFNAME area A.B.C.D prefix-list WORD",
- "Enable routing on an IPv6 interface\n"
- IFNAME_STR
- "Set the OSPF6 area ID\n"
- "OSPF6 area ID in IPv4 address notation\n"
- OSPF6_PREFIX_LIST_STR
- "IPv6 prefix-list name\n"
- )
-{
- if (IS_OSPF6_DUMP_CONFIG)
- zlog_info ("CONFIG: interface %s area %s prefix-list %s",
- argv[0], argv[1], argv[2]);
-
- return ospf6_interface_bind_area (vty, argv[0], argv[1], argv[2], 0);
-}
-
-DEFUN (ospf6_interface_area_plist_passive,
- ospf6_interface_area_plist_passive_cmd,
- "interface IFNAME area A.B.C.D prefix-list WORD passive",
- "Enable routing on an IPv6 interface\n"
- IFNAME_STR
- "Set the OSPF6 area ID\n"
- "OSPF6 area ID in IPv4 address notation\n"
- OSPF6_PREFIX_LIST_STR
- "IPv6 prefix-list name\n"
- "IPv6 prefix-list name\n"
- OSPF6_PASSIVE_STR
- )
-{
- if (IS_OSPF6_DUMP_CONFIG)
- zlog_info ("CONFIG: interface %s area %s prefix-list %s passive",
- argv[0], argv[1], argv[2]);
-
- return ospf6_interface_bind_area (vty, argv[0], argv[1], argv[2], 1);
-}
-
-DEFUN (ospf6_interface_area,
- ospf6_interface_area_cmd,
- "interface IFNAME area A.B.C.D",
- "Enable routing on an IPv6 interface\n"
- IFNAME_STR
- "Set the OSPF6 area ID\n"
- "OSPF6 area ID in IPv4 address notation\n"
- )
-{
- struct interface *ifp;
- struct ospf6_interface *o6i;
- int passive;
- char *plist_name;
-
- if (IS_OSPF6_DUMP_CONFIG)
- zlog_info ("CONFIG: interface %s area %s",
- argv[0], argv[1]);
-
- ifp = if_get_by_name (argv[0]);
- o6i = (struct ospf6_interface *) ifp->info;
- if (o6i)
- {
- passive = CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE);
- plist_name = o6i->plist_name;
- }
- else
- {
- passive = 0;
- plist_name = NULL;
- }
-
- return ospf6_interface_bind_area (vty, argv[0], argv[1],
- plist_name, passive);
-}
-
-DEFUN (ospf6_interface_area_passive,
- ospf6_interface_area_passive_cmd,
- "interface IFNAME area A.B.C.D passive",
- "Enable routing on an IPv6 interface\n"
- IFNAME_STR
- "Set the OSPF6 area ID\n"
- "OSPF6 area ID in IPv4 address notation\n"
- OSPF6_PASSIVE_STR
- )
-{
- if (IS_OSPF6_DUMP_CONFIG)
- zlog_info ("CONFIG: interface %s area %s passive",
- argv[0], argv[1]);
-
- return ospf6_interface_bind_area (vty, argv[0], argv[1], NULL, 1);
-}
-
-DEFUN (no_ospf6_interface_area,
- no_ospf6_interface_area_cmd,
- "no interface IFNAME area A.B.C.D",
- NO_STR
- "Disable routing on an IPv6 interface\n"
- IFNAME_STR)
-{
- struct interface *ifp;
- struct ospf6_interface *o6i;
- struct ospf6 *o6;
- u_int32_t area_id;
-
- o6 = (struct ospf6 *) vty->index;
-
- ifp = if_lookup_by_name (argv[0]);
- if (!ifp)
- return CMD_ERR_NO_MATCH;
-
- o6i = (struct ospf6_interface *) ifp->info;
- if (!o6i)
- return CMD_SUCCESS;
-
- /* parse Area-ID */
- if (inet_pton (AF_INET, argv[1], &area_id) != 1)
- {
- vty_out (vty, "Invalid Area-ID: %s%s", argv[1], VTY_NEWLINE);
- return CMD_ERR_AMBIGUOUS;
- }
-
- if (o6i->area->area_id != area_id)
- {
- vty_out (vty, "Wrong Area-ID: %s aready attached to area %s%s",
- o6i->interface->name, o6i->area->str, VTY_NEWLINE);
- return CMD_ERR_NOTHING_TODO;
- }
-
- if (o6i->area)
- thread_execute (master, interface_down, o6i, 0);
-
- listnode_delete (o6i->area->if_list, o6i);
- o6i->area = (struct ospf6_area *) NULL;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ospf6_area_range,
- ospf6_area_range_cmd,
- "area A.B.C.D range X:X::X:X/M",
- "OSPFv3 area parameters\n"
- "OSPFv3 area ID in IPv4 address format\n"
- "Summarize routes matching address/mask (border routers only)\n"
- "IPv6 address range\n")
-{
- struct ospf6 *o6;
- struct ospf6_area *o6a;
- u_int32_t area_id;
- int ret;
-
- o6 = (struct ospf6 *) vty->index;
- inet_pton (AF_INET, argv[0], &area_id);
- o6a = ospf6_area_lookup (area_id, o6);
- if (! o6a)
- {
- vty_out (vty, "No such area%s", VTY_NEWLINE);
- return CMD_ERR_NO_MATCH;
- }
-
- ret = str2prefix_ipv6 (argv[1], &o6a->area_range);
- if (ret <= 0)
- {
- vty_out (vty, "Malformed IPv6 address%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ospf6_passive_interface,
- ospf6_passive_interface_cmd,
- "passive-interface IFNAME",
- OSPF6_PASSIVE_STR
- IFNAME_STR)
-{
- struct interface *ifp;
- struct ospf6_interface *o6i;
-
- ifp = if_get_by_name (argv[0]);
- if (ifp->info)
- o6i = (struct ospf6_interface *) ifp->info;
- else
- o6i = ospf6_interface_create (ifp);
-
- SET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE);
-
- if (o6i->thread_send_hello)
- {
- thread_cancel (o6i->thread_send_hello);
- o6i->thread_send_hello = (struct thread *) NULL;
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ospf6_passive_interface,
- no_ospf6_passive_interface_cmd,
- "no passive-interface IFNAME",
- NO_STR
- OSPF6_PASSIVE_STR
- IFNAME_STR)
-{
- struct interface *ifp;
- struct ospf6_interface *o6i;
-
- ifp = if_lookup_by_name (argv[0]);
- if (! ifp)
- return CMD_ERR_NO_MATCH;
-
- o6i = (struct ospf6_interface *) ifp->info;
- UNSET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE);
- if (o6i->thread_send_hello == NULL)
- thread_add_event (master, ospf6_send_hello, o6i, 0);
-
- return CMD_SUCCESS;
-}
-
-#ifdef HAVE_SETPROCTITLE
-extern int _argc;
-extern char **_argv;
-
-DEFUN (set_proctitle,
- set_proctitle_cmd,
- "set proctitle (version|normal|none)",
- "Set command\n"
- "Process title\n"
- "Version information\n"
- "Normal command-line options\n"
- "Just program name\n")
-{
- int i;
- char buf[64], tmp[64];
-
- if (strncmp (argv[0], "v", 1) == 0)
- {
- proctitle_mode = 1;
- setproctitle ("%s Zebra: %s", OSPF6_DAEMON_VERSION, QUAGGA_VERSION);
- }
- else if (strncmp (argv[0], "nor", 3) == 0)
- {
- proctitle_mode = 0;
- memset (tmp, 0, sizeof (tmp));
- memset (buf, 0, sizeof (buf));
- for (i = 0; i < _argc; i++)
- {
- snprintf (buf, sizeof (buf), "%s%s ", tmp, _argv[i]);
- memcpy (&tmp, &buf, sizeof (tmp));
- }
- setproctitle (buf);
- }
- else if (strncmp (argv[0], "non", 3) == 0)
- {
- proctitle_mode = -1;
- setproctitle (NULL);
- }
- else
- return CMD_ERR_NO_MATCH;
-
- return CMD_SUCCESS;
-}
-#endif /* HAVE_SETPROCTITLE */
-
-/* OSPF configuration write function. */
-int
-ospf6_config_write (struct vty *vty)
-{
- listnode j, k;
- char buf[64];
- struct ospf6_area *area;
- struct ospf6_interface *o6i;
-
- if (proctitle_mode == 1)
- vty_out (vty, "set proctitle version%s", VTY_NEWLINE);
- else if (proctitle_mode == -1)
- vty_out (vty, "set proctitle none%s", VTY_NEWLINE);
-
- vty_out (vty, "!%s", VTY_NEWLINE);
-
- if (! ospf6)
- return 0;
-
- /* OSPFv6 configuration. */
- if (!ospf6)
- return CMD_SUCCESS;
-
- inet_ntop (AF_INET, &ospf6->router_id, buf, sizeof (buf));
- vty_out (vty, "router ospf6%s", VTY_NEWLINE);
- vty_out (vty, " router-id %s%s", buf, VTY_NEWLINE);
-
- ospf6_redistribute_config_write (vty);
- ospf6_damp_config_write (vty);
-
- for (j = listhead (ospf6->area_list); j; nextnode (j))
- {
- area = (struct ospf6_area *)getdata (j);
- for (k = listhead (area->if_list); k; nextnode (k))
- {
- o6i = (struct ospf6_interface *) getdata (k);
- vty_out (vty, " interface %s area %s%s",
- o6i->interface->name, area->str, VTY_NEWLINE);
- }
- }
+ config_write_ospf6_debug_message (vty);
+ config_write_ospf6_debug_lsa (vty);
+ config_write_ospf6_debug_zebra (vty);
+ config_write_ospf6_debug_interface (vty);
+ config_write_ospf6_debug_neighbor (vty);
+ config_write_ospf6_debug_spf (vty);
+ config_write_ospf6_debug_route (vty);
+ config_write_ospf6_debug_asbr (vty);
vty_out (vty, "!%s", VTY_NEWLINE);
return 0;
}
-/* OSPF6 node structure. */
-struct cmd_node ospf6_node =
+DEFUN (show_ipv6_ospf6_database,
+ show_ipv6_ospf6_database_cmd,
+ "show ipv6 ospf6 database",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ )
{
- OSPF6_NODE,
- "%s(config-ospf6)# ",
- vtysh: 1
-};
+ listnode i, j;
+ struct ospf6 *o = ospf6;
+ void (*showfunc) (struct vty *, struct ospf6_lsa *) = NULL;
+
+ OSPF6_CMD_CHECK_RUNNING ();
+
+ if (argc)
+ {
+ if (! strncmp (argv[0], "de", 2))
+ showfunc = ospf6_lsa_show;
+ else if (! strncmp (argv[0], "du", 2))
+ showfunc = ospf6_lsa_show_dump;
+ else if (! strncmp (argv[0], "in", 2))
+ showfunc = ospf6_lsa_show_internal;
+ }
+ else
+ showfunc = ospf6_lsa_show_summary;
+
+ if (showfunc == ospf6_lsa_show_summary)
+ ospf6_lsa_show_summary_header (vty);
+
+ LSDB_FOREACH_LSA (vty, showfunc, o->lsdb);
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ LSDB_FOREACH_LSA (vty, showfunc, oa->lsdb);
+ }
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ for (j = listhead (oa->if_list); j; nextnode (j))
+ {
+ struct ospf6_interface *oi = (struct ospf6_interface *) getdata (j);
+ LSDB_FOREACH_LSA (vty, showfunc, oi->lsdb);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_database,
+ show_ipv6_ospf6_database_detail_cmd,
+ "show ipv6 ospf6 database (detail|dump|internal)",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Display details of LSAs\n"
+ "Dump LSAs\n"
+ "Display LSA's internal information\n"
+ );
+
+DEFUN (show_ipv6_ospf6_database_type,
+ show_ipv6_ospf6_database_type_cmd,
+ "show ipv6 ospf6 database "
+ "(router|network|inter-prefix|inter-router|as-external|"
+ "group-membership|type-7|link|intra-prefix)",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Display Router LSAs\n"
+ "Display Network LSAs\n"
+ "Display Inter-Area-Prefix LSAs\n"
+ "Display Inter-Area-Router LSAs\n"
+ "Display As-External LSAs\n"
+ "Display Group-Membership LSAs\n"
+ "Display Type-7 LSAs\n"
+ "Display Link LSAs\n"
+ "Display Intra-Area-Prefix LSAs\n"
+ )
+{
+ listnode i, j;
+ struct ospf6 *o = ospf6;
+ void (*showfunc) (struct vty *, struct ospf6_lsa *) = NULL;
+ u_int16_t type = 0;
+
+ OSPF6_CMD_CHECK_RUNNING ();
+
+ if (argc > 1)
+ {
+ if (! strncmp (argv[1], "de", 2))
+ showfunc = ospf6_lsa_show;
+ else if (! strncmp (argv[1], "du", 2))
+ showfunc = ospf6_lsa_show_dump;
+ else if (! strncmp (argv[1], "in", 2))
+ showfunc = ospf6_lsa_show_internal;
+ }
+ else
+ showfunc = ospf6_lsa_show_summary;
+
+ if (showfunc == ospf6_lsa_show_summary)
+ ospf6_lsa_show_summary_header (vty);
+
+ if (! strcmp (argv[0], "router"))
+ type = htons (OSPF6_LSTYPE_ROUTER);
+ else if (! strcmp (argv[0], "network"))
+ type = htons (OSPF6_LSTYPE_NETWORK);
+ else if (! strcmp (argv[0], "as-external"))
+ type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
+ else if (! strcmp (argv[0], "intra-prefix"))
+ type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
+ else if (! strcmp (argv[0], "inter-router"))
+ type = htons (OSPF6_LSTYPE_INTER_ROUTER);
+ else if (! strcmp (argv[0], "inter-prefix"))
+ type = htons (OSPF6_LSTYPE_INTER_PREFIX);
+ else if (! strcmp (argv[0], "link"))
+ type = htons (OSPF6_LSTYPE_LINK);
+
+ LSDB_FOREACH_LSA_T (vty, showfunc, o->lsdb, type);
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ LSDB_FOREACH_LSA_T (vty, showfunc, oa->lsdb, type);
+ }
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ for (j = listhead (oa->if_list); j; nextnode (j))
+ {
+ struct ospf6_interface *oi = (struct ospf6_interface *) getdata (j);
+ LSDB_FOREACH_LSA_T (vty, showfunc, oi->lsdb, type);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_database_type,
+ show_ipv6_ospf6_database_type_detail_cmd,
+ "show ipv6 ospf6 database "
+ "(router|network|inter-prefix|inter-router|as-external|"
+ "group-membership|type-7|link|intra-prefix) "
+ "(detail|dump|internal)",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Display Router LSAs\n"
+ "Display Network LSAs\n"
+ "Display Inter-Area-Prefix LSAs\n"
+ "Display Inter-Area-Router LSAs\n"
+ "Display As-External LSAs\n"
+ "Display Group-Membership LSAs\n"
+ "Display Type-7 LSAs\n"
+ "Display Link LSAs\n"
+ "Display Intra-Area-Prefix LSAs\n"
+ "Display details of LSAs\n"
+ "Dump LSAs\n"
+ "Display LSA's internal information\n"
+ );
+
+DEFUN (show_ipv6_ospf6_database_id,
+ show_ipv6_ospf6_database_id_cmd,
+ "show ipv6 ospf6 database * A.B.C.D",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Any Link state Type\n"
+ "Specify Link state ID as IPv4 address notation\n"
+ )
+{
+ listnode i, j;
+ struct ospf6 *o = ospf6;
+ void (*showfunc) (struct vty *, struct ospf6_lsa *) = NULL;
+ u_int32_t id = 0;
+
+ OSPF6_CMD_CHECK_RUNNING ();
+
+ if (argc > 1)
+ {
+ if (! strncmp (argv[1], "de", 2))
+ showfunc = ospf6_lsa_show;
+ else if (! strncmp (argv[1], "du", 2))
+ showfunc = ospf6_lsa_show_dump;
+ else if (! strncmp (argv[1], "in", 2))
+ showfunc = ospf6_lsa_show_internal;
+ }
+ else
+ showfunc = ospf6_lsa_show_summary;
+
+ if (showfunc == ospf6_lsa_show_summary)
+ ospf6_lsa_show_summary_header (vty);
+
+ if ((inet_pton (AF_INET, argv[0], &id)) != 1)
+ {
+ vty_out (vty, "Link State ID is not parsable: %s%s",
+ argv[0], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ LSDB_FOREACH_LSA_I (vty, showfunc, o->lsdb, id);
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ LSDB_FOREACH_LSA_I (vty, showfunc, oa->lsdb, id);
+ }
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ for (j = listhead (oa->if_list); j; nextnode (j))
+ {
+ struct ospf6_interface *oi = (struct ospf6_interface *) getdata (j);
+ LSDB_FOREACH_LSA_I (vty, showfunc, oi->lsdb, id);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_database_id,
+ show_ipv6_ospf6_database_id_detail_cmd,
+ "show ipv6 ospf6 database * A.B.C.D "
+ "(detail|dump|internal)",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Any Link state Type\n"
+ "Any Link state ID\n"
+ "Specify Link state ID as IPv4 address notation\n"
+ "Display details of LSAs\n"
+ "Dump LSAs\n"
+ "Display LSA's internal information\n"
+ );
+
+DEFUN (show_ipv6_ospf6_database_router,
+ show_ipv6_ospf6_database_router_cmd,
+ "show ipv6 ospf6 database * * A.B.C.D",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Any Link state Type\n"
+ "Any Link state ID\n"
+ "Specify Advertising Router as IPv4 address notation\n"
+ )
+{
+ listnode i, j;
+ struct ospf6 *o = ospf6;
+ void (*showfunc) (struct vty *, struct ospf6_lsa *) = NULL;
+ u_int32_t router = 0;
+
+ OSPF6_CMD_CHECK_RUNNING ();
+
+ if (argc > 1)
+ {
+ if (! strncmp (argv[1], "de", 2))
+ showfunc = ospf6_lsa_show;
+ else if (! strncmp (argv[1], "du", 2))
+ showfunc = ospf6_lsa_show_dump;
+ else if (! strncmp (argv[1], "in", 2))
+ showfunc = ospf6_lsa_show_internal;
+ }
+ else
+ showfunc = ospf6_lsa_show_summary;
+
+ if (showfunc == ospf6_lsa_show_summary)
+ ospf6_lsa_show_summary_header (vty);
+
+ if ((inet_pton (AF_INET, argv[0], &router)) != 1)
+ {
+ vty_out (vty, "Advertising Router is not parsable: %s%s",
+ argv[0], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ LSDB_FOREACH_LSA_R (vty, showfunc, o->lsdb, router);
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ LSDB_FOREACH_LSA_R (vty, showfunc, oa->lsdb, router);
+ }
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ for (j = listhead (oa->if_list); j; nextnode (j))
+ {
+ struct ospf6_interface *oi = (struct ospf6_interface *) getdata (j);
+ LSDB_FOREACH_LSA_R (vty, showfunc, oi->lsdb, router);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_database_router,
+ show_ipv6_ospf6_database_router_detail_cmd,
+ "show ipv6 ospf6 database * * A.B.C.D "
+ "(detail|dump|internal)",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Any Link state Type\n"
+ "Any Link state ID\n"
+ "Specify Advertising Router as IPv4 address notation\n"
+ "Display details of LSAs\n"
+ "Dump LSAs\n"
+ "Display LSA's internal information\n"
+ );
+
+DEFUN (show_ipv6_ospf6_database_type_id,
+ show_ipv6_ospf6_database_type_id_cmd,
+ "show ipv6 ospf6 database "
+ "(router|network|inter-prefix|inter-router|as-external|"
+ "group-membership|type-7|link|intra-prefix) A.B.C.D",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Display Router LSAs\n"
+ "Display Network LSAs\n"
+ "Display Inter-Area-Prefix LSAs\n"
+ "Display Inter-Area-Router LSAs\n"
+ "Display As-External LSAs\n"
+ "Display Group-Membership LSAs\n"
+ "Display Type-7 LSAs\n"
+ "Display Link LSAs\n"
+ "Display Intra-Area-Prefix LSAs\n"
+ "Specify Link state ID as IPv4 address notation\n"
+ )
+{
+ listnode i, j;
+ struct ospf6 *o = ospf6;
+ void (*showfunc) (struct vty *, struct ospf6_lsa *) = NULL;
+ u_int16_t type = 0;
+ u_int32_t id = 0;
+
+ OSPF6_CMD_CHECK_RUNNING ();
+
+ if (argc > 2)
+ {
+ if (! strncmp (argv[2], "de", 2))
+ showfunc = ospf6_lsa_show;
+ else if (! strncmp (argv[2], "du", 2))
+ showfunc = ospf6_lsa_show_dump;
+ else if (! strncmp (argv[2], "in", 2))
+ showfunc = ospf6_lsa_show_internal;
+ }
+ else
+ showfunc = ospf6_lsa_show_summary;
+
+ if (showfunc == ospf6_lsa_show_summary)
+ ospf6_lsa_show_summary_header (vty);
+
+ if (! strcmp (argv[0], "router"))
+ type = htons (OSPF6_LSTYPE_ROUTER);
+ else if (! strcmp (argv[0], "network"))
+ type = htons (OSPF6_LSTYPE_NETWORK);
+ else if (! strcmp (argv[0], "as-external"))
+ type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
+ else if (! strcmp (argv[0], "intra-prefix"))
+ type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
+ else if (! strcmp (argv[0], "inter-router"))
+ type = htons (OSPF6_LSTYPE_INTER_ROUTER);
+ else if (! strcmp (argv[0], "inter-prefix"))
+ type = htons (OSPF6_LSTYPE_INTER_PREFIX);
+ else if (! strcmp (argv[0], "link"))
+ type = htons (OSPF6_LSTYPE_LINK);
+
+ if ((inet_pton (AF_INET, argv[1], &id)) != 1)
+ {
+ vty_out (vty, "Link state ID is not parsable: %s%s",
+ argv[1], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ LSDB_FOREACH_LSA_TI (vty, showfunc, o->lsdb, type, id);
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ LSDB_FOREACH_LSA_TI (vty, showfunc, oa->lsdb, type, id);
+ }
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ for (j = listhead (oa->if_list); j; nextnode (j))
+ {
+ struct ospf6_interface *oi = (struct ospf6_interface *) getdata (j);
+ LSDB_FOREACH_LSA_TI (vty, showfunc, oi->lsdb, type, id);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_database_type_id,
+ show_ipv6_ospf6_database_type_id_detail_cmd,
+ "show ipv6 ospf6 database "
+ "(router|network|inter-prefix|inter-router|as-external|"
+ "group-membership|type-7|link|intra-prefix) A.B.C.D "
+ "(detail|dump|internal)",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Display Router LSAs\n"
+ "Display Network LSAs\n"
+ "Display Inter-Area-Prefix LSAs\n"
+ "Display Inter-Area-Router LSAs\n"
+ "Display As-External LSAs\n"
+ "Display Group-Membership LSAs\n"
+ "Display Type-7 LSAs\n"
+ "Display Link LSAs\n"
+ "Display Intra-Area-Prefix LSAs\n"
+ "Specify Link state ID as IPv4 address notation\n"
+ "Display details of LSAs\n"
+ "Dump LSAs\n"
+ "Display LSA's internal information\n"
+ );
+
+DEFUN (show_ipv6_ospf6_database_type_router,
+ show_ipv6_ospf6_database_type_router_cmd,
+ "show ipv6 ospf6 database "
+ "(router|network|inter-prefix|inter-router|as-external|"
+ "group-membership|type-7|link|intra-prefix) * A.B.C.D",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Display Router LSAs\n"
+ "Display Network LSAs\n"
+ "Display Inter-Area-Prefix LSAs\n"
+ "Display Inter-Area-Router LSAs\n"
+ "Display As-External LSAs\n"
+ "Display Group-Membership LSAs\n"
+ "Display Type-7 LSAs\n"
+ "Display Link LSAs\n"
+ "Display Intra-Area-Prefix LSAs\n"
+ "Any Link state ID\n"
+ "Specify Advertising Router as IPv4 address notation\n"
+ )
+{
+ listnode i, j;
+ struct ospf6 *o = ospf6;
+ void (*showfunc) (struct vty *, struct ospf6_lsa *) = NULL;
+ u_int16_t type = 0;
+ u_int32_t router = 0;
+
+ OSPF6_CMD_CHECK_RUNNING ();
+
+ if (argc > 2)
+ {
+ if (! strncmp (argv[2], "de", 2))
+ showfunc = ospf6_lsa_show;
+ else if (! strncmp (argv[2], "du", 2))
+ showfunc = ospf6_lsa_show_dump;
+ else if (! strncmp (argv[2], "in", 2))
+ showfunc = ospf6_lsa_show_internal;
+ }
+ else
+ showfunc = ospf6_lsa_show_summary;
+
+ if (showfunc == ospf6_lsa_show_summary)
+ ospf6_lsa_show_summary_header (vty);
+
+ if (! strcmp (argv[0], "router"))
+ type = htons (OSPF6_LSTYPE_ROUTER);
+ else if (! strcmp (argv[0], "network"))
+ type = htons (OSPF6_LSTYPE_NETWORK);
+ else if (! strcmp (argv[0], "as-external"))
+ type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
+ else if (! strcmp (argv[0], "intra-prefix"))
+ type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
+ else if (! strcmp (argv[0], "inter-router"))
+ type = htons (OSPF6_LSTYPE_INTER_ROUTER);
+ else if (! strcmp (argv[0], "inter-prefix"))
+ type = htons (OSPF6_LSTYPE_INTER_PREFIX);
+ else if (! strcmp (argv[0], "link"))
+ type = htons (OSPF6_LSTYPE_LINK);
+
+ if ((inet_pton (AF_INET, argv[1], &router)) != 1)
+ {
+ vty_out (vty, "Advertising Router is not parsable: %s%s",
+ argv[1], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ LSDB_FOREACH_LSA_TR (vty, showfunc, o->lsdb, type, router);
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ LSDB_FOREACH_LSA_TR (vty, showfunc, oa->lsdb, type, router);
+ }
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ for (j = listhead (oa->if_list); j; nextnode (j))
+ {
+ struct ospf6_interface *oi = (struct ospf6_interface *) getdata (j);
+ LSDB_FOREACH_LSA_TR (vty, showfunc, oi->lsdb, type, router);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_database_type_router,
+ show_ipv6_ospf6_database_type_router_detail_cmd,
+ "show ipv6 ospf6 database "
+ "(router|network|inter-prefix|inter-router|as-external|"
+ "group-membership|type-7|link|intra-prefix) * A.B.C.D "
+ "(detail|dump|internal)",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Display Router LSAs\n"
+ "Display Network LSAs\n"
+ "Display Inter-Area-Prefix LSAs\n"
+ "Display Inter-Area-Router LSAs\n"
+ "Display As-External LSAs\n"
+ "Display Group-Membership LSAs\n"
+ "Display Type-7 LSAs\n"
+ "Display Link LSAs\n"
+ "Display Intra-Area-Prefix LSAs\n"
+ "Any Link state ID\n"
+ "Specify Advertising Router as IPv4 address notation\n"
+ "Display details of LSAs\n"
+ "Dump LSAs\n"
+ "Display LSA's internal information\n"
+ );
+
+DEFUN (show_ipv6_ospf6_database_id_router,
+ show_ipv6_ospf6_database_id_router_cmd,
+ "show ipv6 ospf6 database * A.B.C.D A.B.C.D",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Any Link state Type\n"
+ "Specify Link state ID as IPv4 address notation\n"
+ "Specify Advertising Router as IPv4 address notation\n"
+ )
+{
+ listnode i, j;
+ struct ospf6 *o = ospf6;
+ void (*showfunc) (struct vty *, struct ospf6_lsa *) = NULL;
+ u_int32_t id = 0;
+ u_int32_t router = 0;
+
+ OSPF6_CMD_CHECK_RUNNING ();
+
+ if (argc > 2)
+ {
+ if (! strncmp (argv[2], "de", 2))
+ showfunc = ospf6_lsa_show;
+ else if (! strncmp (argv[2], "du", 2))
+ showfunc = ospf6_lsa_show_dump;
+ else if (! strncmp (argv[2], "in", 2))
+ showfunc = ospf6_lsa_show_internal;
+ }
+ else
+ showfunc = ospf6_lsa_show_summary;
+
+ if (showfunc == ospf6_lsa_show_summary)
+ ospf6_lsa_show_summary_header (vty);
+
+ if ((inet_pton (AF_INET, argv[0], &id)) != 1)
+ {
+ vty_out (vty, "Link state ID is not parsable: %s%s",
+ argv[1], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ if ((inet_pton (AF_INET, argv[1], &router)) != 1)
+ {
+ vty_out (vty, "Advertising Router is not parsable: %s%s",
+ argv[1], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ LSDB_FOREACH_LSA_IR (vty, showfunc, o->lsdb, id, router);
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ LSDB_FOREACH_LSA_IR (vty, showfunc, oa->lsdb, id, router);
+ }
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ for (j = listhead (oa->if_list); j; nextnode (j))
+ {
+ struct ospf6_interface *oi = (struct ospf6_interface *) getdata (j);
+ LSDB_FOREACH_LSA_IR (vty, showfunc, oi->lsdb, id, router);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_database_id_router,
+ show_ipv6_ospf6_database_id_router_detail_cmd,
+ "show ipv6 ospf6 database * A.B.C.D A.B.C.D "
+ "(detail|dump|internal)",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Any Link state Type\n"
+ "Specify Link state ID as IPv4 address notation\n"
+ "Specify Advertising Router as IPv4 address notation\n"
+ "Display details of LSAs\n"
+ "Dump LSAs\n"
+ "Display LSA's internal information\n"
+ );
+
+DEFUN (show_ipv6_ospf6_database_type_id_router,
+ show_ipv6_ospf6_database_type_id_router_cmd,
+ "show ipv6 ospf6 database "
+ "(router|network|inter-prefix|inter-router|as-external|"
+ "group-membership|type-7|link|intra-prefix) A.B.C.D A.B.C.D",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Display Router LSAs\n"
+ "Display Network LSAs\n"
+ "Display Inter-Area-Prefix LSAs\n"
+ "Display Inter-Area-Router LSAs\n"
+ "Display As-External LSAs\n"
+ "Display Group-Membership LSAs\n"
+ "Display Type-7 LSAs\n"
+ "Display Link LSAs\n"
+ "Display Intra-Area-Prefix LSAs\n"
+ "Specify Link state ID as IPv4 address notation\n"
+ "Specify Advertising Router as IPv4 address notation\n"
+ )
+{
+ listnode i, j;
+ struct ospf6 *o = ospf6;
+ void (*showfunc) (struct vty *, struct ospf6_lsa *) = NULL;
+ u_int16_t type = 0;
+ u_int32_t id = 0;
+ u_int32_t router = 0;
+
+ OSPF6_CMD_CHECK_RUNNING ();
+
+ if (argc > 3)
+ {
+ if (! strncmp (argv[3], "du", 2))
+ showfunc = ospf6_lsa_show_dump;
+ else if (! strncmp (argv[3], "in", 2))
+ showfunc = ospf6_lsa_show_internal;
+ }
+ else
+ showfunc = ospf6_lsa_show;
+
+ if (showfunc == ospf6_lsa_show_summary)
+ ospf6_lsa_show_summary_header (vty);
+
+ if (! strcmp (argv[0], "router"))
+ type = htons (OSPF6_LSTYPE_ROUTER);
+ else if (! strcmp (argv[0], "network"))
+ type = htons (OSPF6_LSTYPE_NETWORK);
+ else if (! strcmp (argv[0], "as-external"))
+ type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
+ else if (! strcmp (argv[0], "intra-prefix"))
+ type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
+ else if (! strcmp (argv[0], "inter-router"))
+ type = htons (OSPF6_LSTYPE_INTER_ROUTER);
+ else if (! strcmp (argv[0], "inter-prefix"))
+ type = htons (OSPF6_LSTYPE_INTER_PREFIX);
+ else if (! strcmp (argv[0], "link"))
+ type = htons (OSPF6_LSTYPE_LINK);
+
+ if ((inet_pton (AF_INET, argv[1], &id)) != 1)
+ {
+ vty_out (vty, "Link state ID is not parsable: %s%s",
+ argv[1], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ if ((inet_pton (AF_INET, argv[2], &router)) != 1)
+ {
+ vty_out (vty, "Advertising Router is not parsable: %s%s",
+ argv[2], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ LSDB_FOREACH_LSA_TIR (vty, showfunc, o->lsdb, type, id, router);
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ LSDB_FOREACH_LSA_TIR (vty, showfunc, oa->lsdb, type, id, router);
+ }
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ for (j = listhead (oa->if_list); j; nextnode (j))
+ {
+ struct ospf6_interface *oi = (struct ospf6_interface *) getdata (j);
+ LSDB_FOREACH_LSA_TIR (vty, showfunc, oi->lsdb, type, id, router);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_database_type_id_router,
+ show_ipv6_ospf6_database_type_id_router_detail_cmd,
+ "show ipv6 ospf6 database "
+ "(router|network|inter-prefix|inter-router|as-external|"
+ "group-membership|type-7|link|intra-prefix) A.B.C.D A.B.C.D "
+ "(dump|internal)",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Display Router LSAs\n"
+ "Display Network LSAs\n"
+ "Display Inter-Area-Prefix LSAs\n"
+ "Display Inter-Area-Router LSAs\n"
+ "Display As-External LSAs\n"
+ "Display Group-Membership LSAs\n"
+ "Display Type-7 LSAs\n"
+ "Display Link LSAs\n"
+ "Display Intra-Area-Prefix LSAs\n"
+ "Specify Link state ID as IPv4 address notation\n"
+ "Specify Advertising Router as IPv4 address notation\n"
+ "Display details of LSAs\n"
+ "Dump LSAs\n"
+ "Display LSA's internal information\n"
+ );
+
+DEFUN (show_ipv6_ospf6_database_self_originated,
+ show_ipv6_ospf6_database_self_originated_cmd,
+ "show ipv6 ospf6 database self-originated",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Display Self-originated LSAs\n"
+ )
+{
+ listnode i, j;
+ struct ospf6 *o = ospf6;
+ void (*showfunc) (struct vty *, struct ospf6_lsa *) = NULL;
+
+ OSPF6_CMD_CHECK_RUNNING ();
+
+ if (argc > 0)
+ {
+ if (! strncmp (argv[0], "de", 2))
+ showfunc = ospf6_lsa_show;
+ else if (! strncmp (argv[0], "du", 2))
+ showfunc = ospf6_lsa_show_dump;
+ else if (! strncmp (argv[0], "in", 2))
+ showfunc = ospf6_lsa_show_internal;
+ }
+ else
+ showfunc = ospf6_lsa_show_summary;
+
+ if (showfunc == ospf6_lsa_show_summary)
+ ospf6_lsa_show_summary_header (vty);
+
+ LSDB_FOREACH_LSA_R (vty, showfunc, o->lsdb, o->router_id);
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ LSDB_FOREACH_LSA_R (vty, showfunc, oa->lsdb, o->router_id);
+ }
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ for (j = listhead (oa->if_list); j; nextnode (j))
+ {
+ struct ospf6_interface *oi = (struct ospf6_interface *) getdata (j);
+ LSDB_FOREACH_LSA_R (vty, showfunc, oi->lsdb, o->router_id);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_database_self_originated,
+ show_ipv6_ospf6_database_self_originated_detail_cmd,
+ "show ipv6 ospf6 database self-originated "
+ "(detail|dump|internal)",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Display Self-originated LSAs\n"
+ "Display details of LSAs\n"
+ "Dump LSAs\n"
+ "Display LSA's internal information\n"
+ );
+
+DEFUN (show_ipv6_ospf6_database_type_self_originated,
+ show_ipv6_ospf6_database_type_self_originated_cmd,
+ "show ipv6 ospf6 database "
+ "(router|network|inter-prefix|inter-router|as-external|"
+ "group-membership|type-7|link|intra-prefix) self-originated",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Display Router LSAs\n"
+ "Display Network LSAs\n"
+ "Display Inter-Area-Prefix LSAs\n"
+ "Display Inter-Area-Router LSAs\n"
+ "Display As-External LSAs\n"
+ "Display Group-Membership LSAs\n"
+ "Display Type-7 LSAs\n"
+ "Display Link LSAs\n"
+ "Display Intra-Area-Prefix LSAs\n"
+ "Display Self-originated LSAs\n"
+ )
+{
+ listnode i, j;
+ struct ospf6 *o = ospf6;
+ void (*showfunc) (struct vty *, struct ospf6_lsa *) = NULL;
+ u_int16_t type = 0;
+
+ OSPF6_CMD_CHECK_RUNNING ();
+
+ if (argc > 1)
+ {
+ if (! strncmp (argv[1], "de", 2))
+ showfunc = ospf6_lsa_show;
+ else if (! strncmp (argv[1], "du", 2))
+ showfunc = ospf6_lsa_show_dump;
+ else if (! strncmp (argv[1], "in", 2))
+ showfunc = ospf6_lsa_show_internal;
+ }
+ else
+ showfunc = ospf6_lsa_show_summary;
+
+ if (showfunc == ospf6_lsa_show_summary)
+ ospf6_lsa_show_summary_header (vty);
+
+ if (! strcmp (argv[0], "router"))
+ type = htons (OSPF6_LSTYPE_ROUTER);
+ else if (! strcmp (argv[0], "network"))
+ type = htons (OSPF6_LSTYPE_NETWORK);
+ else if (! strcmp (argv[0], "as-external"))
+ type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
+ else if (! strcmp (argv[0], "intra-prefix"))
+ type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
+ else if (! strcmp (argv[0], "inter-router"))
+ type = htons (OSPF6_LSTYPE_INTER_ROUTER);
+ else if (! strcmp (argv[0], "inter-prefix"))
+ type = htons (OSPF6_LSTYPE_INTER_PREFIX);
+ else if (! strcmp (argv[0], "link"))
+ type = htons (OSPF6_LSTYPE_LINK);
+
+ LSDB_FOREACH_LSA_TR (vty, showfunc, o->lsdb, type, o->router_id);
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ LSDB_FOREACH_LSA_TR (vty, showfunc, oa->lsdb, type, o->router_id);
+ }
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ for (j = listhead (oa->if_list); j; nextnode (j))
+ {
+ struct ospf6_interface *oi = (struct ospf6_interface *) getdata (j);
+ LSDB_FOREACH_LSA_TR (vty, showfunc, oi->lsdb, type, o->router_id);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_database_type_self_originated,
+ show_ipv6_ospf6_database_type_self_originated_detail_cmd,
+ "show ipv6 ospf6 database "
+ "(router|network|inter-prefix|inter-router|as-external|"
+ "group-membership|type-7|link|intra-prefix) self-originated "
+ "(detail|dump|internal)",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Display Router LSAs\n"
+ "Display Network LSAs\n"
+ "Display Inter-Area-Prefix LSAs\n"
+ "Display Inter-Area-Router LSAs\n"
+ "Display As-External LSAs\n"
+ "Display Group-Membership LSAs\n"
+ "Display Type-7 LSAs\n"
+ "Display Link LSAs\n"
+ "Display Intra-Area-Prefix LSAs\n"
+ "Display Self-originated LSAs\n"
+ "Display details of LSAs\n"
+ "Dump LSAs\n"
+ "Display LSA's internal information\n"
+ );
+
+DEFUN (show_ipv6_ospf6_database_type_id_self_originated,
+ show_ipv6_ospf6_database_type_id_self_originated_cmd,
+ "show ipv6 ospf6 database "
+ "(router|network|inter-prefix|inter-router|as-external|"
+ "group-membership|type-7|link|intra-prefix) A.B.C.D self-originated",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Display Router LSAs\n"
+ "Display Network LSAs\n"
+ "Display Inter-Area-Prefix LSAs\n"
+ "Display Inter-Area-Router LSAs\n"
+ "Display As-External LSAs\n"
+ "Display Group-Membership LSAs\n"
+ "Display Type-7 LSAs\n"
+ "Display Link LSAs\n"
+ "Display Intra-Area-Prefix LSAs\n"
+ "Specify Link state ID as IPv4 address notation\n"
+ "Display Self-originated LSAs\n"
+ )
+{
+ listnode i, j;
+ struct ospf6 *o = ospf6;
+ void (*showfunc) (struct vty *, struct ospf6_lsa *) = NULL;
+ u_int16_t type = 0;
+ u_int32_t id = 0;
+
+ OSPF6_CMD_CHECK_RUNNING ();
+
+ if (argc > 2)
+ {
+ if (! strncmp (argv[2], "du", 2))
+ showfunc = ospf6_lsa_show_dump;
+ else if (! strncmp (argv[2], "in", 2))
+ showfunc = ospf6_lsa_show_internal;
+ }
+ else
+ showfunc = ospf6_lsa_show;
+
+ if (showfunc == ospf6_lsa_show_summary)
+ ospf6_lsa_show_summary_header (vty);
+
+ if (! strcmp (argv[0], "router"))
+ type = htons (OSPF6_LSTYPE_ROUTER);
+ else if (! strcmp (argv[0], "network"))
+ type = htons (OSPF6_LSTYPE_NETWORK);
+ else if (! strcmp (argv[0], "as-external"))
+ type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
+ else if (! strcmp (argv[0], "intra-prefix"))
+ type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
+ else if (! strcmp (argv[0], "inter-router"))
+ type = htons (OSPF6_LSTYPE_INTER_ROUTER);
+ else if (! strcmp (argv[0], "inter-prefix"))
+ type = htons (OSPF6_LSTYPE_INTER_PREFIX);
+ else if (! strcmp (argv[0], "link"))
+ type = htons (OSPF6_LSTYPE_LINK);
+
+ if ((inet_pton (AF_INET, argv[1], &id)) != 1)
+ {
+ vty_out (vty, "Link State ID is not parsable: %s%s",
+ argv[0], VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+
+ LSDB_FOREACH_LSA_TIR (vty, showfunc, o->lsdb, type, id, o->router_id);
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ LSDB_FOREACH_LSA_TIR (vty, showfunc, oa->lsdb, type, id, o->router_id);
+ }
+ for (i = listhead (o->area_list); i; nextnode (i))
+ {
+ struct ospf6_area *oa = (struct ospf6_area *) getdata (i);
+ for (j = listhead (oa->if_list); j; nextnode (j))
+ {
+ struct ospf6_interface *oi = (struct ospf6_interface *) getdata (j);
+ LSDB_FOREACH_LSA_TIR (vty, showfunc, oi->lsdb, type, id, o->router_id);
+ }
+ }
+
+ return CMD_SUCCESS;
+}
+
+ALIAS (show_ipv6_ospf6_database_type_id_self_originated,
+ show_ipv6_ospf6_database_type_id_self_originated_detail_cmd,
+ "show ipv6 ospf6 database "
+ "(router|network|inter-prefix|inter-router|as-external|"
+ "group-membership|type-7|link|intra-prefix) A.B.C.D self-originated "
+ "(dump|internal)",
+ SHOW_STR
+ IPV6_STR
+ OSPF6_STR
+ "Display Link state database\n"
+ "Display Router LSAs\n"
+ "Display Network LSAs\n"
+ "Display Inter-Area-Prefix LSAs\n"
+ "Display Inter-Area-Router LSAs\n"
+ "Display As-External LSAs\n"
+ "Display Group-Membership LSAs\n"
+ "Display Type-7 LSAs\n"
+ "Display Link LSAs\n"
+ "Display Intra-Area-Prefix LSAs\n"
+ "Specify Link state ID as IPv4 address notation\n"
+ "Display Self-originated LSAs\n"
+ "Display details of LSAs\n"
+ "Dump LSAs\n"
+ "Display LSA's internal information\n"
+ );
+
+
/* Install ospf related commands. */
void
ospf6_init ()
{
- /* Install ospf6 top node. */
- install_node (&ospf6_node, ospf6_config_write);
+ install_node (&debug_node, config_write_ospf6_debug);
- install_element (VIEW_NODE, &show_ipv6_ospf6_cmd);
+ install_element_ospf6_debug_message ();
+ install_element_ospf6_debug_lsa ();
+ install_element_ospf6_debug_interface ();
+ install_element_ospf6_debug_neighbor ();
+ install_element_ospf6_debug_zebra ();
+ install_element_ospf6_debug_spf ();
+ install_element_ospf6_debug_route ();
+ install_element_ospf6_debug_asbr ();
+
install_element (VIEW_NODE, &show_version_ospf6_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_detail_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_detail_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_id_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_id_detail_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_router_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_router_detail_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_detail_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_router_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_router_detail_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_id_router_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_id_router_detail_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_router_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_router_detail_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_self_originated_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_self_originated_detail_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_self_originated_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_self_originated_detail_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_self_originated_cmd);
+ install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_self_originated_detail_cmd);
+
install_element (ENABLE_NODE, &show_version_ospf6_cmd);
- install_element (ENABLE_NODE, &reload_cmd);
- install_element (CONFIG_NODE, &router_ospf6_cmd);
- install_element (CONFIG_NODE, &interface_cmd);
- install_element (CONFIG_NODE, &no_interface_cmd);
-#ifdef OSPF6_STATISTICS
- install_element (VIEW_NODE, &show_ipv6_ospf6_statistics_cmd);
- install_element (ENABLE_NODE, &show_ipv6_ospf6_statistics_cmd);
-#endif /* OSPF6_STATISTICS */
-#ifdef OSPF6_GARBAGE_COLLECT
- install_element (ENABLE_NODE, &garbage_collection_cmd);
-#endif /* OSPF6_GARBAGE_COLLECT */
-#ifdef HAVE_SETPROCTITLE
- install_element (CONFIG_NODE, &set_proctitle_cmd);
-#endif /* HAVE_SETPROCTITLE */
-
- install_default (OSPF6_NODE);
- install_element (OSPF6_NODE, &ospf6_router_id_cmd);
- install_element (OSPF6_NODE, &ospf6_interface_area_cmd);
- install_element (OSPF6_NODE, &ospf6_interface_area_passive_cmd);
- install_element (OSPF6_NODE, &ospf6_interface_area_plist_cmd);
- install_element (OSPF6_NODE, &ospf6_interface_area_plist_passive_cmd);
- install_element (OSPF6_NODE, &no_ospf6_interface_area_cmd);
- install_element (OSPF6_NODE, &ospf6_passive_interface_cmd);
- install_element (OSPF6_NODE, &no_ospf6_passive_interface_cmd);
- install_element (OSPF6_NODE, &ospf6_area_range_cmd);
-
- /* Make empty list of top list. */
- if_init ();
-
- /* Install access list */
- access_list_init ();
-
- /* Install prefix list */
- prefix_list_init ();
-
- ospf6_dump_init ();
-
-#ifdef HAVE_OSPF6_DAMP
- ospf6_damp_init ();
-#endif /*HAVE_OSPF6_DAMP*/
-
- ospf6_hook_init ();
- ospf6_lsa_init ();
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_detail_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_detail_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_id_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_id_detail_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_router_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_router_detail_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_id_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_id_detail_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_router_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_router_detail_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_id_router_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_id_router_detail_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_id_router_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_id_router_detail_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_self_originated_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_self_originated_detail_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_self_originated_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_self_originated_detail_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_id_self_originated_cmd);
+ install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_id_self_originated_detail_cmd);
ospf6_top_init ();
ospf6_area_init ();
@@ -776,53 +1256,14 @@
ospf6_neighbor_init ();
ospf6_zebra_init ();
- ospf6_routemap_init ();
- ospf6_lsdb_init ();
-
+ ospf6_lsa_init ();
ospf6_spf_init ();
-
ospf6_intra_init ();
- ospf6_abr_init ();
ospf6_asbr_init ();
+
+ /* Make ospf protocol socket. */
+ ospf6_serv_sock ();
+ thread_add_read (master, ospf6_receive, NULL, ospf6_sock);
}
-void
-ospf6_terminate ()
-{
- /* stop ospf6 */
- ospf6_stop ();
-
- /* log */
- zlog (NULL, LOG_INFO, "OSPF6d terminated");
-}
-
-void
-ospf6_maxage_remover ()
-{
-#if 0
- if (IS_OSPF6_DUMP_LSDB)
- zlog_info ("MaxAge Remover");
-#endif
-
- ospf6_top_schedule_maxage_remover (NULL, 0, ospf6);
- (*ospf6->foreach_area) (ospf6, NULL, 0,
- ospf6_area_schedule_maxage_remover);
- (*ospf6->foreach_if) (ospf6, NULL, 0,
- ospf6_interface_schedule_maxage_remover);
-}
-
-
-
-void *
-ospf6_lsa_get_scope (u_int16_t type, struct ospf6_interface *o6i)
-{
- if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (ntohs (type)))
- return o6i;
- else if (OSPF6_LSA_IS_SCOPE_AREA (ntohs (type)))
- return o6i->area;
- else if (OSPF6_LSA_IS_SCOPE_AS (ntohs (type)))
- return o6i->area->ospf6;
- else
- return NULL;
-}
diff --git a/ospf6d/ospf6d.conf.sample b/ospf6d/ospf6d.conf.sample
index 71972f5..0a6ddb7 100644
--- a/ospf6d/ospf6d.conf.sample
+++ b/ospf6d/ospf6d.conf.sample
@@ -1,32 +1,20 @@
!
! Zebra configuration saved from vty
-! 2000/05/11 02:09:37
+! 2003/11/28 00:49:49
!
-hostname ospf6d@yasu3380
+hostname ospf6d@plant
password zebra
-log file /var/log/zebra-ospf6d.log
log stdout
+service advanced-vty
!
-debug ospf6 message dbdesc
-debug ospf6 message lsreq
-debug ospf6 message lsupdate
-debug ospf6 message lsack
-debug ospf6 neighbor
-debug ospf6 spf
-debug ospf6 interface
-debug ospf6 area
-debug ospf6 lsa
-debug ospf6 zebra
-debug ospf6 config
-debug ospf6 dbex
-debug ospf6 route
+debug ospf6 neighbor state
!
-interface ed0
+interface fxp0
ipv6 ospf6 cost 1
ipv6 ospf6 hello-interval 10
ipv6 ospf6 dead-interval 40
ipv6 ospf6 retransmit-interval 5
- ipv6 ospf6 priority 1
+ ipv6 ospf6 priority 0
ipv6 ospf6 transmit-delay 1
ipv6 ospf6 instance-id 0
!
@@ -40,15 +28,25 @@
ipv6 ospf6 instance-id 0
!
router ospf6
- router-id 0.0.0.1
+ router-id 255.1.1.1
redistribute static route-map static-ospf6
- interface ed0 area 0.0.0.0
- interface lo0 area 0.0.0.0
+ interface fxp0 area 0.0.0.0
!
-ipv6 prefix-list hostroute seq 10 permit 3ffe:501:100c:4380::/60 le 128 ge 128
+access-list access4 permit 127.0.0.1/32
!
-route-map static-ospf6 permit 50
- match ipv6 address prefix-list hostroute
+ipv6 access-list access6 permit 3ffe:501::/32
+ipv6 access-list access6 permit 2001:200::/48
+ipv6 access-list access6 permit ::1/128
+!
+ipv6 prefix-list test-prefix seq 1000 deny any
+!
+route-map static-ospf6 permit 10
+ match ipv6 address prefix-list test-prefix
set metric-type type-2
- set metric 30
+ set metric 2000
+!
+line vty
+ access-class access4
+ ipv6 access-class access6
+ exec-timeout 0 0
!
diff --git a/ospf6d/ospf6d.h b/ospf6d/ospf6d.h
index e867b1c..c08007f 100644
--- a/ospf6d/ospf6d.h
+++ b/ospf6d/ospf6d.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 1999 Yasuhiro Ohara
+ * Copyright (C) 2003 Yasuhiro Ohara
*
* This file is part of GNU Zebra.
*
@@ -22,78 +22,11 @@
#ifndef OSPF6D_H
#define OSPF6D_H
-#include <zebra.h>
-#include "linklist.h"
-
-#ifndef HEADER_DEPENDENCY
-/* Include other stuffs */
-#include <lib/version.h>
-#include "log.h"
-#include "getopt.h"
-#include "thread.h"
-#include "command.h"
-#include "memory.h"
-#include "sockunion.h"
-#include "if.h"
-#include "prefix.h"
-#include "stream.h"
-#include "thread.h"
-#include "filter.h"
-#include "zclient.h"
-#include "table.h"
-#include "plist.h"
-
-/* OSPF stuffs */
-#include "ospf6_hook.h"
-#include "ospf6_types.h"
-#include "ospf6_prefix.h"
-#include "ospf6_lsa.h"
-#include "ospf6_lsdb.h"
-
-#include "ospf6_message.h"
-#include "ospf6_proto.h"
-#include "ospf6_spf.h"
-#include "ospf6_top.h"
-#include "ospf6_area.h"
-#include "ospf6_interface.h"
-#include "ospf6_neighbor.h"
-#include "ospf6_ism.h"
-#include "ospf6_nsm.h"
-#include "ospf6_route.h"
-#include "ospf6_dbex.h"
-#include "ospf6_network.h"
-#include "ospf6_zebra.h"
-#include "ospf6_dump.h"
-#include "ospf6_routemap.h"
-#include "ospf6_asbr.h"
-#include "ospf6_abr.h"
-#include "ospf6_intra.h"
-#endif /*HEADER_DEPENDENCY*/
-
-#define HASHVAL 64
-#define MAXIOVLIST 1024
-
-#define OSPF6_DAEMON_VERSION "0.9.6p"
-
-#define AF_LINKSTATE 0xff
+#define OSPF6_DAEMON_VERSION "0.9.7a"
/* global variables */
-extern char *progname;
extern int errno;
-extern int daemon_mode;
extern struct thread_master *master;
-extern list iflist;
-extern list nexthoplist;
-extern struct sockaddr_in6 allspfrouters6;
-extern struct sockaddr_in6 alldrouters6;
-extern int ospf6_sock;
-extern char *recent_reason;
-
-/* Default configuration file name for ospfd. */
-#define OSPF6_DEFAULT_CONFIG "ospf6d.conf"
-
-/* Default port values. */
-#define OSPF6_VTY_PORT 2606
#ifdef INRIA_IPV6
#ifndef IPV6_PKTINFO
@@ -101,7 +34,7 @@
#endif /* IPV6_PKTINFO */
#endif /* INRIA_IPV6 */
-/* Historycal for KAME. */
+/* Historical for KAME. */
#ifndef IPV6_JOIN_GROUP
#ifdef IPV6_ADD_MEMBERSHIP
#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
@@ -117,6 +50,53 @@
#endif /* IPV6_DROP_MEMBERSHIP */
#endif /* ! IPV6_LEAVE_GROUP */
+/* operation on timeval structure */
+#ifndef timerclear
+#define timerclear(a) (a)->tv_sec = (tvp)->tv_usec = 0
+#endif /*timerclear*/
+#ifndef timersub
+#define timersub(a, b, res) \
+ do { \
+ (res)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+ (res)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+ if ((res)->tv_usec < 0) \
+ { \
+ (res)->tv_sec--; \
+ (res)->tv_usec += 1000000; \
+ } \
+ } while (0)
+#endif /*timersub*/
+#define timerstring(tv, buf, size) \
+ do { \
+ if ((tv)->tv_sec / 60 / 60 / 24) \
+ snprintf (buf, size, "%ldd%02ld:%02ld:%02ld", \
+ (tv)->tv_sec / 60 / 60 / 24, \
+ (tv)->tv_sec / 60 / 60 % 24, \
+ (tv)->tv_sec / 60 % 60, \
+ (tv)->tv_sec % 60); \
+ else \
+ snprintf (buf, size, "%02ld:%02ld:%02ld", \
+ (tv)->tv_sec / 60 / 60 % 24, \
+ (tv)->tv_sec / 60 % 60, \
+ (tv)->tv_sec % 60); \
+ } while (0)
+#define timerstring_local(tv, buf, size) \
+ do { \
+ int ret; \
+ struct tm *tm; \
+ tm = localtime (&(tv)->tv_sec); \
+ ret = strftime (buf, size, "%Y/%m/%d %H:%M:%S", tm); \
+ if (ret == 0) \
+ zlog_warn ("strftime error"); \
+ } while (0)
+
+/* for commands */
+#define OSPF6_AREA_STR "Area information\n"
+#define OSPF6_AREA_ID_STR "Area ID (as an IPv4 notation)\n"
+#define OSPF6_SPF_STR "Shortest Path First tree information\n"
+#define OSPF6_ROUTER_ID_STR "Specify Router-ID\n"
+#define OSPF6_LS_ID_STR "Specify Link State ID\n"
+
#define OSPF6_CMD_CHECK_RUNNING() \
if (ospf6 == NULL) \
{ \
@@ -124,51 +104,13 @@
return CMD_SUCCESS; \
}
-#define OSPF6_LEVEL_NONE 0
-#define OSPF6_LEVEL_NEIGHBOR 1
-#define OSPF6_LEVEL_INTERFACE 2
-#define OSPF6_LEVEL_AREA 3
-#define OSPF6_LEVEL_TOP 4
-#define OSPF6_LEVEL_MAX 5
-
-#define OSPF6_PASSIVE_STR \
- "Suppress routing updates on an interface\n"
-#define OSPF6_PREFIX_LIST_STR \
- "Advertise I/F Address only match entries of prefix-list\n"
-
-#define OSPF6_AREA_STR "Area information\n"
-#define OSPF6_AREA_ID_STR "Area ID (as an IPv4 notation)\n"
-#define OSPF6_SPF_STR "Shortest Path First tree information\n"
-#define OSPF6_ROUTER_ID_STR "Specify Router-ID\n"
-#define OSPF6_LS_ID_STR "Specify Link State ID\n"
-
/* Function Prototypes */
-void
-ospf6_timeval_sub (const struct timeval *t1, const struct timeval *t2,
- struct timeval *result);
-void
-ospf6_timeval_div (const struct timeval *t1, u_int by,
- struct timeval *result);
-void
-ospf6_timeval_sub_equal (const struct timeval *t, struct timeval *result);
-void
-ospf6_timeval_decode (const struct timeval *t, long *dayp, long *hourp,
- long *minp, long *secp, long *msecp, long *usecp);
-void
-ospf6_timeval_string (struct timeval *tv, char *buf, int size);
-void
-ospf6_timeval_string_summary (struct timeval *tv, char *buf, int size);
+struct route_node *route_prev (struct route_node *node);
-void
-ospf6_count_state (void *arg, int val, void *obj);
-
+void ospf6_debug ();
void ospf6_init ();
-void ospf6_terminate ();
-
-void ospf6_maxage_remover ();
-
-void *ospf6_lsa_get_scope (u_int16_t type, struct ospf6_interface *o6i);
#endif /* OSPF6D_H */
+