From 508e53e2eef3eefba4c1aa771529027fd4486ea8 Mon Sep 17 00:00:00 2001 From: hasso Date: Tue, 18 May 2004 18:57:06 +0000 Subject: Ospf6d merge from Zebra repository with added privs stuff and merged zclient changes. --- ospf6d/.cvsignore | 1 - ospf6d/ChangeLog | 28 +- ospf6d/Makefile.am | 22 +- ospf6d/README | 8 + ospf6d/ospf6_abr.c | 655 ---------- ospf6d/ospf6_abr.h | 56 - ospf6d/ospf6_area.c | 928 ++++++++++--- ospf6d/ospf6_area.h | 70 +- ospf6d/ospf6_asbr.c | 1925 +++++++++++++++------------ ospf6d/ospf6_asbr.h | 72 +- ospf6d/ospf6_bintree.c | 436 ------- ospf6d/ospf6_bintree.h | 47 - ospf6d/ospf6_damp.c | 748 ----------- ospf6d/ospf6_damp.h | 109 -- ospf6d/ospf6_dbex.c | 704 ---------- ospf6d/ospf6_dbex.h | 59 - ospf6d/ospf6_dump.c | 315 ----- ospf6d/ospf6_dump.h | 95 -- ospf6d/ospf6_hook.c | 174 --- ospf6d/ospf6_hook.h | 87 -- ospf6d/ospf6_interface.c | 1417 +++++++++++++------- ospf6d/ospf6_interface.h | 121 +- ospf6d/ospf6_intra.c | 1860 ++++++++++++++++---------- ospf6d/ospf6_intra.h | 130 +- ospf6d/ospf6_ism.c | 519 -------- ospf6d/ospf6_ism.h | 53 - ospf6d/ospf6_linklist.c | 193 --- ospf6d/ospf6_linklist.h | 35 - ospf6d/ospf6_lsa.c | 1867 +++++++------------------- ospf6d/ospf6_lsa.h | 510 +++----- ospf6d/ospf6_lsdb.c | 843 ++++-------- ospf6d/ospf6_lsdb.h | 164 ++- ospf6d/ospf6_main.c | 118 +- ospf6d/ospf6_message.c | 3174 +++++++++++++++++++++++---------------------- ospf6d/ospf6_message.h | 192 +-- ospf6d/ospf6_neighbor.c | 1119 ++++++++++------ ospf6d/ospf6_neighbor.h | 169 ++- ospf6d/ospf6_network.c | 362 ++---- ospf6d/ospf6_network.h | 38 +- ospf6d/ospf6_nsm.c | 391 ------ ospf6d/ospf6_nsm.h | 67 - ospf6d/ospf6_prefix.c | 213 --- ospf6d/ospf6_prefix.h | 83 -- ospf6d/ospf6_proto.c | 66 +- ospf6d/ospf6_proto.h | 92 +- ospf6d/ospf6_route.c | 1791 ++++++++++++------------- ospf6d/ospf6_route.h | 294 +++-- ospf6d/ospf6_routemap.c | 385 ------ ospf6d/ospf6_routemap.h | 27 - ospf6d/ospf6_spf.c | 1686 +++++++----------------- ospf6d/ospf6_spf.h | 88 +- ospf6d/ospf6_top.c | 696 ++++++---- ospf6d/ospf6_top.h | 61 +- ospf6d/ospf6_types.h | 43 - ospf6d/ospf6_zebra.c | 590 ++++----- ospf6d/ospf6_zebra.h | 35 +- ospf6d/ospf6d.c | 1671 +++++++++++++++--------- ospf6d/ospf6d.conf.sample | 50 +- ospf6d/ospf6d.h | 164 +-- 59 files changed, 11453 insertions(+), 16463 deletions(-) delete mode 100644 ospf6d/ospf6_abr.c delete mode 100644 ospf6d/ospf6_abr.h delete mode 100644 ospf6d/ospf6_bintree.c delete mode 100644 ospf6d/ospf6_bintree.h delete mode 100644 ospf6d/ospf6_damp.c delete mode 100644 ospf6d/ospf6_damp.h delete mode 100644 ospf6d/ospf6_dbex.c delete mode 100644 ospf6d/ospf6_dbex.h delete mode 100644 ospf6d/ospf6_dump.c delete mode 100644 ospf6d/ospf6_dump.h delete mode 100644 ospf6d/ospf6_hook.c delete mode 100644 ospf6d/ospf6_hook.h delete mode 100644 ospf6d/ospf6_ism.c delete mode 100644 ospf6d/ospf6_ism.h delete mode 100644 ospf6d/ospf6_linklist.c delete mode 100644 ospf6d/ospf6_linklist.h delete mode 100644 ospf6d/ospf6_nsm.c delete mode 100644 ospf6d/ospf6_nsm.h delete mode 100644 ospf6d/ospf6_prefix.c delete mode 100644 ospf6d/ospf6_prefix.h delete mode 100644 ospf6d/ospf6_routemap.c delete mode 100644 ospf6d/ospf6_routemap.h delete mode 100644 ospf6d/ospf6_types.h (limited to 'ospf6d') diff --git a/ospf6d/.cvsignore b/ospf6d/.cvsignore index 5e76e4db..cec4061c 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 0e9d7fc6..b74deada 100644 --- a/ospf6d/ChangeLog +++ b/ospf6d/ChangeLog @@ -1,20 +1,17 @@ -2004-05-08 Paul Jakma +2004-05-18 Hasso Tepper - * ospf6_zebra.c: Sync to zclient changes - -2003-08-11 Taisuke Sasaki + * *.*: 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. - * ospf6_ism.c: DR Election bug fix. - -2003-05-18 Hasso Tepper +2003-08-18 Yasuhiro Ohara - * 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). + * *.[ch]: rewrite all source code from scratch + * ospf6d.h: version 0.9.7 -2003-04-23 Hasso Tepper - - * {ospf6_damp,ospf6d}.c: fix "router xxx" node commands in vtysh +2003-08-11 Taisuke Sasaki + + * ospf6_ism.c: DR Election bug fix. 2003-04-25 Yasuhiro Ohara @@ -22,11 +19,6 @@ prefix of the obsolete LSA. It was wrong so fixed. * version: 0.9.6p -2003-04-19 Hasso Tepper - - * rip_routemap.c: sync daemon's route-map commands to have same - syntax - 2002-11-09 Vincent Jardin * ospf6_interface.c: update link-local address on interface creation. diff --git a/ospf6d/Makefile.am b/ospf6d/Makefile.am index 14b87af4..de183913 100644 --- a/ospf6d/Makefile.am +++ b/ospf6d/Makefile.am @@ -8,22 +8,16 @@ noinst_LIBRARIES = libospf6.a 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 b3b4d16d..883486fa 100644 --- a/ospf6d/README +++ b/ospf6d/README @@ -1,4 +1,12 @@ + 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 diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c deleted file mode 100644 index 864e0c23..00000000 --- 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 510532e8..00000000 --- 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 51af5080..ef283cd1 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,313 +19,850 @@ * Boston, MA 02111-1307, USA. */ +#include + +#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)) +int +ospf6_area_cmp (void *va, void *vb) +{ + 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)); +} -static void -ospf6_area_foreach_interface (struct ospf6_area *o6a, void *arg, int val, - void (*func) (void *, int, void *)) +int +ospf6_area_is_stub (struct ospf6_area *o6a) { - listnode node; - struct ospf6_interface *o6i; + if (OSPF6_OPT_ISSET (o6a->options, OSPF6_OPT_E)) + return 0; + return 1; +} - for (node = listhead (o6a->if_list); node; nextnode (node)) +/* schedule routing table recalculation */ +void +ospf6_area_lsdb_hook_add (struct ospf6_lsa *lsa) +{ + struct ospf6_area *oa; + + oa = (struct ospf6_area *) lsa->scope; + switch (ntohs (lsa->header->type)) { - o6i = (struct ospf6_interface *) getdata (node); - (*func) (arg, val, o6i); + case OSPF6_LSTYPE_ROUTER: + case OSPF6_LSTYPE_NETWORK: + ospf6_spf_schedule (oa); + break; + + 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; } } -static void -ospf6_area_foreach_neighbor (struct ospf6_area *o6a, void *arg, int val, - void (*func) (void *, int, void *)) +void +ospf6_area_lsdb_hook_remove (struct ospf6_lsa *lsa) { - listnode node; - struct ospf6_interface *o6i; + struct ospf6_area *oa; - for (node = listhead (o6a->if_list); node; nextnode (node)) + oa = (struct ospf6_area *) lsa->scope; + switch (ntohs (lsa->header->type)) { - o6i = (struct ospf6_interface *) getdata (node); - (*o6i->foreach_nei) (o6i, arg, val, func); + case OSPF6_LSTYPE_ROUTER: + case OSPF6_LSTYPE_NETWORK: + ospf6_spf_schedule (oa); + break; + + 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; } } -static int -ospf6_area_maxage_remover (struct thread *t) +void +ospf6_area_route_hook_add (struct ospf6_route *route) { - 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; + struct ospf6_route *copy = ospf6_route_copy (route); + ospf6_route_add (copy, ospf6->route_table); } void -ospf6_area_schedule_maxage_remover (void *arg, int val, void *obj) +ospf6_area_route_hook_remove (struct ospf6_route *route) { - struct ospf6_area *o6a = (struct ospf6_area *) obj; + struct ospf6_route *copy; - if (o6a->maxage_remover != NULL) - return; - - o6a->maxage_remover = - thread_add_event (master, ospf6_area_maxage_remover, o6a, 0); + copy = ospf6_route_lookup_identical (route, ospf6->route_table); + if (copy) + ospf6_route_remove (copy, ospf6->route_table); } -int -ospf6_area_is_stub (struct ospf6_area *o6a) +/* Make new area structure */ +struct ospf6_area * +ospf6_area_create (u_int32_t area_id, struct ospf6 *o) { - if (OSPF6_OPT_ISSET (o6a->options, OSPF6_OPT_E)) - return 0; - return 1; + struct ospf6_area *oa; + + oa = XCALLOC (MTYPE_OSPF6_AREA, sizeof (struct ospf6_area)); + + inet_ntop (AF_INET, &area_id, oa->name, sizeof (oa->name)); + oa->area_id = area_id; + oa->if_list = list_new (); + + oa->lsdb = ospf6_lsdb_create (); + oa->lsdb->hook_add = ospf6_area_lsdb_hook_add; + oa->lsdb->hook_remove = ospf6_area_lsdb_hook_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; + + /* 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); + + oa->ospf6 = o; + listnode_add_sort (o->area_list, oa); + + return oa; } -int -ospf6_area_is_transit (struct ospf6_area *o6a) +void +ospf6_area_delete (struct ospf6_area *oa) { - return 0; -} + listnode n; + struct ospf6_interface *oi; - + /* ospf6 interface list */ + for (n = listhead (oa->if_list); n; nextnode (n)) + { + oi = (struct ospf6_interface *) getdata (n); + ospf6_interface_delete (oi); + } + list_delete (oa->if_list); -void -ospf6_area_route_add (void *data) + ospf6_lsdb_delete (oa->lsdb); + ospf6_route_table_delete (oa->spf_table); + ospf6_route_table_delete (oa->route_table); + +#if 0 + ospf6_spftree_delete (oa->spf_tree); + ospf6_route_table_delete (oa->topology_table); +#endif /*0*/ + + THREAD_OFF (oa->thread_spf_calculation); + THREAD_OFF (oa->thread_route_calculation); + + listnode_delete (oa->ospf6->area_list, oa); + oa->ospf6 = NULL; + + /* free area */ + XFREE (MTYPE_OSPF6_AREA, oa); +} + +struct ospf6_area * +ospf6_area_lookup (u_int32_t area_id, struct ospf6 *ospf6) { - struct ospf6_route_req *route = data; - struct in6_addr local; + struct ospf6_area *oa; + listnode n; - inet_pton (AF_INET6, "::1", &local); - if (! memcmp (&route->nexthop.address, &local, sizeof (struct in6_addr))) + for (n = listhead (ospf6->area_list); n; nextnode (n)) { - if (IS_OSPF6_DUMP_AREA) - zlog_info ("AREA: Self-originated route add, ignore"); - return; + oa = (struct ospf6_area *) getdata (n); + if (oa->area_id == area_id) + return oa; } - ospf6_route_add (route, ospf6->route_table); + return (struct ospf6_area *) NULL; } void -ospf6_area_route_remove (void *data) +ospf6_area_enable (struct ospf6_area *oa) { - struct ospf6_route_req *route = data; - struct in6_addr local; + listnode i; + struct ospf6_interface *oi; - inet_pton (AF_INET6, "::1", &local); - if (! memcmp (&route->nexthop.address, &local, sizeof (struct in6_addr))) + UNSET_FLAG (oa->flag, OSPF6_AREA_DISABLE); + + for (i = listhead (oa->if_list); i; nextnode (i)) { - if (IS_OSPF6_DUMP_AREA) - zlog_info ("AREA: Self-originated route remove, ignore"); - return; + oi = (struct ospf6_interface *) getdata (i); + ospf6_interface_enable (oi); } - - ospf6_route_remove (route, ospf6->route_table); } -/* Make new area structure */ -struct ospf6_area * -ospf6_area_create (u_int32_t area_id) +void +ospf6_area_disable (struct ospf6_area *oa) { - struct ospf6_area *o6a; - char namebuf[64]; + listnode i; + struct ospf6_interface *oi; - /* allocate memory */ - o6a = XCALLOC (MTYPE_OSPF6_AREA, sizeof (struct ospf6_area)); + SET_FLAG (oa->flag, OSPF6_AREA_DISABLE); - /* initialize */ - inet_ntop (AF_INET, &area_id, o6a->str, sizeof (o6a->str)); - o6a->area_id = area_id; - o6a->if_list = list_new (); + for (i = listhead (oa->if_list); i; nextnode (i)) + { + oi = (struct ospf6_interface *) getdata (i); + ospf6_interface_disable (oi); + } +} - o6a->lsdb = ospf6_lsdb_create (); - o6a->spf_tree = ospf6_spftree_create (); + +void +ospf6_area_show (struct vty *vty, struct ospf6_area *oa) +{ + listnode i; + struct ospf6_interface *oi; - 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; + 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); - 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; + 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); +} - /* 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); - o6a->foreach_if = ospf6_area_foreach_interface; - o6a->foreach_nei = ospf6_area_foreach_neighbor; +#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; \ + } \ +} - return o6a; +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 *oa; + OSPF6_CMD_AREA_LOOKUP (argv[0], oa); + argc--; + argv++; + return ospf6_route_table_show (vty, argc, argv, oa->route_table); } -void -ospf6_area_bind_top (struct ospf6_area *o6a, struct ospf6 *o6) +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" + ) { - o6a->ospf6 = o6; - CALL_CHANGE_HOOK (&area_hook, o6a); - return; + 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); } -void -ospf6_area_delete (struct ospf6_area *o6a) +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" + ) { - listnode n; - struct ospf6_interface *o6i; + 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); +} - CALL_REMOVE_HOOK (&area_hook, o6a); +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; - /* ospf6 interface list */ - for (n = listhead (o6a->if_list); n; nextnode (n)) + for (node = listhead (ospf6->area_list); node; nextnode (node)) { - o6i = (struct ospf6_interface *) getdata (n); - /* ospf6_interface_delete (o6i); */ + 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); } - list_delete (o6a->if_list); - /* terminate LSDB */ - ospf6_lsdb_remove_all (o6a->lsdb); + return CMD_SUCCESS; +} - /* spf tree terminate */ - /* xxx */ +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" + ); - /* 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; +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; - /* new */ - ospf6_route_table_delete (o6a->route_table); + /* 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_spftree_delete (o6a->spf_tree); - ospf6_route_table_delete (o6a->table_topology); + 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); + } - /* free area */ - XFREE (MTYPE_OSPF6_AREA, o6a); + return CMD_SUCCESS; } -struct ospf6_area * -ospf6_area_lookup (u_int32_t area_id, struct ospf6 *o6) +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" + ) { - struct ospf6_area *o6a; - listnode n; + char *sargv[CMD_ARGC_MAX]; + int i, sargc; + listnode node; + struct ospf6_area *oa; - for (n = listhead (o6->area_list); n; nextnode (n)) + /* 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)) { - o6a = (struct ospf6_area *) getdata (n); - if (o6a->area_id == area_id) - return o6a; + oa = (struct ospf6_area *) getdata (node); + ospf6_route_table_show (vty, sargc, sargv, oa->route_table); } - return (struct ospf6_area *) NULL; + return CMD_SUCCESS; } -void -ospf6_area_show (struct vty *vty, struct ospf6_area *o6a) +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 i; - struct ospf6_interface *o6i; + listnode node; + struct ospf6_area *oa; + struct ospf6_vertex *root; + struct ospf6_route *route; + struct prefix prefix; - 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); + 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_spf_statistics_show (vty, o6a->spf_tree); + ospf6_linkstate_prefix (ospf6->router_id, htonl (0), &prefix); - vty_out (vty, " Interface attached to this area:"); - for (i = listhead (o6a->if_list); i; nextnode (i)) + if (inet_pton (AF_INET, argv[0], &area_id) != 1) { - o6i = (struct ospf6_interface *) getdata (i); - vty_out (vty, " %s", o6i->interface->name); + 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; } - vty_out (vty, "%s", VTY_NEWLINE); - for (i = listhead (o6a->if_list); i; nextnode (i)) + route = ospf6_route_lookup (&prefix, oa->spf_table); + if (route == NULL) { - o6i = (struct ospf6_interface *) getdata (i); - if (listcount (o6i->neighbor_list) != 0) - ospf6_interface_statistics_show (vty, o6i); + 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; } -void -ospf6_area_statistics_show (struct vty *vty, struct ospf6_area *o6a) +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" + ) { -#if 0 - listnode node; - struct ospf6_interface *o6i; + u_int32_t area_id; + struct ospf6_area *oa; - vty_out (vty, " Statistics of Area %s%s", o6a->str, VTY_NEWLINE); -#endif + 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; } -DEFUN (show_ipv6_ospf6_area_route, - show_ipv6_ospf6_area_route_cmd, - "show ipv6 ospf6 area A.B.C.D route", +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 - ROUTE_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" ) { - struct ospf6_area *o6a; u_int32_t area_id; + struct ospf6_area *oa; + char *sargv[CMD_ARGC_MAX]; + int i, sargc; - OSPF6_CMD_CHECK_RUNNING (); - - inet_pton (AF_INET, argv[0], &area_id); - o6a = ospf6_area_lookup (area_id, ospf6); + 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; + } - if (! o6a) - return CMD_SUCCESS; + argc--; + argv++; - argc -= 1; - argv += 1; + /* 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; - return ospf6_route_table_show (vty, argc, argv, o6a->route_table); + ospf6_lsentry_table_show (vty, sargc, sargv, oa->spf_table); + return CMD_SUCCESS; } -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)", +DEFUN (show_ipv6_ospf6_spf_table, + show_ipv6_ospf6_spf_table_cmd, + "show ipv6 ospf6 spf table", SHOW_STR IP6_STR OSPF6_STR - OSPF6_AREA_STR - OSPF6_AREA_ID_STR - ROUTE_STR - "Specify IPv6 address\n" - "Detailed information\n" + "Shortest Path First caculation\n" + "Show table contains SPF result\n" ) +{ + listnode node; + struct ospf6_area *oa; -void -ospf6_area_init () + 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" + ) { - area_index = ospf6_dump_install ("area", "Area information\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); + } - 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); + 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 () +{ + 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_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 06844646..14d3eb9d 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]; - - struct ospf6 *ospf6; /* back pointer */ - u_int32_t area_id; - u_char options[3]; /* OSPF Option including ExternalCapability */ + /* Reference to Top data structure */ + struct ospf6 *ospf6; - list if_list; /* OSPF interface to this area */ + /* Area-ID */ + u_int32_t area_id; - struct ospf6_lsdb *lsdb; + /* Area-ID string */ + char name[16]; - struct thread *spf_calc; - struct thread *route_calc; - int stat_spf_execed; - int stat_route_execed; + /* flag */ + u_char flag; - struct route_table *table; /* new route table */ + /* OSPF Option */ + u_char options[3]; - struct prefix_ipv6 area_range; - struct ospf6_spftree *spf_tree; + /* OSPF interface list */ + list if_list; + 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 5846ab8a..81edb60d 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,963 +30,1180 @@ #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 "ospf6d.h" +#include "ospf6_proto.h" +#include "ospf6_lsa.h" +#include "ospf6_lsdb.h" +#include "ospf6_route.h" #include "ospf6_zebra.h" -#include "ospf6_asbr.h" -#include "ospf6_damp.h" #include "ospf6_top.h" -#include "ospf6_lsdb.h" -#include "ospf6_proto.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 *name; - struct route_map *map; -} rmap [ZEBRA_ROUTE_MAX]; +char *zroute_name[] = +{ "system", "kernel", "connected", "static", + "rip", "ripng", "ospf", "ospf6", "bgp", "unknown" }; -static u_int32_t link_state_id = 0; +char *zroute_abname[] = +{ "X", "K", "C", "S", "R", "R", "O", "O", "B", "?" }; -char * -zroute_name[] = -{ - "system", "kernel", "connected", "static", - "rip", "ripng", "ospf", "ospf6", "isis", "bgp", "unknown" -}; -char * -zroute_abname[] = +#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) { - "X", "K", "C", "S", "R", "R", "O", "O", "I", "B", "?" -}; + char buffer[OSPF6_MAX_LSASIZE]; + struct ospf6_lsa_header *lsa_header; + struct ospf6_lsa *old, *lsa; -#define ZROUTE_NAME(x) \ - (0 < (x) && (x) < ZEBRA_ROUTE_MAX ? \ - zroute_name[(x)] : zroute_name[ZEBRA_ROUTE_MAX]) + struct ospf6_external_info *info = route->route_option; + struct ospf6_as_external_lsa *as_external_lsa; + char buf[64]; + caddr_t p; -#define ZROUTE_ABNAME(x) \ - (0 < (x) && (x) < ZEBRA_ROUTE_MAX ? \ - zroute_abname[(x)] : zroute_abname[ZEBRA_ROUTE_MAX]) + /* find previous LSA */ + old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL), + htonl (info->id), ospf6->router_id, + ospf6->lsdb); -/* redistribute function */ -void -ospf6_asbr_routemap_set (int type, char *mapname) -{ - if (rmap[type].name) - free (rmap[type].name); + 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); - rmap[type].name = strdup (mapname); - rmap[type].map = route_map_lookup_by_name (mapname); + /* 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); } -void -ospf6_asbr_routemap_unset (int type) +int +ospf6_as_external_lsa_reoriginate (struct ospf6_lsa *lsa) { - if (rmap[type].name) - free (rmap[type].name); - rmap[type].name = NULL; - rmap[type].map = NULL; + struct prefix prefix_id; + struct route_node *node; + struct ospf6_route *route; + + /* 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; + + if (route) + ospf6_as_external_lsa_originate_sub (route, 1); + else + ospf6_lsa_premature_aging (lsa); + + return 0; } + + void -ospf6_asbr_routemap_update () +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; - for (i = 0; i < ZEBRA_ROUTE_MAX; 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 (rmap[i].name) - rmap[i].map = route_map_lookup_by_name (rmap[i].name); - else - rmap[i].map = NULL; + if (IS_OSPF6_DEBUG_ASBR) + zlog_info ("Ignore self-originated AS-External-LSA"); + return; } -} -DEFUN (ospf6_redistribute, - ospf6_redistribute_cmd, - "redistribute (static|kernel|connected|ripng|bgp)", - "Redistribute\n" - "Static route\n" - "Kernel route\n" - "Connected route\n" - "RIPng route\n" - "BGP route\n" - ) -{ - int type = 0; + if (OSPF6_ASBR_METRIC (external) == LS_INFINITY) + { + if (IS_OSPF6_DEBUG_ASBR) + zlog_info ("Ignore LSA with LSInfinity Metric"); + return; + } - if (strncmp (argv[0], "sta", 3) == 0) - type = ZEBRA_ROUTE_STATIC; - else if (strncmp (argv[0], "ker", 3) == 0) - type = ZEBRA_ROUTE_KERNEL; - else if (strncmp (argv[0], "con", 3) == 0) - type = ZEBRA_ROUTE_CONNECT; - else if (strncmp (argv[0], "rip", 3) == 0) - type = ZEBRA_ROUTE_RIPNG; - else if (strncmp (argv[0], "bgp", 3) == 0) - type = ZEBRA_ROUTE_BGP; + 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); - ospf6_zebra_no_redistribute (type); - ospf6_asbr_routemap_unset (type); - ospf6_zebra_redistribute (type); - return CMD_SUCCESS; -} + if (asbr_entry == NULL) + { + if (IS_OSPF6_DEBUG_ASBR) + { + prefix2str (&asbr_id, buf, sizeof (buf)); + zlog_info ("ASBR entry not found: %s", buf); + } + return; + } -DEFUN (ospf6_redistribute_routemap, - ospf6_redistribute_routemap_cmd, - "redistribute (static|kernel|connected|ripng|bgp) route-map WORD", - "Redistribute\n" - "Static routes\n" - "Kernel route\n" - "Connected route\n" - "RIPng route\n" - "BGP route\n" - "Route map reference\n" - "Route map name\n" - ) -{ - int type = 0; + 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); - if (strncmp (argv[0], "sta", 3) == 0) - type = ZEBRA_ROUTE_STATIC; - else if (strncmp (argv[0], "ker", 3) == 0) - type = ZEBRA_ROUTE_KERNEL; - else if (strncmp (argv[0], "con", 3) == 0) - type = ZEBRA_ROUTE_CONNECT; - else if (strncmp (argv[0], "rip", 3) == 0) - type = ZEBRA_ROUTE_RIPNG; - else if (strncmp (argv[0], "bgp", 3) == 0) - type = ZEBRA_ROUTE_BGP; + 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; - ospf6_zebra_no_redistribute (type); - ospf6_asbr_routemap_set (type, argv[1]); - ospf6_zebra_redistribute (type); - return CMD_SUCCESS; + 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); } -DEFUN (no_ospf6_redistribute, - no_ospf6_redistribute_cmd, - "no redistribute (static|kernel|connected|ripng|bgp)", - NO_STR - "Redistribute\n" - "Static route\n" - "Kernel route\n" - "Connected route\n" - "RIPng route\n" - "BGP route\n" - ) +void +ospf6_asbr_lsa_remove (struct ospf6_lsa *lsa) { - int type = 0; - struct route_node *node; - struct ospf6_external_route *route; - struct ospf6_external_info *info, *info_next = NULL; + struct ospf6_as_external_lsa *external; + struct prefix prefix; + struct ospf6_route *route; + char buf[64]; - if (strncmp (argv[0], "sta", 3) == 0) - type = ZEBRA_ROUTE_STATIC; - else if (strncmp (argv[0], "ker", 3) == 0) - type = ZEBRA_ROUTE_KERNEL; - else if (strncmp (argv[0], "con", 3) == 0) - type = ZEBRA_ROUTE_CONNECT; - else if (strncmp (argv[0], "rip", 3) == 0) - type = ZEBRA_ROUTE_RIPNG; - else if (strncmp (argv[0], "bgp", 3) == 0) - type = ZEBRA_ROUTE_BGP; + external = (struct ospf6_as_external_lsa *) + OSPF6_LSA_HEADER_END (lsa->header); - ospf6_zebra_no_redistribute (type); - ospf6_asbr_routemap_unset (type); + if (IS_OSPF6_DEBUG_ASBR) + zlog_info ("Withdraw AS-External route for %s", lsa->name); - /* remove redistributed route */ - for (node = route_top (external_table); node; node = route_next (node)) + if (lsa->header->adv_router == ospf6->router_id) { - route = node->info; - if (! route) - continue; - for (info = route->info_head; info; info = info_next) + 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) { - info_next = info->next; - if (info->type != type) - continue; - ospf6_asbr_route_remove (info->type, info->ifindex, - &route->prefix); + prefix2str (&prefix, buf, sizeof (buf)); + zlog_info ("AS-External route %s not found", buf); } + return; } - return CMD_SUCCESS; + 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); + } -int -ospf6_redistribute_config_write (struct vty *vty) + 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) { - int i; + char buf[64]; + struct ospf6_lsa *lsa; + u_int16_t type; + u_int32_t router; - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + if (IS_OSPF6_DEBUG_ASBR) { - if (i == ZEBRA_ROUTE_OSPF6) - continue; + ospf6_linkstate_prefix2str (&asbr_entry->prefix, buf, sizeof (buf)); + zlog_info ("ASBR %s disappeared", buf); + } - if (! ospf6_zebra_is_redistribute (i)) - continue; + 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 (rmap[i].map) - vty_out (vty, " redistribute %s route-map %s%s", - ZROUTE_NAME(i), rmap[i].name, VTY_NEWLINE); - else - vty_out (vty, " redistribute %s%s", - ZROUTE_NAME(i), VTY_NEWLINE); + if (IS_OSPF6_DEBUG_ASBR) + { + ospf6_linkstate_prefix2str (&asbr_entry->prefix, buf, sizeof (buf)); + zlog_info ("Calculation for old ASBR %s done", buf); } +} - return 0; + + +/* redistribute function */ + +void +ospf6_asbr_routemap_set (int type, char *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_redistribute_show_config (struct vty *vty) +ospf6_asbr_routemap_unset (int type) { - int i; + 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 type; - 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)) + if (ospf6 == NULL) return; - vty_out (vty, " Redistributing External Routes from,%s", VTY_NEWLINE); - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { - 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); + if (ospf6->rmap[type].name) + ospf6->rmap[type].map = + route_map_lookup_by_name (ospf6->rmap[type].name); else - vty_out (vty, " %s%s", ZROUTE_NAME(i), VTY_NEWLINE); + ospf6->rmap[type].map = NULL; } } -/* AS External LSA origination */ int -ospf6_asbr_external_lsa_originate (struct thread *thread) +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; - char buffer [MAXLSASIZE]; - struct ospf6_lsa_as_external *e; - char *p; - info = THREAD_ARG (thread); + 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; - /* clear thread */ - info->thread_originate = NULL; + ospf6_asbr_redistribute_remove (info->type, route->nexthop[0].ifindex, + &route->prefix); + } +} - if (info->is_removed) +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 (IS_OSPF6_DUMP_ASBR) + if (ospf6->rmap[type].map == NULL) + ospf6_asbr_routemap_update (); + if (ospf6->rmap[type].map == NULL) { - char pbuf[64]; - prefix2str (&info->route->prefix, pbuf, sizeof (pbuf)); - zlog_info ("ASBR: quit redistribution %s: state is down", - pbuf); + zlog_warn ("route-map \"%s\" not found, suppress redistributing", + ospf6->rmap[type].name); + return; } - return 0; } - /* prepare buffer */ - memset (buffer, 0, sizeof (buffer)); - e = (struct ospf6_lsa_as_external *) buffer; - p = (char *) (e + 1); + /* apply route-map */ + if (ospf6->rmap[type].map) + { + memset (&troute, 0, sizeof (troute)); + memset (&tinfo, 0, sizeof (tinfo)); + troute.route_option = &tinfo; - 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 */ + 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; + } + } - /* 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); + match = ospf6_route_lookup (prefix, ospf6->external_table); + if (match) + { + info = match->route_option; - /* external route tag */ - UNSET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_T); + /* 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)); + } - /* set metric. note: related to E bit */ - OSPF6_ASBR_METRIC_SET (e, info->metric); + info->type = type; + match->nexthop[0].ifindex = ifindex; + if (nexthop_num && nexthop) + memcpy (&match->nexthop[0].address, nexthop, sizeof (struct in6_addr)); - /* prefixlen */ - e->prefix.prefix_length = info->route->prefix.prefixlen; + /* 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; - /* PrefixOptions */ - e->prefix.prefix_options = info->prefix_options; + 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); + } - /* don't use refer LS-type */ - e->prefix.prefix_refer_lstype = htons (0); + ospf6_as_external_lsa_originate_sub (match, 0); + return; + } - /* 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); + /* create new entry */ + route = ospf6_route_create (); + route->type = OSPF6_DEST_TYPE_NETWORK; + memcpy (&route->prefix, prefix, sizeof (struct prefix)); - /* Forwarding address */ - if (CHECK_FLAG (e->bits_metric, OSPF6_ASBR_BIT_F)) + 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) { - memcpy (p, &info->forwarding, sizeof (struct in6_addr)); - p += sizeof (struct in6_addr); + 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)); } - /* External Route Tag */ - if (CHECK_FLAG (e->bits_metric, OSPF6_ASBR_BIT_T)) + 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) { - /* xxx */ + inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf)); + zlog_info ("Advertise as AS-External Id:%s", ibuf); } - ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_AS_EXTERNAL), - htonl (info->id), ospf6->router_id, - (char *) buffer, p - buffer, ospf6); - return 0; + 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); + } } -int -ospf6_asbr_schedule_external (void *data) +void +ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix) { - struct ospf6_external_info *info = data; - u_long elasped_time, time = 0; + 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; - if (info->thread_originate) + match = ospf6_route_lookup (prefix, ospf6->external_table); + if (match == NULL) { - if (IS_OSPF6_DUMP_ASBR) + if (IS_OSPF6_DEBUG_ASBR) { - char pbuf[64]; - prefix2str (&info->route->prefix, pbuf, sizeof (pbuf)); - zlog_info ("ASBR: schedule redistribution %s: another thread", - pbuf); + prefix2str (prefix, pbuf, sizeof (pbuf)); + zlog_info ("No such route %s to withdraw", pbuf); } - return 0; + return; } - 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; + info = match->route_option; + assert (info); - //if (IS_OSPF6_DUMP_ASBR) + if (info->type != type) { - 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 (IS_OSPF6_DEBUG_ASBR) + { + prefix2str (prefix, pbuf, sizeof (pbuf)); + zlog_info ("Original protocol mismatch: %s", pbuf); + } + return; } - 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; -} + 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); + } -int -ospf6_asbr_external_lsa_flush (void *data) -{ - struct ospf6_lsa *lsa = data; + lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL), + htonl (info->id), ospf6->router_id, ospf6->lsdb); if (lsa) ospf6_lsa_premature_aging (lsa); - return 0; + + /* 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); + } } -int -ospf6_asbr_external_lsa_refresh (void *data) +DEFUN (ospf6_redistribute, + ospf6_redistribute_cmd, + "redistribute (static|kernel|connected|ripng|bgp)", + "Redistribute\n" + "Static route\n" + "Kernel route\n" + "Connected route\n" + "RIPng route\n" + "BGP route\n" + ) { - 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; + int type = 0; - if (IS_OSPF6_DUMP_ASBR) - zlog_info ("ASBR: refresh %s", lsa->str); + if (strncmp (argv[0], "sta", 3) == 0) + type = ZEBRA_ROUTE_STATIC; + else if (strncmp (argv[0], "ker", 3) == 0) + type = ZEBRA_ROUTE_KERNEL; + else if (strncmp (argv[0], "con", 3) == 0) + type = ZEBRA_ROUTE_CONNECT; + else if (strncmp (argv[0], "rip", 3) == 0) + type = ZEBRA_ROUTE_RIPNG; + else if (strncmp (argv[0], "bgp", 3) == 0) + type = ZEBRA_ROUTE_BGP; - 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); + ospf6_asbr_redistribute_unset (type); + ospf6_asbr_routemap_unset (type); + ospf6_asbr_redistribute_set (type); + return CMD_SUCCESS; +} - for (node = route_top (external_table); node; node = route_next (node)) - { - route = node->info; - if (route == NULL) - continue; +DEFUN (ospf6_redistribute_routemap, + ospf6_redistribute_routemap_cmd, + "redistribute (static|kernel|connected|ripng|bgp) route-map WORD", + "Redistribute\n" + "Static routes\n" + "Kernel route\n" + "Connected route\n" + "RIPng route\n" + "BGP route\n" + "Route map reference\n" + "Route map name\n" + ) +{ + int type = 0; - for (info = route->info_head; info; info = info->next) - { - if (lsa->header->id == htonl (info->id)) - match = info; - } - } + if (strncmp (argv[0], "sta", 3) == 0) + type = ZEBRA_ROUTE_STATIC; + else if (strncmp (argv[0], "ker", 3) == 0) + type = ZEBRA_ROUTE_KERNEL; + else if (strncmp (argv[0], "con", 3) == 0) + type = ZEBRA_ROUTE_CONNECT; + else if (strncmp (argv[0], "rip", 3) == 0) + type = ZEBRA_ROUTE_RIPNG; + else if (strncmp (argv[0], "bgp", 3) == 0) + type = ZEBRA_ROUTE_BGP; - if (match == NULL) - { - ospf6_lsa_premature_aging (lsa); - return 0; - } + ospf6_asbr_redistribute_unset (type); + ospf6_asbr_routemap_set (type, argv[1]); + ospf6_asbr_redistribute_set (type); + return CMD_SUCCESS; +} + +DEFUN (no_ospf6_redistribute, + no_ospf6_redistribute_cmd, + "no redistribute (static|kernel|connected|ripng|bgp)", + NO_STR + "Redistribute\n" + "Static route\n" + "Kernel route\n" + "Connected route\n" + "RIPng route\n" + "BGP route\n" + ) +{ + int type = 0; + + if (strncmp (argv[0], "sta", 3) == 0) + type = ZEBRA_ROUTE_STATIC; + else if (strncmp (argv[0], "ker", 3) == 0) + type = ZEBRA_ROUTE_KERNEL; + else if (strncmp (argv[0], "con", 3) == 0) + type = ZEBRA_ROUTE_CONNECT; + else if (strncmp (argv[0], "rip", 3) == 0) + type = ZEBRA_ROUTE_RIPNG; + else if (strncmp (argv[0], "bgp", 3) == 0) + type = ZEBRA_ROUTE_BGP; - ospf6_asbr_schedule_external (match); - return 0; + ospf6_asbr_redistribute_unset (type); + ospf6_asbr_routemap_unset (type); -#if 0 - node = route_node_lookup (external_table, &prefix); - if (! node || ! node->info) - { - char pname[64]; + return CMD_SUCCESS; +} - 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; - } +int +ospf6_redistribute_config_write (struct vty *vty) +{ + int type; - /* find external_info */ - route = node->info; - for (info = route->info_head; info; info = info->next) + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { - if (lsa->header->id == htonl (info->id)) - break; - } + if (type == ZEBRA_ROUTE_OSPF6) + continue; + if (! ospf6_zebra_is_redistribute (type)) + continue; - if (info) - ospf6_asbr_schedule_external (info); - else - ospf6_lsa_premature_aging (lsa); + if (ospf6->rmap[type].name) + vty_out (vty, " redistribute %s route-map %s%s", + ZROUTE_NAME (type), ospf6->rmap[type].name, VTY_NEWLINE); + else + vty_out (vty, " redistribute %s%s", + ZROUTE_NAME (type), VTY_NEWLINE); + } return 0; -#endif } void -ospf6_asbr_route_add (int type, int ifindex, struct prefix *prefix, - u_int nexthop_num, struct in6_addr *nexthop) +ospf6_redistribute_show_config (struct vty *vty) { - 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; + int type; + int nroute[ZEBRA_ROUTE_MAX]; + int total; + struct ospf6_route *route; + struct ospf6_external_info *info; - if (! route) + 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)) { - 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; + info = route->route_option; + nroute[info->type]++; + total++; } - for (info = route->info_head; info; info = info->next) + vty_out (vty, "Redistributing External Routes from:%s", VTY_NEWLINE); + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { - if (info->type == type && info->ifindex == ifindex) - break; - } + if (type == ZEBRA_ROUTE_OSPF6) + continue; + if (! ospf6_zebra_is_redistribute (type)) + continue; - 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; - - if (nexthop_num && nexthop) - { - info->nexthop_num = nexthop_num; - if (info->nexthop) - XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info->nexthop); + +/* 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; - 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)); - } + if (type != RMAP_OSPF6) + return RMAP_NOMATCH; - info->is_removed = 0; + plist = prefix_list_lookup (AFI_IP6, (char *) rule); + if (plist == NULL) + return RMAP_NOMATCH; - //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); - } + return (prefix_list_apply (plist, prefix) == PREFIX_DENY ? + RMAP_NOMATCH : RMAP_MATCH); +} -#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; - -#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 */ - - node = route_node_get (external_table, prefix); - route = node->info; - - if (! route) - return; + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} - for (info = route->info_head; info; info = info->next) - { - if (info->type == type && info->ifindex == ifindex) - break; - } +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 (! info) - return; +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; - //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 (type != RMAP_OSPF6) + return RMAP_OKAY; - 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; - - external = OSPF6_LSA_HEADER_END (lsa->header); - - 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; - } - - if (IS_OSPF6_DUMP_ASBR) - zlog_info ("ASBR: new 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; - } - - if (OSPF6_ASBR_METRIC (external) == LS_INFINITY) - { - if (IS_OSPF6_DUMP_ASBR) - zlog_info ("ASBR: metric is infinity, ignore"); - return; - } + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} - 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; +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, +}; - ospf6_route_lookup (&asbr_entry, (struct prefix *) &asbr_id, - ospf6->topology_table); +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 (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; - } + if (type != RMAP_OSPF6) + return RMAP_OKAY; - 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; + route->path.cost = atoi (metric); + return RMAP_OKAY; +} - 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; - 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)); + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} - if (lsa->header->adv_router == ospf6->router_id) - { - if (IS_OSPF6_DUMP_ASBR) - zlog_info ("ASBR: my external LSA, ignore"); - return; - } +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, +}; - 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)); +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; - 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; - } + if (type != RMAP_OSPF6) + return RMAP_OKAY; - while (request.path.origin.id != lsa->header->id || - request.path.origin.adv_router != lsa->header->adv_router) + if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1) { - 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); + memset (&info->forwarding, 0, sizeof (struct in6_addr)); + return RMAP_ERROR; } - 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); - } + return RMAP_OKAY; } -void -ospf6_asbr_external_lsa_change (struct ospf6_lsa *old, struct ospf6_lsa *new) +void * +ospf6_routemap_rule_set_forwarding_compile (char *arg) { - 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); - } + struct in6_addr a; + if (inet_pton (AF_INET6, arg, &a) != 1) + return NULL; + return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg); } void -ospf6_asbr_asbr_entry_add (struct ospf6_route_req *topo_entry) +ospf6_routemap_rule_set_forwarding_free (void *rule) { - struct ospf6_lsdb_node node; + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} - struct prefix_ls *inter_router; - u_int32_t id, adv_router; +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, +}; - inter_router = (struct prefix_ls *) &topo_entry->route.prefix; - id = inter_router->id.s_addr; - adv_router = inter_router->adv_router.s_addr; +int +route_map_command_status (struct vty *vty, int ret) +{ + if (! ret) + return CMD_SUCCESS; - if (IS_OSPF6_DUMP_ASBR) + switch (ret) { - char buf[64]; - inet_ntop (AF_INET, &inter_router->adv_router, buf, sizeof (buf)); - zlog_info ("ASBR: new router found: %s", buf); + 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; +} - if (ntohl (id) != 0 || - ! OSPF6_OPT_ISSET (topo_entry->path.capability, OSPF6_OPT_E)) - { - zlog_warn ("ASBR: Inter topology table malformed"); - return; - } +/* 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); +} - 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); +/* 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); } -void -ospf6_asbr_asbr_entry_remove (struct ospf6_route_req *topo_entry) +/* 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") { - struct prefix_ls *inter_router; - u_int32_t id, adv_router; - struct ospf6_route_req request; + int ret = route_map_delete_set ((struct route_map_index *) vty->index, + "metric-type", argv[0]); + return route_map_command_status (vty, ret); +} - inter_router = (struct prefix_ls *) &topo_entry->route.prefix; - id = inter_router->id.s_addr; - adv_router = inter_router->adv_router.s_addr; +/* 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); +} - 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); - } +/* 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); +} - if (ntohl (id) != 0 || - ! OSPF6_OPT_ISSET (topo_entry->path.capability, OSPF6_OPT_E)) - { - zlog_warn ("ASBR: Inter topology table malformed"); - } +/* 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); +} - 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; +/* 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); +} - ospf6_route_remove (&request, ospf6->route_table); - } +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_asbr_external_show (struct vty *vty, struct ospf6_lsa *lsa) +ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) { - struct ospf6_lsa_as_external *external; - char buf[128], *ptr; - struct in6_addr in6; + struct ospf6_as_external_lsa *external; + char buf[64]; + 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 @@ ospf6_asbr_external_show (struct vty *vty, struct ospf6_lsa *lsa) } 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); -} - -void -ospf6_asbr_register_as_external () -{ - struct ospf6_lsa_slot slot; + struct ospf6_external_info *info = route->route_option; + char prefix[64], id[16], forwarding[64]; + u_int32_t tmp_id; - 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; + 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_external_info_show (struct vty *vty, - struct ospf6_external_info *info) +DEFUN (show_ipv6_ospf6_redistribute, + show_ipv6_ospf6_redistribute_cmd, + "show ipv6 ospf6 redistribute", + SHOW_STR + IP6_STR + OSPF6_STR + "redistributing External information\n" + ) { - char prefix_buf[64], id_buf[16]; - struct in_addr id; + struct ospf6_route *route; - if (info->is_removed) - return; + ospf6_redistribute_show_config (vty); - 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); + for (route = ospf6_route_head (ospf6->external_table); route; + route = ospf6_route_next (route)) + ospf6_asbr_external_route_show (vty, route); + + return CMD_SUCCESS; } -void -ospf6_asbr_external_route_show (struct vty *vty, - struct ospf6_external_route *route) +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" + ) { - struct ospf6_external_info *info; - for (info = route->info_head; info; info = info->next) - ospf6_asbr_external_info_show (vty, info); + ospf6_lsentry_table_show (vty, argc, argv, ospf6->asbr_table); + return CMD_SUCCESS; } -DEFUN (show_ipv6_route_ospf6_external, - show_ipv6_route_ospf6_external_cmd, - "show ipv6 ospf6 route redistribute", +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 - ROUTE_STR OSPF6_STR - "redistributing External information\n" - ) + "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" + ) { - struct route_node *node; - struct ospf6_external_route *route; + char *sargv[CMD_ARGC_MAX]; + int i, sargc; - 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); - } + /* 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_lstype[5].name = "AS-External"; + ospf6_lstype[5].reoriginate = ospf6_as_external_lsa_reoriginate; + ospf6_lstype[5].show = ospf6_as_external_lsa_show; - ospf6_asbr_register_as_external (); + 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 (VIEW_NODE, &show_ipv6_route_ospf6_external_cmd); - install_element (ENABLE_NODE, &show_ipv6_route_ospf6_external_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 153ed21e..f3aabc8d 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 @@ struct ospf6_lsa_as_external { (E)->bits_metric &= htonl (0xff000000); \ (E)->bits_metric |= htonl (0x00ffffff) & htonl (C); } -void ospf6_asbr_routemap_update (); - -int ospf6_redistribute_config_write (struct vty *vty); -void ospf6_redistribute_show_config (struct vty *vty); +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_route_add (int type, int ifindex, struct prefix *prefix, - u_int nexthop_num, struct in6_addr *nexthop); +ospf6_asbr_redistribute_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); +ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix); -void ospf6_asbr_asbr_entry_add (struct ospf6_route_req *topo_entry); -void ospf6_asbr_asbr_entry_remove (struct ospf6_route_req *topo_entry); +int ospf6_redistribute_config_write (struct vty *vty); 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 c1e9e558..00000000 --- a/ospf6d/ospf6_bintree.c +++ /dev/null @@ -1,436 +0,0 @@ - -#include -#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 fad8bbdd..00000000 --- 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 40cf798d..00000000 --- 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 -#include - -#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 19bdbc7a..00000000 --- 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 b10d9aeb..00000000 --- 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 fbb7dc5e..00000000 --- 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 1e3c0c42..00000000 --- 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 - -/* 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 18a6e466..00000000 --- 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 fc9e185d..00000000 --- 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 - -#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 fa882a53..00000000 --- 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 4d632b22..8f01e7dd 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 +#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); - - o6i->maxage_remover = (struct thread *) NULL; + struct ospf6_interface *oi; + struct interface *ifp; - 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; + ifp = if_lookup_by_name (ifname); + if (ifp == NULL) + return (struct ospf6_interface *) NULL; - 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; - - o6i->maxage_remover = - thread_add_event (master, ospf6_interface_maxage_remover, o6i, 0); + 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; + + 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 (); - - o6i->ack_list = ospf6_lsdb_create (); - o6i->lsdb = ospf6_lsdb_create (); - - o6i->transdelay = 1; - o6i->priority = 1; - o6i->hello_interval = 10; - o6i->dead_interval = 40; - o6i->rxmt_interval = 5; - o6i->cost = 1; - o6i->ifmtu = 1280; - - o6i->foreach_nei = ospf6_interface_foreach_neighbor; + 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; + + 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; + + 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; + + oi->route_connected = ospf6_route_table_create (); /* link both */ - o6i->interface = ifp; - ifp->info = o6i; - - CALL_ADD_HOOK (&interface_hook, o6i); - - /* Get the interface's link-local if any */ - ospf6_interface_address_update(ifp); + oi->interface = ifp; + ifp->info = oi; - 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_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_lsdb_delete (o6i->ack_list); - ospf6_lsdb_remove_all (o6i->lsdb); - ospf6_lsdb_delete (o6i->lsdb); + 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, oi); +} + +void +ospf6_interface_enable (struct ospf6_interface *oi) +{ + UNSET_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE); - XFREE (MTYPE_OSPF6_IF, o6i); + 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 @@ ospf6_interface_update_linklocal_address (struct interface *ifp) 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; - /* create new Link-LSA */ - CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, o6i); + /* 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); - CALL_CHANGE_HOOK (&interface_hook, o6i); + /* 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 */ + 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; + + /* log */ + if (IS_OSPF6_DEBUG_INTERFACE) + { + zlog_info ("Interface state change %s: %s -> %s", oi->interface->name, + ospf6_interface_state_str[prev_state], + ospf6_interface_state_str[next_state]); + } - o6i = (struct ospf6_interface *) ifp->info; - return o6i; + 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); + + OSPF6_ROUTER_LSA_SCHEDULE (oi->area); + if (prev_state == OSPF6_INTERFACE_DR || next_state == OSPF6_INTERFACE_DR) + { + OSPF6_NETWORK_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_name (char *ifname) -{ - struct ospf6_interface *o6i; - struct interface *ifp; + +/* DR Election, RFC2328 section 9.4 */ - ifp = if_lookup_by_name (ifname); +#define IS_ELIGIBLE(n) \ + ((n)->state >= OSPF6_NEIGHBOR_TWOWAY && (n)->priority != 0) - if (! ifp) - return (struct ospf6_interface *) NULL; +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; +} - o6i = (struct ospf6_interface *) ifp->info; - return o6i; +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; } -int -ospf6_interface_count_neighbor_in_state (u_char state, - struct ospf6_interface *o6i) +static u_char +dr_election (struct ospf6_interface *oi) { - listnode n; - struct ospf6_neighbor *o6n; - int count = 0; + 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; - for (n = listhead (o6i->neighbor_list); n; nextnode (n)) + /* 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))) { - o6n = (struct ospf6_neighbor *) getdata (n); - if (o6n->state == state) - count++; + 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); + } } - return count; + + oi->drouter = (drouter ? drouter->router_id : htonl (0)); + oi->bdrouter = (bdrouter ? bdrouter->router_id : htonl (0)); + return next_state; } + +/* Interface State Machine */ int -ospf6_interface_count_full_neighbor (struct ospf6_interface *o6i) +interface_up (struct thread *thread) { - listnode n; - struct ospf6_neighbor *o6n; - int count = 0; + 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); - for (n = listhead (o6i->neighbor_list); n; nextnode (n)) + /* 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 { - o6n = (struct ospf6_neighbor *) getdata (n); - if (o6n->state == NBS_FULL) - count++; + ospf6_interface_state_change (OSPF6_INTERFACE_WAITING, oi); + thread_add_timer (master, wait_timer, oi, oi->dead_interval); } - return count; + + 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_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; +} + +int +neighbor_change (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: [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; } -void -ospf6_interface_delayed_ack_remove (struct ospf6_lsa *lsa, - struct ospf6_interface *o6i) +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_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; + 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 @@ ospf6_interface_show (struct vty *vty, struct interface *iface) 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; - - 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); - - 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); - } + 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); + + 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, " 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 @@ DEFUN (show_ipv6_ospf6_interface, 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 @@ DEFUN (show_ipv6_ospf6_interface, { 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 @@ ALIAS (show_ipv6_ospf6_interface, IP6_STR OSPF6_STR INTERFACE_STR + ); + +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_STR + IFNAME_STR + "Display connected prefixes to advertise\n" ) +{ + struct interface *ifp; + struct ospf6_interface *oi; + + 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; + } + + oi = ifp->info; + if (oi == NULL) + { + vty_out (vty, "OSPFv3 is not enabled on %s%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + argc--; + argv++; + ospf6_route_table_show (vty, argc, argv, oi->route_connected); + + return CMD_SUCCESS; +} + +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 + 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" + ) +{ + 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 COST", + "ipv6 ospf6 cost <1-65535>", IP6_STR OSPF6_STR "Interface cost\n" - "<1-65535> Cost\n" + "Outgoing metric of this interface\n" ) { - struct ospf6_interface *o6i; + struct ospf6_interface *oi; struct interface *ifp; - ifp = (struct interface *)vty->index; + ifp = (struct interface *) vty->index; assert (ifp); - o6i = (struct ospf6_interface *)ifp->info; - if (!o6i) - o6i = ospf6_interface_create (ifp); - assert (o6i); + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); - if (o6i->cost == strtol (argv[0], NULL, 10)) + if (oi->cost == strtol (argv[0], NULL, 10)) return CMD_SUCCESS; - o6i->cost = strtol (argv[0], NULL, 10); + oi->cost = strtol (argv[0], NULL, 10); - /* execute LSA hooks */ - CALL_FOREACH_LSA_HOOK (hook_interface, hook_change, o6i); + /* update cost held in route_connected list in ospf6_interface */ + ospf6_interface_connected_route_update (oi->interface); - CALL_CHANGE_HOOK (&interface_hook, o6i); + /* 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; } -/* interface variable set command */ DEFUN (ipv6_ospf6_hellointerval, ipv6_ospf6_hellointerval_cmd, - "ipv6 ospf6 hello-interval HELLO_INTERVAL", + "ipv6 ospf6 hello-interval <1-65535>", IP6_STR OSPF6_STR - "Time between HELLO packets\n" + "Interval time of Hello packets\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->hello_interval = strtol (argv[0], NULL, 10); + 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); + + oi->priority = strtol (argv[0], NULL, 10); - if (ospf6_interface->area) - ifs_change (dr_election (ospf6_interface), "Priority reconfigured", - ospf6_interface); + 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 @@ DEFUN (ipv6_ospf6_passive, "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 @@ DEFUN (no_ipv6_ospf6_passive, "passive interface: No Adjacency will be formed on this I/F\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_PASSIVE); - if (o6i->thread_send_hello == NULL) - thread_add_event (master, ospf6_send_hello, o6i, 0); - - 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 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_FORCE_PREFIX); + 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); - - 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 @@ DEFUN (ipv6_ospf6_advertise_prefix_list, "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 @@ DEFUN (no_ipv6_ospf6_advertise_prefix_list, "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 @@ struct cmd_node interface_node = { 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 @@ ospf6_interface_init () 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 a96ef25a..48b56fc0 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 @@ struct ospf6_interface 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 @@ struct ospf6_interface /* 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 @@ struct ospf6_interface 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 + +extern char *ospf6_interface_state_str[]; -#define OSPF6_INTERFACE_FLAG_PASSIVE 0x01 -#define OSPF6_INTERFACE_FLAG_FORCE_PREFIX 0x02 +/* 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 b9c9ebd0..47cbd39d 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 "ospf6d.h" +#include -static int intra_index; -#define IS_OSPF6_DUMP_INTRA (ospf6_dump_is_on (intra_index)) +#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" -#define ADD 0 -#define REMOVE 1 +#include "ospf6d.h" +#include "ospf6_proto.h" +#include "ospf6_message.h" +#include "ospf6_route.h" +#include "ospf6_lsa.h" +#include "ospf6_lsdb.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" + +/******************************/ +/* 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; - - 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); - } + char *start, *end, *current; + char buf[32], name[32], bits[16], options[32]; + struct ospf6_router_lsa *router_lsa; + struct ospf6_router_lsdesc *lsdesc; - intra_prefix = OSPF6_LSA_HEADER_END (lsa->header); + router_lsa = (struct ospf6_router_lsa *) + ((char *) lsa->header + sizeof (struct ospf6_lsa_header)); - area = lsa->scope; - assert (area); + 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); - 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)) - { - memset (&request, 0, sizeof (request)); - - 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); + for (current = start; current + sizeof (struct ospf6_router_lsdesc) <= end; + current += sizeof (struct ospf6_router_lsdesc)) + { + lsdesc = (struct ospf6_router_lsdesc *) current; + + 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); + + 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; } -int -ospf6_intra_prefix_database_hook_remove (void *data) +void +ospf6_router_lsa_originate_sub (struct ospf6_area *oa, int force) { - 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; + char buffer [OSPF6_MAX_LSASIZE]; + struct ospf6_lsa_header *lsa_header; + struct ospf6_lsa *lsa; + + 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; - area = (struct ospf6_area *) lsa->scope; - assert (area); + if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) + zlog_info ("Originate Router-LSA for Area %s", oa->name); - if (IS_OSPF6_DUMP_INTRA) - zlog_info ("INTRA: area %s remove: %s", area->str, lsa->str); + 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); - 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; + /* describe links for each interfaces */ + lsdesc = (struct ospf6_router_lsdesc *) + ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa)); - if (iap->refer_lstype == htons (OSPF6_LSA_TYPE_ROUTER) && - iap->refer_lsid != htonl (0)) + for (i = listhead (oa->if_list); i; nextnode (i)) { - 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); + 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; + + /* Nor are interfaces without any full adjacencies described */ + count = 0; + for (j = listhead (oi->neighbor_list); j; nextnode (j)) + { + 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 ++; + } + + /* 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; + + 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 */ } - ospf6_route_lookup (&topo_entry, (struct prefix *) &prefix_ls, - area->table_topology); + 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 ++; + } - 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) + /* 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)) { - ospf6_intra_route_calculate (REMOVE, lsa, &topo_entry); - ospf6_route_next (&topo_entry); + if (ntohl (lsa->header->id) < link_state_id) + continue; + ospf6_lsa_premature_aging (lsa); } - return 0; } int -ospf6_intra_prefix_database_hook_add (void *data) +ospf6_router_lsa_originate (struct thread *thread) { - 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; + struct ospf6_area *oa; + int force = 0; - if (lsa->header->type != htons (OSPF6_LSA_TYPE_INTRA_PREFIX)) - return 0; + oa = (struct ospf6_area *) THREAD_ARG (thread); + oa->thread_router_lsa = NULL; + ospf6_router_lsa_originate_sub (oa, force); - area = (struct ospf6_area *) lsa->scope; - assert (area); + return 0; +} - if (IS_LSA_MAXAGE (lsa)) - { - ospf6_intra_prefix_database_hook_remove (lsa); - return 0; - } +int +ospf6_router_lsa_reoriginate (struct ospf6_lsa *lsa) +{ + struct ospf6_area *oa; + int force = 1; - if (IS_OSPF6_DUMP_INTRA) - zlog_info ("INTRA: area %s add: %s", area->str, lsa->str); + oa = (struct ospf6_area *) lsa->scope; + ospf6_router_lsa_originate_sub (oa, force); - iap = OSPF6_LSA_HEADER_END (lsa->header); + return 0; +} - 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); - } +/*******************************/ +/* RFC2740 3.4.3.2 Network-LSA */ +/*******************************/ - ospf6_route_lookup (&topo_entry, (struct prefix *) &prefix_ls, - area->table_topology); +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); - 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) + 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)) { - ospf6_intra_route_calculate (ADD, lsa, &topo_entry); - ospf6_route_next (&topo_entry); + 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_add (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_add (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 ("INTRA: Malformed ID %lu of Router reference in %s", - (u_long) ntohl (iap->refer_lsid), node.lsa->str); - } + if (old) + ospf6_lsa_premature_aging (old); + return; + } - 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; + if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) + zlog_info ("Originate Network-LSA for Interface %s", oi->interface->name); - ospf6_intra_route_calculate (ADD, node.lsa, topo_entry); + /* 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; } -} -void -ospf6_intra_topology_remove (void *data) -{ - struct ospf6_route_req *topo_entry = data; - struct ospf6_area *area; - struct ospf6_intra_area_prefix_lsa *iap; - struct ospf6_lsdb_node node; + /* 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]; + } - area = ospf6_area_lookup (topo_entry->path.area_id, ospf6); - if (! area) - return; + lsdesc = (struct ospf6_network_lsdesc *) + ((caddr_t) network_lsa + sizeof (struct ospf6_network_lsa)); - 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); + /* set Link Description to the router itself */ + lsdesc->router_id = oi->area->ospf6->router_id; + lsdesc++; - for (ospf6_lsdb_type (&node, htons (OSPF6_LSA_TYPE_INTRA_PREFIX), - area->lsdb); - ! ospf6_lsdb_is_end (&node); - ospf6_lsdb_next (&node)) + /* Walk through the neighbors */ + for (i = listhead (oi->neighbor_list); i; nextnode (i)) { - if (IS_LSA_MAXAGE (node.lsa)) + on = (struct ospf6_neighbor *) getdata (i); + + if (on->state != OSPF6_NEIGHBOR_FULL) continue; - iap = OSPF6_LSA_HEADER_END (node.lsa->header); + /* set this neighbor's Router-ID to LSA */ + lsdesc->router_id = on->router_id; + lsdesc++; + } - 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); + /* 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); +} - 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; +int +ospf6_network_lsa_originate (struct thread *thread) +{ + struct ospf6_interface *oi; + int force = 0; - ospf6_intra_route_calculate (REMOVE, node.lsa, topo_entry); - } + oi = (struct ospf6_interface *) THREAD_ARG (thread); + oi->thread_network_lsa = NULL; + ospf6_network_lsa_originate_sub (oi, force); + + return 0; } - -/*****************************************/ -/* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */ -/*****************************************/ +int +ospf6_network_lsa_reoriginate (struct ospf6_lsa *lsa) +{ + struct ospf6_interface *oi; + int force = 1; -#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;\ - } - -#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;\ - } + 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_lsa_intra_prefix_show (struct vty *vty, struct ospf6_lsa *lsa) +ospf6_link_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) { - struct ospf6_intra_area_prefix_lsa *iap_lsa; + char *start, *end, *current; + struct ospf6_link_lsa *link_lsa; + int prefixnum; + char buf[128], options[32]; struct ospf6_prefix *prefix; - unsigned short prefixnum; - char buf[128], type[32], id[32], adv_router[32]; + char *p, *mc, *la, *nu; struct in6_addr in6; - char *start, *end, *current; - 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; - } - - 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); + 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); @@ -378,519 +559,890 @@ ospf6_lsa_intra_prefix_show (struct vty *vty, struct ospf6_lsa *lsa) } 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; - - 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; + char buffer[OSPF6_MAX_LSASIZE]; + struct ospf6_lsa_header *lsa_header; + struct ospf6_lsa *old, *lsa; - list adv_list; + struct ospf6_link_lsa *link_lsa; + struct ospf6_route *route; + struct ospf6_prefix *op; - 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); - } + 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_DEBUG_LSA (ORIGINATE)) + zlog_info ("Originate Link-LSA for Interface %s", oi->interface->name); + + /* can't make Link-LSA if linklocal address not set */ + if (oi->linklocal_addr == NULL) { - if (IS_OSPF6_DUMP_PREFIX) - zlog_info ("Update Intra-Prefix (Transit): %s is Stub", - o6i->interface->name); + 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; } - if (IS_OSPF6_DUMP_PREFIX) - zlog_info ("Update Intra-Prefix (Transit): Interface %s", - o6i->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)) + /* 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)) { - if (IS_LSA_MAXAGE (n.lsa)) - continue; - - if (IS_OSPF6_DUMP_PREFIX) - zlog_info ("Update Intra-Prefix (Transit): Checking %s", - n.lsa->str); - - /* Check status of the advertising router */ - if (n.lsa->header->adv_router != o6i->area->ospf6->router_id) - { - o6n = ospf6_neighbor_lookup (n.lsa->header->adv_router, o6i); - if (! o6n) - { - 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); - continue; - } - } + 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); + } - /* For each Prefix in this Link-LSA */ - link = (struct ospf6_link_lsa *) (n.lsa->header + 1); - prefix_num = ntohl (link->llsa_prefix_num); + /* 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); +} - if (IS_OSPF6_DUMP_PREFIX) - zlog_info (" Prefix #%d", prefix_num); +int +ospf6_link_lsa_originate (struct thread *thread) +{ + struct ospf6_interface *oi; + int force = 0; - 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 = (struct ospf6_prefix *) current; - ospf6_prefix_string (prefix, buf, sizeof (buf)); + oi = (struct ospf6_interface *) THREAD_ARG (thread); + oi->thread_link_lsa = NULL; + ospf6_link_lsa_originate_sub (oi, force); - /* Check duplicate prefix */ - dup = ospf6_prefix_lookup (adv_list, prefix); - if (dup) - { - if (IS_OSPF6_DUMP_PREFIX) - zlog_info (" Duplicate %s", buf); - dup->prefix_options |= prefix->prefix_options; - continue; - } + return 0; +} - if (prefix_num <= 0) - { - zlog_warn (" Wong prefix number ..."); - break; - } +int +ospf6_link_lsa_reoriginate (struct ospf6_lsa *lsa) +{ + struct ospf6_interface *oi; + int force = 1; - if (IS_OSPF6_DUMP_PREFIX) - zlog_info (" Prefix %s", buf); + oi = ospf6_interface_lookup_by_ifindex (ntohl (lsa->header->id)); + ospf6_link_lsa_originate_sub (oi, force); - /* copy prefix to advertise list */ - ospf6_prefix_add (adv_list, prefix); + return 0; +} - prefix_num --; - } - } - /* if no prefix to advertise, return */ - if (listcount (adv_list) == 0) - { - if (IS_OSPF6_DUMP_PREFIX) - zlog_info (" No Prefix to advertise"); - if (old) - ospf6_lsa_premature_aging (old); - return; - } +/*****************************************/ +/* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */ +/*****************************************/ - /* prepare buffer */ - memset (buffer, 0, sizeof (buffer)); - size = sizeof (struct ospf6_intra_area_prefix_lsa); - iap = (struct ospf6_intra_area_prefix_lsa *) buffer; +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; - /* 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; + intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) + ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header)); - dst = (struct ospf6_prefix *) (iap + 1); - for (node = listhead (adv_list); node; nextnode (node)) - { - src = (struct ospf6_prefix *) getdata (node); + prefixnum = ntohs (intra_prefix_lsa->prefix_num); - memcpy (dst, src, OSPF6_PREFIX_SIZE (src)); + vty_out (vty, " Number of Prefix: %d%s", prefixnum, VTY_NEWLINE); - size += OSPF6_PREFIX_SIZE (dst); - dst = OSPF6_NEXT_PREFIX (dst); - } - iap->prefix_number = htons (listcount (adv_list)); + 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); - while ((node = listhead (adv_list)) != NULL) + 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 = getdata (node); - ospf6_prefix_delete (prefix); - listnode_delete (adv_list, 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); } - list_delete (adv_list); - ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_INTRA_PREFIX), - htonl (o6i->if_id), ospf6->router_id, - buffer, size, o6i->area); + return 0; } void -ospf6_lsa_intra_prefix_update_stub (u_int32_t area_id) +ospf6_intra_prefix_lsa_originate_stub_sub (struct ospf6_area *oa, + int force) { - char buffer [MAXLSASIZE]; - u_int16_t size; - struct ospf6_lsa *old; - struct ospf6_area *o6a; - int count; + 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; - 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)]; + /* find previous LSA */ + old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX), + htonl (0), oa->ospf6->router_id, oa->lsdb); - o6a = ospf6_area_lookup (area_id, ospf6); - if (! o6a) + if (CHECK_FLAG (oa->flag, OSPF6_AREA_DISABLE)) { - char tmp[16]; - inet_ntop (AF_INET, &area_id, tmp, sizeof (tmp)); - zlog_warn ("Update Intra-Prefix (Stub): No such area: %s", tmp); + if (old) + ospf6_lsa_premature_aging (old); 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 */ + 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; - adv_list = list_new (); + route_advertise = ospf6_route_table_create (); - /* Examin for each interface */ - for (i = listhead (o6a->if_list); i; nextnode (i)) + for (i = listhead (oa->if_list); i; nextnode (i)) { - o6i = (struct ospf6_interface *) getdata (i); + oi = (struct ospf6_interface *) getdata (i); - if (o6i->state == IFS_DOWN) + if (oi->state == OSPF6_INTERFACE_DOWN) { - if (IS_OSPF6_DUMP_PREFIX) - zlog_info (" Interface %s: down", o6i->interface->name); + if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) + zlog_info (" Interface %s is down, ignore", oi->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) + 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) { - /* This interface's prefix will be included in DR's */ - if (IS_OSPF6_DUMP_PREFIX) - zlog_info (" Interface %s: not stub", o6i->interface->name); + if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) + zlog_info (" Interface %s is not stub, ignore", + oi->interface->name); continue; } - if (IS_OSPF6_DUMP_PREFIX) - zlog_info (" Interface %s:", o6i->interface->name); + if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) + zlog_info (" Interface %s:", oi->interface->name); - /* copy foreach address prefix */ - for (j = listhead (o6i->interface->connected); j; nextnode (j)) + /* connected prefix to advertise */ + for (route = ospf6_route_head (oi->route_connected); route; + route = ospf6_route_best_next (route)) { - c = (struct connected *) getdata (j); + 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); + } + } - /* filter prefix not IPv6 */ - if (c->address->family != AF_INET6) - continue; + if (route_advertise->count == 0) + { + if (old) + ospf6_lsa_premature_aging (old); + ospf6_route_table_delete (route_advertise); + return; + } - /* for log */ - prefix2str (c->address, buf, sizeof (buf)); + /* 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++; + } - 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); + ospf6_route_table_delete (route_advertise); - /* 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; - } - } + if (prefix_num == 0) + { + if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) + zlog_info ("Quit to Advertise Intra-Prefix: no route to advertise"); + return; + } - /* initialize buffer for ospf6 prefix */ - memset (prefix_buf, 0, sizeof (prefix_buf)); - prefix = (struct ospf6_prefix *) prefix_buf; + 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); +} - /* 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)); - } +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]; - ospf6_prefix_string (prefix, buf, sizeof (buf)); - if (IS_OSPF6_DUMP_PREFIX) - zlog_info (" Advertise %s", buf); + if (oi->area == NULL) + return; - /* check in the prefix to advertising prefix list */ - ospf6_prefix_add (adv_list, prefix); - } - } + /* 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 no prefix to advertise */ - if (listcount (adv_list) == 0) + if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE)) { - if (IS_OSPF6_DUMP_PREFIX) - zlog_info (" No prefix to advertise"); 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)); - size = sizeof (struct ospf6_intra_area_prefix_lsa); - iap = (struct ospf6_intra_area_prefix_lsa *) 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)); - /* Set Referenced LSA field */ - iap->refer_lstype = htons (OSPF6_LSA_TYPE_ROUTER); - iap->refer_lsid = htonl (0); - iap->refer_advrtr = o6a->ospf6->router_id; + /* 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; - dst = (struct ospf6_prefix *) (iap + 1); - for (node = listhead (adv_list); node; nextnode (node)) + if (oi->state != OSPF6_INTERFACE_DR) { - src = (struct ospf6_prefix *) getdata (node); + 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; - memcpy (dst, src, OSPF6_PREFIX_SIZE (src)); + if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) + zlog_info (" include prefix from %s", lsa->name); - size += OSPF6_PREFIX_SIZE (dst); - dst = OSPF6_NEXT_PREFIX (dst); + if (lsa->header->adv_router != oi->area->ospf6->router_id) + { + on = ospf6_neighbor_lookup (lsa->header->adv_router, oi); + if (on == NULL || on->state != OSPF6_NEIGHBOR_FULL) + { + if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) + zlog_info (" Neighbor not found or not Full, ignore"); + continue; + } + } + + link_lsa = (struct ospf6_link_lsa *) + ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header)); + + 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)) + { + op = (struct ospf6_prefix *) current; + if (op->prefix_length == 0 || + current + OSPF6_PREFIX_SIZE (op) > end) + break; + + 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)) + { + prefix2str (&route->prefix, buf, sizeof (buf)); + zlog_info (" include %s", buf); + } + + ospf6_route_add (route, route_advertise); + prefix_num--; + } + if (current != end && IS_OSPF6_DEBUG_LSA (ORIGINATE)) + zlog_info ("Trailing garbage in %s", lsa->name); } - iap->prefix_number = htons (listcount (adv_list)); - while ((node = listhead (adv_list)) != NULL) + 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)) { - prefix = getdata (node); - ospf6_prefix_delete (prefix); - listnode_delete (adv_list, prefix); + 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++; } - list_delete (adv_list); - ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_INTRA_PREFIX), - htonl (0) /* xxx */, ospf6->router_id, - buffer, size, o6a); -} + ospf6_route_table_delete (route_advertise); -int -ospf6_lsa_intra_prefix_hook_interface (void *interface) -{ - struct ospf6_interface *o6i = interface; - if (o6i->area) + if (prefix_num == 0) { - ospf6_lsa_intra_prefix_update_transit (o6i->interface->name); - ospf6_lsa_intra_prefix_update_stub (o6i->area->area_id); + if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) + zlog_info ("Quit to Advertise Intra-Prefix: no route to advertise"); + return; } - return 0; + + 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 (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); + + /* 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); } int -ospf6_lsa_intra_prefix_hook_neighbor (void *neighbor) +ospf6_intra_prefix_lsa_originate_stub (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_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_intra_prefix_link_database_hook (void *new) +ospf6_intra_prefix_lsa_originate_transit (struct thread *thread) { - struct ospf6_lsa *lsa = new; - struct ospf6_interface *o6i; - - if (lsa->header->type != htons (OSPF6_LSA_TYPE_LINK)) - return 0; + struct ospf6_interface *oi; + int force = 0; - o6i = lsa->scope; - if (o6i->state != IFS_DR) - return 0; + oi = (struct ospf6_interface *) THREAD_ARG (thread); + oi->thread_intra_prefix_lsa = NULL; + ospf6_intra_prefix_lsa_originate_transit_sub (oi, force); - 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) +ospf6_intra_prefix_lsa_reoriginate (struct ospf6_lsa *lsa) { - 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 + ospf6_lsa_premature_aging (lsa); + + return 0; +} + +void +ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa) +{ + 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]; + + if (IS_OSPF6_DEBUG_ROUTE (INTRA)) + zlog_info ("%s found", lsa->name); + + 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 { - o6a = lsa->scope; - ospf6_lsa_intra_prefix_update_stub (o6a->area_id); + if (IS_OSPF6_DEBUG_ROUTE (INTRA)) + zlog_info ("Unknown reference LS-type: %#hx", + ntohs (intra_prefix_lsa->ref_type)); + return; } - return 0; + 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; + } + + 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_prefix_register () +ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa) { - struct ospf6_lsa_slot slot, *sp; - struct ospf6_hook hook; - - 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); - - 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); - - 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); - - 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); + 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_intra_prefix (struct ospf6_lsa *old, - struct ospf6_lsa *new) +ospf6_intra_route_calculation (struct ospf6_area *oa) { - if (old) - ospf6_intra_prefix_database_hook_remove (old); - if (new && ! IS_LSA_MAXAGE (new)) - ospf6_intra_prefix_database_hook_add (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_database_hook_link (struct ospf6_lsa *old, - struct ospf6_lsa *new) +ospf6_intra_asbr_calculation (struct ospf6_area *oa) { - ospf6_intra_prefix_link_database_hook (new); - ospf6_spf_database_hook (old, new); + 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; - - intra_index = ospf6_dump_install ("intra-area", "Intra-area calculation\n"); - ospf6_intra_prefix_register (); + ospf6_lstype[1].name = "Router"; + ospf6_lstype[2].name = "Network"; + ospf6_lstype[8].name = "Link"; + ospf6_lstype[9].name = "Intra-Prefix"; + + 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 4fb68e95..28780b4a 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 bb14604e..00000000 --- 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 12470d98..00000000 --- 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 8c179359..00000000 --- a/ospf6d/ospf6_linklist.c +++ /dev/null @@ -1,193 +0,0 @@ - -#include - -#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 6d978999..00000000 --- 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 712aa686..13e9a073 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 /* Include other stuffs */ -#include #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) -{ - assert (lsh1 && lsh2); +unsigned char conf_debug_ospf6_lsa = 0; - if (lsh1->adv_router != lsh2->adv_router) - return 0; +struct ospf6_lstype ospf6_lstype[OSPF6_LSTYPE_SIZE]; - if (lsh1->id != lsh2->id) - return 0; +char *ospf6_lstype_str[OSPF6_LSTYPE_SIZE] = + {"Unknown", "Router", "Network", "Inter-Prefix", "Inter-Router", + "AS-External", "Group-Membership", "Type-7", "Link", "Intra-Prefix"}; - if (lsh1->type != lsh2->type) - return 0; +char * +ospf6_lstype_name (u_int16_t type) +{ + static char buf[8]; + int index = ntohs (type) & OSPF6_LSTYPE_FCODE_MASK; + + if (index < OSPF6_LSTYPE_SIZE && ospf6_lstype_str[index]) + return ospf6_lstype_str[index]; - 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 @@ ospf6_lsa_differ (struct ospf6_lsa *lsa1, 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 @@ ospf6_lsa_age_set (struct ospf6_lsa *lsa) 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 @@ ospf6_lsa_age_current (struct ospf6_lsa *lsa) /* 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 @@ ospf6_lsa_age_update_to_send (struct ospf6_lsa *lsa, u_int32_t transdelay) 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 @@ ospf6_lsa_premature_aging (struct ospf6_lsa *lsa) /* 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 @@ ospf6_lsa_check_recent (struct ospf6_lsa *a, struct ospf6_lsa *b) 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 @@ ospf6_lsa_check_recent (struct ospf6_lsa *a, struct ospf6_lsa *b) - (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 @@ ospf6_lsa_check_recent (struct ospf6_lsa *a, struct ospf6_lsa *b) 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) -{ - 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; -} - -void * -ospf6_lsa_lsd_get (int index, struct ospf6_lsa_header *lsa_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; -} - -/* 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) +char * +ospf6_lsa_printbuf (struct ospf6_lsa *lsa, char *buf, int size) { - 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; + 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; } -/* 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) +void +ospf6_lsa_header_print_raw (struct ospf6_lsa_header *header) { - 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; + 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)); } -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_header_print (struct ospf6_lsa *lsa) { - 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; - } - } - - vty_out (vty, "%sUnknown LSA type ...%s", VTY_NEWLINE, VTY_NEWLINE); + 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, "%s", VTY_NEWLINE); } void @@ -439,25 +314,24 @@ ospf6_lsa_show_summary_header (struct vty *vty) 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 @@ ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa) 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 @@ ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa) 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)); -} - -#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); + return ((u_int32_t) htonl (seqnum)); } -#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 @@ ospf6_lsa_summary_create (struct ospf6_lsa_header__ *source) 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; + XFREE (MTYPE_OSPF6_LSA, lsa->header); + XFREE (MTYPE_OSPF6_LSA, lsa); +} - if (lsa->summary) - XFREE (MTYPE_OSPF6_LSA_SUMMARY, 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 - XFREE (MTYPE_OSPF6_LSA, lsa); + 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 */ +/* increment reference counter of struct ospf6_lsa */ void ospf6_lsa_lock (struct ospf6_lsa *lsa) { @@ -680,163 +549,156 @@ ospf6_lsa_lock (struct ospf6_lsa *lsa) 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); - - //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); - - ospf6_dbex_remove_from_all_retrans_list (lsa); - ospf6_dbex_flood (lsa, NULL); - ospf6_lsdb_install (lsa); + LS_REFRESH_TIME); + + if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) + { + zlog_info ("LSA Originate:"); + ospf6_lsa_header_print (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); + zlog_info ("LSA Expire:"); + ospf6_lsa_header_print (lsa); + } - /* 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); + if (lsa->headeronly) + return 0; /* dbexchange will do something ... */ - /* do not free LSA, and do nothing about lslists. - wait event (ospf6_lsdb_check_maxage) */ + /* 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 @@ ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header) } 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; + ospf6_lsa_premature_aging (lsa); 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) +ospf6_unknown_show (struct vty *vty, struct ospf6_lsa *lsa) { - 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)); + u_char *start, *end, *current; + char byte[4]; - if (IS_OSPF6_DUMP_LSA) - zlog_info ("LSA: Slot register: %#x %s", slot->type, slot->name); + start = (char *) lsa->header + sizeof (struct ospf6_lsa_header); + end = (char *) lsa->header + ntohs (lsa->header->length); - if (slot_head == NULL) + vty_out (vty, " Unknown contents:%s", VTY_NEWLINE); + for (current = start; current < end; current ++) { - 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; - - return 0; -} - -int -ospf6_lsa_slot_unregister (u_int16_t type) -{ - struct ospf6_lsa_slot *slot; + if ((current - start) % 16 == 0) + vty_out (vty, "%s ", VTY_NEWLINE); + else if ((current - start) % 4 == 0) + vty_out (vty, " "); - 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; + snprintf (byte, sizeof (byte), "%02x", *current); + vty_out (vty, "%s", byte); } - 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); + vty_out (vty, "%s%s", VTY_NEWLINE, VTY_NEWLINE); return 0; } -char * -ospf6_lsa_type_string (u_int16_t type, char *buf, int bufsize) +void +ospf6_lsa_init () { - struct ospf6_lsa_slot *slot; + memset (ospf6_lstype, 0, sizeof (ospf6_lstype)); - 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; + ospf6_lstype[0].name = "Unknown"; + ospf6_lstype[0].reoriginate = ospf6_unknown_reoriginate; + ospf6_lstype[0].show = ospf6_unknown_show; } -/*******************/ -/* 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); - end = (char *) lsa->header + ntohs (lsa->header->length); - for (current = start; current + sizeof (struct ospf6_router_lsd) <= end; - current += sizeof (struct ospf6_router_lsd)) - { - lsdesc = (struct ospf6_router_lsd *) current; - - 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); - } - 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; +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; + } } - - /* 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)) + 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)) { - 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; + 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; } - - /* 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); + level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV | + OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER; } - 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; + OSPF6_DEBUG_LSA_OFF (level); + return CMD_SUCCESS; } -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; -} +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 -ospf6_lsa_network_refresh (void *old) +config_write_ospf6_debug_lsa (struct vty *vty) { - struct ospf6_lsa *lsa = old; - struct interface *ifp; - - ifp = if_lookup_by_index (ntohl (lsa->header->id)); - if (! ifp) - ospf6_lsa_premature_aging (old); + if (conf_debug_ospf6_lsa == OSPF6_DEBUG_LSA_ALL) + vty_out (vty, "debug ospf6 lsa all%s", VTY_NEWLINE); 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) + if (conf_debug_ospf6_lsa == OSPF6_DEBUG_LSA_DEFAULT) + vty_out (vty, "debug ospf6 lsa%s", VTY_NEWLINE); + else { - 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_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_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); + 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); } - 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 () +install_element_ospf6_debug_lsa () { - 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*/ + 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); } -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; - - 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); -} diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h index 02ad7c6f..8b9d5f34 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,175 +22,56 @@ #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 */ @@ -202,225 +82,175 @@ struct ospf6_lsa_header__ 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 */ - - 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 */ + char name[64]; /* dump string */ - /* 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 *prev; + struct ospf6_lsa *next; -struct ospf6_lsa_slot -{ - struct ospf6_lsa_slot *prev; - struct ospf6_lsa_slot *next; + unsigned char lock; /* reference counter */ + unsigned char flag; /* special meaning (e.g. floodback) */ - u_int16_t type; - char *name; + struct timeval birth; /* tv_sec when LS age 0 */ + struct timeval installed; /* used by MinLSArrival check */ + struct timeval originated; /* used by MinLSInterval check */ - int (*func_print) (struct ospf6_lsa *lsa); - int (*func_show) (struct vty *vty, struct ospf6_lsa *lsa); - int (*func_refresh) (void *lsa); + struct thread *expire; + struct thread *refresh; /* For self-originated LSA */ - int (*database_add) (void *lsa); - int (*database_remove) (void *lsa); + void *scope; /* pointer to scope data structure */ + int headeronly; /* indicate this is LS header only */ - struct ospf6_hook_master database_hook; + unsigned long refcnt; + struct ospf6_lsa *refsrc; - 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; + /* lsa instance */ + struct ospf6_lsa_header *header; }; -#define OSPF6_LSA_FLAG_FLOODBACK 0x01 -#define OSPF6_LSA_FLAG_DUPLICATE 0x02 -#define OSPF6_LSA_FLAG_IMPLIEDACK 0x04 -#define OSPF6_LSA_FLAG_REFRESH 0x08 - -/* 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) - -/* MaxAge check. */ -/* ospf6_lsa_is_maxage (struct ospf6_lsa *lsa) */ -#define IS_LSA_MAXAGE(L) (ospf6_lsa_age_current (L) == OSPF6_LSA_MAXAGE) - -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 OSPF6_LSA_FLOODBACK 0x01 +#define OSPF6_LSA_DUPLICATE 0x02 +#define OSPF6_LSA_IMPLIEDACK 0x04 +#define OSPF6_LSA_REFRESH 0x08 + +struct ospf6_lstype +{ + char *name; + int (*reoriginate) (struct ospf6_lsa *); + int (*show) (struct vty *, struct ospf6_lsa *); +}; + +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) + +#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*/ + +/* Macro for LSA Origination */ +/* void (CONTINUE_IF_...) (struct prefix *addr); */ + +#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 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; \ } -#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 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 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_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; \ } -void ospf6_lsa_init (); +#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 *); - -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 *); +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); -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 *); +u_int32_t ospf6_lsa_new_seqnum (u_int16_t type, u_int32_t id, + u_int32_t adv_router, void *scope); -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); - -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); +void ospf6_lsa_init (); -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 ad53eb4f..97a278e9 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 @@ ospf6_lsdb_delete (struct ospf6_lsdb *lsdb) } 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; - } - } + memcpy ((caddr_t) &key->prefix + key->prefixlen / 8, + (caddr_t) value, len); + key->family = AF_INET6; + key->prefixlen += len * 8; +} - 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); +#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++; - key->family = AF_INET6; - key->prefixlen = len * 8; + 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; - - flag = OSPF6_LSDB_MATCH_TYPE | OSPF6_LSDB_MATCH_ID | - OSPF6_LSDB_MATCH_ADV_ROUTER; - ospf6_lsdb_set_key (&key, flag, lsa->header->type, lsa->header->id, - lsa->header->adv_router); - - rn = route_node_get (lsdb->table, (struct prefix *) &key); - if (rn->info) - old = rn->info; - rn->info = lsa; + struct route_node *current, *nextnode, *prevnode; + struct ospf6_lsa *next, *prev, *old = NULL; + + 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)); + + 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); + } -void -ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb) -{ - int flag; - struct prefix_ipv6 key; - struct route_node *rn; - struct ospf6_lsa *old; + /* 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); + } - 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); + lsdb->count++; + } - rn = route_node_lookup (lsdb->table, (struct prefix *) &key); - if (! rn || ! rn->info) + if (old) { - zlog_warn ("LSDB: Can't remove: no such LSA: %s", lsa->str); - return; + 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); + } + } } - - old = rn->info; - if (old != lsa) + else if (OSPF6_LSA_IS_MAXAGE (lsa)) { - zlog_warn ("LSDB: Can't remove: different instance: %s (%p <-> %p) %s", - lsa->str, lsa, old, old->str); - return; + if (lsdb->hook_remove) + (*lsdb->hook_remove) (lsa); + } + else + { + if (lsdb->hook_add) + (*lsdb->hook_add) (lsa); } - rn->info = NULL; - ospf6_lsa_unlock (old); - 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; - - 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; + if (old) + ospf6_lsa_unlock (old); - node->node = rn; - node->next = route_next (rn); - node->lsa = rn->info; - if (node->next != NULL) - route_unlock_node (node->next); + ospf6_lsdb_count_assert (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) -{ - 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) +ospf6_lsdb_remove (struct ospf6_lsa *lsa, 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); - } -} + struct route_node *node; + struct prefix_ipv6 key; -void -ospf6_lsdb_type (struct ospf6_lsdb_node *node, u_int16_t type, - struct ospf6_lsdb *lsdb) -{ - int flag; - struct route_node *rn; + 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)); - memset (node, 0, sizeof (struct ospf6_lsdb_node)); + node = route_node_lookup (lsdb->table, (struct prefix *) &key); + assert (node && node->info == lsa); - flag = OSPF6_LSDB_MATCH_TYPE; - ospf6_lsdb_set_key (&node->key, flag, type, 0, 0); + if (lsa->prev) + lsa->prev->next = lsa->next; + if (lsa->next) + lsa->next->prev = lsa->prev; - /* get the closest radix node */ - rn = route_node_get (lsdb->table, (struct prefix *) &node->key); + node->info = NULL; + lsdb->count--; - /* 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 (lsdb->hook_remove) + (*lsdb->hook_remove) (lsa); - 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); - } + ospf6_lsa_unlock (lsa); + route_unlock_node (node); + ospf6_lsdb_count_assert (lsdb); } -void -ospf6_lsdb_type_router (struct ospf6_lsdb_node *node, - u_int16_t type, u_int32_t adv_router, - struct ospf6_lsdb *lsdb) +struct ospf6_lsa * +ospf6_lsdb_lookup (u_int16_t type, u_int32_t id, u_int32_t adv_router, + struct ospf6_lsdb *lsdb) { - int flag; - struct route_node *rn; - - memset (node, 0, sizeof (struct ospf6_lsdb_node)); - - flag = OSPF6_LSDB_MATCH_TYPE | OSPF6_LSDB_MATCH_ADV_ROUTER; - ospf6_lsdb_set_key (&node->key, flag, type, 0, adv_router); + struct route_node *node; + struct prefix_ipv6 key; - /* get the closest radix node */ - rn = route_node_get (lsdb->table, (struct prefix *) &node->key); + if (lsdb == NULL) + return NULL; - /* 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); + 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 (rn && rn->info) - { - node->node = rn; - node->next = route_next (rn); - node->lsa = rn->info; - if (node->next != NULL) - route_unlock_node (node->next); - } + 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_next (struct ospf6_lsdb_node *node) +/* Iteration function */ +struct ospf6_lsa * +ospf6_lsdb_head (struct ospf6_lsdb *lsdb) { - struct route_node *rn; - - route_lock_node (node->node); - rn = route_next (node->node); - - /* skip to the real existing lsdb entry */ - while (rn && rn->info == NULL && rn->p.prefixlen >= node->key.prefixlen && - prefix_match ((struct prefix *) &node->key, &rn->p)) - rn = route_next (rn); - - if (rn && rn->info && rn->p.prefixlen >= node->key.prefixlen && - prefix_match ((struct prefix *) &node->key, &rn->p)) - { - node->node = rn; - node->next = route_next (rn); - node->lsa = rn->info; - if (node->next != NULL) - route_unlock_node (node->next); - } - else - { - node->node = NULL; - node->next = NULL; - node->lsa = NULL; - } + struct route_node *node; + + node = route_top (lsdb->table); + if (node == NULL) + return NULL; + + /* 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_lookup (u_int16_t type, u_int32_t id, u_int32_t adv_router, - void *scope) +ospf6_lsdb_next (struct ospf6_lsa *lsa) { - struct ospf6_interface *o6i; - struct ospf6_area *o6a; - listnode i, j; + struct ospf6_lsa *next = lsa->next; - if (scope == (void *) ospf6) - return ospf6_lsdb_lookup_lsdb (type, id, adv_router, ospf6->lsdb); + ospf6_lsa_unlock (lsa); + if (next) + ospf6_lsa_lock (next); - for (i = listhead (ospf6->area_list); i; nextnode (i)) - { - o6a = getdata (i); - - if (scope == (void *) o6a) - return ospf6_lsdb_lookup_lsdb (type, id, adv_router, o6a->lsdb); - - for (j = listhead (o6a->if_list); j; nextnode (j)) - { - o6i = getdata (j); - - if (scope == (void *) o6i) - return ospf6_lsdb_lookup_lsdb (type, id, adv_router, o6i->lsdb); - } - } - - zlog_warn ("LSDB: Can't lookup: unknown scope, type %#hx", ntohs (type)); - return NULL; + return next; } -void -ospf6_lsdb_install (struct ospf6_lsa *new) -{ - struct ospf6_lsdb *lsdb; - struct ospf6_lsa *old; - int need_hook = 0; - void (*hook) (struct ospf6_lsa *, struct ospf6_lsa *); - - struct ospf6 *as = NULL; - struct ospf6_area *area = NULL; - struct ospf6_interface *linklocal = NULL; - hook = NULL; +/* Macro version of check_bit (). */ +#define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1) - switch (ntohs (new->header->type) & OSPF6_LSTYPE_SCOPE_MASK) - { - case OSPF6_LSA_SCOPE_LINKLOCAL: - linklocal = (struct ospf6_interface *) new->scope; - lsdb = linklocal->lsdb; - break; - case OSPF6_LSA_SCOPE_AREA: - area = (struct ospf6_area *) new->scope; - lsdb = area->lsdb; - break; - case OSPF6_LSA_SCOPE_AS: - as = (struct ospf6 *) new->scope; - lsdb = as->lsdb; - break; - default: - zlog_warn ("LSDB: Can't install: scope unknown: %s", new->str); - return; - } +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; - /* whether schedule calculation or not */ - old = ospf6_lsdb_lookup_lsdb (new->header->type, new->header->id, - new->header->adv_router, lsdb); + memset (&key, 0, sizeof (key)); + ospf6_lsdb_set_key (&key, &type, sizeof (type)); + ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router)); - if (! old || ospf6_lsa_differ (old, new)) - need_hook++; + node = lsdb->table->top; - /* log */ - if (IS_OSPF6_DUMP_LSDB) - zlog_info ("LSDB: Install: %s %s", new->str, - ((IS_LSA_MAXAGE (new)) ? "(MaxAge)" : "")); + /* 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 (old) - ospf6_lsa_lock (old); + if (node) + route_lock_node (node); + while (node && node->info == NULL) + node = route_next (node); - ospf6_lsdb_add (new, lsdb); - gettimeofday (&new->installed, NULL); + if (node == NULL) + return NULL; + else + route_unlock_node (node); - hook = ospf6_lsdb_hook[ntohs (new->header->type) & - OSPF6_LSTYPE_CODE_MASK].hook; - if (need_hook && hook) - (*hook) (old, new); + if (! prefix_match ((struct prefix *) &key, &node->p)) + return NULL; - /* old LSA should be freed here */ - if (old) - ospf6_lsa_unlock (old); -} + lsa = node->info; + ospf6_lsa_lock (lsa); -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); + return lsa; } -void -ospf6_lsdb_remove_maxage (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_lsdb_node node; - struct ospf6_lsa *lsa; + struct ospf6_lsa *next = lsa->next; - for (ospf6_lsdb_head (&node, lsdb); ! ospf6_lsdb_is_end (&node); - ospf6_lsdb_next (&node)) + if (next) { - 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); + if (next->header->type != type || + next->header->adv_router != adv_router) + next = NULL; } -} - - - -/* 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; + if (next) + ospf6_lsa_lock (next); + ospf6_lsa_unlock (lsa); + return next; } -int -show_ipv6_ospf6_lsdb (struct vty *vty, int argc, char **argv, - struct ospf6_lsdb *lsdb) +struct ospf6_lsa * +ospf6_lsdb_type_head (u_int16_t type, 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 --; - } + struct route_node *node; + struct prefix_ipv6 key; + struct ospf6_lsa *lsa; - 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); - } + memset (&key, 0, sizeof (key)); + ospf6_lsdb_set_key (&key, &type, sizeof (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; - } - } - } - } + /* 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)]; - 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 (node) + route_lock_node (node); + while (node && node->info == NULL) + node = route_next (node); - if (! CHECK_FLAG (flag, OSPF6_LSDB_SHOW_DETAIL)) - ospf6_lsa_show_summary_header (vty); + if (node == NULL) + return NULL; + else + route_unlock_node (node); - 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 (! prefix_match ((struct prefix *) &key, &node->p)) + return NULL; - 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); - } + lsa = node->info; + ospf6_lsa_lock (lsa); - return CMD_SUCCESS; + return lsa; } -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_lsa * +ospf6_lsdb_type_next (u_int16_t type, struct ospf6_lsa *lsa) { - struct ospf6_area *o6a; - struct ospf6_interface *o6i; - listnode i, j; - - /* call show function for each of LSAs in the LSDBs */ + struct ospf6_lsa *next = lsa->next; - for (i = listhead (ospf6->area_list); i; nextnode (i)) + if (next) { - 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); + if (next->header->type != type) + next = NULL; } - /* 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; + if (next) + ospf6_lsa_lock (next); + ospf6_lsa_unlock (lsa); + return next; } -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 () +ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb) { - 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); + struct ospf6_lsa *lsa; + 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 50eedc85..94dfcb64 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) - -/* 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 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) + +#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, + 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_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb); +void ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb); -void ospf6_lsdb_install (struct ospf6_lsa *new); +struct ospf6_lsa *ospf6_lsdb_head (struct ospf6_lsdb *lsdb); +struct ospf6_lsa *ospf6_lsdb_next (struct ospf6_lsa *lsa); -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_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_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb); -void ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb); 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 3b7cfc9a..4dfcdeea 100644 --- a/ospf6d/ospf6_main.c +++ b/ospf6d/ospf6_main.c @@ -20,32 +20,30 @@ */ #include + #include "getopt.h" #include "thread.h" #include "log.h" -#include +#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 @@ struct option longopts[] = { "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_current[] = OSPF6_DEFAULT_CONFIG; char config_default[] = SYSCONFDIR OSPF6_DEFAULT_CONFIG; /* ospf6d program name. */ +char *progname; /* is daemon? */ int daemon_mode = 0; @@ -96,19 +94,6 @@ struct thread_master *master; /* 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 @@ Daemon which manages OSPF version 3.\n\n\ -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 @@ void sigint (int sig) { zlog_info ("SIGINT received"); - terminate (0); + exit (0); } /* SIGTERM handler. */ @@ -176,7 +138,7 @@ void sigterm (int sig) { zlog_info ("SIGTERM received"); - terminate (0); + exit (0); } /* SIGUSR1 handler. */ @@ -229,8 +191,8 @@ signal_init () #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 @@ main (int argc, char *argv[], char *envp[]) 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 @@ main (int argc, char *argv[], char *envp[]) /* 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 @@ main (int argc, char *argv[], char *envp[]) 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 @@ main (int argc, char *argv[], char *envp[]) 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 @@ main (int argc, char *argv[], char *envp[]) pid_output (pid_file); #endif - /* Make ospf protocol socket. */ - ospf6_serv_sock (); - thread_add_read (master, ospf6_receive, NULL, ospf6_sock); - - /* Make ospf vty socket. */ - vty_serv_sock (vty_addr, vty_port, OSPF6_VTYSH_PATH); + /* Make ospf6 vty socket. */ + vty_serv_sock (vty_addr, + vty_port ? vty_port : OSPF6_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 @@ main (int argc, char *argv[], char *envp[]) /* 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 0e74b651..21b799e0 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 + +#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) -{ - if (type > OSPF6_MESSAGE_TYPE_LSACK) - type = OSPF6_MESSAGE_TYPE_UNKNOWN; +#include "ospf6_top.h" +#include "ospf6_area.h" +#include "ospf6_neighbor.h" +#include "ospf6_interface.h" - 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; -} -#define IS_OSPF6_DUMP_MESSAGE(x) (is_ospf6_message_dump(x)) +#include "ospf6_flood.h" -char *ospf6_message_type_string[] = -{ - "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck", NULL -}; +unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0}; +char *ospf6_message_type_str[] = + { "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck" }; -void -ospf6_message_log_lsa_header (struct ospf6_lsa_header *lsa_header) -{ - 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)); -} +/* print functions */ static void -ospf6_message_log_unknown (struct iovec *message) +ospf6_header_print (struct ospf6_header *oh) { - zlog_info ("Message: 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)); + + 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); } -static void -ospf6_message_log_hello (struct iovec *message) +void +ospf6_hello_print (struct ospf6_header *oh) { - 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; - - /* 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)); - - dbdesc = (struct ospf6_dbdesc *) message[1].iov_base; - ospf6_options_string (dbdesc->options, buffer, sizeof (buffer)); - - 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)); - - 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); - - 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; - } + char options[16]; + char *p; + + ospf6_header_print (oh); + assert (oh->type == OSPF6_MESSAGE_TYPE_DBDESC); + + dbdesc = (struct ospf6_dbdesc *) + ((caddr_t) oh + sizeof (struct ospf6_header)); + + ospf6_options_printbuf (dbdesc->options, options, sizeof (options)); + + 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)); + + 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 (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 (i = 2; message[i].iov_base; i++) + if (p != OSPF6_MESSAGE_END (oh)) { + char buf[32]; + + int num = 0; + memset (buf, 0, sizeof (buf)); - 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; + 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; + /* version check */ + if (oh->version != OSPFV3_VERSION) + { + if (IS_OSPF6_DEBUG_MESSAGE (type, RECV)) + zlog_info ("Message with unknown version"); + return MSG_NG; + } - inet_ntop (AF_INET, &o6h->router_id, router_id, sizeof (router_id)); - inet_ntop (AF_INET, &o6h->area_id, area_id, sizeof (area_id)); + /* 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; + } - 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); + if (IS_OSPF6_DEBUG_MESSAGE (type, RECV)) + zlog_info ("Area-ID mismatch"); + return MSG_NG; + } - 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]); -} + /* 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; + } -int -ospf6_opt_is_mismatch (unsigned char opt, char *options1, char *options2) -{ - return (OSPF6_OPT_ISSET (options1, opt) ^ OSPF6_OPT_ISSET (options2, opt)); -} + /* Router-ID check */ + if (oh->router_id == oi->area->ospf6->router_id) + zlog_warn ("Detect duplicate Router-ID"); - -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"); + return MSG_OK; } void -ospf6_process_hello (struct iovec *message, - struct in6_addr *src, - struct in6_addr *dst, - struct ospf6_interface *o6i, - u_int32_t router_id) +ospf6_hello_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_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) - { - 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)); - } + 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; + 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)); } - /* DR set */ - if (o6n->dr != hello->dr) + /* TwoWay check */ + for (p = (char *) ((caddr_t) hello + sizeof (struct ospf6_hello)); + p + sizeof (u_int32_t) <= OSPF6_MESSAGE_END (oh); + p += sizeof (u_int32_t)) { - /* 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; + u_int32_t *router_id = (u_int32_t *) p; + + if (*router_id == oi->area->ospf6->router_id) + twoway++; } - /* BDR set */ - if (o6n->bdr != hello->bdr) + if (p != OSPF6_MESSAGE_END (oh)) { - /* 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; + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Trailing garbage ignored"); } - /* 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++) + /* RouterPriority check */ + if (on->priority != hello->priority) { - if (*router_id_ptr == o6i->area->ospf6->router_id) - twoway++; - router_id_ptr++; + on->priority = hello->priority; + neighborchange++; } - /* 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); + /* 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++; + } - /* BackupSeen check */ - if (o6i->state == IFS_WAITING) + /* BDR check */ + if (on->bdrouter != hello->bdrouter) { - if (hello->dr == hello->bdr && - hello->dr == o6n->router_id) - zlog_warn ("*** DR Election of %s is illegal", o6n->str); + on->prev_bdrouter = on->bdrouter; + on->bdrouter = hello->bdrouter; + if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id) + neighborchange++; + } - if (hello->bdr == o6n->router_id) + /* BackupSeen check */ + if (oi->state == OSPF6_INTERFACE_WAITING) + { + 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]; + struct ospf6_dbdesc *dbdesc; + char *p; - if (o6n->router_id == ospf6->router_id) + dbdesc = (struct ospf6_dbdesc *) + ((caddr_t) oh + sizeof (struct ospf6_header)); + + if (on->state < OSPF6_NEIGHBOR_INIT) { - inet_ntop (AF_INET6, &o6n->hisaddr, buf, sizeof (buf)); - zlog_warn ("Message: Neighbor router-id conflicts: %s: %s", - o6n->str, buf); - return -1; + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Neighbor state less than Init, ignore"); + return; } - 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; -} + switch (on->state) + { + case OSPF6_NEIGHBOR_TWOWAY: + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Neighbor state is 2-Way, ignore"); + return; -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; - - /* 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: - 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 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); - 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; + /* 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 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 */ + 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; + } - default: - assert (0); - break; /* not reached */ + 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 */ - lsa_count = 0; - for (lsa_header = (struct ospf6_lsa_header *) (dbdesc + 1); - (char *)(lsa_header + 1) <= (char *)dbdesc + length; - lsa_header++) + /* 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)) { - if (ospf6_dbex_check_dbdesc_lsa_header (lsa_header, o6n) < 0) + 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)) { - thread_add_event (master, seqnumber_mismatch, o6n, 0); + 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; } - lsa_count ++; + + 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); } - /* increment dbdesc seqnum */ - o6n->dbdesc_seqnum++; + if (p != OSPF6_MESSAGE_END (oh)) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Trailing garbage ignored"); + } - /* 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; + /* Increment sequence number */ + on->dbdesc_seqnum ++; - /* 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); + /* schedule send lsreq */ + if (on->thread_send_lsreq == NULL) + on->thread_send_lsreq = + thread_add_event (master, ospf6_lsreq_send, on, 0); - /* save last received dbdesc */ - memcpy (&o6n->last_dd, dbdesc, sizeof (struct ospf6_dbdesc)); + THREAD_OFF (on->thread_send_dbdesc); - /* statistics */ - o6n->lsa_receive[OSPF6_MESSAGE_TYPE_DBDESC] += lsa_count; + /* 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); - return; + /* save last received dbdesc */ + memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc)); } -void -ospf6_process_dbdesc_slave (struct iovec *message, struct ospf6_neighbor *o6n) +static void +ospf6_dbdesc_recv_slave (struct ospf6_header *oh, + struct ospf6_neighbor *on) { - 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; + char *p; - 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; + 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; + } - 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 */ + switch (on->state) + { + case OSPF6_NEIGHBOR_TWOWAY: + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Neighbor state is 2-Way, ignore"); + return; - default: - assert (0); - break; /* not reached */ + 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; } - /* process LSA headers */ - lsa_count = 0; - for (lsa_header = (struct ospf6_lsa_header *) (dbdesc + 1); - (char *)(lsa_header + 1) <= (char *)dbdesc + length; - lsa_header++) + /* 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)) { - if (ospf6_dbex_check_dbdesc_lsa_header (lsa_header, o6n) < 0) + 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)) { - thread_add_event (master, seqnumber_mismatch, o6n, 0); + 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; } - lsa_count ++; + + 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); } - /* set dbdesc seqnum to master's */ - o6n->dbdesc_seqnum = ntohl (dbdesc->seqnum); + if (p != OSPF6_MESSAGE_END (oh)) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Trailing garbage ignored"); + } - if (o6n->thread_send_dbdesc) - thread_cancel (o6n->thread_send_dbdesc); - o6n->thread_send_dbdesc = - thread_add_event (master, ospf6_send_dbdesc, o6n, 0); + /* Set sequence number to Master's */ + on->dbdesc_seqnum = ntohl (dbdesc->seqnum); - /* save last received dbdesc */ - memcpy (&o6n->last_dd, dbdesc, sizeof (struct ospf6_dbdesc)); + /* schedule send lsreq */ + if (on->thread_send_lsreq == NULL) + on->thread_send_lsreq = + thread_add_event (master, ospf6_lsreq_send, on, 0); - /* statistics */ - o6n->lsa_receive[OSPF6_MESSAGE_TYPE_DBDESC] += lsa_count; + THREAD_OFF (on->thread_send_dbdesc); + on->thread_send_dbdesc = + thread_add_event (master, ospf6_dbdesc_send_newone, on, 0); - return; + /* save last received dbdesc */ + memcpy (&on->dbdesc_last, dbdesc, sizeof (struct ospf6_dbdesc)); } void -ospf6_process_dbdesc (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_neighbor *on; 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; + if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK) + return; - /* 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_DBDESC) - 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; } - /* interface mtu check */ - /* xxx */ + dbdesc = (struct ospf6_dbdesc *) + ((caddr_t) oh + sizeof (struct ospf6_header)); - /* check am I master */ - Im_master = ospf6_dbdesc_is_master (o6n); - if (Im_master < 0) + /* Interface MTU check */ + if (ntohs (dbdesc->ifmtu) != oi->ifmtu) { - return; /* can't decide which is master, return */ + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("I/F MTU mismatch"); + return; } - if (Im_master) - ospf6_process_dbdesc_master (message, o6n); - else - ospf6_process_dbdesc_slave (message, o6n); + 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; + } - return; + 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_process_lsreq (struct iovec *message, - struct in6_addr *src, - struct in6_addr *dst, - struct ospf6_interface *o6i, - u_int32_t router_id) +ospf6_lsreq_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; + 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); - /* 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); + if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK) + return; - /* 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)); - - /* find instance of database copy */ - lsa = ospf6_lsdb_lookup (lsreq->type, lsreq->id, lsreq->adv_router, - ospf6_lsa_get_scope (lsreq->type, o6i)); + e = (struct ospf6_lsreq_entry *) p; + scope = ospf6_get_lsa_scope (e->type, on); + lsdb = ospf6_get_scoped_lsdb (e->type, scope); - 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; - - /* assert interface */ - assert (o6i); + unsigned long num; + 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); + if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK) + return; - /* 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. */ + /* 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) && + (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_lsack_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_lsa *his, *mine; + struct ospf6_lsdb *lsdb = NULL; + + assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK); + 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; + } - /* process LSAs */ - for (lsa_header = (struct ospf6_lsa_header *) (lsupdate + 1); - lsanum && (char *)lsa_header < (char *)lsupdate + length; - lsanum--) + if (on->state != OSPF6_NEIGHBOR_EXCHANGE && + on->state != OSPF6_NEIGHBOR_LOADING && + on->state != OSPF6_NEIGHBOR_FULL) { - ospf6_dbex_receive_lsa (lsa_header, o6n); - lsa_header = OSPF6_LSA_NEXT (lsa_header); + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Neighbor state less than Exchange, ignore"); + return; } - /* 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); + 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)) + { + 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 (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_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("No database copy"); + ospf6_lsa_delete (his); + continue; + } + + /* 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_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Not on %s's retrans-list", on->name); + ospf6_lsa_delete (his); + continue; + } + + if (ospf6_lsa_compare (his, mine) != 0) + { + /* Log this questionable acknowledgement, + and examine the next one. */ + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Questionable acknowledgement"); + ospf6_lsa_delete (his); + continue; + } + + 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); + } + + if (p != OSPF6_MESSAGE_END (oh)) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Trailing garbage ignored"); + } +} + +char recvbuf[OSPF6_MESSAGE_BUFSIZ]; +char sendbuf[OSPF6_MESSAGE_BUFSIZ]; + +int +ospf6_receive (struct thread *thread) +{ + int sockfd, len; + char srcname[64], dstname[64]; + struct in6_addr src, dst; + unsigned int ifindex; + 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 */ + 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 */ + len = ospf6_recvmsg (&src, &dst, &ifindex, iovector); + if (len > sizeof (recvbuf)) + { + zlog_err ("Excess message read"); + return 0; + } + else if (len < sizeof (struct ospf6_header)) + { + zlog_err ("Deficient message read"); + return 0; + } + + 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; + return 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_send (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; - - /* 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); - - /* find neighbor. if cannot be found, reject this message */ - o6n = ospf6_neighbor_lookup (router_id, o6i); - if (!o6n) - { - if (IS_OSPF6_DUMP_LSACK) - zlog_info ("LSACK: neighbor not found, reject"); - return; - } - - if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr))) - { - if (IS_OSPF6_DUMP_LSACK) - zlog_info ("LSACK: From Secondary I/F of the neighbor: ignore"); - return; - } + int len; + char srcname[64], dstname[64]; + struct iovec iovector[2]; - /* if neighbor state less than ExChange, reject this message */ - if (o6n->state < NBS_EXCHANGE) - { - if (IS_OSPF6_DUMP_LSACK) - zlog_info ("LSACK: neighbor state less than Exchange, reject"); - return; - } + /* 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; - /* 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++) + /* Log */ + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, SEND)) { - /* 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)); - - /* if no database copy */ - if (!copy) - { - if (IS_OSPF6_DUMP_LSACK) - zlog_info ("LSACK: no database copy, ignore"); - 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) - { - if (IS_OSPF6_DUMP_LSACK) - zlog_info ("LSACK: not on %s's retranslist, ignore", o6n->str); - 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); + 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) { - /* Log the 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)); + 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; } - - /* release temporary LSA from Ack message */ - ospf6_lsa_delete (lsa); } - ospf6_maxage_remover (); - return; + /* send message */ + len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector); + if (len != ntohs (oh->length)) + zlog_err ("Could not send entire message"); } -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) +int +ospf6_hello_send (struct thread *thread) { - struct ospf6_header *ospf6_header = NULL; - u_char type; - u_int32_t router_id; - char srcname[64]; - - assert (o6i); - assert (src); - assert (dst); + struct ospf6_interface *oi; + struct ospf6_header *oh; + struct ospf6_hello *hello; + char *p; + listnode node; + struct ospf6_neighbor *on; - /* set ospf6_hdr pointer to head of buffer */ - ospf6_header = (struct ospf6_header *) message[0].iov_base; + oi = (struct ospf6_interface *) THREAD_ARG (thread); + oi->thread_send_hello = (struct thread *) NULL; - /* version check */ - if (ospf6_header->version != OSPF6_VERSION) + if (oi->state <= OSPF6_INTERFACE_DOWN) { - if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) - zlog_info ("version mismatch, drop"); - return; + 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; } - /* 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; - } + /* set next thread */ + oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send, + oi, oi->hello_interval); - if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) - zlog_info ("area id mismatch, drop"); - return; - } + memset (sendbuf, 0, sizeof (sendbuf)); + oh = (struct ospf6_header *) sendbuf; + hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header)); - /* 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; - } + 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; - /* message type check */ - type = (ospf6_header->type >= OSPF6_MESSAGE_TYPE_MAX ? - OSPF6_MESSAGE_TYPE_UNKNOWN : ospf6_header->type); + p = (char *)((caddr_t) hello + sizeof (struct ospf6_hello)); - /* log */ - if (IS_OSPF6_DUMP_MESSAGE (type)) + for (node = listhead (oi->neighbor_list); node; nextnode (node)) { - 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); - } + on = (struct ospf6_neighbor *) getdata (node); - /* 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; - } + 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; + } - /* 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; + memcpy (p, &on->router_id, sizeof (u_int32_t)); + p += sizeof (u_int32_t); + } - /* futher process */ - (*ospf6_message_process_type[type].process) (&message[0], src, dst, o6i, router_id); + oh->type = OSPF6_MESSAGE_TYPE_HELLO; + oh->length = htons (p - sendbuf); - return; + ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh); + return 0; } int -ospf6_receive (struct thread *thread) +ospf6_dbdesc_send (struct thread *thread) { - int sockfd; - 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; + struct ospf6_neighbor *on; + struct ospf6_header *oh; + struct ospf6_dbdesc *dbdesc; + char *p; + struct ospf6_lsa *lsa; - /* get socket */ - sockfd = THREAD_FD (thread); + on = (struct ospf6_neighbor *) THREAD_ARG (thread); + on->thread_send_dbdesc = (struct thread *) NULL; - /* add next read thread */ - thread_add_read (master, ospf6_receive, NULL, sockfd); + 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; + } - /* initialize */ - OSPF6_MESSAGE_CLEAR (message); - memset (&ospf6_header, 0, sizeof (struct ospf6_header)); + /* 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); - OSPF6_MESSAGE_ATTACH (message, &ospf6_header, sizeof (struct ospf6_header)); - OSPF6_MESSAGE_ATTACH (message, buffer, OSPF6_MESSAGE_RECEIVE_BUFSIZE); + memset (sendbuf, 0, sizeof (sendbuf)); + oh = (struct ospf6_header *) sendbuf; + dbdesc = (struct ospf6_dbdesc *)((caddr_t) oh + + sizeof (struct ospf6_header)); - /* receive message */ - ospf6_recvmsg (&src, &dst, &ifindex, message); + /* 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); - 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) + /* 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)) { - //zlog_warn ("*** received interface ospf6 disabled"); - return 0; + 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); + } } - /* 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); + 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; } - -/* send section */ int -ospf6_message_length (struct iovec *message) +ospf6_dbdesc_send_newone (struct thread *thread) { - int i, length = 0; - for (i = 0; i < OSPF6_MESSAGE_IOVEC_SIZE; i++) + 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 (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 + if (size + sizeof (struct ospf6_lsa_header) > on->ospf6_if->ifmtu) { - zlog_warn ("Message: I/F MTU check ignored on %s", - o6i->interface->name); + 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); } - /* Initialize */ - OSPF6_MESSAGE_CLEAR (message); + if (on->summary_list->count == 0) + UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT); - /* 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)); + /* 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); - /* Attach rest to message */ - OSPF6_MESSAGE_JOIN (message, msg); + thread_execute (master, ospf6_dbdesc_send, on, 0); + return 0; +} - /* 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); +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; - /* log */ - if (IS_OSPF6_DUMP_MESSAGE (type)) + 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) { - 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); + 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; } - /* 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); + /* schedule loading_done if request list is empty */ + if (on->request_list->count == 0) + { + thread_add_event (master, loading_done, on, 0); return 0; } - /* clear message buffer */ - OSPF6_MESSAGE_CLEAR (message); + /* set next thread */ + on->thread_send_lsreq = + thread_add_timer (master, ospf6_lsreq_send, on, + on->ospf6_if->rxmt_interval); - /* 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)); + memset (sendbuf, 0, sizeof (sendbuf)); + oh = (struct ospf6_header *) sendbuf; - /* set neighbor router id */ - router_size = 0; - for (n = listhead (o6i->neighbor_list); n; nextnode (n)) + /* 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)) { - o6n = (struct ospf6_neighbor *) getdata (n); - - if (o6n->state < NBS_INIT) - continue; - - if (router_size + sizeof (o6n->router_id) > sizeof (router_buffer)) + /* MTU check */ + if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > on->ospf6_if->ifmtu) { - zlog_warn ("Send HELLO: Buffer shortage on %s", - o6i->interface->name); + ospf6_lsa_unlock (lsa); break; } - /* Copy Router-ID to Buffer */ - memcpy (router_buffer + router_size, &o6n->router_id, - sizeof (o6n->router_id)); - router_size += sizeof (o6n->router_id); + 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); } - 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); + 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; } -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) +ospf6_lsupdate_send_neighbor (struct thread *thread) { - struct ospf6_lsdb_node node; - struct ospf6_neighbor *o6n; - struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; + struct ospf6_neighbor *on; + struct ospf6_header *oh; + struct ospf6_lsupdate *lsupdate; + char *p; + int num; struct ospf6_lsa *lsa; - struct ospf6_lsa_header *lsa_header; - struct ospf6_dbdesc dbdesc; - o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); - assert (o6n); + on = (struct ospf6_neighbor *) THREAD_ARG (thread); + on->thread_send_lsupdate = (struct thread *) NULL; - /* clear thread */ - o6n->thread_rxmt_dbdesc = (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 state less than ExStart, do nothing */ - if (o6n->state < NBS_EXSTART) + /* if we have nothing to send, return */ + if (on->lsupdate_list->count == 0 && + on->retrans_list->count == 0) return 0; - OSPF6_MESSAGE_CLEAR (message); + 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)); - /* 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)); + p = (char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); + num = 0; - /* if this is not initial, set LSA summary to dbdesc */ - if (! DD_IS_IBIT_SET (o6n->dbdesc_bits)) + /* 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)) { - for (ospf6_lsdb_head (&node, o6n->dbdesc_list); - ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node)) + /* MTU check */ + if (p - sendbuf + OSPF6_LSA_SIZE (lsa->header) > on->ospf6_if->ifmtu) { - lsa = node.lsa; + ospf6_lsa_unlock (lsa); + break; + } - /* xxx, no MTU check: no support for Dynamic MTU change */ + if (IS_OSPF6_DEBUG_LSA (SEND)) + ospf6_lsa_header_print (lsa); - /* set age and add InfTransDelay */ - ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay); + 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++; - /* 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)); + 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++; } - /* send dbdesc */ - ospf6_message_send (OSPF6_MESSAGE_TYPE_DBDESC, message, &o6n->hisaddr, - o6n->ospf6_interface->interface->ifindex); + lsupdate->lsa_number = htonl (num); + + oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE; + oh->length = htons (p - sendbuf); - /* 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); + ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, + on->ospf6_if, oh); - /* statistics */ - o6n->ospf6_stat_retrans_dbdesc++; + 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_send_dbdesc (struct thread *thread) +ospf6_lsupdate_send_interface (struct thread *thread) { - struct ospf6_neighbor *o6n; + struct ospf6_interface *oi; + struct ospf6_header *oh; + struct ospf6_lsupdate *lsupdate; + char *p; + int num; 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); + oi = (struct ospf6_interface *) THREAD_ARG (thread); + oi->thread_send_lsupdate = (struct thread *) NULL; - /* 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)) + if (oi->state <= OSPF6_INTERFACE_WAITING) { - 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; + 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; + } - /* debug */ - if (IS_OSPF6_DUMP_DBDESC) - zlog_info ("Include DbDesc: %s", lsa->str); + /* if we have nothing to send, return */ + if (oi->lsupdate_list->count == 0) + return 0; - /* attach to dbdesclist */ - ospf6_neighbor_dbdesc_add (lsa, o6n); - /* detach from summarylist */ - ospf6_neighbor_summary_remove (lsa, o6n); + if (IS_OSPF6_DEBUG_LSA (SEND)) + zlog_info ("LSA Send to %s", oi->interface->name); - /* set age and add InfTransDelay */ - ospf6_lsa_age_update_to_send (lsa, o6n->ospf6_interface->transdelay); + memset (sendbuf, 0, sizeof (sendbuf)); + oh = (struct ospf6_header *) sendbuf; + lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh + + sizeof (struct ospf6_header)); - /* set LSA summary to send buffer */ - OSPF6_MESSAGE_ATTACH (message, lsa->header, - sizeof (struct ospf6_lsa_header)); - } + p = (char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); + num = 0; - if (o6n->summary_list->count == 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) { - /* 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); - } + ospf6_lsa_unlock (lsa); + break; } - } - - /* 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); + if (IS_OSPF6_DEBUG_LSA (SEND)) + ospf6_lsa_header_print (lsa); - /* send dbdesc */ - ospf6_message_send (OSPF6_MESSAGE_TYPE_DBDESC, message, &o6n->hisaddr, - o6n->ospf6_interface->interface->ifindex); + 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++; - /* 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); + assert (lsa->lock == 2); + ospf6_lsdb_remove (lsa, oi->lsupdate_list); + } - /* statistics */ - o6n->lsa_send[OSPF6_MESSAGE_TYPE_DBDESC] += o6n->dbdesc_list->count; + lsupdate->lsa_number = htonl (num); - return 0; -} + oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE; + oh->length = htons (p - sendbuf); -int -ospf6_send_lsreq_rxmt (struct thread *thread) -{ - struct ospf6_neighbor *o6n; + 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); - o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); - assert (o6n); + if (oi->lsupdate_list->count > 0) + { + oi->thread_send_lsupdate = + thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0); + } - 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) +ospf6_lsack_send_neighbor (struct thread *thread) { - struct ospf6_neighbor *o6n; - struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; - struct ospf6_lsreq lsreq[OSPF6_MESSAGE_IOVEC_SIZE]; + struct ospf6_neighbor *on; + struct ospf6_header *oh; + char *p; struct ospf6_lsa *lsa; - struct ospf6_lsdb_node node; - int i; - - o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); - assert (o6n); - - /* LSReq will be send only in ExStart or Loading */ - if (o6n->state != NBS_EXCHANGE && o6n->state != NBS_LOADING) - return 0; - /* 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; + on = (struct ospf6_neighbor *) THREAD_ARG (thread); + on->thread_send_lsack = (struct thread *) NULL; - /* schedule loading_done if request list is empty */ - if (o6n->request_list->count == 0) + if (on->state < OSPF6_NEIGHBOR_EXCHANGE) { - thread_add_event (master, loading_done, o6n, 0); + 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; } - /* 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)) - { - lsa = node.lsa; + /* if we have nothing to send, return */ + if (on->lsack_list->count == 0) + return 0; - /* Buffer Overflow */ - if (i >= OSPF6_MESSAGE_IOVEC_SIZE) - break; + memset (sendbuf, 0, sizeof (sendbuf)); + oh = (struct ospf6_header *) sendbuf; - /* I/F MTU check */ - if (OSPF6_MESSAGE_LENGTH (message) - + sizeof (struct ospf6_lsreq) - + sizeof (struct ospf6_header) - > o6n->ospf6_interface->ifmtu) - break; + p = (char *)((caddr_t) oh + sizeof (struct ospf6_header)); - lsreq[i].mbz = 0; - lsreq[i].type = lsa->header->type; - lsreq[i].id = lsa->header->id; - lsreq[i].adv_router = lsa->header->adv_router; + 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_MESSAGE_ATTACH (message, &lsreq[i], sizeof (struct ospf6_lsreq)); - i++; - } + ospf6_lsa_unlock (lsa); + break; + } - ospf6_message_send (OSPF6_MESSAGE_TYPE_LSREQ, message, &o6n->hisaddr, - o6n->ospf6_interface->interface->ifindex); + 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); - /* set retransmit thread */ - o6n->thread_rxmt_lsreq = - thread_add_timer (master, ospf6_send_lsreq_rxmt, - o6n, o6n->ospf6_interface->rxmt_interval); + assert (lsa->lock == 2); + ospf6_lsdb_remove (lsa, on->lsack_list); + } - /* statistics */ - o6n->lsa_send[OSPF6_MESSAGE_TYPE_LSREQ] += i; + 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; } -/* Send LSUpdate directly to the neighbor, from his retransmission list */ int -ospf6_send_lsupdate_rxmt (struct thread *thread) +ospf6_lsack_send_interface (struct thread *thread) { - struct ospf6_neighbor *o6n; - struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; - struct ospf6_lsupdate lsupdate; + struct ospf6_interface *oi; + struct ospf6_header *oh; + char *p; struct ospf6_lsa *lsa; - struct ospf6_lsdb_node node; - o6n = (struct ospf6_neighbor *) THREAD_ARG (thread); - assert (o6n); + oi = (struct ospf6_interface *) THREAD_ARG (thread); + oi->thread_send_lsack = (struct thread *) NULL; - o6n->send_update = (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 (o6n->ospf6_interface->state <= IFS_WAITING) - return -1; + /* if we have nothing to send, return */ + if (oi->lsack_list->count == 0) + return 0; - /* clear message buffer */ - OSPF6_MESSAGE_CLEAR (message); + memset (sendbuf, 0, sizeof (sendbuf)); + oh = (struct ospf6_header *) sendbuf; - /* set lsupdate header */ - lsupdate.lsupdate_num = 0; /* set gradually */ - OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate)); + p = (char *)((caddr_t) oh + sizeof (struct ospf6_header)); - /* for each LSA listed on retransmission-list */ - for (ospf6_lsdb_head (&node, o6n->retrans_list); - ! ospf6_lsdb_is_end (&node); - ospf6_lsdb_next (&node)) + for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa; + lsa = ospf6_lsdb_next (lsa)) { - lsa = node.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); - /* 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_unlock (lsa); + 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++; - } + ospf6_lsa_age_update_to_send (lsa, oi->transdelay); + memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header)); + p += sizeof (struct ospf6_lsa_header); - /* check and correct lsupdate */ - if (lsupdate.lsupdate_num == 0) - return 0; - lsupdate.lsupdate_num = htonl (lsupdate.lsupdate_num); + assert (lsa->lock == 2); + ospf6_lsdb_remove (lsa, oi->lsack_list); + } - if (IS_OSPF6_DUMP_LSUPDATE) - zlog_info ("MESSAGE: retrsnsmit LSUpdate to %s", o6n->str); + oh->type = OSPF6_MESSAGE_TYPE_LSACK; + oh->length = htons (p - sendbuf); - /* statistics */ - o6n->ospf6_stat_retrans_lsupdate++; + 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); - ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message, - &o6n->hisaddr, o6n->ospf6_interface->if_id); + 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); + } - 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) + +/* 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" + ) { - struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; - struct ospf6_lsupdate lsupdate; - int lsa_len; - - /* clear message buffer */ - OSPF6_MESSAGE_CLEAR (message); + unsigned char level = 0; + int type = 0; + int i; - /* set lsupdate header */ - lsupdate.lsupdate_num = ntohl (1); - OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate)); + assert (argc > 0); - /* 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); + /* 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_ON (i, level); + } + else + OSPF6_DEBUG_MESSAGE_ON (type, level); - ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message, &o6n->hisaddr, - o6n->ospf6_interface->if_id); + return CMD_SUCCESS; } -/* 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); +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" + ); - /* set lsupdate header */ - lsupdate.lsupdate_num = ntohl (1); - OSPF6_MESSAGE_ATTACH (message, &lsupdate, sizeof (struct ospf6_lsupdate)); + +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; - /* 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); + assert (argc > 0); - if (if_is_broadcast (o6i->interface)) + /* 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) { - /* set destination */ - if (o6i->state == IFS_DR || o6i->state == IFS_BDR) - inet_pton (AF_INET6, ALLSPFROUTERS6, &dst); - else - inet_pton (AF_INET6, ALLDROUTERS6, &dst); + for (i = 0; i < 6; i++) + OSPF6_DEBUG_MESSAGE_OFF (i, level); } else - { - /* IPv6 relies on link local multicast */ - inet_pton (AF_INET6, ALLSPFROUTERS6, &dst); - } + OSPF6_DEBUG_MESSAGE_OFF (type, level); - ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, message, &dst, - o6i->if_id); + 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 -ospf6_send_lsack_delayed (struct thread *thread) +config_write_ospf6_debug_message (struct vty *vty) { - 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; + char *type_str[] = {"unknown", "hello", "dbdesc", + "lsreq", "lsupdate", "lsack"}; + unsigned char s = 0, r = 0; + int i; - iov_clear (message, MAXIOVLIST); + 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; + } - for (ospf6_lsdb_head (&node, o6i->ack_list); - ! ospf6_lsdb_is_end (&node); - ospf6_lsdb_next (&node)) + if (s == 0x3f && r == 0x3f) { - lsa = node.lsa; - if (IS_OVER_MTU (message, o6i->ifmtu, sizeof (struct ospf6_lsa_hdr))) - break; + vty_out (vty, "debug ospf6 message all%s", VTY_NEWLINE); + return 0; + } - OSPF6_MESSAGE_ATTACH (message, lsa->header, - sizeof (struct ospf6_lsa_header)); - ospf6_interface_delayed_ack_remove (lsa, o6i); + if (s == 0x3f && r == 0) + { + 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; } - /* statistics */ - o6i->ospf6_stat_delayed_lsack++; + /* 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); - switch (o6i->state) + for (i = 1; i < 6; i++) { - 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; + 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); } - iov_clear (message, MAXIOVLIST); return 0; } +void +install_element_ospf6_debug_message () +{ + 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); +} + + diff --git a/ospf6d/ospf6_message.h b/ospf6d/ospf6_message.h index 105cb4f0..f8be627b 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 @@ struct ospf6_lsreq /* 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.*/ - -/* definition for ospf6_message.c */ -#define OSPF6_MESSAGE_RECEIVE_BUFSIZE 5120 -#define OSPF6_MESSAGE_IOVEC_END 1024 - -#define IS_OVER_MTU(message,mtu,addsize) \ - (iov_totallen(message)+(addsize) >= \ - (mtu)-sizeof(struct ospf6_header)) - -#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) - -#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); +/* It is just a sequence of LSA Headers */ + +/* 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 *); + +int ospf6_receive (struct thread *thread); + +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); + +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 72735d5d..acfd1a42 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 #include "log.h" +#include "memory.h" #include "thread.h" #include "linklist.h" #include "vty.h" #include "command.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_nsm.h" -#include "ospf6_lsa.h" -#include "ospf6_lsdb.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; - - 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; -} + listnode n; + struct ospf6_neighbor *on; -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); + for (n = listhead (oi->neighbor_list); n; nextnode (n)) + { + on = (struct ospf6_neighbor *) getdata (n); + if (on->router_id == router_id) + return on; + } + return (struct ospf6_neighbor *) NULL; } -void -ospf6_neighbor_summary_add (struct ospf6_lsa *lsa, - struct ospf6_neighbor *nei) +/* create ospf6_neighbor */ +struct ospf6_neighbor * +ospf6_neighbor_create (u_int32_t router_id, struct ospf6_interface *oi) { - struct ospf6_lsa *summary; + struct ospf6_neighbor *on; + char buf[16]; - if (IS_OSPF6_DUMP_NEIGHBOR) + on = (struct ospf6_neighbor *) + XMALLOC (MTYPE_OSPF6_NEIGHBOR, sizeof (struct ospf6_neighbor)); + if (on == NULL) { - zlog_info ("Neighbor %s summary-list:", nei->str); - zlog_info (" Add %s", lsa->str); + zlog_warn ("neighbor: malloc failed"); + return NULL; } - ospf6_lsa_age_current (lsa); - summary = ospf6_lsa_summary_create (lsa->header); - ospf6_lsdb_add (summary, nei->summary_list); + memset (on, 0, sizeof (struct ospf6_neighbor)); + inet_ntop (AF_INET, &router_id, buf, sizeof (buf)); + 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; + + on->summary_list = ospf6_lsdb_create (); + on->request_list = ospf6_lsdb_create (); + on->retrans_list = ospf6_lsdb_create (); + + on->dbdesc_list = ospf6_lsdb_create (); + on->lsreq_list = ospf6_lsdb_create (); + on->lsupdate_list = ospf6_lsdb_create (); + on->lsack_list = ospf6_lsdb_create (); + + listnode_add_sort (oi->neighbor_list, on); + return on; } void -ospf6_neighbor_summary_remove (struct ospf6_lsa *lsa, - struct ospf6_neighbor *nei) +ospf6_neighbor_delete (struct ospf6_neighbor *on) { - struct ospf6_lsa *summary; + ospf6_lsdb_remove_all (on->summary_list); + ospf6_lsdb_remove_all (on->request_list); + ospf6_lsdb_remove_all (on->retrans_list); - if (IS_OSPF6_DUMP_NEIGHBOR) - { - zlog_info ("Neighbor %s summary-list:", nei->str); - zlog_info (" Remove %s", lsa->str); - } + 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); + + ospf6_lsdb_delete (on->summary_list); + ospf6_lsdb_delete (on->request_list); + ospf6_lsdb_delete (on->retrans_list); - 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); + ospf6_lsdb_delete (on->dbdesc_list); + ospf6_lsdb_delete (on->lsreq_list); + ospf6_lsdb_delete (on->lsupdate_list); + ospf6_lsdb_delete (on->lsack_list); + + 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); } -void -ospf6_neighbor_request_add (struct ospf6_lsa *lsa, - struct ospf6_neighbor *nei) +static void +ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on) { - struct ospf6_lsa *summary; + u_char prev_state; - if (IS_OSPF6_DUMP_NEIGHBOR) + 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)) { - zlog_info ("Neighbor %s request-list:", nei->str); - zlog_info (" Add %s", lsa->str); + zlog_info ("Neighbor state change %s: [%s]->[%s]", on->name, + ospf6_neighbor_state_str[prev_state], + ospf6_neighbor_state_str[next_state]); } - ospf6_lsa_age_current (lsa); - summary = ospf6_lsa_summary_create (lsa->header); - ospf6_lsdb_add (summary, nei->request_list); -} + 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); + } + } -void -ospf6_neighbor_request_remove (struct ospf6_lsa *lsa, - struct ospf6_neighbor *nei) -{ - struct ospf6_lsa *summary; +#ifdef XXX + if (prev_state == NBS_FULL || next_state == NBS_FULL) + nbs_full_change (on->ospf6_interface); - if (IS_OSPF6_DUMP_NEIGHBOR) + /* 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)) { - zlog_info ("Neighbor %s request-list:", nei->str); - zlog_info (" Remove %s", lsa->str); + ospf6_maxage_remover (); } +#endif /*XXX*/ - 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) +/* RFC2328 section 10.4 */ +int +need_adjacency (struct ospf6_neighbor *on) { - if (IS_OSPF6_DUMP_NEIGHBOR) - { - zlog_info ("Neighbor %s retrans-list:", nei->str); - zlog_info (" Add %s", lsa->str); - } + if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT || + on->ospf6_if->state == OSPF6_INTERFACE_DR || + on->ospf6_if->state == OSPF6_INTERFACE_BDR) + return 1; - ospf6_lsdb_add (lsa, nei->retrans_list); + if (on->ospf6_if->drouter == on->router_id || + on->ospf6_if->bdrouter == on->router_id) + return 1; + + return 0; } -void -ospf6_neighbor_retrans_remove (struct ospf6_lsa *lsa, - struct ospf6_neighbor *nei) +int +hello_received (struct thread *thread) { - if (IS_OSPF6_DUMP_NEIGHBOR) - { - zlog_info ("Neighbor %s retrans-list:", nei->str); - zlog_info (" Remove %s", lsa->str); - } + struct ospf6_neighbor *on; - ospf6_lsdb_remove (lsa, nei->retrans_list); + on = (struct ospf6_neighbor *) THREAD_ARG (thread); + assert (on); - if (nei->retrans_list->count == 0) - { - if (nei->send_update) - thread_cancel (nei->send_update); - nei->send_update = NULL; - } + 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; } -void -ospf6_neighbor_dbdesc_add (struct ospf6_lsa *lsa, - struct ospf6_neighbor *nei) +int +twoway_received (struct thread *thread) { - if (IS_OSPF6_DUMP_NEIGHBOR) + 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)) { - zlog_info ("Neighbor %s dbdesc-list:", nei->str); - zlog_info (" Add %s", lsa->str); + ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on); + return 0; } - ospf6_lsdb_add (lsa, nei->dbdesc_list); + 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; } -void -ospf6_neighbor_dbdesc_remove (struct ospf6_lsa *lsa, - struct ospf6_neighbor *nei) +int +negotiation_done (struct thread *thread) { - if (IS_OSPF6_DUMP_NEIGHBOR) - { - zlog_info ("Neighbor %s dbdesc-list:", nei->str); - zlog_info (" Remove %s", lsa->str); - } + struct ospf6_neighbor *on; + struct ospf6_lsa *lsa; - ospf6_lsdb_remove (lsa, nei->dbdesc_list); -} + on = (struct ospf6_neighbor *) THREAD_ARG (thread); + assert (on); + if (on->state != OSPF6_NEIGHBOR_EXSTART) + return 0; -/* prepare summary-list of his neighbor structure */ -void -ospf6_neighbor_dbex_init (struct ospf6_neighbor *nei) -{ - struct ospf6_lsdb_node node; + if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) + zlog_info ("Neighbor Event %s: *NegotiationDone*", on->name); /* clear ls-list */ - ospf6_neighbor_lslist_clear (nei); + ospf6_lsdb_remove_all (on->summary_list); + ospf6_lsdb_remove_all (on->request_list); + ospf6_lsdb_remove_all (on->retrans_list); - /* AS scope LSAs */ - for (ospf6_lsdb_head (&node, nei->ospf6_interface->area->ospf6->lsdb); - ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node)) + /* Interface scoped LSAs */ + for (lsa = ospf6_lsdb_head (on->ospf6_if->lsdb); lsa; + lsa = ospf6_lsdb_next (lsa)) { - if (IS_LSA_MAXAGE (node.lsa)) - ospf6_neighbor_retrans_add (node.lsa, nei); + 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_neighbor_summary_add (node.lsa, nei); + ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->summary_list); } - /* AREA scope LSAs */ - for (ospf6_lsdb_head (&node, nei->ospf6_interface->area->lsdb); - ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node)) + /* Area scoped LSAs */ + for (lsa = ospf6_lsdb_head (on->ospf6_if->area->lsdb); lsa; + lsa = ospf6_lsdb_next (lsa)) { - if (IS_LSA_MAXAGE (node.lsa)) - ospf6_neighbor_retrans_add (node.lsa, nei); + 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_neighbor_summary_add (node.lsa, nei); + ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->summary_list); } - /* INTERFACE scope LSAs */ - for (ospf6_lsdb_head (&node, nei->ospf6_interface->lsdb); - ! ospf6_lsdb_is_end (&node); ospf6_lsdb_next (&node)) + /* AS scoped LSAs */ + for (lsa = ospf6_lsdb_head (on->ospf6_if->area->ospf6->lsdb); lsa; + lsa = ospf6_lsdb_next (lsa)) { - if (IS_LSA_MAXAGE (node.lsa)) - ospf6_neighbor_retrans_add (node.lsa, nei); + 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_neighbor_summary_add (node.lsa, nei); + 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; } -/* create ospf6_neighbor */ -struct ospf6_neighbor * -ospf6_neighbor_create (u_int32_t router_id, struct ospf6_interface *o6i) +int +exchange_done (struct thread *thread) { - struct ospf6_neighbor *new; - char buf[32]; + struct ospf6_neighbor *on; - new = (struct ospf6_neighbor *) - XMALLOC (MTYPE_OSPF6_NEIGHBOR, sizeof (struct ospf6_neighbor)); - if (new == NULL) + 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)) { - zlog_warn ("neighbor: malloc failed"); - return NULL; + 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); } - memset (new, 0, sizeof (struct ospf6_neighbor)); + return 0; +} - new->state = OSPF6_NEIGHBOR_STATE_DOWN; +int +seqnumber_mismatch (struct thread *thread) +{ + struct ospf6_neighbor *on; - new->router_id = router_id; - 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; + on = (struct ospf6_neighbor *) THREAD_ARG (thread); + assert (on); - new->summary_list = ospf6_lsdb_create (); - new->request_list = ospf6_lsdb_create (); - new->retrans_list = ospf6_lsdb_create (); - new->dbdesc_list = ospf6_lsdb_create (); + if (on->state < OSPF6_NEIGHBOR_EXCHANGE) + return 0; - listnode_add (o6i->neighbor_list, new); - new->ospf6_interface = o6i; + if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) + zlog_info ("Neighbor Event %s: *SeqNumberMismatch*", on->name); - CALL_ADD_HOOK (&neighbor_hook, new); + 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); - return new; + 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; } -void -ospf6_neighbor_delete (struct ospf6_neighbor *o6n) +int +bad_lsreq (struct thread *thread) { - CALL_REMOVE_HOOK (&neighbor_hook, o6n); + struct ospf6_neighbor *on; + + on = (struct ospf6_neighbor *) THREAD_ARG (thread); + assert (on); + + if (on->state < OSPF6_NEIGHBOR_EXCHANGE) + return 0; - ospf6_neighbor_thread_cancel_all (o6n); - ospf6_neighbor_lslist_clear (o6n); + if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) + zlog_info ("Neighbor Event %s: *BadLSReq*", on->name); - list_free (o6n->dbdesc_lsa); + 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_delete (o6n->summary_list); - ospf6_lsdb_delete (o6n->request_list); - ospf6_lsdb_delete (o6n->retrans_list); - ospf6_lsdb_delete (o6n->dbdesc_list); + ospf6_lsdb_remove_all (on->summary_list); + ospf6_lsdb_remove_all (on->request_list); + ospf6_lsdb_remove_all (on->retrans_list); - XFREE (MTYPE_OSPF6_NEIGHBOR, o6n); + THREAD_OFF (on->thread_send_dbdesc); + on->thread_send_dbdesc = + thread_add_event (master, ospf6_dbdesc_send, on, 0); + + return 0; } -struct ospf6_neighbor * -ospf6_neighbor_lookup (u_int32_t router_id, - struct ospf6_interface *o6i) +int +oneway_received (struct thread *thread) { - listnode n; - struct ospf6_neighbor *o6n; + struct ospf6_neighbor *on; - for (n = listhead (o6i->neighbor_list); n; nextnode (n)) - { - o6n = (struct ospf6_neighbor *) getdata (n); - if (o6n->router_id == router_id) - return o6n; - } - return (struct ospf6_neighbor *) NULL; + 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 @@ ospf6_neighbor_show_summary (struct vty *vty, struct ospf6_neighbor *o6n) "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, &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)); - inet_ntop (AF_INET6, &o6n->hisaddr, hisaddr, sizeof (hisaddr)); - vty_out (vty, " Neighbor %s, interface address %s%s", - o6n->str, hisaddr, VTY_NEWLINE); + gettimeofday (&now, NULL); + timersub (&now, &on->last_changed, &res); + timerstring (&res, duration, sizeof (duration)); + + vty_out (vty, " Neighbor %s%s", on->name, + 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, + 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, " Priority: %d, State: %s, %d state changes%s", - o6n->priority, ospf6_neighbor_state_string[o6n->state], - o6n->ospf6_stat_state_changed, VTY_NEWLINE); - 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); -} + 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); -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, " 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, " %-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, " %-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, " 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", +DEFUN (show_ipv6_ospf6_neighbor, + show_ipv6_ospf6_neighbor_cmd, + "show ipv6 ospf6 neighbor", 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; + 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 (); + 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 (argc == 0) + 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); - 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)) + for (i = listhead (ospf6->area_list); i; nextnode (i)) { - o6a = getdata (nodei); - for (nodej = listhead (o6a->if_list); nodej; nextnode (nodej)) + oa = (struct ospf6_area *) getdata (i); + for (j = listhead (oa->if_list); j; nextnode (j)) { - o6i = getdata (nodej); - for (nodek = listhead (o6i->neighbor_list); nodek; nextnode (nodek)) + oi = (struct ospf6_interface *) getdata (j); + for (k = listhead (oi->neighbor_list); k; nextnode (k)) { - 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); + on = (struct ospf6_neighbor *) getdata (k); + (*showfunc) (vty, on); } } } return CMD_SUCCESS; } -ALIAS (show_ipv6_ospf6_neighbor_routerid, - show_ipv6_ospf6_neighbor_cmd, - "show ipv6 ospf6 neighbor", +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_neighborlist, - show_ipv6_ospf6_neighborlist_cmd, - "show ipv6 ospf6 (summary-list|request-list|retrans-list|dbdesc-list)", +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 - "Link State summary list\n" - "Link State request list\n" - "Link State retransmission list\n" - "Link State Description list (Used to retrans DbDesc)\n" - ) + "Neighbor list\n" + "Specify Router-ID as IPv4 address notation\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 *); + u_int32_t router_id; OSPF6_CMD_CHECK_RUNNING (); - i = j = k = l = NULL; + 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)) { - 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); + if (on->router_id == router_id) + (*showfunc) (vty, on); } } } - return CMD_SUCCESS; } @@ -591,12 +836,104 @@ void 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 c3821c67..441ab81c 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 DD , including OSPF capability of this neighbor */ - struct ospf6_dbdesc last_dd; + /* Last received Database Description packet */ + struct ospf6_dbdesc dbdesc_last; - /* LSAs to retransmit to this neighbor */ - list dbdesc_lsa; + /* LS-list */ + struct ospf6_lsdb *summary_list; + struct ospf6_lsdb *request_list; + struct ospf6_lsdb *retrans_list; - /* placeholder for DbDesc */ - struct iovec dbdesc_last_send[1024]; + /* 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; + /* 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 *); - -void -ospf6_neighbor_lslist_clear (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 *); +int ospf6_neighbor_cmp (void *va, void *vb); +void ospf6_neighbor_dbex_init (struct ospf6_neighbor *on); + +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 *); + +/* 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 ece34135..b4f37f6a 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,212 +20,106 @@ */ #include -#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); +int ospf6_sock; +struct in6_addr allspfrouters6; +struct in6_addr alldrouters6; - /* 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) +/* setsockopt ReUseAddr to on */ +void +ospf6_set_reuseaddr () { - 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; + u_int on = 0; + if (setsockopt (ospf6_sock, SOL_SOCKET, SO_REUSEADDR, &on, + sizeof (u_int)) < 0) + zlog_warn ("Network: set SO_REUSEADDR failed: %s", strerror (errno)); } +/* setsockopt MulticastLoop to off */ void -iov_trim_head (int mtype, struct iovec *iov) +ospf6_reset_mcastloop () { - void *base; - - base = iov_detach_first (iov); - XFREE (mtype, base); - return; + u_int off = 0; + if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, + &off, sizeof (u_int)) < 0) + zlog_warn ("Network: reset IPV6_MULTICAST_LOOP failed: %s", + strerror (errno)); } void -iov_free_all (int mtype, struct iovec *iov) +ospf6_set_pktinfo () { - 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; - } + u_int on = 1; +#ifdef IPV6_RECVPKTINFO /*2292bis-01*/ + if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, + &on, sizeof (u_int)) < 0) + zlog_warn ("Network: set IPV6_RECVPKTINFO failed: %s", strerror (errno)); +#else /*RFC2292*/ + if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_PKTINFO, + &on, sizeof (u_int)) < 0) + zlog_warn ("Network: set IPV6_PKTINFO failed: %s", strerror (errno)); +#endif } void -iov_copy_all (struct iovec *dst, struct iovec *src, size_t size) +ospf6_set_checksum () { - int i; - for (i = 0; i < size; i++) - { - dst[i].iov_base = src[i].iov_base; - dst[i].iov_len = src[i].iov_len; - } + int offset = 12; +#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)); +#else + zlog_warn ("Network: Don't set IPV6_CHECKSUM"); +#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"); - + 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; } - 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); + + /* 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; } -/* returns 0 if succeed, else returns -1 */ -int +void ospf6_join_allspfrouters (u_int ifindex) { struct ipv6_mreq mreq6; @@ -233,7 +127,7 @@ ospf6_join_allspfrouters (u_int ifindex) assert (ifindex); mreq6.ipv6mr_interface = ifindex; - memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6.sin6_addr, + memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6, sizeof (struct in6_addr)); retval = setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, @@ -241,13 +135,11 @@ ospf6_join_allspfrouters (u_int ifindex) if (retval < 0) zlog_err ("Network: Join AllSPFRouters on ifindex %d failed: %s", - ifindex, strerror (errno)); + ifindex, strerror (errno)); #if 0 else zlog_info ("Network: Join AllSPFRouters on ifindex %d", ifindex); #endif - - return retval; } void @@ -257,15 +149,17 @@ ospf6_leave_allspfrouters (u_int ifindex) assert (ifindex); mreq6.ipv6mr_interface = ifindex; - memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6.sin6_addr, + 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 @@ -275,15 +169,17 @@ ospf6_join_alldrouters (u_int ifindex) assert (ifindex); mreq6.ipv6mr_interface = ifindex; - memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6.sin6_addr, + 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 @@ -293,66 +189,38 @@ ospf6_leave_alldrouters (u_int ifindex) assert (ifindex); mreq6.ipv6mr_interface = ifindex; - memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6.sin6_addr, + 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 } -/* setsockopt ReUseAddr to on */ -void -ospf6_set_reuseaddr () -{ - u_int on = 0; - if (setsockopt (ospf6_sock, SOL_SOCKET, SO_REUSEADDR, &on, - sizeof (u_int)) < 0) - zlog_warn ("Network: set SO_REUSEADDR failed: %s", strerror (errno)); -} - -/* setsockopt MulticastLoop to off */ -void -ospf6_reset_mcastloop () -{ - u_int off = 0; - if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, - &off, sizeof (u_int)) < 0) - zlog_warn ("Network: reset IPV6_MULTICAST_LOOP failed: %s", - strerror (errno)); -} - -void -ospf6_set_pktinfo () +int +iov_count (struct iovec *iov) { - u_int on = 1; -#ifdef IPV6_RECVPKTINFO /*2292bis-01*/ - if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, - &on, sizeof (u_int)) < 0) - zlog_warn ("Network: set IPV6_RECVPKTINFO failed: %s", strerror (errno)); -#else /*RFC2292*/ - if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_PKTINFO, - &on, sizeof (u_int)) < 0) - zlog_warn ("Network: set IPV6_PKTINFO failed: %s", strerror (errno)); -#endif + int i; + for (i = 0; iov[i].iov_base; i++) + ; + return i; } -void -ospf6_set_checksum () +int +iov_totallen (struct iovec *iov) { - int offset = 12; -#if !defined(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)); -#else - zlog_warn ("Network: Don't set IPV6_CHECKSUM"); -#endif /* DISABLE_IPV6_CHECKSUM */ + int i; + int totallen = 0; + for (i = 0; iov[i].iov_base; i++) + totallen += iov[i].iov_len; + return totallen; } -void +int ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst, unsigned int *ifindex, struct iovec *message) { @@ -403,11 +271,13 @@ ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst, 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 @@ ospf6_recvmsg (struct in6_addr *src, struct in6_addr *dst, 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 @@ ospf6_recvmsg (struct in6_addr *src, struct in6_addr *dst, *ifindex = pktinfo->ipi6_ifindex; if (dst) memcpy (dst, &pktinfo->ipi6_addr, sizeof (struct in6_addr)); -} - -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)); + return retval; } + diff --git a/ospf6d/ospf6_network.h b/ospf6d/ospf6_network.h index 934cce59..9a4d795e 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 @@ +extern int ospf6_sock; +extern struct in6_addr allspfrouters6; +extern struct in6_addr alldrouters6; + /* 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); +void ospf6_set_reuseaddr (); +void ospf6_reset_mcastloop (); +void ospf6_set_pktinfo (); +void ospf6_set_checksum (); int ospf6_serv_sock (); -int ospf6_join_allspfrouters (u_int); + +void ospf6_join_allspfrouters (u_int); void ospf6_leave_allspfrouters (u_int); void ospf6_join_alldrouters (u_int); void ospf6_leave_alldrouters (u_int); -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_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 aa08d40b..00000000 --- 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 d70f1e88..00000000 --- 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 1542200c..00000000 --- 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 - -#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 65a8cbc8..00000000 --- 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 71e575f1..7ee7e0a7 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 +#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) { - char *dc, *r, *n, *mc, *e, *v6; + 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); +} - 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; +void +ospf6_options_printbuf (char *options, char *buf, int size) +{ + char *dc, *r, *n, *mc, *e, *v6; + 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 9a95444a..447513a7 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 */ + +/* 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) -char * -ospf6_options_string (u_char opt_capability[3], char *buffer, int size); +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 b3abedc3..73bdac2d 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 + +#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] = -{ - "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]) +unsigned char conf_debug_ospf6_route = 0; - +void +ospf6_linkstate_prefix (u_int32_t adv_router, u_int32_t id, + struct prefix *prefix) +{ + 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_path_cmp (void *arg1, void *arg2) +void +ospf6_linkstate_prefix2str (struct prefix *prefix, char *buf, int size) { - struct ospf6_path_node *pn1 = arg1; - struct ospf6_path_node *pn2 = arg2; - struct ospf6_path *p1 = &pn1->path; - struct ospf6_path *p2 = &pn2->path; + 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)); +} - if (p1->type < p2->type) - return -1; - else if (p1->type > p2->type) - return 1; +/* Global strings for logging */ +char *ospf6_dest_type_str[OSPF6_DEST_TYPE_MAX] = +{ "Unknown", "Router", "Network", "Discard", "Linkstate", }; - 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; - } +char *ospf6_dest_type_substr[OSPF6_DEST_TYPE_MAX] = +{ "?", "R", "N", "D", "L", }; - if (p1->cost < p2->cost) - return -1; - else if (p1->cost > p2->cost) - return 1; +char *ospf6_path_type_str[OSPF6_PATH_TYPE_MAX] = +{ "Unknown", "Intra-Area", "Inter-Area", "External-1", "External-2", }; - /* 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; +char *ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX] = +{ "??", "Ia", "Ie", "E1", "E2", }; - /* else, always prefer left */ - return -1; -} -int -ospf6_nexthop_cmp (void *arg1, void *arg2) +struct ospf6_route * +ospf6_route_create () { - 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; + struct ospf6_route *route; + route = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route)); + return route; +} - return ret; +void +ospf6_route_delete (struct ospf6_route *route) +{ + XFREE (MTYPE_OSPF6_ROUTE, route); } -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) +struct ospf6_route * +ospf6_route_copy (struct ospf6_route *route) { - assert (request); - assert (rn && pn && nn); + 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; +} - request->route_node = rn->route_node; +void +ospf6_route_lock (struct ospf6_route *route) +{ + route->lock++; +} - 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; +void +ospf6_route_unlock (struct ospf6_route *route) +{ + assert (route->lock > 0); + route->lock--; + if (route->lock == 0) + ospf6_route_delete (route); +} - 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); +/* 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); - for (linklist_head (rn->path_list, &node); ! linklist_end (&node); - linklist_next (&node)) - { - struct ospf6_path_node *pn2 = node.data; + if (ra->type != rb->type) + return (ra->type - rb->type); - zlog_info (" %p: path data with pn(%p): %s", pn2, pn, - (memcmp (&pn->path, &pn2->path, - sizeof (struct ospf6_path)) ? - "different" : "same")); + if (ra->path.area_id != rb->path.area_id) + return (ntohl (ra->path.area_id) - ntohl (rb->path.area_id)); - 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 (ra->path.type != rb->path.type) + return (ra->path.type - rb->path.type); - if (! memcmp (&pn->path, &pn2->path, sizeof (struct ospf6_path))) - { - pn = pn2; - request->nexthop_lnode.data = pn2; - } - } - break; - } - linklist_next (&request->path_lnode); + 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); } - assert (request->path_lnode.data == pn); - - linklist_head (pn->nexthop_list, &request->nexthop_lnode); - while (request->nexthop_lnode.data != nn) + else { - assert (! linklist_end (&request->nexthop_lnode)); - linklist_next (&request->nexthop_lnode); + if (ra->path.cost != rb->path.cost) + return (ra->path.cost - rb->path.cost); } - 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)); -} -int -ospf6_route_count (struct ospf6_route_req *request) -{ - return request->count; + return 0; } -int -ospf6_route_lookup (struct ospf6_route_req *request, - struct prefix *prefix, +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; + + route = (struct ospf6_route *) node->info; + return route; +} - rn = (struct ospf6_route_node *) node->info; - if (! rn) - return 0; +struct ospf6_route * +ospf6_route_lookup_identical (struct ospf6_route *route, + struct ospf6_route_table *table) +{ + struct ospf6_route *target; - if (request) + for (target = ospf6_route_lookup (&route->prefix, table); + target; target = target->next) { - 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); + if (ospf6_route_is_identical (target, route)) + return target; } - - return 1; + return NULL; } -void -ospf6_route_head (struct ospf6_route_req *request, - struct ospf6_route_table *table) +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 * +ospf6_route_add (struct ospf6_route *route, + struct ospf6_route_table *table) { - struct ospf6_route_node *route_node = NULL; - struct ospf6_path_node *path_node = NULL; - struct ospf6_nexthop_node *nexthop_node = NULL; + 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; + + assert (route->rnode == NULL); + assert (route->lock == 0); + assert (route->next == NULL); + assert (route->prev == NULL); + + if (route->type == OSPF6_DEST_TYPE_LINKSTATE) + ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf)); + else + prefix2str (&route->prefix, buf, sizeof (buf)); - 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); - } - } + if (IS_OSPF6_DEBUG_ROUTE (TABLE)) + zlog_info ("route add %s", buf); - path_node = request->path_lnode.data; - if (path_node) - linklist_head (path_node->nexthop_list, &request->nexthop_lnode); - } + gettimeofday (&now, NULL); - nexthop_node = request->nexthop_lnode.data; + node = route_node_get (table->table, &route->prefix); + route->rnode = node; - if (nexthop_node == NULL) + /* find place to insert */ + for (current = node->info; current; current = current->next) { - assert (path_node == NULL); - assert (route_node == NULL); + 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; - memset (&request->route, 0, sizeof (struct ospf6_route)); - memset (&request->path, 0, sizeof (struct ospf6_path)); - memset (&request->nexthop, 0, sizeof (struct ospf6_nexthop)); + if (old || next) + break; } - else + + if (old) { - 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)); - } -} + /* 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"); -#define ADD 0 -#define CHANGE 1 -#define REMOVE 2 + ospf6_route_delete (route); + SET_FLAG (old->flag, OSPF6_ROUTE_ADD); + ospf6_route_count_assert (table); + return old; + } -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 *); + if (IS_OSPF6_DEBUG_ROUTE (TABLE)) + zlog_info (" old route found, replace"); - for (linklist_head (table->hook_list[type], &node); - ! linklist_end (&node); - linklist_next (&node)) - { - func = node.data; - (*func) (request); - } -} + /* replace old one if exists */ + if (node->info == old) + { + node->info = route; + SET_FLAG (route->flag, OSPF6_ROUTE_BEST); + } -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]); -} + if (old->prev) + old->prev->next = route; + route->prev = old->prev; + if (old->next) + old->next->prev = route; + route->next = old->next; -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]); -} + route->installed = old->installed; + route->changed = now; + ospf6_route_unlock (old); /* will be deleted later */ + ospf6_route_lock (route); -int -prefix_ls2str (struct prefix *p, char *str, int size) -{ - char id[BUFSIZ], adv_router[BUFSIZ]; - struct prefix_ls *pl = (struct prefix_ls *) p; + SET_FLAG (route->flag, OSPF6_ROUTE_CHANGE); + if (table->hook_add) + (*table->hook_add) (route); - 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; -} + ospf6_route_count_assert (table); + return route; + } -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)); -} + /* 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); + } -struct ospf6_path_node * -ospf6_route_find_path_node (struct ospf6_route_req *request, - struct ospf6_route_node *rn) -{ - struct linklist_node node; + route->installed = now; + route->changed = now; - for (linklist_head (rn->path_list, &node); ! linklist_end (&node); - linklist_next (&node)) - { - struct ospf6_path_node *path_node = node.data; + ospf6_route_lock (route); + table->count++; + + SET_FLAG (route->flag, OSPF6_ROUTE_ADD); + if (table->hook_add) + (*table->hook_add) (route); - 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; + ospf6_route_count_assert (table); + return route; } -#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)) + /* 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 { - 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); + route_unlock_node (nextnode); + + next = nextnode->info; + route->next = next; + next->prev = route; } -#endif - return NULL; -} + /* lookup real existing prev route */ + prevnode = node; + route_lock_node (prevnode); + do { + prevnode = route_prev (prevnode); + } while (prevnode && prevnode->info == 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)) + /* set prev link */ + if (prevnode == NULL) + route->prev = NULL; + else { - struct ospf6_nexthop_node *nexthop_node = node.data; + route_unlock_node (prevnode); - if (! memcmp (&nexthop_node->nexthop, &request->nexthop, - sizeof (struct ospf6_nexthop))) - return nexthop_node; + prev = prevnode->info; + while (prev->next && ospf6_route_is_same (prev, prev->next)) + prev = prev->next; + route->prev = prev; + prev->next = route; } - return NULL; + + table->count++; + + SET_FLAG (route->flag, OSPF6_ROUTE_ADD); + if (table->hook_add) + (*table->hook_add) (route); + + ospf6_route_count_assert (table); + return route; } void -ospf6_route_add (struct ospf6_route_req *request, - struct ospf6_route_table *table) +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 route_node *node; + struct ospf6_route *current; + char buf[64]; - struct ospf6_route_req route; + if (route->type == OSPF6_DEST_TYPE_LINKSTATE) + ospf6_linkstate_prefix2str (&route->prefix, buf, sizeof (buf)); + else + prefix2str (&route->prefix, buf, sizeof (buf)); - int route_change = 0; - int path_change = 0; - int nexthop_change = 0; + if (IS_OSPF6_DEBUG_ROUTE (TABLE)) + zlog_info ("route remove: %s", buf); - /* find the requested route */ - route_node = route_node_get (table->table, &request->route.prefix); - rn = (struct ospf6_route_node *) route_node->info; + node = route_node_lookup (table->table, &route->prefix); + assert (node); - if (rn) + /* 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 (memcmp (&rn->route, &request->route, sizeof (struct ospf6_route))) - { - memcpy (&rn->route, &request->route, sizeof (struct ospf6_route)); - route_change++; - } - } - 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; + if (current == route) + break; + current = current->next; } + assert (current == route); - /* find the same path */ - pn = ospf6_route_find_path_node (request, rn); + /* adjust doubly linked list */ + if (route->prev) + route->prev->next = route->next; + if (route->next) + route->next->prev = route->prev; - if (pn) + if (node->info == route) { - if (memcmp (&pn->path, &request->path, sizeof (struct ospf6_path))) + if (route->next && ospf6_route_is_same (route->next, route)) { - memcpy (&pn->path, &request->path, sizeof (struct ospf6_path)); - path_change++; + node->info = route->next; + SET_FLAG (route->next->flag, OSPF6_ROUTE_BEST); } - } - 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); + else + node->info = NULL; /* should unlock route_node here ? */ } - /* find the same nexthop */ - nn = ospf6_route_find_nexthop_node (request, pn); + if (table->hook_remove) + (*table->hook_remove) (route); - 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); - } + ospf6_route_unlock (route); + table->count--; - 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); + ospf6_route_count_assert (table); +} - if (table->freeze) - return; +struct ospf6_route * +ospf6_route_head (struct ospf6_route_table *table) +{ + struct route_node *node; + struct ospf6_route *route; - 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"); - } + 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; - 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; + route_unlock_node (node); + assert (node->info); + + route = (struct ospf6_route *) node->info; + assert (route->prev == NULL); + ospf6_route_lock (route); + return route; } -void -ospf6_route_remove (struct ospf6_route_req *request, - struct ospf6_route_table *table) +struct ospf6_route * +ospf6_route_next (struct ospf6_route *route) { - 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 ospf6_route *next = route->next; - /* find the requested route */ - route_node = route_node_get (table->table, &request->route.prefix); - rn = (struct ospf6_route_node *) route_node->info; + ospf6_route_unlock (route); + if (next) + ospf6_route_lock (next); - if (! rn) - { - if (IS_OSPF6_DUMP_ROUTE) - { - ospf6_route_log_request ("Remove", table->name, request); - zlog_info ("ROUTE: Can't remove: No such route"); - } - return; - } + return next; +} - 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; - } +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; +} - 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; - } +/* Macro version of check_bit (). */ +#define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1) - 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; - } +struct ospf6_route * +ospf6_route_match_head (struct prefix *prefix, + struct ospf6_route_table *table) +{ + struct route_node *node; + struct ospf6_route *route; - 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; - } + /* 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)]; - SET_FLAG (nn->flag, OSPF6_ROUTE_FLAG_REMOVE); + 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 (table->freeze) - return; + if (! prefix_match (prefix, &node->p)) + return NULL; - if (IS_OSPF6_DUMP_ROUTE) - ospf6_route_log_request ("Remove", table->name, request); + route = node->info; + ospf6_route_lock (route); + return route; +} - ospf6_route_request (&route, rn, pn, nn); - ospf6_route_hook_call (REMOVE, &route, table); - if (table->hook_remove) - (*table->hook_remove) (&route); - - /* clear flag */ - nn->flag = 0; - - /* remove nexthop */ - linklist_remove (nn, pn->nexthop_list); - rn->count--; - XFREE (MTYPE_OSPF6_ROUTE, nn); - - /* 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); - - /* 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); +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; -} + +/* VTY commands */ void -ospf6_route_table_thaw (struct ospf6_route_table *route_table) +ospf6_route_show (struct vty *vty, struct ospf6_route *route) { - 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); + int i; + char destination[64], nexthop[64]; + char duration[16], ifname[IFNAMSIZ]; + struct timeval now, res; - assert (route_table->freeze == 1); - route_table->freeze = 0; + gettimeofday (&now, (struct timezone *) NULL); + timersub (&now, &route->changed, &res); + timerstring (&res, duration, sizeof (duration)); - for (node = route_top (route_table->table); node; - node = route_next (node)) + /* 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++) { - 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); - } - } + /* 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); } } - -/* VTY commands */ - 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); + + /* 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++) + { + /* 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); +} - for (linklist_head (rn->path_list, &pnode); ! linklist_end (&pnode); - linklist_next (&pnode)) +void +ospf6_route_show_table_summary (struct vty *vty, + struct ospf6_route_table *table) +{ + 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; + + for (i = 0; i < OSPF6_PATH_TYPE_MAX; i++) + pathtype[i] = 0; + + 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++; - 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)) + destination++; + else + multipath++; - 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); + if (! ospf6_nexthop_is_set (&route->nexthop[0])) + nhinval++; + else if (ospf6_nexthop_is_set (&route->nexthop[1])) + ecmp++; - ospf6_timeval_sub (&now, &nn->installed, &res); - ospf6_timeval_string_summary (&res, duration, sizeof (duration)); + if (prev == NULL || ! ospf6_route_is_same (prev, route)) + pathtype[route->path.type]++; - 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); + number++; + prev = route; + } - nc++; - } - pc++; + 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); } } -void -ospf6_route_show_detail (struct vty *vty, struct ospf6_route_node *rn) +int +ospf6_route_table_show (struct vty *vty, int argc, char **argv, + struct ospf6_route_table *table) { - struct linklist_node pnode; - struct linklist_node nnode; - struct ospf6_path_node *pn; - struct ospf6_nexthop_node *nn; + unsigned char flag = 0; +#define MATCH 0x01 +#define DETAIL 0x02 +#define PREFIX 0x04 +#define SUMMARY 0x08 + int i, ret; + struct prefix prefix, *p; + struct ospf6_route *route; - u_int pc = 0; - u_int nc = 0; + memset (&prefix, 0, sizeof (struct prefix)); - char prefix[64], nexthop[64], ifname[IFNAMSIZ]; - char area_id[16], type[16], id[16], adv[16]; - char capa[64]; + for (i = 0; i < argc; i++) + { + /* set "detail" */ + if (! strcmp (argv[i], "summary")) + { + SET_FLAG (flag, SUMMARY); + continue; + } - /* 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)); + /* set "detail" */ + if (! strcmp (argv[i], "detail")) + { + SET_FLAG (flag, DETAIL); + continue; + } + + /* set "match" */ + if (! strcmp (argv[i], "match")) + { + SET_FLAG (flag, MATCH); + continue; + } - 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); + if (prefix.family) + { + vty_out (vty, "Invalid argument: %s%s", argv[i], VTY_NEWLINE); + return CMD_SUCCESS; + } - for (linklist_head (rn->path_list, &pnode); ! linklist_end (&pnode); - linklist_next (&pnode)) - { - pn = pnode.data; - - 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)); - - 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); - - for (linklist_head (pn->nexthop_list, &nnode); ! linklist_end (&nnode); - linklist_next (&nnode)) + ret = str2prefix (argv[i], &prefix); + if (ret != 1 || prefix.family != AF_INET6) { - nn = nnode.data; + vty_out (vty, "Malformed argument: %s%s", argv[i], VTY_NEWLINE); + return CMD_SUCCESS; + } - 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); + if (strchr (argv[i], '/')) + SET_FLAG (flag, PREFIX); + } - vty_out (vty, " %c%s%%%s%s", - (HEAD ? '*' : ' '), nexthop, ifname, VTY_NEWLINE); + /* Give summary of this route table */ + if (CHECK_FLAG (flag, SUMMARY)) + { + ospf6_route_show_table_summary (vty, table); + return CMD_SUCCESS; + } - nc++; + /* Give exact prefix-match route */ + if (prefix.family && ! CHECK_FLAG (flag, MATCH)) + { + /* 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); } - pc++; + + return CMD_SUCCESS; } - vty_out (vty, "%s", VTY_NEWLINE); + + if (prefix.family == 0) + route = ospf6_route_head (table); + else + route = ospf6_route_match_head (&prefix, table); + + while (route) + { + if (CHECK_FLAG (flag, DETAIL)) + ospf6_route_show_detail (vty, route); + else + ospf6_route_show (vty, route); + + if (prefix.family == 0) + route = ospf6_route_next (route); + else + route = ospf6_route_match_next (&prefix, route); + } + + return CMD_SUCCESS; } + int -ospf6_route_table_show (struct vty *vty, int argc, char **argv, - struct ospf6_route_table *table) +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; - 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 adv_router, id, prefix; + struct ospf6_route *route; - memset (&prefix, 0, sizeof (struct prefix)); + 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")) { - detail++; - break; + SET_FLAG (flag, DETAIL); + continue; } - if (! arg_ipv6 && ! arg_ipv4 && ! arg_digit) + /* set "match" */ + if (! strcmp (argv[i], "match")) { + SET_FLAG (flag, MATCH); + continue; + } - if ((ret = inet_pton (AF_INET6, argv[i], &p6->prefix)) == 1) + 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) { - p6->family = AF_INET6; - p6->prefixlen = 128; - arg_ipv6++; - continue; + if (! strcmp (argv[i], "*")) + { + adv_router.family = AF_INET; + adv_router.prefixlen = 0; + ret = 1; + } } - else if ((ret = inet_pton (AF_INET, argv[i], &pl->adv_router)) == 1) + if (ret != 1) { - pl->family = AF_UNSPEC; - pl->prefixlen = 64; /* xxx */ - arg_ipv4++; - continue; + vty_out (vty, "Invalid Router-ID: %s%s", argv[i], VTY_NEWLINE); + return CMD_SUCCESS; } - else + } + else if (id.family == 0) + { + unsigned long val; + char *endptr; + + ret = str2prefix (argv[i], &id); + if (ret != 1) { - 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 + val = strtoul (argv[i], &endptr, 0); + if (val != ULONG_MAX && *endptr == '\0') { - vty_out (vty, "Malformed argument: %s%s", - argv[i], VTY_NEWLINE); - return CMD_SUCCESS; + id.u.prefix4.s_addr = val; + ret = 1; } } - } - if (arg_ipv4 || arg_digit) - { - if ((ret = inet_pton (AF_INET, argv[i], &pl->id)) == 1) + if (ret != 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 Link state ID: %s%s", argv[i], + VTY_NEWLINE); + return CMD_WARNING; } } } - if (arg_ipv4 || arg_ipv6 || arg_digit) + /* Encode to linkstate prefix */ + if (adv_router.family) { - node = route_node_match (table->table, &prefix); - if (node && node->info) - ospf6_route_show_detail (vty, node->info); - return CMD_SUCCESS; + 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); + } } - if (! detail) + /* give exact match entry */ + if (adv_router.family && adv_router.prefixlen == IPV4_MAX_BITLEN && + id.family && id.prefixlen == IPV4_MAX_BITLEN) { - 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); + route = ospf6_route_lookup (&prefix, table); + if (route) + ospf6_route_show_detail (vty, route); + return CMD_SUCCESS; } - for (node = route_top (table->table); node; node = route_next (node)) - { - struct ospf6_route_node *route = node->info; + if (CHECK_FLAG (flag, MATCH)) + route = ospf6_route_match_head (&prefix, table); + else + route = ospf6_route_head (table); - if (! route) - continue; + 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 (detail) - ospf6_route_show_detail (vty, route); + if (CHECK_FLAG (flag, MATCH)) + route = ospf6_route_match_next (&prefix, route); else - ospf6_route_show (vty, route); - - route_count++; - path_count += route->path_list->count; - if (route->path_list->count > 1) - route_redundant++; + route = ospf6_route_next (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; +} +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 71b2562b..834774c3 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 -{ - char name[128]; - - 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; -}; - - +/* 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) -struct ospf6_route +/* Nexthop */ +struct ospf6_nexthop { - /* Destination ID */ - struct prefix prefix; + /* Interface index */ + unsigned int ifindex; - /* Destination Type */ - u_char type; + /* IP address, if any */ + struct in6_addr address; }; +#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 ls_origin 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 @@ struct ospf6_path u_int32_t cost_e2; }; -/* Nexthop */ -struct ospf6_nexthop -{ - /* Interface index */ - unsigned int ifindex; +#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 - /* IP address, if any */ - struct in6_addr address; -}; +#include "prefix.h" +#include "table.h" -struct ospf6_route_node +struct ospf6_route { - struct ospf6_route_table *table; - int count; - u_int32_t route_id; + struct route_node *rnode; - struct route_node *route_node; - struct ospf6_route route; - struct linklist *path_list; -}; + struct ospf6_route *prev; + struct ospf6_route *next; -struct ospf6_path_node -{ - struct ospf6_route_node *route_node; - struct ospf6_path path; - struct linklist *nexthop_list; -}; + unsigned int lock; -struct ospf6_nexthop_node -{ - int flag; + /* Destination Type */ + u_char type; + + /* Destination ID */ + struct prefix prefix; + + /* 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; - - int count; - struct ospf6_route route; - struct ospf6_path path; - struct ospf6_nexthop nexthop; + /* path */ + struct ospf6_path path; + + /* 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_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 - -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); - -void ospf6_route_add (struct ospf6_route_req *, struct ospf6_route_table *); -void ospf6_route_remove (struct ospf6_route_req *, struct ospf6_route_table *); -void ospf6_route_remove_all (struct ospf6_route_table *); +#define OSPF6_ROUTE_CHANGE 0x01 +#define OSPF6_ROUTE_ADD 0x02 +#define OSPF6_ROUTE_REMOVE 0x04 +#define OSPF6_ROUTE_BEST 0x08 -struct ospf6_route_table *ospf6_route_table_create (); -void ospf6_route_table_delete (struct ospf6_route_table *); +struct ospf6_route_table +{ + /* patricia tree */ + struct route_table *table; -void ospf6_route_table_freeze (struct ospf6_route_table *); -void ospf6_route_table_thaw (struct ospf6_route_table *); + u_int32_t count; -void ospf6_route_log_request (char *what, char *where, - struct ospf6_route_req *request); + /* 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_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); +ospf6_route_remove (struct ospf6_route *route, struct ospf6_route_table *table); -void ospf6_route_init (); +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_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 f617e913..00000000 --- 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 - -#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 c68e0ffc..00000000 --- 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 fd7fc779..10b73b83 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 -#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_area.h" #include "ospf6_spf.h" -#include "ospf6_neighbor.h" +#include "ospf6_intra.h" #include "ospf6_interface.h" -#include "ospf6_area.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; -}; - -int -ospf6_spf_candidate_node_cmp (void *a, void *b) -{ - struct ospf6_spf_candidate_node *ca = a; - struct ospf6_spf_candidate_node *cb = b; - return ca->cost - cb->cost; -} +unsigned char conf_debug_ospf6_spf = 0; int -ospf6_spf_vertex_cmp (void *a, void *b) +ospf6_vertex_cmp (void *a, void *b) { - return 1; -} + struct ospf6_vertex *va = (struct ospf6_vertex *) a; + struct ospf6_vertex *vb = (struct ospf6_vertex *) b; -void -ospf6_spf_candidate_node_print (int indent_num, void *node) -{ - struct ospf6_spf_candidate_node *cn = node; - char format[256]; - - snprintf (format, sizeof (format), "%%%ds %%d (num: %%d)", - indent_num * 2 + 1); - zlog_info (format, " ", cn->cost, cn->list->count); + /* ascending order */ + return (va->cost - vb->cost); } -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 () +int +ospf6_vertex_id_cmp (void *a, void *b) { - struct ospf6_spf_candidate_node *node; - struct linklist_node lnode; - struct ospf6_vertex *ret; + struct ospf6_vertex *va = (struct ospf6_vertex *) a; + struct ospf6_vertex *vb = (struct ospf6_vertex *) b; + int ret = 0; - 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_adv_router (&va->vertex_id)) - + ntohl (ospf6_linkstate_prefix_adv_router (&vb->vertex_id)); + if (ret) + return ret; + ret = ntohl (ospf6_linkstate_prefix_id (&va->vertex_id)) - + ntohl (ospf6_linkstate_prefix_id (&vb->vertex_id)); return ret; } -void -ospf6_spf_candidate_remove (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 ospf6_vertex * +ospf6_vertex_create (struct ospf6_lsa *lsa) { - struct timeval tmp; - ospf6_timeval_add (t, result, &tmp); - result->tv_sec = tmp.tv_sec; - result->tv_usec = tmp.tv_usec; -} + struct ospf6_vertex *v; + int i; -/* 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); -} + v = (struct ospf6_vertex *) + XMALLOC (MTYPE_OSPF6_VERTEX, sizeof (struct ospf6_vertex)); - -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); + /* 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 - type = htons (OSPF6_LSA_TYPE_ROUTER); - id = V->vertex_id.id.s_addr; - adv_router = V->vertex_id.adv_router.s_addr; + assert (0); - 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; - } + /* vertex_id */ + ospf6_linkstate_prefix (lsa->header->adv_router, lsa->header->id, + &v->vertex_id); - return ospf6_lsa_lsd_num ((struct ospf6_lsa_header *) lsa->header); -} + /* name */ + ospf6_linkstate_prefix2str (&v->vertex_id, v->name, sizeof (v->name)); -/* 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; + /* Associated LSA */ + v->lsa = lsa; - for (node = listhead (c->parent_list); node; nextnode (node)) - { - p = (struct ospf6_vertex *) getdata (node); + /* 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); - if (p == spf_tree->root) - return 0; + for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++) + ospf6_nexthop_clear (&v->nexthop[i]); - if (p->vertex_id.id.s_addr == 0) /* this is router */ - continue; - else if (ospf6_spf_is_router_to_root (p, spf_tree)) - continue; + v->parent = NULL; + v->child_list = list_new (); + v->child_list->cmp = ospf6_vertex_id_cmp; - return 0; - } - - return 1; + return v; } -static struct in6_addr * -ospf6_spf_get_ipaddr (u_int32_t id, u_int32_t adv_router, u_int32_t ifindex) +void +ospf6_vertex_delete (struct ospf6_vertex *v) { - 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; + list_delete (v->child_list); + XFREE (MTYPE_OSPF6_VERTEX, v); } -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_lsa * +ospf6_lsdesc_lsa (caddr_t lsdesc, struct ospf6_vertex *v) { - 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; + struct ospf6_lsa *lsa; + u_int16_t type = 0; + u_int32_t id = 0, adv_router = 0; - nexthop_ifindex = 0; - memset (&nexthop_ipaddr, 0, sizeof (struct in6_addr)); - if (spf_tree->root && V == spf_tree->root) + if (VERTEX_IS_TYPE (NETWORK, v)) { - 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)); - } + type = htons (OSPF6_LSTYPE_ROUTER); + id = htonl (0); + adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc); } 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) + if (ROUTER_LSDESC_IS_TYPE (POINTTOPOINT, lsdesc)) { - /* 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); + type = htons (OSPF6_LSTYPE_ROUTER); id = htonl (0); + adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc); } - else if (router_lsd->type == OSPF6_ROUTER_LSD_TYPE_TRANSIT_NETWORK) + else if (ROUTER_LSDESC_IS_TYPE (TRANSIT_NETWORK, lsdesc)) { - type = htons (OSPF6_LSA_TYPE_NETWORK); - id = router_lsd->neighbor_interface_id; + type = htons (OSPF6_LSTYPE_NETWORK); + id = htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc)); + adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc); } - 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; - } + lsa = ospf6_lsdb_lookup (type, id, adv_router, v->area->lsdb); - if (IS_LSA_MAXAGE (lsa)) + if (IS_OSPF6_DEBUG_SPF (DETAIL)) { - 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); - XFREE (MTYPE_OSPF6_VERTEX, v); -} - -static void -ospf6_spf_vertex_merge (struct ospf6_vertex *w, struct ospf6_vertex *x) -{ - 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)); + 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); } - /* merge nexthop list */ - for (linklist_head (w->nexthop_list, &lnode); ! linklist_end (&lnode); - linklist_next (&lnode)) - linklist_add (lnode.data, x->nexthop_list); + return lsa; } -static void -ospf6_spf_initialize (list candidate_list, struct ospf6_area *o6a) +char * +ospf6_lsdesc_backlink (struct ospf6_lsa *lsa, + caddr_t lsdesc, struct ospf6_vertex *v) { - listnode node; - struct ospf6_vertex *v; - struct ospf6_lsa *lsa; - u_int16_t type; - u_int32_t id, adv_router; - struct linklist_node lnode; - - struct ospf6_nexthop *nexthop; - struct interface *ifp; - char buf_router[64], buf_id[64]; + caddr_t backlink, found = NULL; + int size; - /* 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)) + 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) { - v = (struct ospf6_vertex *) getdata (node); - ospf6_spf_vertex_delete (v); - } - 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); + assert (! (OSPF6_LSA_IS_TYPE (NETWORK, lsa) && + VERTEX_IS_TYPE (NETWORK, v))); - /* 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; + 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; + } } - 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); + if (IS_OSPF6_DEBUG_SPF (DETAIL)) + zlog_info (" Backlink %s", (found ? "OK" : "FAIL")); - o6a->spf_tree->root = v; - listnode_add (candidate_list, v); - - ospf6_spf_candidate_enqueue (v); + return found; } -static struct ospf6_vertex * -ospf6_spf_get_closest_candidate (list candidate_list) +void +ospf6_nexthop_calc (struct ospf6_vertex *w, struct ospf6_vertex *v, + caddr_t lsdesc) { - listnode node; - struct ospf6_vertex *candidate, *closest; + 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]; - closest = (struct ospf6_vertex *) NULL; - for (node = listhead (candidate_list); node; nextnode (node)) + 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) { - 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; + if (IS_OSPF6_DEBUG_SPF (SUMMARY)) + zlog_warn ("Can't find interface in SPF: ifindex %d", ifindex); + return; } - return closest; -} + type = htons (OSPF6_LSTYPE_LINK); + adv_router = (VERTEX_IS_TYPE (NETWORK, v) ? + NETWORK_LSDESC_GET_NBR_ROUTERID (lsdesc) : + ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc)); -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)) + 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)) { - 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) + if (VERTEX_IS_TYPE (ROUTER, v) && + htonl (ROUTER_LSDESC_GET_NBR_IFID (lsdesc)) != lsa->header->id) continue; - if (same) - zlog_warn ("SPF: duplicate candidates in candidate_list"); + 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); + } - same = c; + 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++; + } } - return same; + if (i == 0 && IS_OSPF6_DEBUG_SPF (SUMMARY)) + zlog_info ("No nexthop for %s found", w->name); } -static void -ospf6_spf_install (struct ospf6_vertex *vertex, struct ospf6_area *o6a) +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; - 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_DEBUG_SPF (SUMMARY)) + zlog_info ("SPF install %s hops %d cost %d", + v->name, v->hops, v->cost); - if (IS_OSPF6_DUMP_SPF) + route = ospf6_route_lookup (&v->vertex_id, result_table); + if (route && route->path.cost < v->cost) { - zlog_info ("SPF: Install: %s", vertex->string); + if (IS_OSPF6_DEBUG_SPF (SUMMARY)) + zlog_info (" already installed with lower cost (%d), ignore", + route->path.cost); + ospf6_vertex_delete (v); + return -1; } - - listnode_add (o6a->spf_tree->list, vertex); - - for (node = listhead (vertex->parent_list); node; nextnode (node)) + else if (route && route->path.cost == v->cost) { - parent = (struct ospf6_vertex *) getdata (node); - listnode_add (parent->path_list, vertex); - vertex->depth = parent->depth + 1; - } + if (IS_OSPF6_DEBUG_SPF (SUMMARY)) + zlog_info (" another path found, merge"); -#if 0 - if (vertex == o6a->spf_tree->root) - return; -#endif /*0*/ + 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; + } + } - /* 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; + 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); - request.nexthop.ifindex = nexthop->ifindex; - memcpy (&request.nexthop.address, &nexthop->address, - sizeof (request.nexthop.address)); + ospf6_vertex_delete (prev); + route->route_option = v; + } + else + ospf6_vertex_delete (v); - ospf6_route_add (&request, o6a->table_topology); + 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; } -struct ospf6_vertex * -ospf6_spf_lookup (struct ospf6_vertex *w, struct ospf6_area *o6a) +void +ospf6_spf_table_finish (struct ospf6_route_table *result_table) { - listnode node; + struct ospf6_route *route; struct ospf6_vertex *v; - - for (node = listhead (o6a->spf_tree->list); node; nextnode (node)) + for (route = ospf6_route_head (result_table); route; + route = ospf6_route_next (route)) { - 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; + v = (struct ospf6_vertex *) route->route_option; + ospf6_vertex_delete (v); + ospf6_route_remove (route, result_table); } - - 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; - } +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; - stat_spf ++; - stat_node = 0; - stat_candidate = 0; - stat_candidate_max = 0; + /* initialize */ + candidate_list = pqueue_create (); + candidate_list->cmp = ospf6_vertex_cmp; - if (IS_OSPF6_DUMP_SPF) - zlog_info ("SPF: Calculation for area %s", o6a->str); + ospf6_spf_table_finish (result_table); - ospf6_route_table_freeze (o6a->table_topology); - ospf6_route_remove_all (o6a->table_topology); + /* 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); - /* (1): Initialize the algorithm's data structures */ - candidate_list = list_new (); - ospf6_spf_initialize (candidate_list, o6a); - stat_candidate ++; + /* Actually insert root to the candidate-list as the only candidate */ + pqueue_enqueue (root, candidate_list); - /* (3): Install closest from candidate list; if empty, break */ - while (listcount (candidate_list)) + /* Iterate until candidate-list becomes empty */ + while (candidate_list->size) { - 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 (); + /* get closest candidate from priority queue */ + v = pqueue_dequeue (candidate_list); -#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); + /* install may result in merging and rejecting of the vertex */ + if (ospf6_spf_install (v, result_table) < 0) + continue; - /* (2): Examin LSA of just added vertex */ - ldnum = ospf6_spf_lsd_num (V, o6a); - for (i = 0; i < ldnum; i++) + /* 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) { - /* (b): If no LSA, or MaxAge, or LinkBack fail, examin next */ - W = ospf6_spf_vertex_create (i, V, o6a); - if (! W) + lsa = ospf6_lsdesc_lsa (lsdesc, v); + if (lsa == NULL) 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; - } + if (! ospf6_lsdesc_backlink (lsa, lsdesc, v)) + continue; - /* (d) */ - X = ospf6_spf_get_same_candidate (W, candidate_list); - if (X && X->distance < W->distance) + w = ospf6_vertex_create (lsa); + w->area = oa; + w->parent = v; + if (VERTEX_IS_TYPE (ROUTER, v)) { - if (IS_OSPF6_DUMP_SPF) - zlog_info ("SPF: %s: More closer found", W->string); - ospf6_spf_vertex_delete (W); - continue; + w->cost = v->cost + ROUTER_LSDESC_GET_METRIC (lsdesc); + w->hops = v->hops + (VERTEX_IS_TYPE (NETWORK, w) ? 0 : 1); } - if (X && X->distance == W->distance) + else /* NETWORK */ { - 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; + w->cost = v->cost; + w->hops = v->hops + 1; } - 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); - } + /* 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 { - if (IS_OSPF6_DUMP_SPF) - zlog_info ("SPF: %s: New Candidate", W->string); + 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]); } - 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); + /* 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); } } - assert (listcount (candidate_list) == 0); - list_free (candidate_list); - assert (ospf6_spf_candidate_count () == 0); - - /* Clear thread timer */ - o6a->spf_tree->t_spf_calculation = (struct thread *) NULL; - - if (IS_OSPF6_DUMP_SPF) - { - 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); - } - - ospf6_route_table_thaw (o6a->table_topology); - return 0; + 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) - { - 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) + 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; - } - 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) -{ - 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) +ospf6_spf_schedule (struct ospf6_area *oa) { - 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; + struct ospf6_vertex *c; + char *next_prefix; + int len; + int restnum; - ifname = NULL; + /* "prefix" is the space prefix of the display line */ + vty_out (vty, "%s+-%s [%d]%s", prefix, v->name, v->cost, VTY_NEWLINE); - o6i = ospf6_interface_lookup_by_index (nexthop->ifindex); - if (! o6i) + len = strlen (prefix) + 4; + next_prefix = (char *) malloc (len); + if (next_prefix == NULL) { - 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); + vty_out (vty, "malloc failed%s", VTY_NEWLINE); + return; } - if (! list_isempty (vertex->parent_list)) - vty_out (vty, "%s", VTY_NEWLINE); + snprintf (next_prefix, len, "%s%s", prefix, (rest ? "| " : " ")); - 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)) + restnum = listcount (v->child_list); + LIST_LOOP (v->child_list, c, node) { - v = (struct ospf6_vertex *) getdata (node); - vty_out (vty, "%s ", v->string); + restnum--; + ospf6_spf_display_subtree (vty, next_prefix, restnum, c); } - if (! list_isempty (vertex->path_list)) - vty_out (vty, "%s", VTY_NEWLINE); - vty_out (vty, "%s", VTY_NEWLINE); + free (next_prefix); } -void -ospf6_spf_statistics_show (struct vty *vty, struct ospf6_spftree *spf_tree) +DEFUN (debug_ospf6_spf_detail, + debug_ospf6_spf_detail_cmd, + "debug ospf6 spf detail", + DEBUG_STR + OSPF6_STR + "Debug SPF Calculation\n" + "Debug Detailed SPF\n" + ) { - 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); + 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_spf_node, - show_ipv6_ospf6_area_spf_node_cmd, - "show ipv6 ospf6 area A.B.C.D spf node", - 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 - "Shortest Path First caculation\n" - "vertex infomation\n" - ) + "Debug SPF Calculation\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); - } - + unsigned char level = 0; + level = OSPF6_DEBUG_SPF_SUMMARY; + OSPF6_DEBUG_SPF_ON (level); return CMD_SUCCESS; } -static void -ospf6_spftree_show (struct vty *vty, char *prefix, int current_rest, - struct ospf6_vertex *v) +DEFUN (no_debug_ospf6_spf_detail, + no_debug_ospf6_spf_detail_cmd, + "no debug ospf6 spf detail", + NO_STR + DEBUG_STR + OSPF6_STR + "Quit Debugging SPF Calculation\n" + "Quit Debugging Detailed SPF (change to debug summary)\n" + ) { - char *p; - int psize; - int restnum; - listnode node; - - vty_out (vty, "%s+-%s%s", prefix, v->string, VTY_NEWLINE); - - if (listcount (v->path_list) == 0) - return; - - psize = strlen (prefix) + 3; - p = malloc (psize); - if (!p) - { - vty_out (vty, "depth too long ...%s", VTY_NEWLINE); - return; - } - - restnum = listcount (v->path_list); - for (node = listhead (v->path_list); node; nextnode (node)) - { - --restnum; - snprintf (p, psize, "%s%s", prefix, (current_rest ? "| " : " ")); - ospf6_spftree_show (vty, p, restnum, - (struct ospf6_vertex *) getdata (node)); - } - - free (p); + unsigned char level = 0; + level = OSPF6_DEBUG_SPF_DETAIL; + OSPF6_DEBUG_SPF_OFF (level); + 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 +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 - "Shortest Path First caculation\n" - "Displays spf tree\n") + "Quit Debugging SPF Calculation\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_OFF (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 - OSPF6_STR - OSPF6_AREA_STR - OSPF6_AREA_ID_STR - OSPF6_SPF_STR - "Displays SPF topology table\n") +int +config_write_ospf6_debug_spf (struct vty *vty) { - 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); + 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; } -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 - 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 - ) - -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 - 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 - ) +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 de50e94a..1c04afb4 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 @@ struct ospf6_vertex 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; - - /* root of this tree */ - struct ospf6_vertex *root; - - /* 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_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); -void ospf6_spf_database_hook (struct ospf6_lsa *old, struct ospf6_lsa *new); +void ospf6_spf_display_subtree (struct vty *vty, char *prefix, + int rest, struct ospf6_vertex *v); +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 f9cc3299..b1c1644e 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)) - { - o6a = (struct ospf6_area *) getdata (node); - (*o6a->foreach_nei) (o6a, arg, val, func); - } -} + o = XMALLOC (MTYPE_OSPF6_TOP, sizeof (struct ospf6)); + memset (o, 0, sizeof (struct ospf6)); -static int -ospf6_top_maxage_remover (struct thread *t) -{ - int count; - struct ospf6 *o6 = (struct ospf6 *) THREAD_ARG (t); + /* 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; - o6->maxage_remover = (struct thread *) NULL; + 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; - 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; + 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; - ospf6_lsdb_remove_maxage (o6->lsdb); - return 0; -} - -void -ospf6_top_schedule_maxage_remover (void *arg, int val, struct ospf6 *o6) -{ - if (o6->maxage_remover != NULL) - return; + o->external_table = ospf6_route_table_create (); + o->external_id_table = route_table_init (); - o6->maxage_remover = - thread_add_event (master, ospf6_top_maxage_remover, o6, 0); + return o; } void -ospf6_show (struct vty *vty) +ospf6_delete (struct ospf6 *o) { - listnode n; - struct ospf6_area *area; - char id_string[32]; - unsigned long day, hour, min, sec; - struct timeval now, running; + listnode i; + struct ospf6_area *oa; - /* 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); + for (i = listhead (o->area_list); i; nextnode (i)) + { + oa = (struct ospf6_area *) getdata (i); + ospf6_area_delete (oa); + } - /* 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); + ospf6_lsdb_delete (o->lsdb); - vty_out (vty, " Supports only single TOS(TOS0) routes%s", VTY_NEWLINE); + ospf6_route_table_delete (o->route_table); + ospf6_route_table_delete (o->asbr_table); - /* Redistribute config */ - ospf6_redistribute_show_config (vty); + ospf6_route_table_delete (o->external_table); + route_table_finish (o->external_id_table); - /* 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); + XFREE (MTYPE_OSPF6_TOP, o); +} - /* Route Statistics */ -#if 0 - ospf6_route_statistics_show (vty, ospf6->route_table); -#endif +void +ospf6_enable (struct ospf6 *o) +{ + listnode i; + struct ospf6_area *oa; - /* 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)) + if (CHECK_FLAG (o->flag, OSPF6_DISABLED)) { - area = (struct ospf6_area *) getdata (n); - ospf6_area_show (vty, area); + 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); + } } } void -ospf6_statistics_show (struct vty *vty, struct ospf6 *o6) +ospf6_disable (struct ospf6 *o) { - listnode node; - struct ospf6_area *o6a; - char running_time[128]; - struct timeval now, running; + listnode i; + struct ospf6_area *oa; - gettimeofday (&now, (struct timezone *) NULL); - ospf6_timeval_sub (&now, &o6->starttime, &running); - ospf6_timeval_string (&running, running_time, sizeof (running_time)); + 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); + } + + ospf6_lsdb_remove_all (o->lsdb); + ospf6_route_remove_all (o->route_table); + ospf6_route_remove_all (o->asbr_table); + } +} - vty_out (vty, "Statistics of OSPF process %ld%s", - o6->process_id, VTY_NEWLINE); - vty_out (vty, " Running: %s%s", running_time, VTY_NEWLINE); +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; -#if 0 - ospf6_route_statistics_show (vty, o6->route_table); -#endif + o->maxage_remover = (struct thread *) NULL; + if (IS_OSPF6_DEBUG_LSA (TIMER)) + zlog_info ("Maxage Remover"); - for (node = listhead (o6->area_list); node; nextnode (node)) + for (i = listhead (o->area_list); i; nextnode (i)) { - o6a = (struct ospf6_area *) getdata (node); - ospf6_area_statistics_show (vty, o6a); + 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; + } + } } -} -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; + 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_free (struct ospf6 *ospf6) +ospf6_maxage_remove (struct ospf6 *o) { - XFREE (MTYPE_OSPF6_TOP, ospf6); + if (o && ! o->maxage_remover) + o->maxage_remover = thread_add_event (master, ospf6_maxage_remover, o, 0); } -void -ospf6_top_topology_add (struct ospf6_route_req *request) +/* start ospf6 */ +DEFUN (router_ospf6, + router_ospf6_cmd, + "router ospf6", + ROUTER_STR + OSPF6_STR) { - 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); + 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; } -void -ospf6_top_topology_remove (struct ospf6_route_req *request) +/* stop ospf6 */ +DEFUN (no_router_ospf6, + no_router_ospf6_cmd, + "no router ospf6", + NO_STR + OSPF6_ROUTER_STR) { - 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); + 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; } -struct ospf6 * -ospf6_create (unsigned long process_id) +/* 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) { - struct ospf6 *o6; - char namebuf[64]; + int ret; + u_int32_t router_id; + struct ospf6 *o; - o6 = ospf6_new (); + o = (struct ospf6 *) vty->index; - /* 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; + 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; } -void -ospf6_delete (struct ospf6 *ospf6) +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" + ) { - if (!ospf6) - return; + 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; + } - ospf6_route_remove_all (ospf6->route_table); - ospf6_free (ospf6); + /* 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; } -struct ospf6 * -ospf6_start () +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" + ) { - if (ospf6) - return ospf6; + struct ospf6 *o; + struct ospf6_interface *oi; + struct interface *ifp; + u_int32_t area_id; - ospf6 = ospf6_create (0); - return ospf6; + 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_stop () +ospf6_show (struct vty *vty, struct ospf6 *o) { - if (!ospf6) - return; + listnode n; + struct ospf6_area *oa; + char router_id[16], duration[32]; + struct timeval now, running; + + /* process id, router id */ + 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); + timersub (&now, &o->starttime, &running); + timerstring (&running, duration, sizeof (duration)); + vty_out (vty, " Running %s%s", duration, VTY_NEWLINE); + + /* Redistribute configuration */ + /* XXX */ + + /* LSAs */ + vty_out (vty, " Number of AS scoped LSAs is %u%s", + o->lsdb->count, VTY_NEWLINE); - ospf6_delete (ospf6); - ospf6 = NULL; + /* Areas */ + vty_out (vty, " Number of areas in this router is %u%s", + listcount (o->area_list), VTY_NEWLINE); + for (n = listhead (o->area_list); n; nextnode (n)) + { + oa = (struct ospf6_area *) getdata (n); + ospf6_area_show (vty, oa); + } } -int -ospf6_is_asbr (struct ospf6 *o6) +/* show top level structures */ +DEFUN (show_ipv6_ospf6, + show_ipv6_ospf6_cmd, + "show ipv6 ospf6", + SHOW_STR + IP6_STR + OSPF6_STR) { - 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_CMD_CHECK_RUNNING (); + + ospf6_show (vty, ospf6); + return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_route, @@ -332,73 +451,146 @@ DEFUN (show_ipv6_ospf6_route, 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; + + /* 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; +} -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 - ) +/* 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 4c687563..bd1336f4 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 ospf6 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; }; - -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); +#define OSPF6_DISABLED 0x01 -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 *); +/* global pointer for OSPF top data structure */ +extern struct ospf6 *ospf6; +/* prototypes */ 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 574e2f35..00000000 --- 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 4e8815f3..b6220866 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 "ospf6d.h" +#include + +#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 @@ struct zclient *zclient = NULL; 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 @@ ospf6_zebra_if_add (int command, struct zclient *zclient, zebra_size_t length) 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 @@ int 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 @@ ospf6_zebra_if_state_update (int command, struct zclient *zclient, 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 @@ ospf6_zebra_if_state_update (int command, struct zclient *zclient, 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 @@ ospf6_zebra_if_address_update_add (int command, struct zclient *zclient, 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 @@ ospf6_zebra_if_address_update_delete (int command, struct zclient *zclient, 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 @@ ospf6_zebra_if_address_update_delete (int command, struct zclient *zclient, 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 @@ ospf6_zebra_read_ipv6 (int command, struct zclient *zclient, 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 @@ ospf6_zebra_read_ipv6 (int command, struct zclient *zclient, 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 @@ ospf6_zebra_read_ipv6 (int command, struct zclient *zclient, return 0; } + + DEFUN (show_zebra, show_zebra_cmd, @@ -280,18 +249,24 @@ DEFUN (show_zebra, "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 @@ DEFUN (router_zebra, "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 @@ DEFUN (no_router_zebra, "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 @@ DEFUN (no_router_zebra, /* 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 @@ struct cmd_node zebra_node = { 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 @@ ospf6_zebra_route_update (int type, struct ospf6_route_req *request) (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)) { - /* this is not preferred best route, ignore */ - if (IS_OSPF6_DUMP_ZEBRA) - zlog_info ("ZEBRA: not best path, ignore"); - return; + if (IS_OSPF6_DEBUG_ZEBRA (SEND)) + zlog_info (" Best-path removal resulted Sencondary addition"); + type = ADD; + request = request->next; } - nexthop_list = linklist_create (); - - /* for each nexthop */ - for (ospf6_route_lookup (&route, &request->route.prefix, request->table); - ! ospf6_route_end (&route); ospf6_route_next (&route)) + /* Only the best path will be sent to zebra. */ + if (! ospf6_route_is_best (request)) { - 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); + /* this is not preferred best route, ignore */ + if (IS_OSPF6_DEBUG_ZEBRA (SEND)) + zlog_info (" Ignore non-best route"); + return; } - 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); - } - } - } + nhcount = 0; + for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++) + if (ospf6_nexthop_is_set (&request->nexthop[i])) + nhcount++; - if (nexthop_list->count == 0) + if (nhcount == 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 @@ ospf6_zebra_route_update (int type, struct ospf6_route_req *request) } void -ospf6_zebra_route_update_add (struct ospf6_route_req *request) +ospf6_zebra_route_update_add (struct ospf6_route *request) { - ospf6_zebra_route_update (ADD, request); -} - -void -ospf6_zebra_route_update_remove (struct ospf6_route_req *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 (ADD, request); } -static void -ospf6_zebra_no_redistribute_ospf6 () +void +ospf6_zebra_route_update_remove (struct ospf6_route *request) { - struct route_node *node; - - if (! ospf6) - return; - - 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_remove (node->info); + ospf6->route_table->hook_add = NULL; + ospf6->route_table->hook_remove = NULL; + return; } + ospf6_zebra_route_update (REM, request); } - 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 @@ DEFUN (no_redistribute_ospf6, "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_init () /* 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; } +/* 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" + ) +{ + 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 -ospf6_zebra_finish () +install_element_ospf6_debug_zebra () { - zclient_stop (zclient); - zclient_free (zclient); - zclient = (struct zclient *) NULL; + 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 d86b2db7..fb9877bf 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 e83e1eab..362d6794 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 "ospf6d.h" +#include -#include "ospf6_damp.h" +#include "thread.h" +#include "linklist.h" +#include "vty.h" +#include "command.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 "ospf6d.h" +#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 () +{ +} + +static struct route_node * +_route_next_until (struct route_node *node, struct route_node *limit) { - long usec, movedown = 0; + 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 (t1->tv_sec < t2->tv_sec || - (t1->tv_sec == t2->tv_sec && t1->tv_usec < t2->tv_usec)) + 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 (t1->tv_usec < t2->tv_usec) + if (node->l_right) { - usec = t1->tv_usec + TIMER_SEC_MICRO; - movedown++; + next = node->l_right; + if (next == limit) + { + route_unlock_node (node); + return NULL; + } + route_lock_node (next); + route_unlock_node (node); + return next; } - 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) + start = node; + while (node->parent) { - 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; - - 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 (dayp) *dayp = day; - if (hourp) *hourp = hour; - if (minp) *minp = min; - if (secp) *secp = sec; - if (msecp) *msecp = msec; - if (usecp) *usecp = usec; -} - -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 : "")); -} + struct route_node *end; + struct route_node *prev = NULL; -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); -} + if (node->parent == NULL) + { + route_unlock_node (node); + return NULL; + } -/* 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 (node->parent->l_left == node) + { + prev = node->parent; + route_lock_node (prev); + route_unlock_node (node); + return prev; + } - if (nei->state == state) - (*count)++; -} - -/* VTY commands. */ -DEFUN (reload, - reload_cmd, - "reload", - "Reloads\n") -{ - extern void _reload (); - _reload (); - return CMD_SUCCESS; -} + 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); -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; + return prev; } -/* 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 @@ DEFUN (show_version_ospf6, 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; + DEBUG_NODE, + "" +}; - return CMD_SUCCESS; +int +config_write_ospf6_debug (struct vty *vty) +{ + 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; } -/* stop ospf6 */ -DEFUN (no_router_ospf6, - no_router_ospf6_cmd, - "no router ospf6", - NO_STR - OSPF6_ROUTER_STR) +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" + ) { - if (!ospf6) - vty_out (vty, "OSPFv3 is not running%s", VTY_NEWLINE); + 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 - ospf6_stop (); + showfunc = ospf6_lsa_show_summary; + + if (showfunc == ospf6_lsa_show_summary) + ospf6_lsa_show_summary_header (vty); - /* return to config node . */ - vty->node = CONFIG_NODE; - vty->index = NULL; + 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; } -/* show top level structures */ -DEFUN (show_ipv6_ospf6, - show_ipv6_ospf6_cmd, - "show ipv6 ospf6", +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 - IP6_STR - OSPF6_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 (); - ospf6_show (vty); + 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; } -DEFUN (show_ipv6_ospf6_nexthoplist, - show_ipv6_ospf6_nexthoplist_cmd, - "show ipv6 ospf6 nexthop-list", +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 - IP6_STR + IPV6_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", + "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 - IP6_STR + IPV6_STR OSPF6_STR - "Statistics\n") + "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 (); - ospf6_statistics_show (vty, ospf6); - return CMD_SUCCESS; -} + 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; -/* 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; + if (showfunc == ospf6_lsa_show_summary) + ospf6_lsa_show_summary_header (vty); - ret = inet_pton (AF_INET, argv[0], &router_id); - if (!ret) + if ((inet_pton (AF_INET, argv[0], &id)) != 1) { - vty_out (vty, "malformed ospf router identifier%s", VTY_NEWLINE); - vty_out (vty, "%s", VTY_NEWLINE); - return CMD_WARNING; + vty_out (vty, "Link State ID is not parsable: %s%s", + argv[0], VTY_NEWLINE); + return CMD_SUCCESS; } - if (IS_OSPF6_DUMP_CONFIG) - zlog_info ("CONFIG: router-id %s", argv[0]); - ospf6->router_id = router_id; + 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; } -int -ospf6_interface_bind_area (struct vty *vty, - char *if_name, char *area_name, - char *plist_name, int passive) +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" + ) { - struct interface *ifp; - struct ospf6_interface *o6i; - struct ospf6_area *o6a; - u_int32_t area_id; + listnode i, j; + struct ospf6 *o = ospf6; + void (*showfunc) (struct vty *, struct ospf6_lsa *) = NULL; + u_int32_t router = 0; - /* find/create ospf6 interface */ - ifp = if_get_by_name (if_name); - o6i = (struct ospf6_interface *) ifp->info; - if (! o6i) - o6i = ospf6_interface_create (ifp); + OSPF6_CMD_CHECK_RUNNING (); - /* parse Area-ID */ - if (inet_pton (AF_INET, area_name, &area_id) != 1) + if (argc > 1) { - vty_out (vty, "Invalid Area-ID: %s%s", area_name, VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; + 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; - /* find/create ospf6 area */ - o6a = ospf6_area_lookup (area_id, ospf6); - if (!o6a) + if (showfunc == ospf6_lsa_show_summary) + ospf6_lsa_show_summary_header (vty); + + if ((inet_pton (AF_INET, argv[0], &router)) != 1) { - o6a = ospf6_area_create (area_id); - o6a->ospf6 = ospf6; - listnode_add (ospf6->area_list, o6a); + vty_out (vty, "Advertising Router is not parsable: %s%s", + argv[0], VTY_NEWLINE); + return CMD_SUCCESS; } - if (o6i->area) + LSDB_FOREACH_LSA_R (vty, showfunc, o->lsdb, router); + for (i = listhead (o->area_list); i; nextnode (i)) { - if (o6i->area != o6a) - { - vty_out (vty, "Aready attached to area %s%s", - o6i->area->str, VTY_NEWLINE); - return CMD_ERR_NOTHING_TODO; - } + struct ospf6_area *oa = (struct ospf6_area *) getdata (i); + LSDB_FOREACH_LSA_R (vty, showfunc, oa->lsdb, router); } - else + for (i = listhead (o->area_list); i; nextnode (i)) { - listnode_add (o6a->if_list, o6i); - o6i->area = o6a; + 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); + } } - /* prefix-list name */ - if (plist_name) + 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 (o6i->plist_name) - XFREE (MTYPE_PREFIX_LIST_STR, o6i->plist_name); - o6i->plist_name = XSTRDUP (MTYPE_PREFIX_LIST_STR, plist_name); + 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) { - if (o6i->plist_name) - XFREE (MTYPE_PREFIX_LIST_STR, o6i->plist_name); - o6i->plist_name = NULL; + vty_out (vty, "Link state ID is not parsable: %s%s", + argv[1], VTY_NEWLINE); + return CMD_SUCCESS; } - if (passive) + LSDB_FOREACH_LSA_TI (vty, showfunc, o->lsdb, type, id); + for (i = listhead (o->area_list); i; nextnode (i)) { - 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); - } + struct ospf6_area *oa = (struct ospf6_area *) getdata (i); + LSDB_FOREACH_LSA_TI (vty, showfunc, oa->lsdb, type, id); } - else + for (i = listhead (o->area_list); i; nextnode (i)) { - UNSET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE); - if (o6i->thread_send_hello == NULL) - thread_add_event (master, ospf6_send_hello, o6i, 0); + 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); + } } - /* 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" +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" ) { - struct interface *ifp; - struct ospf6_interface *o6i; - int passive; - char *plist_name; + 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; - if (IS_OSPF6_DUMP_CONFIG) - zlog_info ("CONFIG: interface %s area %s", - argv[0], argv[1]); + OSPF6_CMD_CHECK_RUNNING (); - ifp = if_get_by_name (argv[0]); - o6i = (struct ospf6_interface *) ifp->info; - if (o6i) + if (argc > 2) { - passive = CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE); - plist_name = o6i->plist_name; + 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) { - passive = 0; - plist_name = NULL; + vty_out (vty, "Advertising Router is not parsable: %s%s", + argv[1], VTY_NEWLINE); + return CMD_SUCCESS; } - 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]); + 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 ospf6_interface_bind_area (vty, argv[0], argv[1], NULL, 1); + 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) +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" + ) { - struct interface *ifp; - struct ospf6_interface *o6i; - struct ospf6 *o6; - u_int32_t area_id; + 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; - o6 = (struct ospf6 *) vty->index; + OSPF6_CMD_CHECK_RUNNING (); - ifp = if_lookup_by_name (argv[0]); - if (!ifp) - return CMD_ERR_NO_MATCH; + 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; - o6i = (struct ospf6_interface *) ifp->info; - if (!o6i) - return CMD_SUCCESS; + if (showfunc == ospf6_lsa_show_summary) + ospf6_lsa_show_summary_header (vty); - /* parse Area-ID */ - if (inet_pton (AF_INET, argv[1], &area_id) != 1) + if ((inet_pton (AF_INET, argv[0], &id)) != 1) { - vty_out (vty, "Invalid Area-ID: %s%s", argv[1], VTY_NEWLINE); - return CMD_ERR_AMBIGUOUS; + vty_out (vty, "Link state ID is not parsable: %s%s", + argv[1], VTY_NEWLINE); + return CMD_SUCCESS; } - if (o6i->area->area_id != area_id) + if ((inet_pton (AF_INET, argv[1], &router)) != 1) { - 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; + vty_out (vty, "Advertising Router is not parsable: %s%s", + argv[1], VTY_NEWLINE); + return CMD_SUCCESS; } - if (o6i->area) - thread_execute (master, interface_down, o6i, 0); - - listnode_delete (o6i->area->if_list, o6i); - o6i->area = (struct ospf6_area *) NULL; + 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; } -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") +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" + ) { - struct ospf6 *o6; - struct ospf6_area *o6a; - u_int32_t area_id; - int ret; + 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 (); - o6 = (struct ospf6 *) vty->index; - inet_pton (AF_INET, argv[0], &area_id); - o6a = ospf6_area_lookup (area_id, o6); - if (! o6a) + if (argc > 3) { - vty_out (vty, "No such area%s", VTY_NEWLINE); - return CMD_ERR_NO_MATCH; + 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; } - ret = str2prefix_ipv6 (argv[1], &o6a->area_range); - if (ret <= 0) + if ((inet_pton (AF_INET, argv[2], &router)) != 1) { - vty_out (vty, "Malformed IPv6 address%s", VTY_NEWLINE); - return CMD_WARNING; + 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; } -DEFUN (ospf6_passive_interface, - ospf6_passive_interface_cmd, - "passive-interface IFNAME", - OSPF6_PASSIVE_STR - IFNAME_STR) +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" + ) { - struct interface *ifp; - struct ospf6_interface *o6i; + listnode i, j; + struct ospf6 *o = ospf6; + void (*showfunc) (struct vty *, struct ospf6_lsa *) = NULL; - ifp = if_get_by_name (argv[0]); - if (ifp->info) - o6i = (struct ospf6_interface *) ifp->info; + 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 - o6i = ospf6_interface_create (ifp); + showfunc = ospf6_lsa_show_summary; - SET_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE); + if (showfunc == ospf6_lsa_show_summary) + ospf6_lsa_show_summary_header (vty); - if (o6i->thread_send_hello) + 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)) { - thread_cancel (o6i->thread_send_hello); - o6i->thread_send_hello = (struct thread *) NULL; + 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; } -DEFUN (no_ospf6_passive_interface, - no_ospf6_passive_interface_cmd, - "no passive-interface IFNAME", - NO_STR - OSPF6_PASSIVE_STR - IFNAME_STR) +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" + ) { - struct interface *ifp; - struct ospf6_interface *o6i; + listnode i, j; + struct ospf6 *o = ospf6; + void (*showfunc) (struct vty *, struct ospf6_lsa *) = NULL; + u_int16_t type = 0; - 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]; + OSPF6_CMD_CHECK_RUNNING (); - if (strncmp (argv[0], "v", 1) == 0) + if (argc > 1) { - proctitle_mode = 1; - setproctitle ("%s Zebra: %s", OSPF6_DAEMON_VERSION, QUAGGA_VERSION); + 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 if (strncmp (argv[0], "nor", 3) == 0) + 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)) { - 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); + struct ospf6_area *oa = (struct ospf6_area *) getdata (i); + LSDB_FOREACH_LSA_TR (vty, showfunc, oa->lsdb, type, o->router_id); } - else if (strncmp (argv[0], "non", 3) == 0) + for (i = listhead (o->area_list); i; nextnode (i)) { - proctitle_mode = -1; - setproctitle (NULL); + 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); + } } - else - return CMD_ERR_NO_MATCH; return CMD_SUCCESS; } -#endif /* HAVE_SETPROCTITLE */ -/* OSPF configuration write function. */ -int -ospf6_config_write (struct vty *vty) +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 j, k; - char buf[64]; - struct ospf6_area *area; - struct ospf6_interface *o6i; + 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; - 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_CMD_CHECK_RUNNING (); - ospf6_redistribute_config_write (vty); - ospf6_damp_config_write (vty); + 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; + } - for (j = listhead (ospf6->area_list); j; nextnode (j)) + LSDB_FOREACH_LSA_TIR (vty, showfunc, o->lsdb, type, id, o->router_id); + for (i = listhead (o->area_list); i; nextnode (i)) { - area = (struct ospf6_area *)getdata (j); - for (k = listhead (area->if_list); k; nextnode (k)) + 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)) { - o6i = (struct ospf6_interface *) getdata (k); - vty_out (vty, " interface %s area %s%s", - o6i->interface->name, area->str, VTY_NEWLINE); + struct ospf6_interface *oi = (struct ospf6_interface *) getdata (j); + LSDB_FOREACH_LSA_TIR (vty, showfunc, oi->lsdb, type, id, o->router_id); } } - vty_out (vty, "!%s", VTY_NEWLINE); - return 0; + + return CMD_SUCCESS; } -/* OSPF6 node structure. */ -struct cmd_node ospf6_node = -{ - OSPF6_NODE, - "%s(config-ospf6)# ", - vtysh: 1 -}; +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_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_ipv6_ospf6_cmd); 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_init () 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 (); -} - -void -ospf6_terminate () -{ - /* stop ospf6 */ - ospf6_stop (); - /* log */ - zlog (NULL, LOG_INFO, "OSPF6d terminated"); + /* Make ospf protocol socket. */ + ospf6_serv_sock (); + thread_add_read (master, ospf6_receive, NULL, ospf6_sock); } -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 71972f59..0a6ddb71 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 -! -interface ed0 +debug ospf6 neighbor state +! +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 @@ interface lo0 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 +! +access-list access4 permit 127.0.0.1/32 ! -ipv6 prefix-list hostroute seq 10 permit 3ffe:501:100c:4380::/60 le 128 ge 128 +ipv6 access-list access6 permit 3ffe:501::/32 +ipv6 access-list access6 permit 2001:200::/48 +ipv6 access-list access6 permit ::1/128 ! -route-map static-ospf6 permit 50 - match ipv6 address prefix-list hostroute +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 e867b1c1..c08007f0 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 -#include "linklist.h" - -#ifndef HEADER_DEPENDENCY -/* Include other stuffs */ -#include -#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 @@ extern char *recent_reason; #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 @@ extern char *recent_reason; #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 @@ extern char *recent_reason; 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); - -void -ospf6_count_state (void *arg, int val, void *obj); +struct route_node *route_prev (struct route_node *node); +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 */ + -- cgit v1.2.1