mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 23:58:44 +00:00
Ospf6d merge from Zebra repository with added privs stuff and merged
zclient changes.
This commit is contained in:
parent
6708fa3c3e
commit
508e53e2ee
@ -1,5 +1,4 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
*.patch
|
||||
ospf6d
|
||||
|
@ -1,32 +1,24 @@
|
||||
2004-05-08 Paul Jakma <paul@dishone.st>
|
||||
2004-05-18 Hasso Tepper <hasso@estpak.ee>
|
||||
|
||||
* ospf6_zebra.c: Sync to zclient changes
|
||||
* *.*: Merge rewritten ospf6d from Zebra repository.
|
||||
* ospf6_network.c, ospf6_main.c: Merged privs stuff back in.
|
||||
* ospf6_zebra.c: Sync back to zclient changes.
|
||||
|
||||
2003-08-18 Yasuhiro Ohara <yasu@sfc.wide.ad.jp>
|
||||
|
||||
* *.[ch]: rewrite all source code from scratch
|
||||
* ospf6d.h: version 0.9.7
|
||||
|
||||
2003-08-11 Taisuke Sasaki <sasaki@soft.net.fujitsu.co.jp>
|
||||
|
||||
* ospf6_ism.c: DR Election bug fix.
|
||||
|
||||
2003-05-18 Hasso Tepper <hasso@estpak.ee>
|
||||
|
||||
* ospf6_{dump,interface,zebra}.c,ospf6d.c: show router and interface
|
||||
nodes from ospf6d when using vtysh, and don't show defaults in
|
||||
interface node (from ^WIND patch).
|
||||
|
||||
2003-04-23 Hasso Tepper <hasso@estpak.ee>
|
||||
|
||||
* {ospf6_damp,ospf6d}.c: fix "router xxx" node commands in vtysh
|
||||
|
||||
2003-04-25 Yasuhiro Ohara <yasu@sfc.wide.ad.jp>
|
||||
|
||||
* ospf6_asbr.c: AS-External LSA refresh was based on the
|
||||
prefix of the obsolete LSA. It was wrong so fixed.
|
||||
* version: 0.9.6p
|
||||
|
||||
2003-04-19 Hasso Tepper <hasso@estpak.ee>
|
||||
|
||||
* rip_routemap.c: sync daemon's route-map commands to have same
|
||||
syntax
|
||||
|
||||
2002-11-09 Vincent Jardin <jardin@6wind.com>
|
||||
|
||||
* ospf6_interface.c: update link-local address on interface creation.
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* OSPF6 Area Data Structure
|
||||
* Copyright (C) 1999 Yasuhiro Ohara
|
||||
* Copyright (C) 2003 Yasuhiro Ohara
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
@ -23,67 +22,54 @@
|
||||
#ifndef OSPF_AREA_H
|
||||
#define OSPF_AREA_H
|
||||
|
||||
/* This file defines area parameters and data structures. */
|
||||
|
||||
#define OSPF6_AREA_RANGE_ADVERTISE 0
|
||||
#define OSPF6_AREA_RANGE_NOT_ADVERTISE 1
|
||||
|
||||
#include "ospf6_spf.h"
|
||||
#include "ospf6_top.h"
|
||||
|
||||
struct ospf6_area
|
||||
{
|
||||
char str[16];
|
||||
/* Reference to Top data structure */
|
||||
struct ospf6 *ospf6;
|
||||
|
||||
struct ospf6 *ospf6; /* back pointer */
|
||||
/* Area-ID */
|
||||
u_int32_t area_id;
|
||||
u_char options[3]; /* OSPF Option including ExternalCapability */
|
||||
|
||||
list if_list; /* OSPF interface to this area */
|
||||
/* Area-ID string */
|
||||
char name[16];
|
||||
|
||||
/* flag */
|
||||
u_char flag;
|
||||
|
||||
/* OSPF Option */
|
||||
u_char options[3];
|
||||
|
||||
/* OSPF interface list */
|
||||
list if_list;
|
||||
|
||||
struct ospf6_lsdb *lsdb;
|
||||
|
||||
struct thread *spf_calc;
|
||||
struct thread *route_calc;
|
||||
int stat_spf_execed;
|
||||
int stat_route_execed;
|
||||
|
||||
struct route_table *table; /* new route table */
|
||||
|
||||
struct prefix_ipv6 area_range;
|
||||
struct ospf6_spftree *spf_tree;
|
||||
|
||||
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 */
|
||||
|
2025
ospf6d/ospf6_asbr.c
2025
ospf6d/ospf6_asbr.c
File diff suppressed because it is too large
Load Diff
@ -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,
|
||||
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);
|
||||
ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix);
|
||||
|
||||
void ospf6_asbr_external_lsa_add (struct ospf6_lsa *lsa);
|
||||
void ospf6_asbr_external_lsa_remove (struct ospf6_lsa *lsa);
|
||||
void ospf6_asbr_external_lsa_change (struct ospf6_lsa *old,
|
||||
struct ospf6_lsa *new);
|
||||
|
||||
void ospf6_asbr_asbr_entry_add (struct ospf6_route_req *topo_entry);
|
||||
void ospf6_asbr_asbr_entry_remove (struct ospf6_route_req *topo_entry);
|
||||
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 */
|
||||
|
||||
|
@ -1,436 +0,0 @@
|
||||
|
||||
#include <zebra.h>
|
||||
#include "ospf6_bintree.h"
|
||||
|
||||
static struct bintree_node *
|
||||
bintree_lookup_node_min (struct bintree_node *subroot)
|
||||
{
|
||||
struct bintree_node *node;
|
||||
|
||||
if (subroot == NULL)
|
||||
return NULL;
|
||||
|
||||
node = subroot;
|
||||
while (node->bl_left)
|
||||
node = node->bl_left;
|
||||
return node;
|
||||
}
|
||||
|
||||
static struct bintree_node *
|
||||
bintree_lookup_node_max (struct bintree_node *subroot)
|
||||
{
|
||||
struct bintree_node *node;
|
||||
|
||||
assert (subroot != NULL);
|
||||
node = subroot;
|
||||
while (node->bl_right)
|
||||
node = node->bl_right;
|
||||
return node;
|
||||
}
|
||||
|
||||
void *
|
||||
bintree_lookup (void *data, struct bintree *tree)
|
||||
{
|
||||
int cmp;
|
||||
struct bintree_node *node;
|
||||
|
||||
node = tree->root;
|
||||
|
||||
while (node)
|
||||
{
|
||||
if (tree->cmp)
|
||||
cmp = (*tree->cmp) (node->data, data);
|
||||
else
|
||||
cmp = (node->data - data);
|
||||
|
||||
if (cmp == 0)
|
||||
break;
|
||||
|
||||
if (cmp > 0)
|
||||
node = node->bl_left;
|
||||
else /* if (cmp < 0) */
|
||||
node = node->bl_right;
|
||||
}
|
||||
|
||||
if (node)
|
||||
return node->data;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
bintree_lookup_min (struct bintree *tree)
|
||||
{
|
||||
struct bintree_node *node;
|
||||
node = bintree_lookup_node_min (tree->root);
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
return node->data;
|
||||
}
|
||||
|
||||
void *
|
||||
bintree_lookup_max (struct bintree *tree)
|
||||
{
|
||||
struct bintree_node *node;
|
||||
node = bintree_lookup_node_max (tree->root);
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
return node->data;
|
||||
}
|
||||
|
||||
int
|
||||
bintree_add (void *data, struct bintree *tree)
|
||||
{
|
||||
int cmp = 0;
|
||||
struct bintree_node *node, *parent;
|
||||
|
||||
node = tree->root;
|
||||
parent = NULL;
|
||||
|
||||
while (node)
|
||||
{
|
||||
if (tree->cmp)
|
||||
cmp = (*tree->cmp) (node->data, data);
|
||||
else
|
||||
cmp = (node->data - data);
|
||||
|
||||
if (cmp == 0)
|
||||
break;
|
||||
|
||||
parent = node;
|
||||
if (cmp > 0)
|
||||
node = node->bl_left;
|
||||
else /* if (cmp < 0) */
|
||||
node = node->bl_right;
|
||||
}
|
||||
|
||||
if (node)
|
||||
return -1;
|
||||
|
||||
node = malloc (sizeof (struct bintree_node));
|
||||
memset (node, 0, sizeof (struct bintree_node));
|
||||
node->tree = tree;
|
||||
node->data = data;
|
||||
|
||||
if (parent)
|
||||
{
|
||||
node->parent = parent;
|
||||
|
||||
assert (cmp != 0);
|
||||
if (cmp > 0)
|
||||
{
|
||||
node->parent_link = BL_LEFT;
|
||||
parent->bl_left = node;
|
||||
}
|
||||
else /* if (cmp < 0) */
|
||||
{
|
||||
node->parent_link = BL_RIGHT;
|
||||
parent->bl_right = node;
|
||||
}
|
||||
}
|
||||
else
|
||||
tree->root = node;
|
||||
|
||||
tree->count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
bintree_remove_nochild (struct bintree_node *node)
|
||||
{
|
||||
assert (node->bl_left == NULL && node->bl_right == NULL);
|
||||
|
||||
if (node->parent == NULL)
|
||||
node->tree->root = NULL;
|
||||
else
|
||||
node->parent->link[node->parent_link] = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bintree_remove_onechild (struct bintree_node *node)
|
||||
{
|
||||
assert ((node->bl_left == NULL && node->bl_right != NULL) ||
|
||||
(node->bl_left != NULL && node->bl_right == NULL));
|
||||
|
||||
if (node->bl_left)
|
||||
{
|
||||
if (node->parent == NULL)
|
||||
{
|
||||
node->tree->root = node->bl_left;
|
||||
node->bl_left->parent = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
node->parent->link[node->parent_link] = node->bl_left;
|
||||
node->bl_left->parent = node->parent;
|
||||
node->bl_left->parent_link = node->parent_link;
|
||||
}
|
||||
}
|
||||
else if (node->bl_right)
|
||||
{
|
||||
if (node->parent == NULL)
|
||||
{
|
||||
node->tree->root = node->bl_right;
|
||||
node->bl_right->parent = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
node->parent->link[node->parent_link] = node->bl_right;
|
||||
node->bl_right->parent = node->parent;
|
||||
node->bl_right->parent_link = node->parent_link;
|
||||
}
|
||||
}
|
||||
else
|
||||
assert (0);
|
||||
}
|
||||
|
||||
int
|
||||
bintree_remove (void *data, struct bintree *tree)
|
||||
{
|
||||
int cmp;
|
||||
struct bintree_node *node;
|
||||
|
||||
node = tree->root;
|
||||
|
||||
while (node)
|
||||
{
|
||||
if (tree->cmp)
|
||||
cmp = (*tree->cmp) (node->data, data);
|
||||
else
|
||||
cmp = (node->data - data);
|
||||
|
||||
if (cmp == 0)
|
||||
break;
|
||||
|
||||
if (cmp > 0)
|
||||
node = node->bl_left;
|
||||
else /* if (cmp < 0) */
|
||||
node = node->bl_right;
|
||||
}
|
||||
|
||||
if (node == NULL)
|
||||
return -1;
|
||||
|
||||
if (node->bl_left == NULL && node->bl_right == NULL)
|
||||
{
|
||||
bintree_remove_nochild (node);
|
||||
free (node);
|
||||
tree->count--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((node->bl_left == NULL && node->bl_right != NULL) ||
|
||||
(node->bl_left != NULL && node->bl_right == NULL))
|
||||
{
|
||||
bintree_remove_onechild (node);
|
||||
free (node);
|
||||
tree->count--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (node->bl_left != NULL && node->bl_right != NULL)
|
||||
{
|
||||
struct bintree_node *successor;
|
||||
|
||||
/* find successor of the removing node */
|
||||
successor = bintree_lookup_node_min (node->bl_right);
|
||||
|
||||
/* remove successor from tree */
|
||||
if (successor->bl_right)
|
||||
bintree_remove_onechild (successor);
|
||||
else
|
||||
bintree_remove_nochild (successor);
|
||||
|
||||
/* swap removing node with successor */
|
||||
successor->parent = node->parent;
|
||||
successor->parent_link = node->parent_link;
|
||||
successor->bl_left = node->bl_left;
|
||||
successor->bl_right = node->bl_right;
|
||||
|
||||
/* if the successor was the node->bl_right itself,
|
||||
bintree_remove_**child may touch node->bl_right,
|
||||
so only the successor->bl_right may be NULL
|
||||
by above assignment */
|
||||
successor->bl_left->parent = successor;
|
||||
if (successor->bl_right)
|
||||
successor->bl_right->parent = successor;
|
||||
|
||||
if (successor->parent == NULL)
|
||||
tree->root = successor;
|
||||
else
|
||||
successor->parent->link[successor->parent_link] = successor;
|
||||
|
||||
free (node);
|
||||
tree->count--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* not reached */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* in-order traversal */
|
||||
|
||||
void
|
||||
bintree_head (struct bintree *tree, struct bintree_node *node)
|
||||
{
|
||||
struct bintree_node *head;
|
||||
|
||||
head = bintree_lookup_node_min (tree->root);
|
||||
if (head == NULL)
|
||||
{
|
||||
node->parent = NULL;
|
||||
node->bl_left = NULL;
|
||||
node->bl_right = NULL;
|
||||
node->data = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
node->tree = head->tree;
|
||||
node->parent = head->parent;
|
||||
node->parent_link = head->parent_link;
|
||||
node->bl_left = head->bl_left;
|
||||
node->bl_right = head->bl_right;
|
||||
node->data = head->data;
|
||||
}
|
||||
|
||||
int
|
||||
bintree_end (struct bintree_node *node)
|
||||
{
|
||||
if (node->parent || node->bl_left || node->bl_right || node->data)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define GOTO_PROCED_SUBTREE_TOP(node) \
|
||||
while (node->parent && node->parent->bl_right && \
|
||||
node->parent->bl_right->data == node->data) \
|
||||
{ \
|
||||
node->data = node->parent->data; \
|
||||
node->bl_left = node->parent->bl_left; \
|
||||
node->bl_right = node->parent->bl_right; \
|
||||
node->parent_link = node->parent->parent_link; \
|
||||
node->parent = node->parent->parent; \
|
||||
}
|
||||
|
||||
void
|
||||
bintree_next (struct bintree_node *node)
|
||||
{
|
||||
struct bintree_node *next = NULL;
|
||||
|
||||
/* if node have just been removed, current point should have just been
|
||||
replaced with its successor. that certainly will not be processed
|
||||
yet, so process it */
|
||||
if (node->parent == NULL)
|
||||
{
|
||||
if (node->tree->root == NULL)
|
||||
{
|
||||
assert (node->tree->count == 0);
|
||||
node->parent = NULL;
|
||||
node->bl_left = NULL;
|
||||
node->bl_right = NULL;
|
||||
node->data = NULL;
|
||||
return;
|
||||
}
|
||||
else if (node->tree->root->data != node->data)
|
||||
next = node->tree->root;
|
||||
}
|
||||
else if (node->parent->link[node->parent_link] == NULL)
|
||||
{
|
||||
if (node->parent_link == BL_LEFT)
|
||||
next = node->parent;
|
||||
else
|
||||
{
|
||||
GOTO_PROCED_SUBTREE_TOP (node);
|
||||
next = node->parent;
|
||||
}
|
||||
}
|
||||
else if (node->parent->link[node->parent_link]->data != node->data)
|
||||
next = node->parent->link[node->parent_link];
|
||||
|
||||
if (next == NULL)
|
||||
{
|
||||
if (node->bl_right)
|
||||
next = bintree_lookup_node_min (node->bl_right);
|
||||
else
|
||||
{
|
||||
GOTO_PROCED_SUBTREE_TOP (node);
|
||||
next = node->parent;
|
||||
}
|
||||
}
|
||||
|
||||
if (next)
|
||||
{
|
||||
node->tree = next->tree;
|
||||
node->parent = next->parent;
|
||||
node->parent_link = next->parent_link;
|
||||
node->bl_left = next->bl_left;
|
||||
node->bl_right = next->bl_right;
|
||||
node->data = next->data;
|
||||
}
|
||||
else
|
||||
{
|
||||
node->parent = NULL;
|
||||
node->bl_left = NULL;
|
||||
node->bl_right = NULL;
|
||||
node->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct bintree *
|
||||
bintree_create ()
|
||||
{
|
||||
struct bintree *tree;
|
||||
|
||||
tree = malloc (sizeof (struct bintree));
|
||||
memset (tree, 0, sizeof (struct bintree));
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
void
|
||||
bintree_delete (struct bintree *tree)
|
||||
{
|
||||
struct bintree_node node;
|
||||
|
||||
for (bintree_head (tree, &node); ! bintree_end (&node);
|
||||
bintree_next (&node))
|
||||
bintree_remove (node.data, tree);
|
||||
|
||||
assert (tree->count == 0);
|
||||
free (tree);
|
||||
}
|
||||
|
||||
int indent_num = 0;
|
||||
|
||||
void
|
||||
bintree_print_sub (void (*print) (int, void *), struct bintree_node *subroot)
|
||||
{
|
||||
if (subroot == NULL)
|
||||
return;
|
||||
|
||||
if (subroot->bl_right)
|
||||
{
|
||||
indent_num++;
|
||||
bintree_print_sub (print, subroot->bl_right);
|
||||
indent_num--;
|
||||
}
|
||||
|
||||
(*print) (indent_num, subroot->data);
|
||||
|
||||
if (subroot->bl_left)
|
||||
{
|
||||
indent_num++;
|
||||
bintree_print_sub (print, subroot->bl_left);
|
||||
indent_num--;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bintree_print (void (*print) (int, void *), struct bintree *tree)
|
||||
{
|
||||
indent_num = 0;
|
||||
bintree_print_sub (print, tree->root);
|
||||
}
|
||||
|
||||
|
@ -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_*/
|
||||
|
@ -1,748 +0,0 @@
|
||||
/*
|
||||
* OSPF flap dampening by Manav Bhatia
|
||||
* Copyright (C) 2002
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
* GNU Zebra is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* GNU Zebra is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Zebra; see the file COPYING. If not, write to the Free
|
||||
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "prefix.h"
|
||||
#include "thread.h"
|
||||
#include "table.h"
|
||||
#include "command.h"
|
||||
#include "vty.h"
|
||||
|
||||
extern struct thread_master *master;
|
||||
|
||||
#include "ospf6_damp.h"
|
||||
|
||||
#ifdef HAVE_OSPF6_DAMP
|
||||
|
||||
#define DELTA_REUSE 10 /* Time granularity for reuse lists */
|
||||
#define DELTA_T 5 /* Time granularity for decay arrays */
|
||||
#define DEFAULT_HALF_LIFE 60 /* (sec) 1 min */
|
||||
|
||||
#define DEFAULT_PENALTY 1000
|
||||
#define DEFAULT_REUSE 750
|
||||
#define DEFAULT_SUPPRESS 2000
|
||||
|
||||
#define REUSE_LIST_SIZE 256
|
||||
#define REUSE_ARRAY_SIZE 1024
|
||||
|
||||
/* Global variable to access damping configuration */
|
||||
struct ospf6_damp_config damp_config;
|
||||
struct ospf6_damp_config *dc = &damp_config;
|
||||
u_int reuse_array_offset = 0;
|
||||
struct route_table *damp_info_table[OSPF6_DAMP_TYPE_MAX];
|
||||
struct thread *ospf6_reuse_thread = NULL;
|
||||
|
||||
int ospf6_damp_debug = 0;
|
||||
#define IS_OSPF6_DEBUG_DAMP (ospf6_damp_debug)
|
||||
|
||||
static struct ospf6_damp_info *
|
||||
ospf6_damp_lookup (u_short type, struct prefix *name)
|
||||
{
|
||||
struct route_node *node;
|
||||
|
||||
node = route_node_lookup (damp_info_table[type], name);
|
||||
if (node && node->info)
|
||||
return (struct ospf6_damp_info *) node->info;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct ospf6_damp_info *
|
||||
ospf6_damp_create (u_short type, struct prefix *name)
|
||||
{
|
||||
struct route_node *node;
|
||||
struct ospf6_damp_info *di;
|
||||
char namebuf[64];
|
||||
|
||||
di = ospf6_damp_lookup (type, name);
|
||||
if (di)
|
||||
return di;
|
||||
|
||||
if (IS_OSPF6_DEBUG_DAMP)
|
||||
{
|
||||
prefix2str (name, namebuf, sizeof (namebuf));
|
||||
zlog_info ("DAMP: create: type: %d, name: %s", type, namebuf);
|
||||
}
|
||||
|
||||
di = (struct ospf6_damp_info *)
|
||||
malloc (sizeof (struct ospf6_damp_info));
|
||||
memset (di, 0, sizeof (struct ospf6_damp_info));
|
||||
di->type = type;
|
||||
prefix_copy (&di->name, name);
|
||||
|
||||
node = route_node_get (damp_info_table[type], name);
|
||||
node->info = di;
|
||||
|
||||
return di;
|
||||
}
|
||||
|
||||
static void
|
||||
ospf6_damp_delete (u_short type, struct prefix *name)
|
||||
{
|
||||
struct route_node *node;
|
||||
struct ospf6_damp_info *di;
|
||||
char namebuf[64];
|
||||
|
||||
node = route_node_lookup (damp_info_table[type], name);
|
||||
if (! node || ! node->info)
|
||||
return;
|
||||
|
||||
di = node->info;
|
||||
|
||||
if (IS_OSPF6_DEBUG_DAMP)
|
||||
{
|
||||
prefix2str (&di->name, namebuf, sizeof (namebuf));
|
||||
zlog_info ("DAMP: delete: type: %d, name: %s",
|
||||
di->type, namebuf);
|
||||
}
|
||||
|
||||
node->info = NULL;
|
||||
free (di);
|
||||
}
|
||||
|
||||
/* compute and fill the configuration parameter */
|
||||
void
|
||||
ospf6_damp_init_config (u_int half_life, u_int reuse,
|
||||
u_int suppress, u_int t_hold)
|
||||
{
|
||||
int i;
|
||||
double max_ratio, max_ratio1, max_ratio2;
|
||||
|
||||
dc->half_life = half_life ? half_life : DEFAULT_HALF_LIFE;
|
||||
dc->reuse = reuse ? reuse : DEFAULT_REUSE;
|
||||
dc->suppress = suppress ? suppress : DEFAULT_SUPPRESS;
|
||||
dc->t_hold = t_hold ? t_hold : 4 * dc->half_life;
|
||||
|
||||
/* Initialize system-wide params */
|
||||
dc->delta_t = DELTA_T;
|
||||
dc->delta_reuse = DELTA_REUSE;
|
||||
dc->default_penalty = DEFAULT_PENALTY;
|
||||
dc->reuse_index_array_size = REUSE_ARRAY_SIZE;
|
||||
|
||||
/* ceiling is the maximum penalty a route may attain */
|
||||
/* ceiling = reuse * 2^(T-hold/half-life) */
|
||||
dc->ceiling = (int)
|
||||
(dc->reuse * (pow (2, (double) dc->t_hold / dc->half_life)));
|
||||
|
||||
/* Decay-array computations */
|
||||
/* decay_array_size = decay memory/time granularity */
|
||||
dc->decay_array_size = ceil ((double) dc->t_hold / dc->delta_t);
|
||||
dc->decay_array = malloc (sizeof (double) * (dc->decay_array_size));
|
||||
|
||||
/* Each i-th element is per tick delay raised to the i-th power */
|
||||
dc->decay_array[0] = 1.0;
|
||||
dc->decay_array[1] = exp ((1.0 / (dc->half_life / dc->delta_t)) * log (0.5));
|
||||
for (i = 2; i < dc->decay_array_size; i++)
|
||||
dc->decay_array[i] = dc->decay_array[i - 1] * dc->decay_array[1];
|
||||
|
||||
/* Reuse-list computations (reuse queue head array ?) */
|
||||
dc->reuse_list_size = ceil ((double) dc->t_hold / dc->delta_reuse) + 1;
|
||||
if (dc->reuse_list_size == 0 || dc->reuse_list_size > REUSE_LIST_SIZE)
|
||||
dc->reuse_list_size = REUSE_LIST_SIZE;
|
||||
dc->reuse_list_array = (struct ospf6_damp_info **)
|
||||
malloc (dc->reuse_list_size * sizeof (struct ospf6_reuse_list *));
|
||||
memset (dc->reuse_list_array, 0x00,
|
||||
dc->reuse_list_size * sizeof (struct ospf6_reuse_list *));
|
||||
|
||||
/* Reuse-array computations */
|
||||
dc->reuse_index_array = malloc (sizeof (int) * dc->reuse_index_array_size);
|
||||
|
||||
/*
|
||||
* This is the maximum ratio between the current value of the penalty and
|
||||
* the reuse value which can be indexed by the reuse array. It will be
|
||||
* limited by the ceiling or by the amount of time that the reuse list
|
||||
* covers
|
||||
*/
|
||||
max_ratio1 = (double) dc->ceiling / dc->reuse;
|
||||
max_ratio2 = exp ((double) dc->t_hold / dc->half_life) * log10 (2.0);
|
||||
max_ratio = (max_ratio2 != 0 && max_ratio2 < max_ratio1 ?
|
||||
max_ratio2 : max_ratio1);
|
||||
|
||||
/*
|
||||
* reuse array is just an estimator and we need something
|
||||
* to use the full array
|
||||
*/
|
||||
dc->scale_factor = (double) dc->reuse_index_array_size / (max_ratio - 1);
|
||||
|
||||
for (i = 0; i < dc->reuse_index_array_size; i++)
|
||||
{
|
||||
dc->reuse_index_array[i] = (int)
|
||||
(((double) dc->half_life / dc->delta_reuse) *
|
||||
log10 (1.0 / (dc->reuse * (1.0 + ((double) i / dc->scale_factor))))
|
||||
/ log10 (0.5));
|
||||
}
|
||||
|
||||
dc->enabled = ON;
|
||||
}
|
||||
|
||||
static double
|
||||
ospf6_damp_decay (time_t tdiff)
|
||||
{
|
||||
int index = tdiff / dc->delta_t;
|
||||
|
||||
if (index >= dc->decay_array_size)
|
||||
return 0;
|
||||
|
||||
return dc->decay_array[index];
|
||||
}
|
||||
|
||||
static int
|
||||
ospf6_damp_reuse_index (int penalty)
|
||||
{
|
||||
int index;
|
||||
|
||||
index = (int) (((double) penalty / dc->reuse - 1.0) * dc->scale_factor);
|
||||
|
||||
if (index >= dc->reuse_index_array_size)
|
||||
index = dc->reuse_index_array_size - 1;
|
||||
|
||||
return (dc->reuse_index_array[index] - dc->reuse_index_array[0]);
|
||||
}
|
||||
|
||||
static int
|
||||
ospf6_reuse_list_lookup (struct ospf6_damp_info *di)
|
||||
{
|
||||
struct ospf6_damp_info *info;
|
||||
|
||||
for (info = dc->reuse_list_array[di->index]; info; info = info->next)
|
||||
{
|
||||
if (info == di)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ospf6_reuse_list_remove (struct ospf6_damp_info *di)
|
||||
{
|
||||
if (di->prev)
|
||||
di->prev->next = di->next;
|
||||
else
|
||||
dc->reuse_list_array[di->index] = di->next;
|
||||
if (di->next)
|
||||
di->next->prev = di->prev;
|
||||
|
||||
di->index = -1;
|
||||
di->prev = NULL;
|
||||
di->next = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
ospf6_reuse_list_add (struct ospf6_damp_info *di)
|
||||
{
|
||||
/* set the index of reuse-array */
|
||||
di->index = (reuse_array_offset + (ospf6_damp_reuse_index (di->penalty)))
|
||||
% dc->reuse_list_size;
|
||||
|
||||
/* insert to the head of the reuse list */
|
||||
di->next = dc->reuse_list_array[di->index];
|
||||
if (di->next)
|
||||
di->next->prev = di;
|
||||
di->prev = NULL;
|
||||
dc->reuse_list_array[di->index] = di;
|
||||
}
|
||||
|
||||
/* When we quit damping for a target, we should execute proper event
|
||||
which have been postponed during damping */
|
||||
static void
|
||||
ospf6_damp_stop (struct ospf6_damp_info *di)
|
||||
{
|
||||
time_t t_now;
|
||||
char namebuf[64];
|
||||
struct timeval now;
|
||||
|
||||
if (IS_OSPF6_DEBUG_DAMP)
|
||||
{
|
||||
t_now = time (NULL);
|
||||
prefix2str (&di->name, namebuf, sizeof (namebuf));
|
||||
gettimeofday (&now, NULL);
|
||||
zlog_info ("DAMP: %lu.%06lu stop damping: %ld: type: %d, name: %s",
|
||||
now.tv_sec, now.tv_usec,
|
||||
(long)t_now, di->type, namebuf);
|
||||
}
|
||||
|
||||
/* set flag indicates that we're damping this target */
|
||||
di->damping = OFF;
|
||||
|
||||
/* if the target's current status differ from that it should be,
|
||||
execute the proper event to repair his status */
|
||||
if (di->target_status != di->event_type)
|
||||
{
|
||||
(*(di->event)) (di->target);
|
||||
di->target_status = di->event_type;
|
||||
|
||||
di->event = NULL;
|
||||
di->event_type = event_none;
|
||||
}
|
||||
}
|
||||
|
||||
/* ospf6_reuse_timer is called every DELTA_REUSE seconds.
|
||||
Each route in the current reuse-list is evaluated
|
||||
and is used or requeued */
|
||||
int
|
||||
ospf6_damp_reuse_timer (struct thread *t)
|
||||
{
|
||||
struct ospf6_damp_info *di, *next;
|
||||
time_t t_now, t_diff;
|
||||
char namebuf[64];
|
||||
struct timeval now;
|
||||
|
||||
/* Restart the reuse timer */
|
||||
ospf6_reuse_thread =
|
||||
thread_add_timer (master, ospf6_damp_reuse_timer, NULL, dc->delta_reuse);
|
||||
|
||||
t_now = time (NULL);
|
||||
|
||||
/* get the damp info list head */
|
||||
di = dc->reuse_list_array[reuse_array_offset];
|
||||
dc->reuse_list_array[reuse_array_offset] = NULL;
|
||||
|
||||
/* rotate the circular reuse list head array */
|
||||
reuse_array_offset = (reuse_array_offset + 1) % dc->reuse_list_size;
|
||||
|
||||
/* for each damp info */
|
||||
while (di)
|
||||
{
|
||||
next = di->next;
|
||||
di->next = NULL;
|
||||
|
||||
/* Update penalty */
|
||||
t_diff = t_now - di->t_updated;
|
||||
di->t_updated = t_now;
|
||||
di->penalty = (int)
|
||||
((double) di->penalty * ospf6_damp_decay (t_diff));
|
||||
/* configration of ceiling may be just changed */
|
||||
if (di->penalty > dc->ceiling)
|
||||
di->penalty = dc->ceiling;
|
||||
|
||||
if (IS_OSPF6_DEBUG_DAMP)
|
||||
{
|
||||
prefix2str (&di->name, namebuf, sizeof (namebuf));
|
||||
gettimeofday (&now, NULL);
|
||||
zlog_info ("DAMP: %lu.%06lu update penalty: type: %d, name: %s, penalty: %d",
|
||||
now.tv_sec, now.tv_usec,
|
||||
di->type, namebuf, di->penalty);
|
||||
}
|
||||
|
||||
/* If the penalty becomes under reuse,
|
||||
call real event that we have been postponed. */
|
||||
if (di->penalty < dc->reuse && di->damping == ON)
|
||||
ospf6_damp_stop (di);
|
||||
|
||||
/* If the penalty becomes less than the half of the
|
||||
reuse value, this damp info will be freed from reuse-list,
|
||||
by assuming that it is considered to be stable enough already,
|
||||
and there's no need to maintain flapping history for this. */
|
||||
if (di->penalty <= dc->reuse / 2)
|
||||
{
|
||||
ospf6_damp_delete (di->type, &di->name);
|
||||
di = next;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* re-insert to the reuse-list */
|
||||
ospf6_reuse_list_add (di);
|
||||
|
||||
di = next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ospf6_damp_event (damp_event_t event_type,
|
||||
u_short type, struct prefix *name,
|
||||
int (*event) (void *), void *target)
|
||||
{
|
||||
time_t t_now, t_diff;
|
||||
struct ospf6_damp_info *di;
|
||||
char namebuf[64];
|
||||
struct timeval now;
|
||||
|
||||
if (dc->enabled == OFF)
|
||||
{
|
||||
(*event) (target);
|
||||
return;
|
||||
}
|
||||
|
||||
di = ospf6_damp_lookup (type, name);
|
||||
if (! di)
|
||||
di = ospf6_damp_create (type, name);
|
||||
|
||||
t_now = time (NULL);
|
||||
|
||||
di->event = event;
|
||||
di->target = target;
|
||||
di->event_type = event_type;
|
||||
|
||||
if (! ospf6_reuse_list_lookup (di))
|
||||
di->t_start = t_now;
|
||||
else
|
||||
{
|
||||
ospf6_reuse_list_remove (di);
|
||||
|
||||
t_diff = t_now - di->t_updated;
|
||||
di->penalty = (int) (di->penalty * ospf6_damp_decay (t_diff));
|
||||
}
|
||||
|
||||
/* penalty only on down event */
|
||||
if (event_type == event_down)
|
||||
{
|
||||
di->flap++;
|
||||
di->penalty += dc->default_penalty;
|
||||
}
|
||||
|
||||
/* limit penalty up to ceiling */
|
||||
if (di->penalty > dc->ceiling)
|
||||
di->penalty = dc->ceiling;
|
||||
|
||||
if (IS_OSPF6_DEBUG_DAMP)
|
||||
{
|
||||
prefix2str (&di->name, namebuf, sizeof (namebuf));
|
||||
gettimeofday (&now, NULL);
|
||||
zlog_info ("DAMP: %lu.%06lu update penalty: type: %d, name: %s, penalty: %d",
|
||||
now.tv_sec, now.tv_usec,
|
||||
di->type, namebuf, di->penalty);
|
||||
}
|
||||
|
||||
/* if penalty < reuse, stop damping here */
|
||||
if (di->penalty < dc->reuse && di->damping == ON)
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_DAMP)
|
||||
{
|
||||
prefix2str (&di->name, namebuf, sizeof (namebuf));
|
||||
gettimeofday (&now, NULL);
|
||||
zlog_info ("DAMP: %lu.%06lu stop damping: %ld: type: %d, name: %s",
|
||||
now.tv_sec, now.tv_usec,
|
||||
(long)t_now, di->type, namebuf);
|
||||
}
|
||||
di->damping = OFF;
|
||||
}
|
||||
|
||||
/* if event == up and if penalty >= suppress , start damping here */
|
||||
if (di->event_type == event_up && di->penalty >= dc->suppress &&
|
||||
di->damping == OFF)
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_DAMP)
|
||||
{
|
||||
prefix2str (&di->name, namebuf, sizeof (namebuf));
|
||||
gettimeofday (&now, NULL);
|
||||
zlog_info ("DAMP: %lu.%06lu start damping: %ld: type: %d, name: %s",
|
||||
now.tv_sec, now.tv_usec,
|
||||
(long)t_now, type, namebuf);
|
||||
}
|
||||
di->damping = ON;
|
||||
}
|
||||
|
||||
/* execute event if we're not damping */
|
||||
if (di->damping == OFF)
|
||||
{
|
||||
(*(di->event)) (di->target);
|
||||
di->target_status = di->event_type;
|
||||
}
|
||||
|
||||
/* if the penalty goes beyond suppress value, start damping */
|
||||
if (di->penalty >= dc->suppress && di->damping == OFF)
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_DAMP)
|
||||
{
|
||||
prefix2str (name, namebuf, sizeof (namebuf));
|
||||
gettimeofday (&now, NULL);
|
||||
zlog_info ("DAMP: %lu.%06lu start damping: %ld: type: %d, name: %s",
|
||||
now.tv_sec, now.tv_usec,
|
||||
(long) t_now, type, namebuf);
|
||||
}
|
||||
di->damping = ON;
|
||||
}
|
||||
|
||||
/* update last-updated-time field */
|
||||
di->t_updated = t_now;
|
||||
|
||||
/* Insert it into the reuse list */
|
||||
ospf6_reuse_list_add (di);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_damp_event_up (u_short type, struct prefix *name,
|
||||
int (*event) (void *), void *target)
|
||||
{
|
||||
struct timeval now;
|
||||
|
||||
gettimeofday (&now, NULL);
|
||||
if (IS_OSPF6_DEBUG_DAMP)
|
||||
zlog_info ("DAMP: Up Event at %lu.%06lu", now.tv_sec, now.tv_usec);
|
||||
|
||||
ospf6_damp_event (event_up, type, name, event, target);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_damp_event_down (u_short type, struct prefix *name,
|
||||
int (*event) (void *), void *target)
|
||||
{
|
||||
struct timeval now;
|
||||
|
||||
gettimeofday (&now, NULL);
|
||||
if (IS_OSPF6_DEBUG_DAMP)
|
||||
zlog_info ("DAMP: Down Event at %lu.%06lu", now.tv_sec, now.tv_usec);
|
||||
|
||||
ospf6_damp_event (event_down, type, name, event, target);
|
||||
}
|
||||
|
||||
int
|
||||
ospf6_damp_debug_thread (struct thread *thread)
|
||||
{
|
||||
int i;
|
||||
struct ospf6_damp_info *di;
|
||||
char buf[256];
|
||||
time_t t_now;
|
||||
struct timeval now;
|
||||
|
||||
for (i = 0; i < dc->reuse_list_size; i++)
|
||||
{
|
||||
for (di = dc->reuse_list_array[i]; di; di = di->next)
|
||||
{
|
||||
t_now = time (NULL);
|
||||
gettimeofday (&now, NULL);
|
||||
prefix2str (&di->name, buf, sizeof (buf));
|
||||
zlog_info ("DAMP: %lu.%06lu %c %-32s penalty %7u",
|
||||
now.tv_sec, now.tv_usec,
|
||||
(di->damping == ON ? 'D' : 'A'), buf,
|
||||
(u_int) (di->penalty *
|
||||
ospf6_damp_decay (t_now - di->t_updated)));
|
||||
}
|
||||
}
|
||||
thread_add_timer (master, ospf6_damp_debug_thread, NULL, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFUN (show_ipv6_ospf6_route_flapping,
|
||||
show_ipv6_ospf6_route_flapping_cmd,
|
||||
"show ipv6 ospf6 route flapping",
|
||||
SHOW_STR
|
||||
IP6_STR
|
||||
OSPF6_STR)
|
||||
{
|
||||
int i;
|
||||
struct ospf6_damp_info *di;
|
||||
char buf[256];
|
||||
time_t t_now;
|
||||
|
||||
t_now = time (NULL);
|
||||
vty_out (vty, "%c %-32s %7s%s", ' ', "Prefix", "penalty", VTY_NEWLINE);
|
||||
|
||||
for (i = 0; i < dc->reuse_list_size; i++)
|
||||
{
|
||||
for (di = dc->reuse_list_array[i]; di; di = di->next)
|
||||
{
|
||||
prefix2str (&di->name, buf, sizeof (buf));
|
||||
vty_out (vty, "%c %-32s %7u%s",
|
||||
(di->damping == ON ? 'D' : ' '), buf,
|
||||
(u_int) (di->penalty *
|
||||
ospf6_damp_decay (t_now - di->t_updated)),
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ospf6_flap_damping_route,
|
||||
ospf6_flap_damping_route_cmd,
|
||||
"flap-damping route <0-4294967295> <0-4294967295> "
|
||||
"<0-4294967295> <0-4294967295>",
|
||||
"enable flap dampening\n"
|
||||
"enable route flap dampening\n"
|
||||
"half-life in second\n"
|
||||
"reuse value\n"
|
||||
"suppress value\n"
|
||||
"t-hold in second (maximum time that the target can be damped)\n"
|
||||
)
|
||||
{
|
||||
u_int half_life, reuse, suppress, t_hold;
|
||||
|
||||
if (argc)
|
||||
{
|
||||
half_life = (u_int) strtoul (argv[0], NULL, 10);
|
||||
reuse = (u_int) strtoul (argv[1], NULL, 10);
|
||||
suppress = (u_int) strtoul (argv[2], NULL, 10);
|
||||
t_hold = (u_int) strtoul (argv[3], NULL, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
half_life = (u_int) DEFAULT_HALF_LIFE;
|
||||
reuse = (u_int) DEFAULT_REUSE;
|
||||
suppress = (u_int) DEFAULT_SUPPRESS;
|
||||
t_hold = (u_int) DEFAULT_HALF_LIFE * 4;
|
||||
}
|
||||
|
||||
if (reuse && suppress && reuse >= suppress)
|
||||
{
|
||||
vty_out (vty, "reuse value exceeded suppress value, failed%s\n",
|
||||
VTY_NEWLINE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
if (half_life && t_hold && half_life >= t_hold)
|
||||
{
|
||||
vty_out (vty, "half-life exceeded t-hold, failed%s\n", VTY_NEWLINE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
ospf6_damp_init_config (half_life, reuse, suppress, t_hold);
|
||||
|
||||
if (ospf6_reuse_thread == NULL)
|
||||
ospf6_reuse_thread =
|
||||
thread_add_timer (master, ospf6_damp_reuse_timer, NULL, dc->delta_reuse);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_ipv6_ospf6_damp_config,
|
||||
show_ipv6_ospf6_camp_config_cmd,
|
||||
"show ipv6 ospf6 damp config",
|
||||
SHOW_STR
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"Flap-dampening information\n"
|
||||
"shows dampening configuration\n"
|
||||
)
|
||||
{
|
||||
int i;
|
||||
|
||||
vty_out (vty, "%10s %10s %10s %10s%s",
|
||||
"Half life", "Suppress", "Reuse", "T-hold",
|
||||
VTY_NEWLINE);
|
||||
vty_out (vty, "%10u %10u %10u %10u%s",
|
||||
dc->half_life, dc->suppress, dc->reuse, dc->t_hold,
|
||||
VTY_NEWLINE);
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
|
||||
vty_out (vty, "Delta-t = %u%s", dc->delta_t, VTY_NEWLINE);
|
||||
vty_out (vty, "Delta-Reuse = %u%s", dc->delta_reuse, VTY_NEWLINE);
|
||||
vty_out (vty, "Default-Penalty = %u%s", dc->default_penalty, VTY_NEWLINE);
|
||||
vty_out (vty, "Ceiling = %u%s", dc->ceiling, VTY_NEWLINE);
|
||||
vty_out (vty, "ScaleFactor = %f%s", dc->scale_factor, VTY_NEWLINE);
|
||||
|
||||
vty_out (vty, "DecayArray(%d) =%s", dc->decay_array_size, VTY_NEWLINE);
|
||||
for (i = 0; i < dc->decay_array_size; i++)
|
||||
{
|
||||
if (i % 10 == 0)
|
||||
vty_out (vty, " ");
|
||||
vty_out (vty, " %f", dc->decay_array[i]);
|
||||
if (i % 10 == 0)
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
}
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
|
||||
vty_out (vty, "ReuseIndexArray(%d) =%s",
|
||||
dc->reuse_index_array_size, VTY_NEWLINE);
|
||||
for (i = 0; i < dc->reuse_index_array_size; i++)
|
||||
{
|
||||
if (i % 10 == 0)
|
||||
vty_out (vty, " ");
|
||||
vty_out (vty, " %d", dc->reuse_index_array[i]);
|
||||
if (i % 10 == 0)
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
}
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_damp_config_write (struct vty *vty)
|
||||
{
|
||||
if (dc->enabled == ON)
|
||||
{
|
||||
vty_out (vty, " flap-damping route %u %u %u %u%s",
|
||||
dc->half_life, dc->reuse, dc->suppress, dc->t_hold,
|
||||
VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
||||
DEFUN (debug_ospf6_damp,
|
||||
debug_ospf6_damp_cmd,
|
||||
"debug ospf6 damp",
|
||||
DEBUG_STR
|
||||
OSPF6_STR
|
||||
"Flap-dampening information\n"
|
||||
)
|
||||
{
|
||||
ospf6_damp_debug = 1;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_debug_ospf6_damp,
|
||||
no_debug_ospf6_damp_cmd,
|
||||
"no debug ospf6 damp",
|
||||
NO_STR
|
||||
DEBUG_STR
|
||||
OSPF6_STR
|
||||
"Flap-dampening information\n"
|
||||
)
|
||||
{
|
||||
ospf6_damp_debug = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_debug_ospf6_damp,
|
||||
show_debug_ospf6_damp_cmd,
|
||||
"show debugging ospf6 damp",
|
||||
SHOW_STR
|
||||
DEBUG_STR
|
||||
OSPF6_STR
|
||||
"Flap-dampening information\n"
|
||||
)
|
||||
{
|
||||
vty_out (vty, "debugging ospf6 damp is ");
|
||||
if (IS_OSPF6_DEBUG_DAMP)
|
||||
vty_out (vty, "enabled.");
|
||||
else
|
||||
vty_out (vty, "disabled.");
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_damp_init ()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < OSPF6_DAMP_TYPE_MAX; i++)
|
||||
damp_info_table[i] = route_table_init ();
|
||||
|
||||
install_element (VIEW_NODE, &show_ipv6_ospf6_route_flapping_cmd);
|
||||
install_element (ENABLE_NODE, &show_ipv6_ospf6_route_flapping_cmd);
|
||||
install_element (ENABLE_NODE, &show_ipv6_ospf6_camp_config_cmd);
|
||||
install_element (OSPF6_NODE, &ospf6_flap_damping_route_cmd);
|
||||
|
||||
install_element (ENABLE_NODE, &show_debug_ospf6_damp_cmd);
|
||||
install_element (CONFIG_NODE, &debug_ospf6_damp_cmd);
|
||||
install_element (CONFIG_NODE, &no_debug_ospf6_damp_cmd);
|
||||
|
||||
thread_add_event (master, ospf6_damp_debug_thread, NULL, 0);
|
||||
}
|
||||
|
||||
#endif /* HAVE_OSPF6_DAMP */
|
||||
|
||||
|
@ -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 ();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -1,315 +0,0 @@
|
||||
/*
|
||||
* Logging function
|
||||
* Copyright (C) 1999-2002 Yasuhiro Ohara
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
* GNU Zebra is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* GNU Zebra is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Zebra; see the file COPYING. If not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
/* Include other stuffs */
|
||||
#include "log.h"
|
||||
#include "command.h"
|
||||
#include "ospf6_dump.h"
|
||||
|
||||
#define CMD_SHOW 0
|
||||
#define CMD_ENABLE 1
|
||||
#define CMD_DISABLE 2
|
||||
#define CMD_MAX 3
|
||||
|
||||
struct ospf6_dump
|
||||
{
|
||||
struct cmd_element cmd[CMD_MAX];
|
||||
char *name;
|
||||
int config;
|
||||
};
|
||||
|
||||
#define DUMP_MAX 512
|
||||
struct ospf6_dump *ospf6_dump[DUMP_MAX];
|
||||
unsigned int dump_size = 0;
|
||||
|
||||
static int
|
||||
ospf6_dump_index (struct cmd_element *cmd, int command)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DUMP_MAX; i++)
|
||||
{
|
||||
if (cmd != &ospf6_dump[i]->cmd[command])
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == DUMP_MAX)
|
||||
return -1;
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
ospf6_dump_is_on (int index)
|
||||
{
|
||||
if (ospf6_dump[index] == NULL)
|
||||
return 0;
|
||||
|
||||
return ospf6_dump[index]->config;
|
||||
}
|
||||
|
||||
int
|
||||
ospf6_dump_show (struct cmd_element *cmd,
|
||||
struct vty *vty, int argc, char **argv)
|
||||
{
|
||||
int index;
|
||||
|
||||
index = ospf6_dump_index (cmd, CMD_SHOW);
|
||||
assert (index != -1);
|
||||
|
||||
vty_out (vty, " %-16s: %s%s", ospf6_dump[index]->name,
|
||||
(ospf6_dump[index]->config ? "on" : "off"),
|
||||
VTY_NEWLINE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
ospf6_dump_enable (struct cmd_element *cmd,
|
||||
struct vty *vty, int argc, char **argv)
|
||||
{
|
||||
int index;
|
||||
|
||||
index = ospf6_dump_index (cmd, CMD_ENABLE);
|
||||
assert (index != -1);
|
||||
|
||||
ospf6_dump[index]->config = 1;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
ospf6_dump_disable (struct cmd_element *cmd,
|
||||
struct vty *vty, int argc, char **argv)
|
||||
{
|
||||
int index;
|
||||
|
||||
index = ospf6_dump_index (cmd, CMD_DISABLE);
|
||||
assert (index != -1);
|
||||
|
||||
ospf6_dump[index]->config = 0;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
ospf6_dump_install (char *name, char *help)
|
||||
{
|
||||
struct cmd_element *cmd;
|
||||
char string[256];
|
||||
char helpstring[256];
|
||||
|
||||
if (dump_size + 1 >= DUMP_MAX)
|
||||
return -1;
|
||||
|
||||
ospf6_dump[dump_size] = malloc (sizeof (struct ospf6_dump));
|
||||
if (ospf6_dump[dump_size] == NULL)
|
||||
return -1;
|
||||
memset (ospf6_dump[dump_size], 0, sizeof (struct ospf6_dump));
|
||||
|
||||
ospf6_dump[dump_size]->name = strdup (name);
|
||||
|
||||
cmd = &ospf6_dump[dump_size]->cmd[CMD_SHOW];
|
||||
snprintf (string, sizeof (string), "show debugging ospf6 %s", name);
|
||||
snprintf (helpstring, sizeof (helpstring), "%s%s%s%s",
|
||||
SHOW_STR, DEBUG_STR, OSPF6_STR, help);
|
||||
memset (cmd, 0, sizeof (struct cmd_element));
|
||||
cmd->string = strdup (string);
|
||||
cmd->func = ospf6_dump_show;
|
||||
cmd->doc = strdup (helpstring);
|
||||
install_element (VIEW_NODE, cmd);
|
||||
install_element (ENABLE_NODE, cmd);
|
||||
|
||||
cmd = &ospf6_dump[dump_size]->cmd[CMD_ENABLE];
|
||||
snprintf (string, sizeof (string), "debug ospf6 %s", name);
|
||||
snprintf (helpstring, sizeof (helpstring), "%s%s%s",
|
||||
DEBUG_STR, OSPF6_STR, help);
|
||||
memset (cmd, 0, sizeof (struct cmd_element));
|
||||
cmd->string = strdup (string);
|
||||
cmd->func = ospf6_dump_enable;
|
||||
cmd->doc = strdup (helpstring);
|
||||
install_element (CONFIG_NODE, cmd);
|
||||
|
||||
cmd = &ospf6_dump[dump_size]->cmd[CMD_DISABLE];
|
||||
snprintf (string, sizeof (string), "no debug ospf6 %s", name);
|
||||
snprintf (helpstring, sizeof (helpstring), "%s%s%s%s",
|
||||
NO_STR, DEBUG_STR, OSPF6_STR, help);
|
||||
memset (cmd, 0, sizeof (struct cmd_element));
|
||||
cmd->string = strdup (string);
|
||||
cmd->func = ospf6_dump_disable;
|
||||
cmd->doc = strdup (helpstring);
|
||||
install_element (CONFIG_NODE, cmd);
|
||||
|
||||
return dump_size++;
|
||||
}
|
||||
|
||||
DEFUN(show_debug_ospf6,
|
||||
show_debug_ospf6_cmd,
|
||||
"show debugging ospf6",
|
||||
SHOW_STR
|
||||
DEBUG_STR
|
||||
OSPF6_STR)
|
||||
{
|
||||
int i;
|
||||
|
||||
vty_out (vty, "OSPF6 debugging status:%s", VTY_NEWLINE);
|
||||
|
||||
for (i = 0; i < DUMP_MAX; i++)
|
||||
{
|
||||
if (ospf6_dump[i] == NULL)
|
||||
continue;
|
||||
ospf6_dump_show (&ospf6_dump[i]->cmd[CMD_SHOW], vty, 0, NULL);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (debug_ospf6_all,
|
||||
debug_ospf6_all_cmd,
|
||||
"debug ospf6 all",
|
||||
DEBUG_STR
|
||||
OSPF6_STR
|
||||
"Turn on ALL OSPFv3 debugging\n")
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DUMP_MAX; i++)
|
||||
{
|
||||
if (ospf6_dump[i] == NULL)
|
||||
continue;
|
||||
ospf6_dump_enable (&ospf6_dump[i]->cmd[CMD_ENABLE], vty, 0, NULL);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_debug_ospf6_all,
|
||||
no_debug_ospf6_all_cmd,
|
||||
"no debug ospf6 all",
|
||||
NO_STR
|
||||
DEBUG_STR
|
||||
OSPF6_STR
|
||||
"Turn off ALL OSPFv3 debugging\n")
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DUMP_MAX; i++)
|
||||
{
|
||||
if (ospf6_dump[i] == NULL)
|
||||
continue;
|
||||
ospf6_dump_disable (&ospf6_dump[i]->cmd[CMD_DISABLE], vty, 0, NULL);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
struct cmd_node debug_node =
|
||||
{
|
||||
DEBUG_NODE,
|
||||
"",
|
||||
vtysh: 1
|
||||
};
|
||||
|
||||
int
|
||||
ospf6_dump_config_write (struct vty *vty)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dump_size; i++)
|
||||
{
|
||||
if (ospf6_dump[i] == NULL)
|
||||
continue;
|
||||
|
||||
if (ospf6_dump[i]->config == 0)
|
||||
continue;
|
||||
|
||||
vty_out (vty, "debug ospf6 %s%s", ospf6_dump[i]->name, VTY_NEWLINE);
|
||||
}
|
||||
|
||||
vty_out (vty, "!%s", VTY_NEWLINE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char dump_index[OSPF6_DUMP_MAX];
|
||||
|
||||
void
|
||||
ospf6_dump_init ()
|
||||
{
|
||||
memset (ospf6_dump, 0, sizeof (ospf6_dump));
|
||||
|
||||
install_node (&debug_node, ospf6_dump_config_write);
|
||||
|
||||
install_element (VIEW_NODE, &show_debug_ospf6_cmd);
|
||||
install_element (ENABLE_NODE, &show_debug_ospf6_cmd);
|
||||
|
||||
install_element (CONFIG_NODE, &debug_ospf6_all_cmd);
|
||||
install_element (CONFIG_NODE, &no_debug_ospf6_all_cmd);
|
||||
|
||||
/* bellow is for backward compatibility
|
||||
should be moved to each modules */
|
||||
|
||||
#define MESSAGE_STR "OSPFv3 Messages\n"
|
||||
|
||||
dump_index[OSPF6_DUMP_HELLO] =
|
||||
ospf6_dump_install ("message hello",
|
||||
MESSAGE_STR "Hello\n");
|
||||
dump_index[OSPF6_DUMP_DBDESC] =
|
||||
ospf6_dump_install ("message dbdesc",
|
||||
MESSAGE_STR "Database Description\n");
|
||||
dump_index[OSPF6_DUMP_LSREQ] =
|
||||
ospf6_dump_install ("message lsreq",
|
||||
MESSAGE_STR "Link State Request\n");
|
||||
dump_index[OSPF6_DUMP_LSUPDATE] =
|
||||
ospf6_dump_install ("message lsupdate",
|
||||
MESSAGE_STR "Link State Update\n");
|
||||
dump_index[OSPF6_DUMP_LSACK] =
|
||||
ospf6_dump_install ("message lsack",
|
||||
MESSAGE_STR "Link State Acknowledge\n");
|
||||
dump_index[OSPF6_DUMP_NEIGHBOR] =
|
||||
ospf6_dump_install ("neighbor", "Neighbors\n");
|
||||
dump_index[OSPF6_DUMP_INTERFACE] =
|
||||
ospf6_dump_install ("interface", "Interfaces\n");
|
||||
dump_index[OSPF6_DUMP_LSA] =
|
||||
ospf6_dump_install ("lsa", "Link State Advertisement\n");
|
||||
dump_index[OSPF6_DUMP_ZEBRA] =
|
||||
ospf6_dump_install ("zebra", "Communication with zebra\n");
|
||||
dump_index[OSPF6_DUMP_CONFIG] =
|
||||
ospf6_dump_install ("config", "Configuration Changes\n");
|
||||
dump_index[OSPF6_DUMP_DBEX] =
|
||||
ospf6_dump_install ("dbex", "Database Exchange/Flooding\n");
|
||||
dump_index[OSPF6_DUMP_SPF] =
|
||||
ospf6_dump_install ("spf", "SPF Calculation\n");
|
||||
dump_index[OSPF6_DUMP_ROUTE] =
|
||||
ospf6_dump_install ("route", "Route Calculation\n");
|
||||
dump_index[OSPF6_DUMP_LSDB] =
|
||||
ospf6_dump_install ("lsdb", "Link State Database\n");
|
||||
dump_index[OSPF6_DUMP_REDISTRIBUTE] =
|
||||
ospf6_dump_install ("redistribute",
|
||||
"Route Exchange with other protocols\n");
|
||||
dump_index[OSPF6_DUMP_HOOK] =
|
||||
ospf6_dump_install ("hook", "Hooks\n");
|
||||
dump_index[OSPF6_DUMP_ASBR] =
|
||||
ospf6_dump_install ("asbr", "AS Boundary Router function\n");
|
||||
dump_index[OSPF6_DUMP_PREFIX] =
|
||||
ospf6_dump_install ("prefix", "Prefix\n");
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -1,174 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Yasuhiro Ohara
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
* GNU Zebra is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* GNU Zebra is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Zebra; see the file COPYING. If not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "memory.h"
|
||||
|
||||
#include "ospf6_hook.h"
|
||||
|
||||
struct ospf6_hook_master neighbor_hook;
|
||||
struct ospf6_hook_master interface_hook;
|
||||
struct ospf6_hook_master area_hook;
|
||||
struct ospf6_hook_master top_hook;
|
||||
struct ospf6_hook_master database_hook;
|
||||
struct ospf6_hook_master intra_topology_hook;
|
||||
struct ospf6_hook_master inter_topology_hook;
|
||||
struct ospf6_hook_master route_hook;
|
||||
struct ospf6_hook_master redistribute_hook;
|
||||
|
||||
static struct ospf6_hook *
|
||||
ospf6_hook_create ()
|
||||
{
|
||||
struct ospf6_hook *new;
|
||||
new = XMALLOC (MTYPE_OSPF6_OTHER, sizeof (struct ospf6_hook));
|
||||
if (new == NULL)
|
||||
return NULL;
|
||||
memset (new, 0, sizeof (struct ospf6_hook));
|
||||
return new;
|
||||
}
|
||||
|
||||
static void
|
||||
ospf6_hook_delete (struct ospf6_hook *hook)
|
||||
{
|
||||
XFREE (MTYPE_OSPF6_OTHER, hook);
|
||||
}
|
||||
|
||||
static int
|
||||
ospf6_hook_issame (struct ospf6_hook *hook1, struct ospf6_hook *hook2)
|
||||
{
|
||||
if (hook1->name && hook2->name &&
|
||||
strcmp (hook1->name, hook2->name) != 0)
|
||||
return 0;
|
||||
if (hook1->hook_add != hook2->hook_add)
|
||||
return 0;
|
||||
if (hook1->hook_change != hook2->hook_change)
|
||||
return 0;
|
||||
if (hook1->hook_remove != hook2->hook_remove)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_hook_register (struct ospf6_hook *hook,
|
||||
struct ospf6_hook_master *master)
|
||||
{
|
||||
struct ospf6_hook *new;
|
||||
|
||||
new = ospf6_hook_create ();
|
||||
|
||||
if (hook->name)
|
||||
new->name = strdup (hook->name);
|
||||
new->hook_add = hook->hook_add;
|
||||
new->hook_change = hook->hook_change;
|
||||
new->hook_remove = hook->hook_remove;
|
||||
|
||||
new->prev = master->tail;
|
||||
if (master->tail)
|
||||
master->tail->next = new;
|
||||
|
||||
master->tail = new;
|
||||
if (! master->head)
|
||||
master->head = new;
|
||||
|
||||
master->count++;
|
||||
|
||||
if (IS_OSPF6_DUMP_HOOK)
|
||||
{
|
||||
zlog_info ("HOOK: Register hook%s%s%s%s",
|
||||
(hook->name ? " " : ""),
|
||||
(hook->name ? hook->name : ""),
|
||||
(master->name ? " to " : ""),
|
||||
(master->name ? master->name : ""));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_hook_unregister (struct ospf6_hook *req,
|
||||
struct ospf6_hook_master *master)
|
||||
{
|
||||
struct ospf6_hook *hook;
|
||||
|
||||
for (hook = master->head; hook; hook = hook->next)
|
||||
{
|
||||
if (ospf6_hook_issame (hook, req))
|
||||
break;
|
||||
}
|
||||
if (! hook)
|
||||
return;
|
||||
|
||||
if (hook->prev)
|
||||
hook->prev->next = hook->next;
|
||||
if (hook->next)
|
||||
hook->next->prev = hook->prev;
|
||||
if (master->head == hook)
|
||||
master->head = hook->next;
|
||||
if (master->tail == hook)
|
||||
master->tail = hook->prev;
|
||||
|
||||
master->count--;
|
||||
|
||||
if (IS_OSPF6_DUMP_HOOK)
|
||||
{
|
||||
zlog_info ("HOOK: Unregister hook%s%s%s%s",
|
||||
(hook->name ? " " : ""),
|
||||
(hook->name ? hook->name : ""),
|
||||
(master->name ? " to " : ""),
|
||||
(master->name ? master->name : ""));
|
||||
}
|
||||
|
||||
if (hook->name)
|
||||
free (hook->name);
|
||||
ospf6_hook_delete (hook);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_hook_unregister_all (struct ospf6_hook_master *master)
|
||||
{
|
||||
struct ospf6_hook *hook, *next;
|
||||
|
||||
for (hook = master->head; hook; hook = next)
|
||||
{
|
||||
next = hook->next;
|
||||
ospf6_hook_delete (hook);
|
||||
}
|
||||
|
||||
master->head = NULL;
|
||||
master->tail = NULL;
|
||||
master->count = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ospf6_hook_init ()
|
||||
{
|
||||
neighbor_hook.name = "Neighbor Hooklist";
|
||||
interface_hook.name = "Interface Hooklist";
|
||||
area_hook.name = "Area Hooklist";
|
||||
top_hook.name = "Top Hooklist";
|
||||
database_hook.name = "Database Hooklist";
|
||||
intra_topology_hook.name = "IntraTopology Hooklist";
|
||||
inter_topology_hook.name = "InterTopology Hooklist";
|
||||
route_hook.name = "Route Hooklist";
|
||||
}
|
||||
|
||||
|
@ -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*/
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
||||
#define OSPF6_INTERFACE_FLAG_PASSIVE 0x01
|
||||
#define OSPF6_INTERFACE_FLAG_FORCE_PREFIX 0x02
|
||||
extern char *ospf6_interface_state_str[];
|
||||
|
||||
/* flags */
|
||||
#define OSPF6_INTERFACE_DISABLE 0x01
|
||||
#define OSPF6_INTERFACE_PASSIVE 0x02
|
||||
|
||||
|
||||
/* Function Prototypes */
|
||||
|
||||
void
|
||||
ospf6_interface_schedule_maxage_remover (void *arg, int val, void *obj);
|
||||
struct ospf6_interface *ospf6_interface_lookup_by_ifindex (int);
|
||||
struct ospf6_interface *ospf6_interface_lookup_by_name (char *);
|
||||
struct ospf6_interface *ospf6_interface_create (struct interface *);
|
||||
void ospf6_interface_delete (struct ospf6_interface *);
|
||||
|
||||
struct ospf6_interface *
|
||||
ospf6_interface_create (struct interface *);
|
||||
void
|
||||
ospf6_interface_delete (struct ospf6_interface *);
|
||||
|
||||
struct ospf6_interface *
|
||||
ospf6_interface_lookup_by_index (int);
|
||||
struct ospf6_interface *
|
||||
ospf6_interface_lookup_by_name (char *);
|
||||
void ospf6_interface_enable (struct ospf6_interface *);
|
||||
void ospf6_interface_disable (struct ospf6_interface *);
|
||||
|
||||
void ospf6_interface_if_add (struct interface *);
|
||||
void ospf6_interface_if_del (struct interface *);
|
||||
void ospf6_interface_state_update (struct interface *);
|
||||
void ospf6_interface_address_update (struct interface *);
|
||||
void ospf6_interface_connected_route_update (struct interface *);
|
||||
|
||||
/* interface event */
|
||||
int interface_up (struct thread *);
|
||||
int interface_down (struct thread *);
|
||||
int wait_timer (struct thread *);
|
||||
int backup_seen (struct thread *);
|
||||
int neighbor_change (struct thread *);
|
||||
|
||||
void ospf6_interface_init ();
|
||||
|
||||
#if 0
|
||||
int
|
||||
ospf6_interface_count_neighbor_in_state (u_char state,
|
||||
struct ospf6_interface *o6i);
|
||||
int
|
||||
ospf6_interface_count_full_neighbor (struct ospf6_interface *);
|
||||
#endif
|
||||
|
||||
int ospf6_interface_is_enabled (u_int32_t ifindex);
|
||||
|
||||
void
|
||||
ospf6_interface_delayed_ack_add (struct ospf6_lsa *lsa,
|
||||
struct ospf6_interface *o6i);
|
||||
void
|
||||
ospf6_interface_delayed_ack_remove (struct ospf6_lsa *lsa,
|
||||
struct ospf6_interface *o6i);
|
||||
|
||||
void
|
||||
ospf6_interface_statistics_show (struct vty *vty,
|
||||
struct ospf6_interface *o6i);
|
||||
int config_write_ospf6_debug_interface (struct vty *vty);
|
||||
void install_element_ospf6_debug_interface ();
|
||||
|
||||
#endif /* OSPF6_INTERFACE_H */
|
||||
|
||||
|
2060
ospf6d/ospf6_intra.c
2060
ospf6d/ospf6_intra.c
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -1,193 +0,0 @@
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "ospf6_linklist.h"
|
||||
|
||||
static struct linklist_node *
|
||||
linklist_lookup_node (void *data, struct linklist *linklist)
|
||||
{
|
||||
struct linklist_node *node;
|
||||
|
||||
for (node = linklist->head; node; node = node->next)
|
||||
{
|
||||
if (linklist->cmp && (*linklist->cmp) (node->data, data) == 0)
|
||||
return node;
|
||||
if (node->data == data)
|
||||
return node;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
linklist_lookup (void *data, struct linklist *linklist)
|
||||
{
|
||||
struct linklist_node *node;
|
||||
|
||||
node = linklist_lookup_node (data, linklist);
|
||||
if (node)
|
||||
return node->data;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
linklist_add (void *data, struct linklist *linklist)
|
||||
{
|
||||
struct linklist_node *node = NULL, *add;
|
||||
|
||||
if (linklist_lookup_node (data, linklist))
|
||||
return -1;
|
||||
|
||||
add = malloc (sizeof (struct linklist_node));
|
||||
if (add == NULL)
|
||||
return -1;
|
||||
memset (add, 0, sizeof (struct linklist_node));
|
||||
add->data = data;
|
||||
|
||||
if (linklist->cmp)
|
||||
{
|
||||
for (node = linklist->head; node; node = node->next)
|
||||
{
|
||||
if ((*linklist->cmp) (node->data, add->data) > 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! node)
|
||||
{
|
||||
/* add to tail */
|
||||
if (linklist->tail)
|
||||
{
|
||||
linklist->tail->next = add;
|
||||
add->prev = linklist->tail;
|
||||
}
|
||||
else
|
||||
{
|
||||
linklist->head = add;
|
||||
add->prev = NULL;
|
||||
}
|
||||
|
||||
linklist->tail = add;
|
||||
add->next = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* insert just before 'node' */
|
||||
if (node->prev)
|
||||
{
|
||||
node->prev->next = add;
|
||||
add->prev = node->prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
linklist->head = add;
|
||||
add->prev = NULL;
|
||||
}
|
||||
|
||||
add->next = node;
|
||||
node->prev = add;
|
||||
}
|
||||
|
||||
linklist->count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
linklist_remove (void *data, struct linklist *linklist)
|
||||
{
|
||||
struct linklist_node *rem;
|
||||
|
||||
rem = linklist_lookup_node (data, linklist);
|
||||
if (rem == NULL)
|
||||
return -1;
|
||||
|
||||
if (rem->prev)
|
||||
rem->prev->next = rem->next;
|
||||
else
|
||||
linklist->head = rem->next;
|
||||
|
||||
if (rem->next)
|
||||
rem->next->prev = rem->prev;
|
||||
else
|
||||
linklist->tail = rem->prev;
|
||||
|
||||
free (rem);
|
||||
linklist->count--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
linklist_head (struct linklist *linklist, struct linklist_node *node)
|
||||
{
|
||||
if (linklist->head == NULL)
|
||||
{
|
||||
node->prev = NULL;
|
||||
node->next = NULL;
|
||||
node->data = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
node->prev = linklist->head->prev;
|
||||
node->next = linklist->head->next;
|
||||
node->data = linklist->head->data;
|
||||
}
|
||||
|
||||
int
|
||||
linklist_end (struct linklist_node *node)
|
||||
{
|
||||
if (node->data == NULL && node->next == NULL)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
linklist_next (struct linklist_node *node)
|
||||
{
|
||||
if (node->next == NULL)
|
||||
{
|
||||
node->prev = NULL;
|
||||
node->next = NULL;
|
||||
node->data = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
node->data = node->next->data;
|
||||
node->prev = node->next->prev;
|
||||
node->next = node->next->next;
|
||||
}
|
||||
|
||||
struct linklist *
|
||||
linklist_create ()
|
||||
{
|
||||
struct linklist *linklist;
|
||||
|
||||
linklist = malloc (sizeof (struct linklist));
|
||||
if (linklist == NULL)
|
||||
return NULL;
|
||||
memset (linklist, 0, sizeof (struct linklist));
|
||||
|
||||
return linklist;
|
||||
}
|
||||
|
||||
void
|
||||
linklist_remove_all (struct linklist *linklist)
|
||||
{
|
||||
struct linklist_node node;
|
||||
|
||||
for (linklist_head (linklist, &node); ! linklist_end (&node);
|
||||
linklist_next (&node))
|
||||
linklist_remove (node.data, linklist);
|
||||
}
|
||||
|
||||
void
|
||||
linklist_delete (struct linklist *linklist)
|
||||
{
|
||||
linklist_remove_all (linklist);
|
||||
assert (linklist->count == 0);
|
||||
assert (linklist->head == NULL);
|
||||
assert (linklist->tail == NULL);
|
||||
|
||||
free (linklist);
|
||||
}
|
||||
|
||||
|
@ -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_*/
|
||||
|
1915
ospf6d/ospf6_lsa.c
1915
ospf6d/ospf6_lsa.c
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
char name[64]; /* dump string */
|
||||
|
||||
struct ospf6_lsa *prev;
|
||||
struct ospf6_lsa *next;
|
||||
|
||||
unsigned char lock; /* reference counter */
|
||||
unsigned char flag; /* special meaning (e.g. floodback) */
|
||||
|
||||
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 timeval installed; /* used by MinLSArrival check */
|
||||
struct timeval originated; /* used by MinLSInterval check */
|
||||
|
||||
struct thread *expire;
|
||||
struct thread *refresh; /* For self-originated LSA */
|
||||
u_int32_t from; /* from which neighbor */
|
||||
|
||||
void *scope; /* pointer to scope data structure */
|
||||
int headeronly; /* indicate this is LS header only */
|
||||
|
||||
unsigned long refcnt;
|
||||
struct ospf6_lsa *refsrc;
|
||||
|
||||
/* lsa instance */
|
||||
struct ospf6_lsa_hdr *lsa_hdr;
|
||||
struct ospf6_lsa_header__ *header;
|
||||
|
||||
/* statistics */
|
||||
u_long turnover_num;
|
||||
u_long turnover_total;
|
||||
u_long turnover_min;
|
||||
u_long turnover_max;
|
||||
struct ospf6_lsa_header *header;
|
||||
};
|
||||
|
||||
struct ospf6_lsa_slot
|
||||
#define OSPF6_LSA_FLOODBACK 0x01
|
||||
#define OSPF6_LSA_DUPLICATE 0x02
|
||||
#define OSPF6_LSA_IMPLIEDACK 0x04
|
||||
#define OSPF6_LSA_REFRESH 0x08
|
||||
|
||||
struct ospf6_lstype
|
||||
{
|
||||
struct ospf6_lsa_slot *prev;
|
||||
struct ospf6_lsa_slot *next;
|
||||
|
||||
u_int16_t type;
|
||||
char *name;
|
||||
|
||||
int (*func_print) (struct ospf6_lsa *lsa);
|
||||
int (*func_show) (struct vty *vty, struct ospf6_lsa *lsa);
|
||||
int (*func_refresh) (void *lsa);
|
||||
|
||||
int (*database_add) (void *lsa);
|
||||
int (*database_remove) (void *lsa);
|
||||
|
||||
struct ospf6_hook_master database_hook;
|
||||
|
||||
struct ospf6_hook hook_neighbor;
|
||||
struct ospf6_hook hook_interface;
|
||||
struct ospf6_hook hook_area;
|
||||
struct ospf6_hook hook_top;
|
||||
struct ospf6_hook hook_database;
|
||||
struct ospf6_hook hook_route;
|
||||
int (*reoriginate) (struct ospf6_lsa *);
|
||||
int (*show) (struct vty *, struct ospf6_lsa *);
|
||||
};
|
||||
|
||||
#define OSPF6_LSA_FLAG_FLOODBACK 0x01
|
||||
#define OSPF6_LSA_FLAG_DUPLICATE 0x02
|
||||
#define OSPF6_LSA_FLAG_IMPLIEDACK 0x04
|
||||
#define OSPF6_LSA_FLAG_REFRESH 0x08
|
||||
extern struct ospf6_lstype ospf6_lstype[OSPF6_LSTYPE_SIZE];
|
||||
#define OSPF6_LSTYPE_INDEX(type) \
|
||||
(((type) & OSPF6_LSTYPE_FCODE_MASK) < OSPF6_LSTYPE_SIZE ? \
|
||||
((type) & OSPF6_LSTYPE_FCODE_MASK) : OSPF6_LSTYPE_UNKNOWN)
|
||||
|
||||
/* Back pointer check, Is X's reference field bound to Y ? */
|
||||
#define x_ipl(x) ((struct intra_area_prefix_lsa *)LSH_NEXT((x)->lsa_hdr))
|
||||
#define is_reference_network_ok(x,y) \
|
||||
((x_ipl(x))->intra_prefix_refer_lstype == (y)->lsa_hdr->lsh_type &&\
|
||||
(x_ipl(x))->intra_prefix_refer_lsid == (y)->lsa_hdr->lsh_id &&\
|
||||
(x_ipl(x))->intra_prefix_refer_advrtr == (y)->lsa_hdr->lsh_advrtr)
|
||||
/* referencing router's ifid must be 0,
|
||||
see draft-ietf-ospf-ospfv6-06.txt */
|
||||
#define is_reference_router_ok(x,y) \
|
||||
((x_ipl(x))->intra_prefix_refer_lstype == (y)->lsa_hdr->lsh_type &&\
|
||||
(x_ipl(x))->intra_prefix_refer_lsid == htonl (0) &&\
|
||||
(x_ipl(x))->intra_prefix_refer_advrtr == (y)->lsa_hdr->lsh_advrtr)
|
||||
#if 0
|
||||
extern char *ospf6_lstype_str[OSPF6_LSTYPE_SIZE];
|
||||
#define OSPF6_LSTYPE_NAME(type) \
|
||||
((ntohs (type) & OSPF6_LSTYPE_FCODE_MASK) < OSPF6_LSTYPE_SIZE ? \
|
||||
ospf6_lstype_str[ntohs (type) & OSPF6_LSTYPE_FCODE_MASK] : \
|
||||
ospf6_lstype_str[OSPF6_LSTYPE_UNKNOWN])
|
||||
#else /*0*/
|
||||
#define OSPF6_LSTYPE_NAME(type) (ospf6_lstype_name (type))
|
||||
#endif /*0*/
|
||||
|
||||
/* MaxAge check. */
|
||||
/* ospf6_lsa_is_maxage (struct ospf6_lsa *lsa) */
|
||||
#define IS_LSA_MAXAGE(L) (ospf6_lsa_age_current (L) == OSPF6_LSA_MAXAGE)
|
||||
/* Macro for LSA Origination */
|
||||
/* void (CONTINUE_IF_...) (struct prefix *addr); */
|
||||
|
||||
struct ospf6_lsa_slot *ospf6_lsa_slot_get (u_int16_t type);
|
||||
int ospf6_lsa_slot_register (struct ospf6_lsa_slot *src);
|
||||
int ospf6_lsa_slot_unregister (u_int16_t type);
|
||||
|
||||
extern struct ospf6_lsa_slot *slot_head;
|
||||
#define CALL_FOREACH_LSA_HOOK(hook,func,data) \
|
||||
if (ospf6)\
|
||||
{\
|
||||
struct ospf6_lsa_slot *slot;\
|
||||
for (slot = slot_head; slot; slot = slot->next)\
|
||||
{\
|
||||
if (slot->hook.func)\
|
||||
(*slot->hook.func) (data);\
|
||||
}\
|
||||
}
|
||||
#define CALL_LSA_FUNC(type,func,data) \
|
||||
if (ospf6)\
|
||||
{\
|
||||
struct ospf6_lsa_slot *slot;\
|
||||
slot = ospf6_lsa_slot_get (type);\
|
||||
if (slot && slot->func)\
|
||||
{\
|
||||
(*slot->func) (data);\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
zlog_warn ("LSA: No slot for type %#x: %s line:%d",\
|
||||
ntohs (type), __FILE__, __LINE__);\
|
||||
}\
|
||||
#define CONTINUE_IF_ADDRESS_LINKLOCAL(addr)\
|
||||
if (IN6_IS_ADDR_LINKLOCAL (&(addr)->u.prefix6)) \
|
||||
{ \
|
||||
char buf[64]; \
|
||||
prefix2str (addr, buf, sizeof (buf)); \
|
||||
if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) \
|
||||
zlog_info ("Filter out Linklocal: %s", buf); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
#define CALL_LSA_DATABASE_ADD(type,data) \
|
||||
if (ospf6)\
|
||||
{\
|
||||
struct ospf6_lsa_slot *slot;\
|
||||
slot = ospf6_lsa_slot_get (type);\
|
||||
if (slot)\
|
||||
{\
|
||||
CALL_ADD_HOOK (&slot->database_hook, data);\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
zlog_warn ("LSA: No slot for type %#x: %s line:%d",\
|
||||
ntohs (type), __FILE__, __LINE__);\
|
||||
}\
|
||||
}
|
||||
#define CALL_LSA_DATABASE_CHANGE(type,data) \
|
||||
if (ospf6)\
|
||||
{\
|
||||
struct ospf6_lsa_slot *slot;\
|
||||
slot = ospf6_lsa_slot_get (type);\
|
||||
if (slot)\
|
||||
{\
|
||||
CALL_CHANGE_HOOK (&slot->database_hook, data);\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
zlog_warn ("LSA: No slot for type %#x: %s line:%d",\
|
||||
ntohs (type), __FILE__, __LINE__);\
|
||||
}\
|
||||
}
|
||||
#define CALL_LSA_DATABASE_REMOVE(type,data) \
|
||||
if (ospf6)\
|
||||
{\
|
||||
struct ospf6_lsa_slot *slot;\
|
||||
slot = ospf6_lsa_slot_get (type);\
|
||||
if (slot)\
|
||||
{\
|
||||
CALL_REMOVE_HOOK (&slot->database_hook, data);\
|
||||
}\
|
||||
else\
|
||||
{\
|
||||
zlog_warn ("LSA: No slot for type %#x: %s line:%d",\
|
||||
ntohs (type), __FILE__, __LINE__);\
|
||||
}\
|
||||
#define CONTINUE_IF_ADDRESS_UNSPECIFIED(addr) \
|
||||
if (IN6_IS_ADDR_UNSPECIFIED (&(addr)->u.prefix6)) \
|
||||
{ \
|
||||
char buf[64]; \
|
||||
prefix2str (addr, buf, sizeof (buf)); \
|
||||
if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) \
|
||||
zlog_info ("Filter out Unspecified: %s", buf); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
void ospf6_lsa_init ();
|
||||
#define CONTINUE_IF_ADDRESS_LOOPBACK(addr) \
|
||||
if (IN6_IS_ADDR_LOOPBACK (&(addr)->u.prefix6)) \
|
||||
{ \
|
||||
char buf[64]; \
|
||||
prefix2str (addr, buf, sizeof (buf)); \
|
||||
if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) \
|
||||
zlog_info ("Filter out Loopback: %s", buf); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
#define CONTINUE_IF_ADDRESS_V4COMPAT(addr) \
|
||||
if (IN6_IS_ADDR_V4COMPAT (&(addr)->u.prefix6)) \
|
||||
{ \
|
||||
char buf[64]; \
|
||||
prefix2str (addr, buf, sizeof (buf)); \
|
||||
if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) \
|
||||
zlog_info ("Filter out V4Compat: %s", buf); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
#define CONTINUE_IF_ADDRESS_V4MAPPED(addr) \
|
||||
if (IN6_IS_ADDR_V4MAPPED (&(addr)->u.prefix6)) \
|
||||
{ \
|
||||
char buf[64]; \
|
||||
prefix2str (addr, buf, sizeof (buf)); \
|
||||
if (IS_OSPF6_DEBUG_LSA (ORIGINATE)) \
|
||||
zlog_info ("Filter out V4Mapped: %s", buf); \
|
||||
continue; \
|
||||
}
|
||||
|
||||
|
||||
/* Function Prototypes */
|
||||
char *ospf6_lstype_name (u_int16_t type);
|
||||
int ospf6_lsa_is_differ (struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2);
|
||||
int ospf6_lsa_is_changed (struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2);
|
||||
u_int16_t ospf6_lsa_age_current (struct ospf6_lsa *);
|
||||
void ospf6_lsa_age_update_to_send (struct ospf6_lsa *, u_int32_t);
|
||||
void ospf6_lsa_premature_aging (struct ospf6_lsa *);
|
||||
int ospf6_lsa_compare (struct ospf6_lsa *, struct ospf6_lsa *);
|
||||
|
||||
struct router_lsd *
|
||||
get_router_lsd (u_int32_t, struct ospf6_lsa *);
|
||||
unsigned long get_ifindex_to_router (u_int32_t, struct ospf6_lsa *);
|
||||
char *ospf6_lsa_printbuf (struct ospf6_lsa *lsa, char *buf, int size);
|
||||
void ospf6_lsa_header_print_raw (struct ospf6_lsa_header *header);
|
||||
void ospf6_lsa_header_print (struct ospf6_lsa *lsa);
|
||||
void ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa);
|
||||
void ospf6_lsa_show_summary_header (struct vty *vty);
|
||||
void ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa);
|
||||
void ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa);
|
||||
void ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa);
|
||||
|
||||
int ospf6_lsa_differ (struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2);
|
||||
int ospf6_lsa_match (u_int16_t, u_int32_t, u_int32_t,
|
||||
struct ospf6_lsa_header *);
|
||||
u_int32_t ospf6_lsa_new_seqnum (u_int16_t type, u_int32_t id,
|
||||
u_int32_t adv_router, void *scope);
|
||||
|
||||
void ospf6_lsa_show (struct vty *, struct ospf6_lsa *);
|
||||
void ospf6_lsa_show_dump (struct vty *, struct ospf6_lsa *);
|
||||
void ospf6_lsa_show_summary (struct vty *, struct ospf6_lsa *);
|
||||
void ospf6_lsa_show_summary_header (struct vty *);
|
||||
|
||||
struct ospf6_lsa *
|
||||
ospf6_lsa_create (struct ospf6_lsa_header *);
|
||||
struct ospf6_lsa *
|
||||
ospf6_lsa_summary_create (struct ospf6_lsa_header__ *);
|
||||
void
|
||||
ospf6_lsa_delete (struct ospf6_lsa *);
|
||||
struct ospf6_lsa *ospf6_lsa_create (struct ospf6_lsa_header *header);
|
||||
struct ospf6_lsa *ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header);
|
||||
void ospf6_lsa_delete (struct ospf6_lsa *lsa);
|
||||
struct ospf6_lsa *ospf6_lsa_copy (struct ospf6_lsa *);
|
||||
|
||||
void ospf6_lsa_lock (struct ospf6_lsa *);
|
||||
void ospf6_lsa_unlock (struct ospf6_lsa *);
|
||||
|
||||
unsigned short ospf6_lsa_age_current (struct ospf6_lsa *);
|
||||
int ospf6_lsa_is_maxage (struct ospf6_lsa *);
|
||||
void ospf6_lsa_age_update_to_send (struct ospf6_lsa *, u_int32_t);
|
||||
void ospf6_lsa_premature_aging (struct ospf6_lsa *);
|
||||
|
||||
int ospf6_lsa_check_recent (struct ospf6_lsa *, struct ospf6_lsa *);
|
||||
|
||||
int
|
||||
ospf6_lsa_lsd_num (struct ospf6_lsa_header *lsa_header);
|
||||
void *
|
||||
ospf6_lsa_lsd_get (int index, struct ospf6_lsa_header *lsa_header);
|
||||
int
|
||||
ospf6_lsa_lsd_is_refer_ok (int index1, struct ospf6_lsa_header *lsa_header1,
|
||||
int index2, struct ospf6_lsa_header *lsa_header2);
|
||||
|
||||
void ospf6_lsa_originate (struct ospf6_lsa *);
|
||||
void ospf6_lsa_re_originate (struct ospf6_lsa *lsa);
|
||||
int ospf6_lsa_expire (struct thread *);
|
||||
int ospf6_lsa_refresh (struct thread *);
|
||||
|
||||
u_short ospf6_lsa_checksum (struct ospf6_lsa_header *);
|
||||
unsigned short ospf6_lsa_checksum (struct ospf6_lsa_header *);
|
||||
int ospf6_lsa_prohibited_duration (u_int16_t type, u_int32_t id,
|
||||
u_int32_t adv_router, void *scope);
|
||||
|
||||
void ospf6_lsa_update_network (char *ifname);
|
||||
void ospf6_lsa_update_link (char *ifname);
|
||||
void ospf6_lsa_update_as_external (u_int32_t ls_id);
|
||||
void ospf6_lsa_update_intra_prefix_transit (char *ifname);
|
||||
void ospf6_lsa_update_intra_prefix_stub (u_int32_t area_id);
|
||||
void ospf6_lsa_init ();
|
||||
|
||||
u_int16_t ospf6_lsa_get_scope_type (u_int16_t);
|
||||
int ospf6_lsa_is_known_type (struct ospf6_lsa_header *lsa_header);
|
||||
|
||||
char *ospf6_lsa_type_string (u_int16_t type, char *buf, int bufsize);
|
||||
char *ospf6_lsa_router_bits_string (u_char router_bits, char *buf, int size);
|
||||
|
||||
u_long
|
||||
ospf6_lsa_has_elasped (u_int16_t, u_int32_t, u_int32_t, void *);
|
||||
void
|
||||
ospf6_lsa_originate (u_int16_t, u_int32_t, u_int32_t, char *, int, void *);
|
||||
int config_write_ospf6_debug_lsa (struct vty *vty);
|
||||
void install_element_ospf6_debug_lsa ();
|
||||
|
||||
#endif /* OSPF6_LSA_H */
|
||||
|
||||
|
@ -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));
|
||||
|
||||
if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_TYPE))
|
||||
{
|
||||
len += 2;
|
||||
if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_ADV_ROUTER))
|
||||
{
|
||||
len += 4;
|
||||
if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_ID))
|
||||
len += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (len > 0)
|
||||
memcpy ((char *)&key->prefix, &type, 2);
|
||||
if (len > 2)
|
||||
memcpy ((char *)&key->prefix + 2, &adv_router, 4);
|
||||
if (len > 6)
|
||||
memcpy ((char *)&key->prefix + 6, &id, 4);
|
||||
assert (key->prefixlen % 8 == 0);
|
||||
|
||||
memcpy ((caddr_t) &key->prefix + key->prefixlen / 8,
|
||||
(caddr_t) value, len);
|
||||
key->family = AF_INET6;
|
||||
key->prefixlen = len * 8;
|
||||
key->prefixlen += len * 8;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
static void
|
||||
_lsdb_count_assert (struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
struct ospf6_lsa *debug;
|
||||
int num = 0;
|
||||
for (debug = ospf6_lsdb_head (lsdb); debug;
|
||||
debug = ospf6_lsdb_next (debug))
|
||||
num++;
|
||||
|
||||
if (num == lsdb->count)
|
||||
return;
|
||||
|
||||
if (IS_OSPF6_DEBUG_LSA (DATABASE))
|
||||
{
|
||||
zlog_info ("PANIC !! lsdb[%p]->count = %d, real = %d",
|
||||
lsdb, lsdb->count, num);
|
||||
for (debug = ospf6_lsdb_head (lsdb); debug;
|
||||
debug = ospf6_lsdb_next (debug))
|
||||
zlog_info ("%p %p %s", debug->prev, debug->next, debug->name);
|
||||
zlog_info ("DUMP END");
|
||||
}
|
||||
assert (num == lsdb->count);
|
||||
}
|
||||
#define ospf6_lsdb_count_assert(t) (_lsdb_count_assert (t))
|
||||
#else /*NDEBUG*/
|
||||
#define ospf6_lsdb_count_assert(t) ((void) 0)
|
||||
#endif /*NDEBUG*/
|
||||
|
||||
void
|
||||
ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
int flag;
|
||||
struct prefix_ipv6 key;
|
||||
struct route_node *rn;
|
||||
struct ospf6_lsa *old = NULL;
|
||||
struct route_node *current, *nextnode, *prevnode;
|
||||
struct ospf6_lsa *next, *prev, *old = NULL;
|
||||
|
||||
flag = OSPF6_LSDB_MATCH_TYPE | OSPF6_LSDB_MATCH_ID |
|
||||
OSPF6_LSDB_MATCH_ADV_ROUTER;
|
||||
ospf6_lsdb_set_key (&key, flag, lsa->header->type, lsa->header->id,
|
||||
lsa->header->adv_router);
|
||||
memset (&key, 0, sizeof (key));
|
||||
ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type));
|
||||
ospf6_lsdb_set_key (&key, &lsa->header->adv_router,
|
||||
sizeof (lsa->header->adv_router));
|
||||
ospf6_lsdb_set_key (&key, &lsa->header->id, sizeof (lsa->header->id));
|
||||
|
||||
rn = route_node_get (lsdb->table, (struct prefix *) &key);
|
||||
if (rn->info)
|
||||
old = rn->info;
|
||||
rn->info = lsa;
|
||||
current = route_node_get (lsdb->table, (struct prefix *) &key);
|
||||
old = current->info;
|
||||
current->info = lsa;
|
||||
ospf6_lsa_lock (lsa);
|
||||
|
||||
if (old)
|
||||
ospf6_lsa_unlock (old);
|
||||
{
|
||||
if (old->prev)
|
||||
old->prev->next = lsa;
|
||||
if (old->next)
|
||||
old->next->prev = lsa;
|
||||
lsa->next = old->next;
|
||||
lsa->prev = old->prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next link */
|
||||
nextnode = current;
|
||||
route_lock_node (nextnode);
|
||||
do {
|
||||
nextnode = route_next (nextnode);
|
||||
} while (nextnode && nextnode->info == NULL);
|
||||
if (nextnode == NULL)
|
||||
lsa->next = NULL;
|
||||
else
|
||||
{
|
||||
next = nextnode->info;
|
||||
lsa->next = next;
|
||||
next->prev = lsa;
|
||||
route_unlock_node (nextnode);
|
||||
}
|
||||
|
||||
/* prev link */
|
||||
prevnode = current;
|
||||
route_lock_node (prevnode);
|
||||
do {
|
||||
prevnode = route_prev (prevnode);
|
||||
} while (prevnode && prevnode->info == NULL);
|
||||
if (prevnode == NULL)
|
||||
lsa->prev = NULL;
|
||||
else
|
||||
{
|
||||
prev = prevnode->info;
|
||||
lsa->prev = prev;
|
||||
prev->next = lsa;
|
||||
route_unlock_node (prevnode);
|
||||
}
|
||||
|
||||
lsdb->count++;
|
||||
}
|
||||
|
||||
if (old)
|
||||
{
|
||||
if (OSPF6_LSA_IS_CHANGED (old, lsa))
|
||||
{
|
||||
if (OSPF6_LSA_IS_MAXAGE (lsa))
|
||||
{
|
||||
if (lsdb->hook_remove)
|
||||
{
|
||||
(*lsdb->hook_remove) (old);
|
||||
(*lsdb->hook_remove) (lsa);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lsdb->hook_remove)
|
||||
(*lsdb->hook_remove) (old);
|
||||
if (lsdb->hook_add)
|
||||
(*lsdb->hook_add) (lsa);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (OSPF6_LSA_IS_MAXAGE (lsa))
|
||||
{
|
||||
if (lsdb->hook_remove)
|
||||
(*lsdb->hook_remove) (lsa);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lsdb->hook_add)
|
||||
(*lsdb->hook_add) (lsa);
|
||||
}
|
||||
|
||||
if (old)
|
||||
ospf6_lsa_unlock (old);
|
||||
|
||||
ospf6_lsdb_count_assert (lsdb);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
int flag;
|
||||
struct route_node *node;
|
||||
struct prefix_ipv6 key;
|
||||
struct route_node *rn;
|
||||
struct ospf6_lsa *old;
|
||||
|
||||
flag = OSPF6_LSDB_MATCH_TYPE | OSPF6_LSDB_MATCH_ID |
|
||||
OSPF6_LSDB_MATCH_ADV_ROUTER;
|
||||
ospf6_lsdb_set_key (&key, flag, lsa->header->type, lsa->header->id,
|
||||
lsa->header->adv_router);
|
||||
memset (&key, 0, sizeof (key));
|
||||
ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type));
|
||||
ospf6_lsdb_set_key (&key, &lsa->header->adv_router,
|
||||
sizeof (lsa->header->adv_router));
|
||||
ospf6_lsdb_set_key (&key, &lsa->header->id, sizeof (lsa->header->id));
|
||||
|
||||
rn = route_node_lookup (lsdb->table, (struct prefix *) &key);
|
||||
if (! rn || ! rn->info)
|
||||
{
|
||||
zlog_warn ("LSDB: Can't remove: no such LSA: %s", lsa->str);
|
||||
return;
|
||||
}
|
||||
node = route_node_lookup (lsdb->table, (struct prefix *) &key);
|
||||
assert (node && node->info == lsa);
|
||||
|
||||
old = rn->info;
|
||||
if (old != lsa)
|
||||
{
|
||||
zlog_warn ("LSDB: Can't remove: different instance: %s (%p <-> %p) %s",
|
||||
lsa->str, lsa, old, old->str);
|
||||
return;
|
||||
}
|
||||
if (lsa->prev)
|
||||
lsa->prev->next = lsa->next;
|
||||
if (lsa->next)
|
||||
lsa->next->prev = lsa->prev;
|
||||
|
||||
rn->info = NULL;
|
||||
ospf6_lsa_unlock (old);
|
||||
node->info = NULL;
|
||||
lsdb->count--;
|
||||
}
|
||||
|
||||
static void
|
||||
ospf6_lsdb_lookup_node (struct ospf6_lsdb_node *node,
|
||||
u_int16_t type, u_int32_t id, u_int32_t adv_router,
|
||||
struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
int flag;
|
||||
struct route_node *rn;
|
||||
if (lsdb->hook_remove)
|
||||
(*lsdb->hook_remove) (lsa);
|
||||
|
||||
memset (node, 0, sizeof (struct ospf6_lsdb_node));
|
||||
|
||||
flag = OSPF6_LSDB_MATCH_TYPE | OSPF6_LSDB_MATCH_ID |
|
||||
OSPF6_LSDB_MATCH_ADV_ROUTER;
|
||||
ospf6_lsdb_set_key (&node->key, flag, type, id, adv_router);
|
||||
|
||||
rn = route_node_lookup (lsdb->table, (struct prefix *) &node->key);
|
||||
if (! rn || ! rn->info)
|
||||
return;
|
||||
|
||||
node->node = rn;
|
||||
node->next = route_next (rn);
|
||||
node->lsa = rn->info;
|
||||
if (node->next != NULL)
|
||||
route_unlock_node (node->next);
|
||||
}
|
||||
|
||||
struct ospf6_lsa *
|
||||
ospf6_lsdb_lookup_lsdb (u_int16_t type, u_int32_t id, u_int32_t adv_router,
|
||||
struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
struct ospf6_lsdb_node node;
|
||||
ospf6_lsdb_lookup_node (&node, type, id, adv_router, lsdb);
|
||||
return node.lsa;
|
||||
}
|
||||
|
||||
/* Iteration function */
|
||||
void
|
||||
ospf6_lsdb_head (struct ospf6_lsdb_node *node, struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
struct route_node *rn;
|
||||
|
||||
memset (node, 0, sizeof (struct ospf6_lsdb_node));
|
||||
|
||||
rn = route_top (lsdb->table);
|
||||
if (rn == NULL)
|
||||
return;
|
||||
|
||||
while (rn && rn->info == NULL)
|
||||
rn = route_next (rn);
|
||||
|
||||
if (rn && rn->info)
|
||||
{
|
||||
node->node = rn;
|
||||
node->next = route_next (rn);
|
||||
node->lsa = rn->info;
|
||||
if (node->next != NULL)
|
||||
route_unlock_node (node->next);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_lsdb_type (struct ospf6_lsdb_node *node, u_int16_t type,
|
||||
struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
int flag;
|
||||
struct route_node *rn;
|
||||
|
||||
memset (node, 0, sizeof (struct ospf6_lsdb_node));
|
||||
|
||||
flag = OSPF6_LSDB_MATCH_TYPE;
|
||||
ospf6_lsdb_set_key (&node->key, flag, type, 0, 0);
|
||||
|
||||
/* get the closest radix node */
|
||||
rn = route_node_get (lsdb->table, (struct prefix *) &node->key);
|
||||
|
||||
/* skip to the real existing lsdb entry */
|
||||
while (rn && rn->info == NULL && rn->p.prefixlen >= node->key.prefixlen &&
|
||||
prefix_match ((struct prefix *) &node->key, &rn->p))
|
||||
rn = route_next (rn);
|
||||
|
||||
if (rn && rn->info)
|
||||
{
|
||||
node->node = rn;
|
||||
node->next = route_next (rn);
|
||||
node->lsa = rn->info;
|
||||
if (node->next != NULL)
|
||||
route_unlock_node (node->next);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_lsdb_type_router (struct ospf6_lsdb_node *node,
|
||||
u_int16_t type, u_int32_t adv_router,
|
||||
struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
int flag;
|
||||
struct route_node *rn;
|
||||
|
||||
memset (node, 0, sizeof (struct ospf6_lsdb_node));
|
||||
|
||||
flag = OSPF6_LSDB_MATCH_TYPE | OSPF6_LSDB_MATCH_ADV_ROUTER;
|
||||
ospf6_lsdb_set_key (&node->key, flag, type, 0, adv_router);
|
||||
|
||||
/* get the closest radix node */
|
||||
rn = route_node_get (lsdb->table, (struct prefix *) &node->key);
|
||||
|
||||
/* skip to the real existing lsdb entry */
|
||||
while (rn && rn->info == NULL && rn->p.prefixlen >= node->key.prefixlen &&
|
||||
prefix_match ((struct prefix *) &node->key, &rn->p))
|
||||
rn = route_next (rn);
|
||||
|
||||
if (rn && rn->info)
|
||||
{
|
||||
node->node = rn;
|
||||
node->next = route_next (rn);
|
||||
node->lsa = rn->info;
|
||||
if (node->next != NULL)
|
||||
route_unlock_node (node->next);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_lsdb_next (struct ospf6_lsdb_node *node)
|
||||
{
|
||||
struct route_node *rn;
|
||||
|
||||
route_lock_node (node->node);
|
||||
rn = route_next (node->node);
|
||||
|
||||
/* skip to the real existing lsdb entry */
|
||||
while (rn && rn->info == NULL && rn->p.prefixlen >= node->key.prefixlen &&
|
||||
prefix_match ((struct prefix *) &node->key, &rn->p))
|
||||
rn = route_next (rn);
|
||||
|
||||
if (rn && rn->info && rn->p.prefixlen >= node->key.prefixlen &&
|
||||
prefix_match ((struct prefix *) &node->key, &rn->p))
|
||||
{
|
||||
node->node = rn;
|
||||
node->next = route_next (rn);
|
||||
node->lsa = rn->info;
|
||||
if (node->next != NULL)
|
||||
route_unlock_node (node->next);
|
||||
}
|
||||
else
|
||||
{
|
||||
node->node = NULL;
|
||||
node->next = NULL;
|
||||
node->lsa = NULL;
|
||||
}
|
||||
ospf6_lsa_unlock (lsa);
|
||||
route_unlock_node (node);
|
||||
ospf6_lsdb_count_assert (lsdb);
|
||||
}
|
||||
|
||||
struct ospf6_lsa *
|
||||
ospf6_lsdb_lookup (u_int16_t type, u_int32_t id, u_int32_t adv_router,
|
||||
void *scope)
|
||||
struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
struct ospf6_interface *o6i;
|
||||
struct ospf6_area *o6a;
|
||||
listnode i, j;
|
||||
struct route_node *node;
|
||||
struct prefix_ipv6 key;
|
||||
|
||||
if (scope == (void *) ospf6)
|
||||
return ospf6_lsdb_lookup_lsdb (type, id, adv_router, ospf6->lsdb);
|
||||
|
||||
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));
|
||||
if (lsdb == NULL)
|
||||
return NULL;
|
||||
|
||||
memset (&key, 0, sizeof (key));
|
||||
ospf6_lsdb_set_key (&key, &type, sizeof (type));
|
||||
ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router));
|
||||
ospf6_lsdb_set_key (&key, &id, sizeof (id));
|
||||
|
||||
node = route_node_lookup (lsdb->table, (struct prefix *) &key);
|
||||
if (node == NULL || node->info == NULL)
|
||||
return NULL;
|
||||
return (struct ospf6_lsa *) node->info;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_lsdb_install (struct ospf6_lsa *new)
|
||||
/* Iteration function */
|
||||
struct ospf6_lsa *
|
||||
ospf6_lsdb_head (struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
struct ospf6_lsdb *lsdb;
|
||||
struct ospf6_lsa *old;
|
||||
int need_hook = 0;
|
||||
void (*hook) (struct ospf6_lsa *, struct ospf6_lsa *);
|
||||
struct route_node *node;
|
||||
|
||||
struct ospf6 *as = NULL;
|
||||
struct ospf6_area *area = NULL;
|
||||
struct ospf6_interface *linklocal = NULL;
|
||||
hook = NULL;
|
||||
node = route_top (lsdb->table);
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
|
||||
switch (ntohs (new->header->type) & OSPF6_LSTYPE_SCOPE_MASK)
|
||||
/* skip to the existing lsdb entry */
|
||||
while (node && node->info == NULL)
|
||||
node = route_next (node);
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
|
||||
route_unlock_node (node);
|
||||
if (node->info)
|
||||
ospf6_lsa_lock ((struct ospf6_lsa *) node->info);
|
||||
return (struct ospf6_lsa *) node->info;
|
||||
}
|
||||
|
||||
struct ospf6_lsa *
|
||||
ospf6_lsdb_next (struct ospf6_lsa *lsa)
|
||||
{
|
||||
struct ospf6_lsa *next = lsa->next;
|
||||
|
||||
ospf6_lsa_unlock (lsa);
|
||||
if (next)
|
||||
ospf6_lsa_lock (next);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
/* Macro version of check_bit (). */
|
||||
#define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1)
|
||||
|
||||
struct ospf6_lsa *
|
||||
ospf6_lsdb_type_router_head (u_int16_t type, u_int32_t adv_router,
|
||||
struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
struct route_node *node;
|
||||
struct prefix_ipv6 key;
|
||||
struct ospf6_lsa *lsa;
|
||||
|
||||
memset (&key, 0, sizeof (key));
|
||||
ospf6_lsdb_set_key (&key, &type, sizeof (type));
|
||||
ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router));
|
||||
|
||||
node = lsdb->table->top;
|
||||
|
||||
/* Walk down tree. */
|
||||
while (node && node->p.prefixlen <= key.prefixlen &&
|
||||
prefix_match (&node->p, (struct prefix *) &key))
|
||||
node = node->link[CHECK_BIT(&key.prefix, node->p.prefixlen)];
|
||||
|
||||
if (node)
|
||||
route_lock_node (node);
|
||||
while (node && node->info == NULL)
|
||||
node = route_next (node);
|
||||
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
else
|
||||
route_unlock_node (node);
|
||||
|
||||
if (! prefix_match ((struct prefix *) &key, &node->p))
|
||||
return NULL;
|
||||
|
||||
lsa = node->info;
|
||||
ospf6_lsa_lock (lsa);
|
||||
|
||||
return lsa;
|
||||
}
|
||||
|
||||
struct ospf6_lsa *
|
||||
ospf6_lsdb_type_router_next (u_int16_t type, u_int32_t adv_router,
|
||||
struct ospf6_lsa *lsa)
|
||||
{
|
||||
struct ospf6_lsa *next = lsa->next;
|
||||
|
||||
if (next)
|
||||
{
|
||||
case OSPF6_LSA_SCOPE_LINKLOCAL:
|
||||
linklocal = (struct ospf6_interface *) new->scope;
|
||||
lsdb = linklocal->lsdb;
|
||||
break;
|
||||
case OSPF6_LSA_SCOPE_AREA:
|
||||
area = (struct ospf6_area *) new->scope;
|
||||
lsdb = area->lsdb;
|
||||
break;
|
||||
case OSPF6_LSA_SCOPE_AS:
|
||||
as = (struct ospf6 *) new->scope;
|
||||
lsdb = as->lsdb;
|
||||
break;
|
||||
default:
|
||||
zlog_warn ("LSDB: Can't install: scope unknown: %s", new->str);
|
||||
return;
|
||||
if (next->header->type != type ||
|
||||
next->header->adv_router != adv_router)
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
/* whether schedule calculation or not */
|
||||
old = ospf6_lsdb_lookup_lsdb (new->header->type, new->header->id,
|
||||
new->header->adv_router, lsdb);
|
||||
if (next)
|
||||
ospf6_lsa_lock (next);
|
||||
ospf6_lsa_unlock (lsa);
|
||||
return next;
|
||||
}
|
||||
|
||||
if (! old || ospf6_lsa_differ (old, new))
|
||||
need_hook++;
|
||||
struct ospf6_lsa *
|
||||
ospf6_lsdb_type_head (u_int16_t type, struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
struct route_node *node;
|
||||
struct prefix_ipv6 key;
|
||||
struct ospf6_lsa *lsa;
|
||||
|
||||
/* log */
|
||||
if (IS_OSPF6_DUMP_LSDB)
|
||||
zlog_info ("LSDB: Install: %s %s", new->str,
|
||||
((IS_LSA_MAXAGE (new)) ? "(MaxAge)" : ""));
|
||||
memset (&key, 0, sizeof (key));
|
||||
ospf6_lsdb_set_key (&key, &type, sizeof (type));
|
||||
|
||||
if (old)
|
||||
ospf6_lsa_lock (old);
|
||||
/* Walk down tree. */
|
||||
node = lsdb->table->top;
|
||||
while (node && node->p.prefixlen <= key.prefixlen &&
|
||||
prefix_match (&node->p, (struct prefix *) &key))
|
||||
node = node->link[CHECK_BIT(&key.prefix, node->p.prefixlen)];
|
||||
|
||||
ospf6_lsdb_add (new, lsdb);
|
||||
gettimeofday (&new->installed, NULL);
|
||||
if (node)
|
||||
route_lock_node (node);
|
||||
while (node && node->info == NULL)
|
||||
node = route_next (node);
|
||||
|
||||
hook = ospf6_lsdb_hook[ntohs (new->header->type) &
|
||||
OSPF6_LSTYPE_CODE_MASK].hook;
|
||||
if (need_hook && hook)
|
||||
(*hook) (old, new);
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
else
|
||||
route_unlock_node (node);
|
||||
|
||||
/* old LSA should be freed here */
|
||||
if (old)
|
||||
ospf6_lsa_unlock (old);
|
||||
if (! prefix_match ((struct prefix *) &key, &node->p))
|
||||
return NULL;
|
||||
|
||||
lsa = node->info;
|
||||
ospf6_lsa_lock (lsa);
|
||||
|
||||
return lsa;
|
||||
}
|
||||
|
||||
struct ospf6_lsa *
|
||||
ospf6_lsdb_type_next (u_int16_t type, struct ospf6_lsa *lsa)
|
||||
{
|
||||
struct ospf6_lsa *next = lsa->next;
|
||||
|
||||
if (next)
|
||||
{
|
||||
if (next->header->type != type)
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
if (next)
|
||||
ospf6_lsa_lock (next);
|
||||
ospf6_lsa_unlock (lsa);
|
||||
return next;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
struct ospf6_lsdb_node node;
|
||||
for (ospf6_lsdb_head (&node, lsdb); ! ospf6_lsdb_is_end (&node);
|
||||
ospf6_lsdb_next (&node))
|
||||
ospf6_lsdb_remove (node.lsa, lsdb);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_lsdb_remove_maxage (struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
struct ospf6_lsdb_node node;
|
||||
struct ospf6_lsa *lsa;
|
||||
|
||||
for (ospf6_lsdb_head (&node, lsdb); ! ospf6_lsdb_is_end (&node);
|
||||
ospf6_lsdb_next (&node))
|
||||
{
|
||||
lsa = node.lsa;
|
||||
|
||||
/* contiue if it's not MaxAge */
|
||||
if (! IS_LSA_MAXAGE (lsa))
|
||||
continue;
|
||||
|
||||
/* continue if it's referenced by some retrans-lists */
|
||||
if (lsa->lock != 1)
|
||||
continue;
|
||||
|
||||
if (IS_OSPF6_DUMP_LSDB)
|
||||
zlog_info ("Remove MaxAge LSA: %s", lsa->str);
|
||||
|
||||
for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa))
|
||||
ospf6_lsdb_remove (lsa, lsdb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* vty functions */
|
||||
|
||||
static int
|
||||
ospf6_lsdb_match (int flag, u_int16_t type, u_int32_t id,
|
||||
u_int32_t adv_router, struct ospf6_lsa *lsa)
|
||||
{
|
||||
if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_TYPE) &&
|
||||
lsa->header->type != type)
|
||||
return 0;
|
||||
|
||||
if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_ID) &&
|
||||
lsa->header->id != id)
|
||||
return 0;
|
||||
|
||||
if (CHECK_FLAG (flag, OSPF6_LSDB_MATCH_ADV_ROUTER) &&
|
||||
lsa->header->adv_router != adv_router)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
show_ipv6_ospf6_lsdb (struct vty *vty, int argc, char **argv,
|
||||
struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
u_int flag;
|
||||
u_int16_t type = 0;
|
||||
u_int32_t id, adv_router;
|
||||
int ret;
|
||||
struct ospf6_lsdb_node node;
|
||||
char invalid[32], *invalidp;
|
||||
int l_argc = argc;
|
||||
char **l_argv = argv;
|
||||
|
||||
flag = 0;
|
||||
memset (invalid, 0, sizeof (invalid));
|
||||
invalidp = invalid;
|
||||
|
||||
/* chop tail if the words is 'dump' or 'summary' */
|
||||
if (l_argc > 0 && ! strcmp (l_argv[l_argc - 1], "dump"))
|
||||
{
|
||||
SET_FLAG (flag, OSPF6_LSDB_SHOW_DUMP);
|
||||
l_argc --;
|
||||
}
|
||||
else if (l_argc > 0 && ! strcmp (l_argv[l_argc - 1], "detail"))
|
||||
{
|
||||
SET_FLAG (flag, OSPF6_LSDB_SHOW_DETAIL);
|
||||
l_argc --;
|
||||
}
|
||||
|
||||
if (l_argc > 0)
|
||||
{
|
||||
SET_FLAG (flag, OSPF6_LSDB_MATCH_TYPE);
|
||||
if (! strncmp (l_argv[0], "r", 1))
|
||||
type = htons (OSPF6_LSA_TYPE_ROUTER);
|
||||
if (! strncmp (l_argv[0], "n", 1))
|
||||
type = htons (OSPF6_LSA_TYPE_NETWORK);
|
||||
if (! strncmp (l_argv[0], "a", 1))
|
||||
type = htons (OSPF6_LSA_TYPE_AS_EXTERNAL);
|
||||
if (! strcmp (l_argv[0], "intra-prefix"))
|
||||
type = htons (OSPF6_LSA_TYPE_INTRA_PREFIX);
|
||||
if (! strcmp (l_argv[0], "inter-router"))
|
||||
type = htons (OSPF6_LSA_TYPE_INTER_ROUTER);
|
||||
if (! strcmp (l_argv[0], "inter-prefix"))
|
||||
type = htons (OSPF6_LSA_TYPE_INTER_PREFIX);
|
||||
if (! strncmp (l_argv[0], "l", 1))
|
||||
type = htons (OSPF6_LSA_TYPE_LINK);
|
||||
if (! strncmp (l_argv[0], "0x", 2) && strlen (l_argv[0]) == 6)
|
||||
type = htons ((short) strtol (l_argv[0], (char **)NULL, 16));
|
||||
if (! strncmp (l_argv[0], "*", 1))
|
||||
UNSET_FLAG (flag, OSPF6_LSDB_MATCH_TYPE);
|
||||
}
|
||||
|
||||
if (l_argc > 1)
|
||||
{
|
||||
SET_FLAG (flag, OSPF6_LSDB_MATCH_ID);
|
||||
if (! strncmp (l_argv[1], "*", 1))
|
||||
UNSET_FLAG (flag, OSPF6_LSDB_MATCH_ID);
|
||||
else
|
||||
{
|
||||
ret = inet_pton (AF_INET, l_argv[1], &id);
|
||||
if (ret != 1)
|
||||
{
|
||||
id = htonl (strtoul (l_argv[1], &invalidp, 10));
|
||||
if (invalid[0] != '\0')
|
||||
{
|
||||
vty_out (vty, "Link State ID is not parsable: %s%s",
|
||||
l_argv[1], VTY_NEWLINE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (l_argc > 2)
|
||||
{
|
||||
SET_FLAG (flag, OSPF6_LSDB_MATCH_ADV_ROUTER);
|
||||
if (! strncmp (l_argv[2], "*", 1))
|
||||
UNSET_FLAG (flag, OSPF6_LSDB_MATCH_ADV_ROUTER);
|
||||
else
|
||||
{
|
||||
ret = inet_pton (AF_INET, l_argv[2], &adv_router);
|
||||
if (ret != 1)
|
||||
{
|
||||
adv_router = htonl (strtoul (l_argv[2], &invalidp, 10));
|
||||
if (invalid[0] != '\0')
|
||||
{
|
||||
vty_out (vty, "Advertising Router is not parsable: %s%s",
|
||||
l_argv[2], VTY_NEWLINE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! CHECK_FLAG (flag, OSPF6_LSDB_SHOW_DETAIL))
|
||||
ospf6_lsa_show_summary_header (vty);
|
||||
|
||||
for (ospf6_lsdb_head (&node, lsdb); ! ospf6_lsdb_is_end (&node);
|
||||
ospf6_lsdb_next (&node))
|
||||
{
|
||||
if (! ospf6_lsdb_match (flag, type, id, adv_router, node.lsa))
|
||||
continue;
|
||||
|
||||
if (CHECK_FLAG (flag, OSPF6_LSDB_SHOW_DUMP))
|
||||
ospf6_lsa_show_dump (vty, node.lsa);
|
||||
else if (CHECK_FLAG (flag, OSPF6_LSDB_SHOW_DETAIL))
|
||||
ospf6_lsa_show (vty, node.lsa);
|
||||
else
|
||||
ospf6_lsa_show_summary (vty, node.lsa);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_ipv6_ospf6_database,
|
||||
show_ipv6_ospf6_database_cmd,
|
||||
"show ipv6 ospf6 database",
|
||||
SHOW_STR
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"LSA Database\n"
|
||||
)
|
||||
{
|
||||
struct ospf6_area *o6a;
|
||||
struct ospf6_interface *o6i;
|
||||
listnode i, j;
|
||||
|
||||
/* call show function for each of LSAs in the LSDBs */
|
||||
|
||||
for (i = listhead (ospf6->area_list); i; nextnode (i))
|
||||
{
|
||||
o6a = (struct ospf6_area *) getdata (i);
|
||||
|
||||
/* LinkLocal LSDBs */
|
||||
for (j = listhead (o6a->if_list); j; nextnode (j))
|
||||
{
|
||||
o6i = (struct ospf6_interface *) getdata (j);
|
||||
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
vty_out (vty, " Interface %s (Area: %s):%s",
|
||||
o6i->interface->name, o6a->str, VTY_NEWLINE);
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
show_ipv6_ospf6_lsdb (vty, argc, argv, o6i->lsdb);
|
||||
}
|
||||
|
||||
/* Area LSDBs */
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
vty_out (vty, " Area %s:%s", o6a->str, VTY_NEWLINE);
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
show_ipv6_ospf6_lsdb (vty, argc, argv, o6a->lsdb);
|
||||
}
|
||||
|
||||
/* AS LSDBs */
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
vty_out (vty, " AS:%s", VTY_NEWLINE);
|
||||
vty_out (vty, "%s", VTY_NEWLINE);
|
||||
show_ipv6_ospf6_lsdb (vty, argc, argv, ospf6->lsdb);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
ALIAS (show_ipv6_ospf6_database,
|
||||
show_ipv6_ospf6_database_type_cmd,
|
||||
"show ipv6 ospf6 database (router|network|as-external|intra-prefix|inter-prefix|inter-router|link|*|HEX|dump|detail)",
|
||||
SHOW_STR
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"LSA Database\n"
|
||||
"Router-LSA\n"
|
||||
"Network-LSA\n"
|
||||
"AS-External-LSA\n"
|
||||
"Intra-Area-Prefix-LSA\n"
|
||||
"Inter-Area-Router-LSA\n"
|
||||
"Inter-Area-Prefix-LSA\n"
|
||||
"Link-LSA\n"
|
||||
"All LS Type\n"
|
||||
"Specify LS Type by Hex\n"
|
||||
"Dump raw LSA data in Hex\n"
|
||||
"show detail of LSAs\n"
|
||||
)
|
||||
|
||||
ALIAS (show_ipv6_ospf6_database,
|
||||
show_ipv6_ospf6_database_type_id_cmd,
|
||||
"show ipv6 ospf6 database (router|network|as-external|intra-prefix|inter-prefix|inter-router|link|*|HEX) (A.B.C.D|*|dump|detail)",
|
||||
SHOW_STR
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"LSA Database\n"
|
||||
"Router-LSA\n"
|
||||
"Network-LSA\n"
|
||||
"AS-External-LSA\n"
|
||||
"Intra-Area-Prefix-LSA\n"
|
||||
"Inter-Area-Router-LSA\n"
|
||||
"Inter-Area-Prefix-LSA\n"
|
||||
"Link-LSA\n"
|
||||
"All LS Type\n"
|
||||
"Specify LS Type by Hex\n"
|
||||
"Link State ID\n"
|
||||
"All Link State ID\n"
|
||||
"Dump raw LSA data in Hex\n"
|
||||
"show detail of LSAs\n"
|
||||
)
|
||||
|
||||
ALIAS (show_ipv6_ospf6_database,
|
||||
show_ipv6_ospf6_database_type_id_adv_router_cmd,
|
||||
"show ipv6 ospf6 database (router|network|as-external|intra-prefix|inter-prefix|inter-router|link|*|HEX) (A.B.C.D|*) (A.B.C.D|*|dump|detail)",
|
||||
SHOW_STR
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"LSA Database\n"
|
||||
"Router-LSA\n"
|
||||
"Network-LSA\n"
|
||||
"AS-External-LSA\n"
|
||||
"Intra-Area-Prefix-LSA\n"
|
||||
"Inter-Area-Router-LSA\n"
|
||||
"Inter-Area-Prefix-LSA\n"
|
||||
"Link-LSA\n"
|
||||
"All LS Type\n"
|
||||
"Specify LS Type by Hex\n"
|
||||
"Link State ID\n"
|
||||
"All Link State ID\n"
|
||||
"Advertising Router\n"
|
||||
"All Advertising Router\n"
|
||||
"Dump raw LSA data in Hex\n"
|
||||
"show detail of LSAs\n"
|
||||
)
|
||||
|
||||
ALIAS (show_ipv6_ospf6_database,
|
||||
show_ipv6_ospf6_database_type_id_adv_router_dump_cmd,
|
||||
"show ipv6 ospf6 database (router|network|as-external|intra-prefix|inter-prefix|inter-router|link|*|HEX) (A.B.C.D|*) (A.B.C.D|*) (dump|detail|)",
|
||||
SHOW_STR
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"LSA Database\n"
|
||||
"Router-LSA\n"
|
||||
"Network-LSA\n"
|
||||
"AS-External-LSA\n"
|
||||
"Intra-Area-Prefix-LSA\n"
|
||||
"Inter-Area-Router-LSA\n"
|
||||
"Inter-Area-Prefix-LSA\n"
|
||||
"Link-LSA\n"
|
||||
"All LS Type\n"
|
||||
"Specify LS Type by Hex\n"
|
||||
"Link State ID\n"
|
||||
"All Link State ID\n"
|
||||
"Advertising Router\n"
|
||||
"All Advertising Router\n"
|
||||
"Dump raw LSA data in Hex\n"
|
||||
"show detail of LSAs\n"
|
||||
)
|
||||
|
||||
void
|
||||
ospf6_lsdb_init ()
|
||||
{
|
||||
install_element (VIEW_NODE, &show_ipv6_ospf6_database_cmd);
|
||||
install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_cmd);
|
||||
install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_cmd);
|
||||
install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_adv_router_cmd);
|
||||
install_element (VIEW_NODE, &show_ipv6_ospf6_database_type_id_adv_router_dump_cmd);
|
||||
|
||||
install_element (ENABLE_NODE, &show_ipv6_ospf6_database_cmd);
|
||||
install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_cmd);
|
||||
install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_id_cmd);
|
||||
install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_id_adv_router_cmd);
|
||||
install_element (ENABLE_NODE, &show_ipv6_ospf6_database_type_id_adv_router_dump_cmd);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2002 Yasuhiro Ohara
|
||||
* Copyright (C) 2003 Yasuhiro Ohara
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
@ -25,64 +25,146 @@
|
||||
#include "prefix.h"
|
||||
#include "table.h"
|
||||
|
||||
#include "ospf6_prefix.h"
|
||||
#include "ospf6_lsa.h"
|
||||
|
||||
struct ospf6_lsdb_node
|
||||
{
|
||||
struct prefix_ipv6 key;
|
||||
|
||||
struct route_node *node;
|
||||
struct route_node *next;
|
||||
|
||||
struct ospf6_lsa *lsa;
|
||||
};
|
||||
|
||||
struct ospf6_lsdb
|
||||
{
|
||||
struct route_table *table;
|
||||
u_int32_t count;
|
||||
void (*hook) (struct ospf6_lsa *);
|
||||
void (*hook_add) (struct ospf6_lsa *);
|
||||
void (*hook_remove) (struct ospf6_lsa *);
|
||||
};
|
||||
|
||||
/* int ospf6_lsdb_is_end (struct ospf6_lsdb_node *lsdb_node); */
|
||||
#define ospf6_lsdb_is_end(lsdb_node) ((lsdb_node)->node == NULL ? 1 : 0)
|
||||
#define LSDB_FOREACH_LSA(vty, func, lsdb) \
|
||||
do { \
|
||||
struct ospf6_lsa *lsa; \
|
||||
for (lsa = ospf6_lsdb_head (lsdb); lsa; \
|
||||
lsa = ospf6_lsdb_next (lsa)) \
|
||||
{ \
|
||||
(*(func)) (vty, lsa); \
|
||||
} \
|
||||
} while (0)
|
||||
#define LSDB_FOREACH_LSA_T(vty, func, lsdb, type) \
|
||||
do { \
|
||||
struct ospf6_lsa *lsa; \
|
||||
for (lsa = ospf6_lsdb_type_head (type, lsdb); lsa; \
|
||||
lsa = ospf6_lsdb_type_next (type, lsa)) \
|
||||
{ \
|
||||
(*(func)) (vty, lsa); \
|
||||
} \
|
||||
} while (0)
|
||||
#define LSDB_FOREACH_LSA_I(vty, func, lsdb, id) \
|
||||
do { \
|
||||
struct ospf6_lsa *lsa; \
|
||||
for (lsa = ospf6_lsdb_head (lsdb); lsa; \
|
||||
lsa = ospf6_lsdb_next (lsa)) \
|
||||
{ \
|
||||
if (lsa->header->id != id) \
|
||||
continue; \
|
||||
(*(func)) (vty, lsa); \
|
||||
} \
|
||||
} while (0)
|
||||
#define LSDB_FOREACH_LSA_R(vty, func, lsdb, router) \
|
||||
do { \
|
||||
struct ospf6_lsa *lsa; \
|
||||
for (lsa = ospf6_lsdb_head (lsdb); lsa; \
|
||||
lsa = ospf6_lsdb_next (lsa)) \
|
||||
{ \
|
||||
if (lsa->header->adv_router != router) \
|
||||
continue; \
|
||||
(*(func)) (vty, lsa); \
|
||||
} \
|
||||
} while (0)
|
||||
#define LSDB_FOREACH_LSA_TI(vty, func, lsdb, type, id) \
|
||||
do { \
|
||||
struct ospf6_lsa *lsa; \
|
||||
for (lsa = ospf6_lsdb_type_head (type, lsdb); lsa; \
|
||||
lsa = ospf6_lsdb_type_next (type, lsa)) \
|
||||
{ \
|
||||
if (lsa->header->id != id) \
|
||||
continue; \
|
||||
(*(func)) (vty, lsa); \
|
||||
} \
|
||||
} while (0)
|
||||
#define LSDB_FOREACH_LSA_TR(vty, func, lsdb, type, router) \
|
||||
do { \
|
||||
struct ospf6_lsa *lsa; \
|
||||
for (lsa = ospf6_lsdb_type_router_head (type, router, lsdb); lsa; \
|
||||
lsa = ospf6_lsdb_type_router_next (type, router, lsa)) \
|
||||
{ \
|
||||
(*(func)) (vty, lsa); \
|
||||
} \
|
||||
} while (0)
|
||||
#define LSDB_FOREACH_LSA_IR(vty, func, lsdb, id, router) \
|
||||
do { \
|
||||
struct ospf6_lsa *lsa; \
|
||||
for (lsa = ospf6_lsdb_head (lsdb); lsa; \
|
||||
lsa = ospf6_lsdb_next (lsa)) \
|
||||
{ \
|
||||
if (lsa->header->adv_router != router) \
|
||||
continue; \
|
||||
if (lsa->header->id != id) \
|
||||
continue; \
|
||||
(*(func)) (vty, lsa); \
|
||||
} \
|
||||
} while (0)
|
||||
#define LSDB_FOREACH_LSA_TIR(vty, func, lsdb, type, id, router) \
|
||||
do { \
|
||||
struct ospf6_lsa *lsa; \
|
||||
lsa = ospf6_lsdb_lookup (type, id, router, lsdb); \
|
||||
if (lsa) \
|
||||
(*(func)) (vty, lsa); \
|
||||
} while (0)
|
||||
|
||||
/* global holding hooks for each LS type */
|
||||
struct ospf6_lsdb_hook_t
|
||||
{
|
||||
void (*hook) (struct ospf6_lsa *old, struct ospf6_lsa *new);
|
||||
};
|
||||
extern struct ospf6_lsdb_hook_t *ospf6_lsdb_hook;
|
||||
#define OSPF6_LSDB_MAXAGE_REMOVER(lsdb) \
|
||||
do { \
|
||||
struct ospf6_lsa *lsa; \
|
||||
for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa)) \
|
||||
{ \
|
||||
if (! OSPF6_LSA_IS_MAXAGE (lsa)) \
|
||||
continue; \
|
||||
if (lsa->refcnt != 0) \
|
||||
continue; \
|
||||
if (IS_OSPF6_DEBUG_LSA (TIMER)) \
|
||||
zlog_info (" remove maxage %s", lsa->name); \
|
||||
ospf6_lsdb_remove (lsa, lsdb); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Function Prototypes */
|
||||
struct ospf6_lsdb * ospf6_lsdb_create ();
|
||||
struct ospf6_lsdb *ospf6_lsdb_create ();
|
||||
void ospf6_lsdb_delete (struct ospf6_lsdb *lsdb);
|
||||
|
||||
void ospf6_lsdb_remove_maxage (struct ospf6_lsdb *lsdb);
|
||||
|
||||
struct ospf6_lsa *
|
||||
ospf6_lsdb_lookup (u_int16_t type, u_int32_t id, u_int32_t adv_router,
|
||||
void *scope);
|
||||
|
||||
void ospf6_lsdb_install (struct ospf6_lsa *new);
|
||||
|
||||
void ospf6_lsdb_head (struct ospf6_lsdb_node *node, struct ospf6_lsdb *lsdb);
|
||||
void ospf6_lsdb_type (struct ospf6_lsdb_node *node, u_int16_t type,
|
||||
struct ospf6_lsa *ospf6_lsdb_lookup (u_int16_t type, u_int32_t id,
|
||||
u_int32_t adv_router,
|
||||
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);
|
||||
|
||||
void ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb);
|
||||
void ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb);
|
||||
|
||||
struct ospf6_lsa *ospf6_lsdb_head (struct ospf6_lsdb *lsdb);
|
||||
struct ospf6_lsa *ospf6_lsdb_next (struct ospf6_lsa *lsa);
|
||||
|
||||
struct ospf6_lsa *ospf6_lsdb_type_router_head (u_int16_t type,
|
||||
u_int32_t adv_router,
|
||||
struct ospf6_lsdb *lsdb);
|
||||
struct ospf6_lsa *ospf6_lsdb_type_router_next (u_int16_t type,
|
||||
u_int32_t adv_router,
|
||||
struct ospf6_lsa *lsa);
|
||||
|
||||
struct ospf6_lsa *ospf6_lsdb_type_head (u_int16_t type,
|
||||
struct ospf6_lsdb *lsdb);
|
||||
struct ospf6_lsa *ospf6_lsdb_type_next (u_int16_t type,
|
||||
struct ospf6_lsa *lsa);
|
||||
|
||||
void ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb);
|
||||
|
||||
struct ospf6_lsa *
|
||||
ospf6_lsdb_lookup_lsdb (u_int16_t type, u_int32_t id, u_int32_t adv_router,
|
||||
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 */
|
||||
|
||||
|
||||
|
@ -20,27 +20,25 @@
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "getopt.h"
|
||||
#include "thread.h"
|
||||
#include "log.h"
|
||||
#include <lib/version.h>
|
||||
#include "version.h"
|
||||
#include "command.h"
|
||||
#include "vty.h"
|
||||
#include "memory.h"
|
||||
#include "if.h"
|
||||
#include "filter.h"
|
||||
#include "prefix.h"
|
||||
#include "plist.h"
|
||||
#include "privs.h"
|
||||
|
||||
#include "ospf6d.h"
|
||||
#include "ospf6_network.h"
|
||||
|
||||
void ospf6_init ();
|
||||
void ospf6_terminate ();
|
||||
void nexthop_init ();
|
||||
int ospf6_receive (struct thread *);
|
||||
|
||||
extern int ospf6_sock;
|
||||
|
||||
/* Default configuration file name for ospf6d. */
|
||||
#define OSPF6_DEFAULT_CONFIG "ospf6d.conf"
|
||||
|
||||
/* Default port values. */
|
||||
#define OSPF6_VTY_PORT 2606
|
||||
|
||||
@ -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)
|
||||
{
|
||||
@ -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_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 ospf6 vty socket. */
|
||||
vty_serv_sock (vty_addr,
|
||||
vty_port ? vty_port : OSPF6_VTY_PORT, OSPF6_VTYSH_PATH);
|
||||
|
||||
/* Make ospf vty socket. */
|
||||
vty_serv_sock (vty_addr, vty_port, OSPF6_VTYSH_PATH);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Print start message */
|
||||
zlog_notice ("OSPF6d (Zebra-%s ospf6d-%s) starts",
|
||||
zlog_notice ("OSPF6d (Quagga-%s ospf6d-%s) starts",
|
||||
QUAGGA_VERSION, OSPF6_DAEMON_VERSION);
|
||||
#endif
|
||||
|
||||
/* Start finite state machine, here we go! */
|
||||
while (thread_fetch (master, &thread))
|
||||
@ -363,9 +317,9 @@ main (int argc, char *argv[], char *envp[])
|
||||
|
||||
/* Log in case thread failed */
|
||||
zlog_warn ("Thread failed");
|
||||
terminate (0);
|
||||
|
||||
/* Not reached. */
|
||||
exit (0);
|
||||
}
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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.*/
|
||||
/* It is just a sequence of LSA Headers */
|
||||
|
||||
/* definition for ospf6_message.c */
|
||||
#define OSPF6_MESSAGE_RECEIVE_BUFSIZE 5120
|
||||
#define OSPF6_MESSAGE_IOVEC_END 1024
|
||||
/* Function definition */
|
||||
void ospf6_hello_print (struct ospf6_header *);
|
||||
void ospf6_dbdesc_print (struct ospf6_header *);
|
||||
void ospf6_lsreq_print (struct ospf6_header *);
|
||||
void ospf6_lsupdate_print (struct ospf6_header *);
|
||||
void ospf6_lsack_print (struct ospf6_header *);
|
||||
|
||||
#define IS_OVER_MTU(message,mtu,addsize) \
|
||||
(iov_totallen(message)+(addsize) >= \
|
||||
(mtu)-sizeof(struct ospf6_header))
|
||||
int ospf6_receive (struct thread *thread);
|
||||
|
||||
#define OSPF6_MESSAGE_IOVEC_SIZE 1024
|
||||
#define OSPF6_MESSAGE_CLEAR(msg) \
|
||||
do { \
|
||||
int x; \
|
||||
for (x = 0; x < OSPF6_MESSAGE_IOVEC_SIZE; x++) \
|
||||
{ \
|
||||
(msg)[x].iov_base = NULL; \
|
||||
(msg)[x].iov_len = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
int ospf6_hello_send (struct thread *thread);
|
||||
int ospf6_dbdesc_send (struct thread *thread);
|
||||
int ospf6_dbdesc_send_newone (struct thread *thread);
|
||||
int ospf6_lsreq_send (struct thread *thread);
|
||||
int ospf6_lsupdate_send_interface (struct thread *thread);
|
||||
int ospf6_lsupdate_send_neighbor (struct thread *thread);
|
||||
int ospf6_lsack_send_interface (struct thread *thread);
|
||||
int ospf6_lsack_send_neighbor (struct thread *thread);
|
||||
|
||||
#define OSPF6_MESSAGE_ATTACH(msg,buf,bufsize) \
|
||||
do { \
|
||||
int x; \
|
||||
for (x = 0; x < OSPF6_MESSAGE_IOVEC_SIZE; x++) \
|
||||
if ((msg)[x].iov_base == (void *)NULL && (msg)[x].iov_len == 0) \
|
||||
break; \
|
||||
if (x < OSPF6_MESSAGE_IOVEC_SIZE - 1) \
|
||||
{ \
|
||||
(msg)[x].iov_base = (void *)(buf); \
|
||||
(msg)[x].iov_len = (bufsize); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define OSPF6_MESSAGE_JOIN(msg,join) \
|
||||
do { \
|
||||
int x,y; \
|
||||
for (x = 0; x < OSPF6_MESSAGE_IOVEC_SIZE; x++) \
|
||||
if ((msg)[x].iov_base == NULL && (msg)[x].iov_len == 0) \
|
||||
break; \
|
||||
for (y = x; y < OSPF6_MESSAGE_IOVEC_SIZE; y++) \
|
||||
{ \
|
||||
(msg)[y].iov_base = (join)[y - x].iov_base; \
|
||||
(msg)[y].iov_len = (join)[y - x].iov_len; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Statistics */
|
||||
struct ospf6_message_stat
|
||||
{
|
||||
u_int32_t send;
|
||||
u_int32_t send_octet;
|
||||
u_int32_t recv;
|
||||
u_int32_t recv_octet;
|
||||
};
|
||||
|
||||
/* Type string */
|
||||
extern char *ospf6_message_type_string[];
|
||||
|
||||
/* Function Prototypes */
|
||||
int ospf6_receive (struct thread *);
|
||||
|
||||
int ospf6_send_hello (struct thread *);
|
||||
int ospf6_send_dbdesc_rxmt (struct thread *);
|
||||
int ospf6_send_dbdesc (struct thread *);
|
||||
int ospf6_send_lsreq (struct thread *);
|
||||
|
||||
struct ospf6_neighbor;
|
||||
struct ospf6_interface;
|
||||
int
|
||||
ospf6_send_lsupdate_rxmt (struct thread *);
|
||||
void
|
||||
ospf6_send_lsupdate_direct (struct ospf6_lsa *, struct ospf6_neighbor *);
|
||||
void
|
||||
ospf6_send_lsupdate_flood (struct ospf6_lsa *, struct ospf6_interface *);
|
||||
|
||||
int ospf6_send_lsack_delayed (struct thread *);
|
||||
int ospf6_send_lsack_direct (struct thread *);
|
||||
|
||||
void ospf6_message_send (u_char, struct iovec *, struct in6_addr *, u_int);
|
||||
int config_write_ospf6_debug_message (struct vty *);
|
||||
void install_element_ospf6_debug_message ();
|
||||
|
||||
#endif /* OSPF6_MESSAGE_H */
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 1999 Yasuhiro Ohara
|
||||
* Copyright (C) 2003 Yasuhiro Ohara
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
@ -22,140 +22,117 @@
|
||||
#ifndef OSPF6_NEIGHBOR_H
|
||||
#define OSPF6_NEIGHBOR_H
|
||||
|
||||
/* Debug option */
|
||||
extern unsigned char conf_debug_ospf6_neighbor;
|
||||
#define OSPF6_DEBUG_NEIGHBOR_STATE 0x01
|
||||
#define OSPF6_DEBUG_NEIGHBOR_EVENT 0x02
|
||||
#define OSPF6_DEBUG_NEIGHBOR_ON(level) \
|
||||
(conf_debug_ospf6_neighbor |= (level))
|
||||
#define OSPF6_DEBUG_NEIGHBOR_OFF(level) \
|
||||
(conf_debug_ospf6_neighbor &= ~(level))
|
||||
#define IS_OSPF6_DEBUG_NEIGHBOR(level) \
|
||||
(conf_debug_ospf6_neighbor & OSPF6_DEBUG_NEIGHBOR_ ## level)
|
||||
|
||||
/* Neighbor structure */
|
||||
struct ospf6_neighbor
|
||||
{
|
||||
/* Neighbor Router ID String */
|
||||
char str[32];
|
||||
char name[32];
|
||||
|
||||
/* OSPFv3 Interface this neighbor belongs to */
|
||||
struct ospf6_interface *ospf6_interface;
|
||||
struct ospf6_interface *ospf6_if;
|
||||
|
||||
/* Neighbor state */
|
||||
u_char state;
|
||||
|
||||
/* timestamp of last changing state */
|
||||
struct timeval last_changed;
|
||||
|
||||
/* Neighbor Router ID */
|
||||
u_int32_t router_id;
|
||||
|
||||
/* Neighbor Interface ID */
|
||||
u_int32_t ifindex;
|
||||
|
||||
/* Router Priority of this neighbor */
|
||||
u_char priority;
|
||||
|
||||
u_int32_t ifid;
|
||||
u_int32_t dr;
|
||||
u_int32_t bdr;
|
||||
u_int32_t prevdr;
|
||||
u_int32_t prevbdr;
|
||||
u_int32_t drouter;
|
||||
u_int32_t bdrouter;
|
||||
u_int32_t prev_drouter;
|
||||
u_int32_t prev_bdrouter;
|
||||
|
||||
/* Link-LSA's options field */
|
||||
/* Options field (Capability) */
|
||||
char options[3];
|
||||
|
||||
/* IPaddr of I/F on our side link */
|
||||
struct in6_addr hisaddr;
|
||||
|
||||
/* new */
|
||||
struct ospf6_lsdb *summary_list;
|
||||
struct ospf6_lsdb *request_list;
|
||||
struct ospf6_lsdb *retrans_list;
|
||||
struct in6_addr linklocal_addr;
|
||||
|
||||
/* For Database Exchange */
|
||||
u_char dbdesc_bits;
|
||||
u_int32_t dbdesc_seqnum;
|
||||
struct ospf6_dbdesc *dbdesc_previous;
|
||||
/* Last received Database Description packet */
|
||||
struct ospf6_dbdesc dbdesc_last;
|
||||
|
||||
/* last received DD , including OSPF capability of this neighbor */
|
||||
struct ospf6_dbdesc last_dd;
|
||||
/* LS-list */
|
||||
struct ospf6_lsdb *summary_list;
|
||||
struct ospf6_lsdb *request_list;
|
||||
struct ospf6_lsdb *retrans_list;
|
||||
|
||||
/* LSAs to retransmit to this neighbor */
|
||||
list dbdesc_lsa;
|
||||
|
||||
/* 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 *);
|
||||
int ospf6_neighbor_cmp (void *va, void *vb);
|
||||
void ospf6_neighbor_dbex_init (struct ospf6_neighbor *on);
|
||||
|
||||
void
|
||||
ospf6_neighbor_lslist_clear (struct ospf6_neighbor *);
|
||||
struct ospf6_neighbor *ospf6_neighbor_lookup (u_int32_t,
|
||||
struct ospf6_interface *);
|
||||
struct ospf6_neighbor *ospf6_neighbor_create (u_int32_t,
|
||||
struct ospf6_interface *);
|
||||
void ospf6_neighbor_delete (struct ospf6_neighbor *);
|
||||
|
||||
void
|
||||
ospf6_neighbor_summary_add (struct ospf6_lsa *, struct ospf6_neighbor *);
|
||||
void
|
||||
ospf6_neighbor_summary_remove (struct ospf6_lsa *, struct ospf6_neighbor *);
|
||||
|
||||
void
|
||||
ospf6_neighbor_request_add (struct ospf6_lsa *, struct ospf6_neighbor *);
|
||||
void
|
||||
ospf6_neighbor_request_remove (struct ospf6_lsa *, struct ospf6_neighbor *);
|
||||
|
||||
void
|
||||
ospf6_neighbor_retrans_add (struct ospf6_lsa *, struct ospf6_neighbor *);
|
||||
void
|
||||
ospf6_neighbor_retrans_remove (struct ospf6_lsa *, struct ospf6_neighbor *);
|
||||
|
||||
void
|
||||
ospf6_neighbor_dbdesc_add (struct ospf6_lsa *lsa,
|
||||
struct ospf6_neighbor *nei);
|
||||
void
|
||||
ospf6_neighbor_dbdesc_remove (struct ospf6_lsa *lsa,
|
||||
struct ospf6_neighbor *nei);
|
||||
|
||||
void
|
||||
ospf6_neighbor_dbex_init (struct ospf6_neighbor *nei);
|
||||
|
||||
void
|
||||
ospf6_neighbor_thread_cancel_all (struct ospf6_neighbor *);
|
||||
|
||||
struct ospf6_neighbor *
|
||||
ospf6_neighbor_create (u_int32_t, struct ospf6_interface *);
|
||||
void
|
||||
ospf6_neighbor_delete (struct ospf6_neighbor *);
|
||||
struct ospf6_neighbor *
|
||||
ospf6_neighbor_lookup (u_int32_t, struct ospf6_interface *);
|
||||
/* Neighbor event */
|
||||
int hello_received (struct thread *);
|
||||
int twoway_received (struct thread *);
|
||||
int negotiation_done (struct thread *);
|
||||
int exchange_done (struct thread *);
|
||||
int loading_done (struct thread *);
|
||||
int adj_ok (struct thread *);
|
||||
int seqnumber_mismatch (struct thread *);
|
||||
int bad_lsreq (struct thread *);
|
||||
int oneway_received (struct thread *);
|
||||
int inactivity_timer (struct thread *);
|
||||
|
||||
void ospf6_neighbor_init ();
|
||||
int config_write_ospf6_debug_neighbor (struct vty *vty);
|
||||
void install_element_ospf6_debug_neighbor ();
|
||||
|
||||
#endif /* OSPF6_NEIGHBOR_H */
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 1999 Yasuhiro Ohara
|
||||
* Copyright (C) 2003 Yasuhiro Ohara
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
@ -20,288 +20,20 @@
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
#include "memory.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "memory.h"
|
||||
#include "sockunion.h"
|
||||
#include "privs.h"
|
||||
|
||||
#include "ospf6d.h"
|
||||
#include "ospf6_proto.h"
|
||||
#include "ospf6_network.h"
|
||||
|
||||
extern int errno;
|
||||
extern struct sockaddr_in6 allspfrouters6;
|
||||
extern struct sockaddr_in6 alldrouters6;
|
||||
extern int ospf6_sock;
|
||||
extern struct thread_master *master;
|
||||
extern struct zebra_privs_t ospf6d_privs;
|
||||
|
||||
/* iovec functions */
|
||||
void
|
||||
iov_clear (struct iovec *iov, size_t iovlen)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < iovlen; i++)
|
||||
{
|
||||
iov[i].iov_base = NULL;
|
||||
iov[i].iov_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
iov_count (struct iovec *iov)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; iov[i].iov_base; i++)
|
||||
;
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
iov_totallen (struct iovec *iov)
|
||||
{
|
||||
int i;
|
||||
int totallen = 0;
|
||||
for (i = 0; iov[i].iov_base; i++)
|
||||
totallen += iov[i].iov_len;
|
||||
return totallen;
|
||||
}
|
||||
|
||||
void *
|
||||
iov_prepend (int mtype, struct iovec *iov, size_t len)
|
||||
{
|
||||
int i, iovlen;
|
||||
void *base;
|
||||
|
||||
base = (void *) XMALLOC (mtype, len);
|
||||
if (!base)
|
||||
{
|
||||
zlog_warn ("Network: iov_prepend failed");
|
||||
return NULL;
|
||||
}
|
||||
memset (base, 0, len);
|
||||
|
||||
iovlen = iov_count (iov);
|
||||
for (i = iovlen; i; i--)
|
||||
{
|
||||
iov[i].iov_base = iov[i - 1].iov_base;
|
||||
iov[i].iov_len = iov[i - 1].iov_len;
|
||||
}
|
||||
iov[0].iov_base = (char *)base;
|
||||
iov[0].iov_len = len;
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
void *
|
||||
iov_append (int mtype, struct iovec *iov, size_t len)
|
||||
{
|
||||
int i;
|
||||
void *base;
|
||||
|
||||
base = (void *)XMALLOC (mtype, len);
|
||||
if (!base)
|
||||
{
|
||||
zlog_warn ("Network: iov_append failed");
|
||||
return NULL;
|
||||
}
|
||||
memset (base, 0, len);
|
||||
|
||||
/* proceed to the end */
|
||||
i = iov_count (iov);
|
||||
|
||||
iov[i].iov_base = (char *)base;
|
||||
iov[i].iov_len = len;
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
void *
|
||||
iov_attach_last (struct iovec *iov, void *base, size_t len)
|
||||
{
|
||||
int i;
|
||||
i = iov_count (iov);
|
||||
iov[i].iov_base = (char *)base;
|
||||
iov[i].iov_len = len;
|
||||
return base;
|
||||
}
|
||||
|
||||
void *
|
||||
iov_detach_first (struct iovec *iov)
|
||||
{
|
||||
int i, iovlen;
|
||||
void *base;
|
||||
size_t len;
|
||||
|
||||
base = iov[0].iov_base;
|
||||
len = iov[0].iov_len;
|
||||
iovlen = iov_count (iov);
|
||||
for (i = 0; i < iovlen; i++)
|
||||
{
|
||||
iov[i].iov_base = iov[i + 1].iov_base;
|
||||
iov[i].iov_len = iov[i + 1].iov_len;
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
int
|
||||
iov_free (int mtype, struct iovec *iov, u_int begin, u_int end)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = begin; i < end; i++)
|
||||
{
|
||||
XFREE (mtype, iov[i].iov_base);
|
||||
iov[i].iov_base = NULL;
|
||||
iov[i].iov_len = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
iov_trim_head (int mtype, struct iovec *iov)
|
||||
{
|
||||
void *base;
|
||||
|
||||
base = iov_detach_first (iov);
|
||||
XFREE (mtype, base);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
iov_free_all (int mtype, struct iovec *iov)
|
||||
{
|
||||
int i, end = iov_count (iov);
|
||||
for (i = 0; i < end; i++)
|
||||
{
|
||||
XFREE (mtype, iov[i].iov_base);
|
||||
iov[i].iov_base = NULL;
|
||||
iov[i].iov_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
iov_copy_all (struct iovec *dst, struct iovec *src, size_t size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
dst[i].iov_base = src[i].iov_base;
|
||||
dst[i].iov_len = src[i].iov_len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Make ospf6d's server socket. */
|
||||
int
|
||||
ospf6_serv_sock ()
|
||||
{
|
||||
|
||||
if (ospf6d_privs.change (ZPRIVS_RAISE))
|
||||
zlog_err ("ospf6_serv_sock: could not raise privs");
|
||||
|
||||
ospf6_sock = socket (AF_INET6, SOCK_RAW, IPPROTO_OSPFIGP);
|
||||
if (ospf6_sock < 0)
|
||||
{
|
||||
zlog_warn ("Network: can't create OSPF6 socket.");
|
||||
return -1;
|
||||
}
|
||||
sockopt_reuseaddr (ospf6_sock);
|
||||
|
||||
if (ospf6d_privs.change (ZPRIVS_LOWER))
|
||||
zlog_err ("ospf_sock_init: could not lower privs");
|
||||
|
||||
/* setup global sockaddr_in6, allspf6 & alldr6 for later use */
|
||||
allspfrouters6.sin6_family = AF_INET6;
|
||||
alldrouters6.sin6_family = AF_INET6;
|
||||
#ifdef SIN6_LEN
|
||||
allspfrouters6.sin6_len = sizeof (struct sockaddr_in6);
|
||||
alldrouters6.sin6_len = sizeof (struct sockaddr_in6);
|
||||
#endif /* SIN6_LEN */
|
||||
inet_pton (AF_INET6, ALLSPFROUTERS6, &allspfrouters6.sin6_addr);
|
||||
inet_pton (AF_INET6, ALLDROUTERS6, &alldrouters6.sin6_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* returns 0 if succeed, else returns -1 */
|
||||
int
|
||||
ospf6_join_allspfrouters (u_int ifindex)
|
||||
{
|
||||
struct ipv6_mreq mreq6;
|
||||
int retval;
|
||||
|
||||
assert (ifindex);
|
||||
mreq6.ipv6mr_interface = ifindex;
|
||||
memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6.sin6_addr,
|
||||
sizeof (struct in6_addr));
|
||||
|
||||
retval = setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
|
||||
&mreq6, sizeof (mreq6));
|
||||
|
||||
if (retval < 0)
|
||||
zlog_err ("Network: Join AllSPFRouters on ifindex %d failed: %s",
|
||||
ifindex, strerror (errno));
|
||||
#if 0
|
||||
else
|
||||
zlog_info ("Network: Join AllSPFRouters on ifindex %d", ifindex);
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_leave_allspfrouters (u_int ifindex)
|
||||
{
|
||||
struct ipv6_mreq mreq6;
|
||||
|
||||
assert (ifindex);
|
||||
mreq6.ipv6mr_interface = ifindex;
|
||||
memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6.sin6_addr,
|
||||
sizeof (struct in6_addr));
|
||||
|
||||
if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
|
||||
&mreq6, sizeof (mreq6)) < 0)
|
||||
zlog_warn ("Network: Leave AllSPFRouters on ifindex %d Failed: %s",
|
||||
ifindex, strerror (errno));
|
||||
else
|
||||
zlog_info ("Network: Leave AllSPFRouters on ifindex %d", ifindex);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_join_alldrouters (u_int ifindex)
|
||||
{
|
||||
struct ipv6_mreq mreq6;
|
||||
|
||||
assert (ifindex);
|
||||
mreq6.ipv6mr_interface = ifindex;
|
||||
memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6.sin6_addr,
|
||||
sizeof (struct in6_addr));
|
||||
|
||||
if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
|
||||
&mreq6, sizeof (mreq6)) < 0)
|
||||
zlog_warn ("Network: Join AllDRouters on ifindex %d Failed: %s",
|
||||
ifindex, strerror (errno));
|
||||
else
|
||||
zlog_info ("Network: Join AllDRouters on ifindex %d", ifindex);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_leave_alldrouters (u_int ifindex)
|
||||
{
|
||||
struct ipv6_mreq mreq6;
|
||||
|
||||
assert (ifindex);
|
||||
mreq6.ipv6mr_interface = ifindex;
|
||||
memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6.sin6_addr,
|
||||
sizeof (struct in6_addr));
|
||||
|
||||
if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
|
||||
&mreq6, sizeof (mreq6)) < 0)
|
||||
zlog_warn ("Network: Leave AllDRouters on ifindex %d Failed", ifindex);
|
||||
else
|
||||
zlog_info ("Network: Leave AllDRouters on ifindex %d", ifindex);
|
||||
}
|
||||
int ospf6_sock;
|
||||
struct in6_addr allspfrouters6;
|
||||
struct in6_addr alldrouters6;
|
||||
|
||||
/* setsockopt ReUseAddr to on */
|
||||
void
|
||||
@ -343,7 +75,7 @@ void
|
||||
ospf6_set_checksum ()
|
||||
{
|
||||
int offset = 12;
|
||||
#if !defined(DISABLE_IPV6_CHECKSUM)
|
||||
#ifndef DISABLE_IPV6_CHECKSUM
|
||||
if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_CHECKSUM,
|
||||
&offset, sizeof (offset)) < 0)
|
||||
zlog_warn ("Network: set IPV6_CHECKSUM failed: %s", strerror (errno));
|
||||
@ -352,7 +84,143 @@ ospf6_set_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");
|
||||
|
||||
ospf6_sock = socket (AF_INET6, SOCK_RAW, IPPROTO_OSPFIGP);
|
||||
if (ospf6_sock < 0)
|
||||
{
|
||||
zlog_warn ("Network: can't create OSPF6 socket.");
|
||||
if (ospf6d_privs.change (ZPRIVS_LOWER))
|
||||
zlog_err ("ospf_sock_init: could not lower privs");
|
||||
return -1;
|
||||
}
|
||||
if (ospf6d_privs.change (ZPRIVS_LOWER))
|
||||
zlog_err ("ospf_sock_init: could not lower privs");
|
||||
|
||||
/* set socket options */
|
||||
#if 1
|
||||
sockopt_reuseaddr (ospf6_sock);
|
||||
#else
|
||||
ospf6_set_reuseaddr ();
|
||||
#endif /*1*/
|
||||
ospf6_reset_mcastloop ();
|
||||
ospf6_set_pktinfo ();
|
||||
ospf6_set_checksum ();
|
||||
|
||||
/* setup global in6_addr, allspf6 and alldr6 for later use */
|
||||
inet_pton (AF_INET6, ALLSPFROUTERS6, &allspfrouters6);
|
||||
inet_pton (AF_INET6, ALLDROUTERS6, &alldrouters6);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_join_allspfrouters (u_int ifindex)
|
||||
{
|
||||
struct ipv6_mreq mreq6;
|
||||
int retval;
|
||||
|
||||
assert (ifindex);
|
||||
mreq6.ipv6mr_interface = ifindex;
|
||||
memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6,
|
||||
sizeof (struct in6_addr));
|
||||
|
||||
retval = setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
|
||||
&mreq6, sizeof (mreq6));
|
||||
|
||||
if (retval < 0)
|
||||
zlog_err ("Network: Join AllSPFRouters on ifindex %d failed: %s",
|
||||
ifindex, strerror (errno));
|
||||
#if 0
|
||||
else
|
||||
zlog_info ("Network: Join AllSPFRouters on ifindex %d", ifindex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_leave_allspfrouters (u_int ifindex)
|
||||
{
|
||||
struct ipv6_mreq mreq6;
|
||||
|
||||
assert (ifindex);
|
||||
mreq6.ipv6mr_interface = ifindex;
|
||||
memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6,
|
||||
sizeof (struct in6_addr));
|
||||
|
||||
if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
|
||||
&mreq6, sizeof (mreq6)) < 0)
|
||||
zlog_warn ("Network: Leave AllSPFRouters on ifindex %d Failed: %s",
|
||||
ifindex, strerror (errno));
|
||||
#if 0
|
||||
else
|
||||
zlog_info ("Network: Leave AllSPFRouters on ifindex %d", ifindex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_join_alldrouters (u_int ifindex)
|
||||
{
|
||||
struct ipv6_mreq mreq6;
|
||||
|
||||
assert (ifindex);
|
||||
mreq6.ipv6mr_interface = ifindex;
|
||||
memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6,
|
||||
sizeof (struct in6_addr));
|
||||
|
||||
if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
|
||||
&mreq6, sizeof (mreq6)) < 0)
|
||||
zlog_warn ("Network: Join AllDRouters on ifindex %d Failed: %s",
|
||||
ifindex, strerror (errno));
|
||||
#if 0
|
||||
else
|
||||
zlog_info ("Network: Join AllDRouters on ifindex %d", ifindex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_leave_alldrouters (u_int ifindex)
|
||||
{
|
||||
struct ipv6_mreq mreq6;
|
||||
|
||||
assert (ifindex);
|
||||
mreq6.ipv6mr_interface = ifindex;
|
||||
memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6,
|
||||
sizeof (struct in6_addr));
|
||||
|
||||
if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
|
||||
&mreq6, sizeof (mreq6)) < 0)
|
||||
zlog_warn ("Network: Leave AllDRouters on ifindex %d Failed", ifindex);
|
||||
#if 0
|
||||
else
|
||||
zlog_info ("Network: Leave AllDRouters on ifindex %d", ifindex);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
iov_count (struct iovec *iov)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; iov[i].iov_base; i++)
|
||||
;
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
iov_totallen (struct iovec *iov)
|
||||
{
|
||||
int i;
|
||||
int totallen = 0;
|
||||
for (i = 0; iov[i].iov_base; i++)
|
||||
totallen += iov[i].iov_len;
|
||||
return totallen;
|
||||
}
|
||||
|
||||
int
|
||||
ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst,
|
||||
unsigned int *ifindex, struct iovec *message)
|
||||
{
|
||||
@ -403,11 +271,13 @@ 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));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_recvmsg_peek (struct in6_addr *src, struct in6_addr *dst,
|
||||
unsigned int *ifindex, struct iovec *message)
|
||||
{
|
||||
int retval;
|
||||
struct msghdr rmsghdr;
|
||||
struct cmsghdr *rcmsgp;
|
||||
u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
|
||||
struct in6_pktinfo *pktinfo;
|
||||
struct sockaddr_in6 src_sin6;
|
||||
|
||||
rcmsgp = (struct cmsghdr *)cmsgbuf;
|
||||
pktinfo = (struct in6_pktinfo *)(CMSG_DATA(rcmsgp));
|
||||
memset (&src_sin6, 0, sizeof (struct sockaddr_in6));
|
||||
|
||||
/* receive control msg */
|
||||
rcmsgp->cmsg_level = IPPROTO_IPV6;
|
||||
rcmsgp->cmsg_type = IPV6_PKTINFO;
|
||||
rcmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));
|
||||
/* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */
|
||||
|
||||
/* receive msg hdr */
|
||||
rmsghdr.msg_iov = message;
|
||||
rmsghdr.msg_iovlen = iov_count (message);
|
||||
rmsghdr.msg_name = (caddr_t) &src_sin6;
|
||||
rmsghdr.msg_namelen = sizeof (struct sockaddr_in6);
|
||||
rmsghdr.msg_control = (caddr_t) cmsgbuf;
|
||||
rmsghdr.msg_controllen = sizeof (cmsgbuf);
|
||||
|
||||
retval = recvmsg (ospf6_sock, &rmsghdr, MSG_PEEK);
|
||||
if (retval != iov_totallen (message))
|
||||
zlog_warn ("Network: recvmsg failed: %s", strerror (errno));
|
||||
|
||||
/* source address */
|
||||
assert (src);
|
||||
memcpy (src, &src_sin6.sin6_addr, sizeof (struct in6_addr));
|
||||
|
||||
/* destination address */
|
||||
if (ifindex)
|
||||
*ifindex = pktinfo->ipi6_ifindex;
|
||||
if (dst)
|
||||
memcpy (dst, &pktinfo->ipi6_addr, sizeof (struct in6_addr));
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 1999 Yasuhiro Ohara
|
||||
* Copyright (C) 2003 Yasuhiro Ohara
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
@ -24,34 +24,26 @@
|
||||
|
||||
|
||||
|
||||
/* Function Prototypes */
|
||||
void iov_clear (struct iovec *, size_t);
|
||||
int iov_count (struct iovec *);
|
||||
int iov_totallen (struct iovec *);
|
||||
void *iov_prepend (int, struct iovec *, size_t);
|
||||
void *iov_append (int, struct iovec *, size_t);
|
||||
void *iov_attach_last (struct iovec *, void *, size_t);
|
||||
void *iov_detach_first (struct iovec *);
|
||||
int iov_free (int, struct iovec *, u_int, u_int);
|
||||
void iov_trim_head (int, struct iovec *);
|
||||
void iov_free_all (int, struct iovec *);
|
||||
void iov_copy_all (struct iovec *, struct iovec *, size_t);
|
||||
extern int ospf6_sock;
|
||||
extern struct in6_addr allspfrouters6;
|
||||
extern struct in6_addr alldrouters6;
|
||||
|
||||
int ospf6_serv_sock ();
|
||||
int ospf6_join_allspfrouters (u_int);
|
||||
void ospf6_leave_allspfrouters (u_int);
|
||||
void ospf6_join_alldrouters (u_int);
|
||||
void ospf6_leave_alldrouters (u_int);
|
||||
/* Function Prototypes */
|
||||
void ospf6_set_reuseaddr ();
|
||||
void ospf6_reset_mcastloop ();
|
||||
void ospf6_set_pktinfo ();
|
||||
void ospf6_set_checksum ();
|
||||
|
||||
void ospf6_sendmsg (struct in6_addr *, struct in6_addr *,
|
||||
int ospf6_serv_sock ();
|
||||
|
||||
void ospf6_join_allspfrouters (u_int);
|
||||
void ospf6_leave_allspfrouters (u_int);
|
||||
void ospf6_join_alldrouters (u_int);
|
||||
void ospf6_leave_alldrouters (u_int);
|
||||
|
||||
int ospf6_sendmsg (struct in6_addr *, struct in6_addr *,
|
||||
unsigned int *, struct iovec *);
|
||||
void ospf6_recvmsg (struct in6_addr *, struct in6_addr *,
|
||||
unsigned int *, struct iovec *);
|
||||
void ospf6_recvmsg_peek (struct in6_addr *, struct in6_addr *,
|
||||
int ospf6_recvmsg (struct in6_addr *, struct in6_addr *,
|
||||
unsigned int *, struct iovec *);
|
||||
|
||||
#endif /* OSPF6_NETWORK_H */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -1,213 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 1999 Yasuhiro Ohara
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
* GNU Zebra is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* GNU Zebra is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Zebra; see the file COPYING. If not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "prefix.h"
|
||||
#include "memory.h"
|
||||
#include "linklist.h"
|
||||
|
||||
#include "ospf6_prefix.h"
|
||||
|
||||
#else /*0*/
|
||||
|
||||
#include "ospf6d.h"
|
||||
|
||||
#endif /*0*/
|
||||
|
||||
struct ospf6_prefix *
|
||||
ospf6_prefix_create (u_int8_t options, u_int16_t metric, struct prefix_ipv6 *p)
|
||||
{
|
||||
struct prefix_ipv6 prefix;
|
||||
struct ospf6_prefix *o6p;
|
||||
size_t size;
|
||||
|
||||
/* copy prefix and apply mask */
|
||||
prefix_copy ((struct prefix *) &prefix, (struct prefix *) p);
|
||||
apply_mask_ipv6 (&prefix);
|
||||
|
||||
size = OSPF6_PREFIX_SPACE (prefix.prefixlen) + sizeof (struct ospf6_prefix);
|
||||
o6p = (struct ospf6_prefix *) XMALLOC (MTYPE_OSPF6_PREFIX, size);
|
||||
if (! o6p)
|
||||
zlog_warn ("Can't allocate memory for ospf6 prefix: size: %d", size);
|
||||
else
|
||||
memset (o6p, 0, size);
|
||||
|
||||
o6p->prefix_length = prefix.prefixlen;
|
||||
o6p->prefix_options = options;
|
||||
o6p->prefix_metric = htons (metric);
|
||||
memcpy (o6p + 1, &prefix.prefix, OSPF6_PREFIX_SPACE (prefix.prefixlen));
|
||||
|
||||
return o6p;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_prefix_delete (struct ospf6_prefix *p)
|
||||
{
|
||||
XFREE (MTYPE_OSPF6_PREFIX, p);
|
||||
}
|
||||
|
||||
int
|
||||
ospf6_prefix_issame (struct ospf6_prefix *p1, struct ospf6_prefix *p2)
|
||||
{
|
||||
if (p1->prefix_length != p2->prefix_length)
|
||||
return 0;
|
||||
if (memcmp (&p1->u, &p2->u, sizeof (p1->u)))
|
||||
return 0;
|
||||
if (memcmp (p1 + 1, p2 + 1, OSPF6_PREFIX_SPACE (p1->prefix_length)))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct ospf6_prefix *
|
||||
ospf6_prefix_lookup (list l, struct ospf6_prefix *p1)
|
||||
{
|
||||
listnode node;
|
||||
struct ospf6_prefix *p2;
|
||||
for (node = listhead (l); node; nextnode (node))
|
||||
{
|
||||
p2 = (struct ospf6_prefix *) getdata (node);
|
||||
if (ospf6_prefix_issame (p1, p2))
|
||||
return p2;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add a copy of given prefix to the list */
|
||||
void
|
||||
ospf6_prefix_add (list l, struct ospf6_prefix *p)
|
||||
{
|
||||
struct ospf6_prefix *add;
|
||||
add = (struct ospf6_prefix *) XMALLOC (MTYPE_OSPF6_PREFIX,
|
||||
OSPF6_PREFIX_SIZE (p));
|
||||
if (add == NULL)
|
||||
{
|
||||
zlog_warn ("Can't allocate memory for ospf6 prefix");
|
||||
return;
|
||||
}
|
||||
else
|
||||
memcpy (add, p, OSPF6_PREFIX_SIZE (p));
|
||||
|
||||
if (ospf6_prefix_lookup (l, add))
|
||||
{
|
||||
ospf6_prefix_delete (add);
|
||||
return;
|
||||
}
|
||||
listnode_add (l, add);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_prefix_remove (list l, struct ospf6_prefix *p)
|
||||
{
|
||||
struct ospf6_prefix *rem;
|
||||
rem = ospf6_prefix_lookup (l, p);
|
||||
if (rem)
|
||||
{
|
||||
listnode_delete (l, rem);
|
||||
ospf6_prefix_delete (rem);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_prefix_in6_addr (struct ospf6_prefix *o6p, struct in6_addr *in6)
|
||||
{
|
||||
memset (in6, 0, sizeof (struct in6_addr));
|
||||
memcpy (in6, o6p + 1, OSPF6_PREFIX_SPACE (o6p->prefix_length));
|
||||
return;
|
||||
}
|
||||
|
||||
char *
|
||||
ospf6_prefix_options_str (u_int8_t opt, char *buf, size_t bufsize)
|
||||
{
|
||||
char *p, *mc, *la, *nu;
|
||||
|
||||
p = (CHECK_FLAG (opt, OSPF6_PREFIX_OPTION_P) ? "P" : "-");
|
||||
mc = (CHECK_FLAG (opt, OSPF6_PREFIX_OPTION_MC) ? "MC" : "--");
|
||||
la = (CHECK_FLAG (opt, OSPF6_PREFIX_OPTION_LA) ? "LA" : "--");
|
||||
nu = (CHECK_FLAG (opt, OSPF6_PREFIX_OPTION_NU) ? "NU" : "--");
|
||||
|
||||
snprintf (buf, bufsize, "%s|%s|%s|%s", p, mc, la, nu);
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *
|
||||
ospf6_prefix_string (struct ospf6_prefix *prefix, char *buf, size_t size)
|
||||
{
|
||||
struct in6_addr in6;
|
||||
char s[64];
|
||||
|
||||
memset (&in6, 0, sizeof (in6));
|
||||
memcpy (&in6, prefix + 1, OSPF6_PREFIX_SPACE (prefix->prefix_length));
|
||||
inet_ntop (AF_INET6, &in6, s, sizeof (s));
|
||||
|
||||
snprintf (buf, size, "%s/%d", s, prefix->prefix_length);
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_prefix_copy (struct ospf6_prefix *dst, struct ospf6_prefix *src,
|
||||
size_t dstsize)
|
||||
{
|
||||
size_t srcsize;
|
||||
|
||||
memset (dst, 0, dstsize);
|
||||
|
||||
srcsize = OSPF6_PREFIX_SIZE (src);
|
||||
if (dstsize < srcsize)
|
||||
memcpy (dst, src, dstsize);
|
||||
else
|
||||
memcpy (dst, src, srcsize);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_prefix_apply_mask (struct ospf6_prefix *o6p)
|
||||
{
|
||||
u_char *pnt, mask;
|
||||
int index, offset;
|
||||
|
||||
char buf[128];
|
||||
struct in6_addr in6;
|
||||
ospf6_prefix_in6_addr (o6p, &in6);
|
||||
inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
|
||||
|
||||
pnt = (u_char *)(o6p + 1);
|
||||
index = o6p->prefix_length / 8;
|
||||
offset = o6p->prefix_length % 8;
|
||||
mask = 0xff << (8 - offset);
|
||||
|
||||
if (index >= 16)
|
||||
return;
|
||||
|
||||
pnt[index] &= mask;
|
||||
index ++;
|
||||
|
||||
while (index < OSPF6_PREFIX_SPACE (o6p->prefix_length))
|
||||
pnt[index++] = 0;
|
||||
|
||||
ospf6_prefix_in6_addr (o6p, &in6);
|
||||
inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 1999 Yasuhiro Ohara
|
||||
* Copyright (C) 2003 Yasuhiro Ohara
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
@ -21,20 +21,62 @@
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#include "ospf6_proto.h"
|
||||
|
||||
char *
|
||||
ospf6_options_string (u_char opt_capability[3], char *buffer, int size)
|
||||
void
|
||||
ospf6_prefix_apply_mask (struct ospf6_prefix *op)
|
||||
{
|
||||
char *dc, *r, *n, *mc, *e, *v6;
|
||||
u_char *pnt, mask;
|
||||
int index, offset;
|
||||
|
||||
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;
|
||||
pnt = (u_char *)((caddr_t) op + sizeof (struct ospf6_prefix));
|
||||
index = op->prefix_length / 8;
|
||||
offset = op->prefix_length % 8;
|
||||
mask = 0xff << (8 - offset);
|
||||
|
||||
if (index >= 16)
|
||||
{
|
||||
zlog_warn ("Apply mask to ospf6_prefix failed");
|
||||
return;
|
||||
}
|
||||
|
||||
pnt[index] &= mask;
|
||||
index ++;
|
||||
|
||||
while (index < OSPF6_PREFIX_SPACE (op->prefix_length))
|
||||
pnt[index++] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_prefix_options_printbuf (u_int8_t prefix_options, char *buf, int size)
|
||||
{
|
||||
snprintf (buf, size, "xxx");
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_capability_printbuf (char capability, char *buf, int size)
|
||||
{
|
||||
char w, v, e, b;
|
||||
w = (capability & OSPF6_ROUTER_BIT_W ? 'W' : '-');
|
||||
v = (capability & OSPF6_ROUTER_BIT_V ? 'V' : '-');
|
||||
e = (capability & OSPF6_ROUTER_BIT_E ? 'E' : '-');
|
||||
b = (capability & OSPF6_ROUTER_BIT_B ? 'B' : '-');
|
||||
snprintf (buf, size, "----%c%c%c%c", w, v, e, b);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_options_printbuf (char *options, char *buf, int size)
|
||||
{
|
||||
char *dc, *r, *n, *mc, *e, *v6;
|
||||
dc = (OSPF6_OPT_ISSET (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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,12 +31,12 @@
|
||||
#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 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 */
|
||||
@ -44,15 +44,18 @@
|
||||
#define INITIAL_SEQUENCE_NUMBER 0x80000001 /* signed 32-bit integer */
|
||||
#define MAX_SEQUENCE_NUMBER 0x7fffffff /* signed 32-bit integer */
|
||||
|
||||
#define MAXOSPFMESSAGELEN 4096
|
||||
|
||||
#define ALLSPFROUTERS6 "ff02::5"
|
||||
#define ALLDROUTERS6 "ff02::6"
|
||||
|
||||
/* Configurable Constants */
|
||||
|
||||
#define DEFAULT_HELLO_INTERVAL 10
|
||||
#define DEFAULT_ROUTER_DEAD_TIMER 40
|
||||
#define DEFAULT_ROUTER_DEAD_INTERVAL 40
|
||||
|
||||
#define OSPF6_ROUTER_BIT_W (1 << 3)
|
||||
#define OSPF6_ROUTER_BIT_V (1 << 2)
|
||||
#define OSPF6_ROUTER_BIT_E (1 << 1)
|
||||
#define OSPF6_ROUTER_BIT_B (1 << 0)
|
||||
|
||||
/* OSPF options */
|
||||
/* present in HELLO, DD, LSA */
|
||||
@ -61,15 +64,58 @@
|
||||
#define OSPF6_OPT_CLEAR(x,opt) ((x)[2] &= ~(opt))
|
||||
#define OSPF6_OPT_CLEAR_ALL(x) ((x)[0] = (x)[1] = (x)[2] = 0)
|
||||
|
||||
#define OSPF6_OPT_V6 (1 << 0) /* IPv6 forwarding Capability */
|
||||
#define OSPF6_OPT_E (1 << 1) /* AS External Capability */
|
||||
#define OSPF6_OPT_MC (1 << 2) /* Multicasting Capability */
|
||||
#define OSPF6_OPT_N (1 << 3) /* Handling Type-7 LSA Capability */
|
||||
#define OSPF6_OPT_R (1 << 4) /* Forwarding Capability (Any Protocol) */
|
||||
#define OSPF6_OPT_DC (1 << 5) /* Demand Circuit handling Capability */
|
||||
#define OSPF6_OPT_R (1 << 4) /* Forwarding Capability (Any Protocol) */
|
||||
#define OSPF6_OPT_N (1 << 3) /* Handling Type-7 LSA Capability */
|
||||
#define OSPF6_OPT_MC (1 << 2) /* Multicasting Capability */
|
||||
#define OSPF6_OPT_E (1 << 1) /* AS External Capability */
|
||||
#define OSPF6_OPT_V6 (1 << 0) /* IPv6 forwarding Capability */
|
||||
|
||||
char *
|
||||
ospf6_options_string (u_char opt_capability[3], char *buffer, int size);
|
||||
/* OSPF6 Prefix */
|
||||
struct ospf6_prefix
|
||||
{
|
||||
u_int8_t prefix_length;
|
||||
u_int8_t prefix_options;
|
||||
union {
|
||||
u_int16_t _prefix_metric;
|
||||
u_int16_t _prefix_referenced_lstype;
|
||||
} u;
|
||||
#define prefix_metric u._prefix_metric
|
||||
#define prefix_refer_lstype u._prefix_referenced_lstype
|
||||
/* followed by one address_prefix */
|
||||
};
|
||||
|
||||
#define OSPF6_PREFIX_OPTION_NU (1 << 0) /* No Unicast */
|
||||
#define OSPF6_PREFIX_OPTION_LA (1 << 1) /* Local Address */
|
||||
#define OSPF6_PREFIX_OPTION_MC (1 << 2) /* MultiCast */
|
||||
#define OSPF6_PREFIX_OPTION_P (1 << 3) /* Propagate (NSSA) */
|
||||
|
||||
/* caddr_t OSPF6_PREFIX_BODY (struct ospf6_prefix *); */
|
||||
#define OSPF6_PREFIX_BODY(x) ((caddr_t)(x) + sizeof (struct ospf6_prefix))
|
||||
|
||||
/* size_t OSPF6_PREFIX_SPACE (int prefixlength); */
|
||||
#define OSPF6_PREFIX_SPACE(x) ((((x) + 31) / 32) * 4)
|
||||
|
||||
/* size_t OSPF6_PREFIX_SIZE (struct ospf6_prefix *); */
|
||||
#define OSPF6_PREFIX_SIZE(x) \
|
||||
(OSPF6_PREFIX_SPACE ((x)->prefix_length) + sizeof (struct ospf6_prefix))
|
||||
|
||||
/* struct ospf6_prefix *OSPF6_PREFIX_NEXT (struct ospf6_prefix *); */
|
||||
#define OSPF6_PREFIX_NEXT(x) \
|
||||
((struct ospf6_prefix *)((caddr_t)(x) + OSPF6_PREFIX_SIZE (x)))
|
||||
|
||||
#define ospf6_prefix_in6_addr(in6, op) \
|
||||
do { \
|
||||
memset (in6, 0, sizeof (struct in6_addr)); \
|
||||
memcpy (in6, (caddr_t) (op) + sizeof (struct ospf6_prefix), \
|
||||
OSPF6_PREFIX_SPACE ((op)->prefix_length)); \
|
||||
} while (0)
|
||||
|
||||
void ospf6_prefix_apply_mask (struct ospf6_prefix *op);
|
||||
void ospf6_prefix_options_printbuf (u_int8_t prefix_options,
|
||||
char *buf, int size);
|
||||
void ospf6_capability_printbuf (char capability, char *buf, int size);
|
||||
void ospf6_options_printbuf (char *options, char *buf, int size);
|
||||
|
||||
#endif /* OSPF6_PROTO_H */
|
||||
|
||||
|
1935
ospf6d/ospf6_route.c
1935
ospf6d/ospf6_route.c
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 1999 Yasuhiro Ohara
|
||||
* Copyright (C) 2003 Yasuhiro Ohara
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
@ -22,40 +22,49 @@
|
||||
#ifndef OSPF6_ROUTE_H
|
||||
#define OSPF6_ROUTE_H
|
||||
|
||||
#include "ospf6_hook.h"
|
||||
#include "ospf6_linklist.h"
|
||||
#define OSPF6_MULTI_PATH_LIMIT 4
|
||||
|
||||
struct ospf6_route_table
|
||||
/* Debug option */
|
||||
extern unsigned char conf_debug_ospf6_route;
|
||||
#define OSPF6_DEBUG_ROUTE_TABLE 0x01
|
||||
#define OSPF6_DEBUG_ROUTE_INTRA 0x02
|
||||
#define OSPF6_DEBUG_ROUTE_INTER 0x04
|
||||
#define OSPF6_DEBUG_ROUTE_ON(level) \
|
||||
(conf_debug_ospf6_route |= (level))
|
||||
#define OSPF6_DEBUG_ROUTE_OFF(level) \
|
||||
(conf_debug_ospf6_route &= ~(level))
|
||||
#define IS_OSPF6_DEBUG_ROUTE(e) \
|
||||
(conf_debug_ospf6_route & OSPF6_DEBUG_ROUTE_ ## e)
|
||||
|
||||
/* Nexthop */
|
||||
struct ospf6_nexthop
|
||||
{
|
||||
char name[128];
|
||||
/* Interface index */
|
||||
unsigned int ifindex;
|
||||
|
||||
int freeze;
|
||||
|
||||
/* radix tree */
|
||||
struct route_table *table;
|
||||
|
||||
/* list of hooks */
|
||||
struct linklist *hook_list[3];
|
||||
void (*hook_add) (void *);
|
||||
void (*hook_change) (void *);
|
||||
void (*hook_remove) (void *);
|
||||
|
||||
u_int32_t route_id;
|
||||
/* IP address, if any */
|
||||
struct in6_addr address;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct ospf6_route
|
||||
{
|
||||
/* Destination ID */
|
||||
struct prefix prefix;
|
||||
|
||||
/* Destination Type */
|
||||
u_char type;
|
||||
};
|
||||
#define ospf6_nexthop_is_set(x) \
|
||||
((x)->ifindex || ! IN6_IS_ADDR_UNSPECIFIED (&(x)->address))
|
||||
#define ospf6_nexthop_is_same(a,b) \
|
||||
((a)->ifindex == (b)->ifindex && \
|
||||
IN6_ARE_ADDR_EQUAL (&(a)->address, &(b)->address))
|
||||
#define ospf6_nexthop_clear(x) \
|
||||
do { \
|
||||
(x)->ifindex = 0; \
|
||||
memset (&(x)->address, 0, sizeof (struct in6_addr)); \
|
||||
} while (0)
|
||||
#define ospf6_nexthop_copy(a, b) \
|
||||
do { \
|
||||
(a)->ifindex = (b)->ifindex; \
|
||||
memcpy (&(a)->address, &(b)->address, \
|
||||
sizeof (struct in6_addr)); \
|
||||
} while (0)
|
||||
|
||||
/* Path */
|
||||
struct ls_origin
|
||||
struct ospf6_ls_origin
|
||||
{
|
||||
u_int16_t type;
|
||||
u_int32_t id;
|
||||
@ -65,13 +74,13 @@ struct 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
|
||||
#define OSPF6_PATH_TYPE_NONE 0
|
||||
#define OSPF6_PATH_TYPE_INTRA 1
|
||||
#define OSPF6_PATH_TYPE_INTER 2
|
||||
#define OSPF6_PATH_TYPE_EXTERNAL1 3
|
||||
#define OSPF6_PATH_TYPE_EXTERNAL2 4
|
||||
#define OSPF6_PATH_TYPE_MAX 5
|
||||
|
||||
#include "prefix.h"
|
||||
#include "table.h"
|
||||
|
||||
struct ospf6_route
|
||||
{
|
||||
/* Interface index */
|
||||
unsigned int ifindex;
|
||||
struct route_node *rnode;
|
||||
|
||||
/* IP address, if any */
|
||||
struct in6_addr address;
|
||||
};
|
||||
struct ospf6_route *prev;
|
||||
struct ospf6_route *next;
|
||||
|
||||
struct ospf6_route_node
|
||||
{
|
||||
struct ospf6_route_table *table;
|
||||
int count;
|
||||
u_int32_t route_id;
|
||||
unsigned int lock;
|
||||
|
||||
struct route_node *route_node;
|
||||
struct ospf6_route route;
|
||||
struct linklist *path_list;
|
||||
};
|
||||
/* Destination Type */
|
||||
u_char type;
|
||||
|
||||
struct ospf6_path_node
|
||||
{
|
||||
struct ospf6_route_node *route_node;
|
||||
struct ospf6_path path;
|
||||
struct linklist *nexthop_list;
|
||||
};
|
||||
/* Destination ID */
|
||||
struct prefix prefix;
|
||||
|
||||
struct ospf6_nexthop_node
|
||||
{
|
||||
int flag;
|
||||
/* Time */
|
||||
struct timeval installed;
|
||||
struct timeval changed;
|
||||
|
||||
struct ospf6_path_node *path_node;
|
||||
struct ospf6_nexthop nexthop;
|
||||
};
|
||||
/* flag */
|
||||
u_char flag;
|
||||
|
||||
struct ospf6_route_req
|
||||
{
|
||||
struct ospf6_route_table *table;
|
||||
struct route_node *route_node;
|
||||
struct linklist_node path_lnode;
|
||||
struct linklist_node nexthop_lnode;
|
||||
u_int32_t route_id;
|
||||
|
||||
int count;
|
||||
struct ospf6_route route;
|
||||
/* path */
|
||||
struct ospf6_path path;
|
||||
struct ospf6_nexthop nexthop;
|
||||
|
||||
/* nexthop */
|
||||
struct ospf6_nexthop nexthop[OSPF6_MULTI_PATH_LIMIT];
|
||||
|
||||
/* route option */
|
||||
void *route_option;
|
||||
};
|
||||
|
||||
#define OSPF6_DEST_TYPE_NONE 0
|
||||
#define OSPF6_DEST_TYPE_ROUTER 1
|
||||
#define OSPF6_DEST_TYPE_NETWORK 2
|
||||
#define OSPF6_DEST_TYPE_DISCARD 3
|
||||
#define OSPF6_DEST_TYPE_MAX 4
|
||||
#define OSPF6_DEST_TYPE_LINKSTATE 4
|
||||
#define OSPF6_DEST_TYPE_MAX 5
|
||||
|
||||
#define OSPF6_PATH_TYPE_NONE 0
|
||||
#define OSPF6_PATH_TYPE_INTRA 1
|
||||
#define OSPF6_PATH_TYPE_INTER 2
|
||||
#define OSPF6_PATH_TYPE_EXTERNAL1 3
|
||||
#define OSPF6_PATH_TYPE_EXTERNAL2 4
|
||||
#define OSPF6_PATH_TYPE_ZOFFSET 5
|
||||
#define OSPF6_PATH_TYPE_ZSYSTEM (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_SYSTEM)
|
||||
#define OSPF6_PATH_TYPE_ZKERNEL (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_KERNEL)
|
||||
#define OSPF6_PATH_TYPE_ZCONNECT (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_CONNECT)
|
||||
#define OSPF6_PATH_TYPE_ZSTATIC (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_STATIC)
|
||||
#define OSPF6_PATH_TYPE_ZRIP (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_RIP)
|
||||
#define OSPF6_PATH_TYPE_ZRIPNG (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_RIPNG)
|
||||
#define OSPF6_PATH_TYPE_ZOSPF (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_OSPF)
|
||||
#define OSPF6_PATH_TYPE_ZOSPF6 (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_OSPF6)
|
||||
#define OSPF6_PATH_TYPE_ZBGP (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_BGP)
|
||||
#define OSPF6_PATH_TYPE_MAX (OSPF6_PATH_TYPE_ZOFFSET + ZEBRA_ROUTE_MAX)
|
||||
#define OSPF6_ROUTE_CHANGE 0x01
|
||||
#define OSPF6_ROUTE_ADD 0x02
|
||||
#define OSPF6_ROUTE_REMOVE 0x04
|
||||
#define OSPF6_ROUTE_BEST 0x08
|
||||
|
||||
#define OSPF6_ROUTE_FLAG_ROUTE_CHANGE 0x01
|
||||
#define OSPF6_ROUTE_FLAG_PATH_CHANGE 0x02
|
||||
#define OSPF6_ROUTE_FLAG_ADD 0x04
|
||||
#define OSPF6_ROUTE_FLAG_REMOVE 0x08
|
||||
#define OSPF6_ROUTE_FLAG_CHANGE 0x10
|
||||
struct ospf6_route_table
|
||||
{
|
||||
/* patricia tree */
|
||||
struct route_table *table;
|
||||
|
||||
int ospf6_route_lookup (struct ospf6_route_req *request,
|
||||
struct prefix *prefix,
|
||||
u_int32_t count;
|
||||
|
||||
/* 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);
|
||||
void ospf6_route_head (struct ospf6_route_req *request,
|
||||
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);
|
||||
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 *);
|
||||
struct ospf6_route *
|
||||
ospf6_route_add (struct ospf6_route *route, struct ospf6_route_table *table);
|
||||
void
|
||||
ospf6_route_remove (struct ospf6_route *route, struct ospf6_route_table *table);
|
||||
|
||||
struct ospf6_route *ospf6_route_head (struct ospf6_route_table *table);
|
||||
struct ospf6_route *ospf6_route_next (struct ospf6_route *route);
|
||||
struct ospf6_route *ospf6_route_best_next (struct ospf6_route *route);
|
||||
|
||||
struct ospf6_route *ospf6_route_match_head (struct prefix *prefix,
|
||||
struct ospf6_route_table *table);
|
||||
struct ospf6_route *ospf6_route_match_next (struct prefix *prefix,
|
||||
struct ospf6_route *route);
|
||||
|
||||
void ospf6_route_remove_all (struct ospf6_route_table *);
|
||||
|
||||
struct ospf6_route_table *ospf6_route_table_create ();
|
||||
void ospf6_route_table_delete (struct ospf6_route_table *);
|
||||
|
||||
void ospf6_route_table_freeze (struct ospf6_route_table *);
|
||||
void ospf6_route_table_thaw (struct ospf6_route_table *);
|
||||
|
||||
void ospf6_route_log_request (char *what, char *where,
|
||||
struct ospf6_route_req *request);
|
||||
|
||||
void
|
||||
ospf6_route_hook_register (void (*add) (struct ospf6_route_req *),
|
||||
void (*change) (struct ospf6_route_req *),
|
||||
void (*remove) (struct ospf6_route_req *),
|
||||
struct ospf6_route_table *table);
|
||||
void
|
||||
ospf6_route_hook_unregister (void (*add) (struct ospf6_route_req *),
|
||||
void (*change) (struct ospf6_route_req *),
|
||||
void (*remove) (struct ospf6_route_req *),
|
||||
struct ospf6_route_table *table);
|
||||
|
||||
void ospf6_route_init ();
|
||||
void ospf6_route_dump (struct ospf6_route_table *table);
|
||||
|
||||
int ospf6_route_table_show (struct vty *, int, char **,
|
||||
struct ospf6_route_table *);
|
||||
int ospf6_lsentry_table_show (struct vty *, int, char **,
|
||||
struct ospf6_route_table *);
|
||||
|
||||
int config_write_ospf6_debug_route (struct vty *vty);
|
||||
void install_element_ospf6_debug_route ();
|
||||
void ospf6_route_init ();
|
||||
|
||||
#endif /* OSPF6_ROUTE_H */
|
||||
|
||||
|
@ -1,385 +0,0 @@
|
||||
/*
|
||||
* OSPFv3 Route-Map
|
||||
* Copyright (C) 1999 Yasuhiro Ohara
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
* GNU Zebra is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* GNU Zebra is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Zebra; see the file COPYING. If not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "memory.h"
|
||||
#include "linklist.h"
|
||||
#include "prefix.h"
|
||||
#include "command.h"
|
||||
#include "vty.h"
|
||||
#include "routemap.h"
|
||||
#include "table.h"
|
||||
#include "plist.h"
|
||||
|
||||
#include "ospf6_route.h"
|
||||
#include "ospf6_prefix.h"
|
||||
#include "ospf6_lsa.h"
|
||||
#include "ospf6_asbr.h"
|
||||
|
||||
route_map_result_t
|
||||
ospf6_routemap_rule_match_address_prefixlist (void *rule,
|
||||
struct prefix *prefix,
|
||||
route_map_object_t type,
|
||||
void *object)
|
||||
{
|
||||
struct prefix_list *plist;
|
||||
|
||||
if (type != RMAP_OSPF6)
|
||||
return RMAP_NOMATCH;
|
||||
|
||||
plist = prefix_list_lookup (AFI_IP6, (char *) rule);
|
||||
|
||||
if (plist == NULL)
|
||||
return RMAP_NOMATCH;
|
||||
|
||||
return (prefix_list_apply (plist, prefix) == PREFIX_DENY ?
|
||||
RMAP_NOMATCH : RMAP_MATCH);
|
||||
}
|
||||
|
||||
void *
|
||||
ospf6_routemap_rule_match_address_prefixlist_compile (char *arg)
|
||||
{
|
||||
return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_routemap_rule_match_address_prefixlist_free (void *rule)
|
||||
{
|
||||
XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||
}
|
||||
|
||||
struct route_map_rule_cmd
|
||||
ospf6_routemap_rule_match_address_prefixlist_cmd =
|
||||
{
|
||||
"ipv6 address prefix-list",
|
||||
ospf6_routemap_rule_match_address_prefixlist,
|
||||
ospf6_routemap_rule_match_address_prefixlist_compile,
|
||||
ospf6_routemap_rule_match_address_prefixlist_free,
|
||||
};
|
||||
|
||||
route_map_result_t
|
||||
ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix,
|
||||
route_map_object_t type, void *object)
|
||||
{
|
||||
char *metric_type = rule;
|
||||
struct ospf6_external_info *info = object;
|
||||
|
||||
if (type != RMAP_OSPF6)
|
||||
return RMAP_OKAY;
|
||||
|
||||
if (strcmp (metric_type, "type-2") == 0)
|
||||
info->metric_type = 2;
|
||||
else
|
||||
info->metric_type = 1;
|
||||
|
||||
return RMAP_OKAY;
|
||||
}
|
||||
|
||||
void *
|
||||
ospf6_routemap_rule_set_metric_type_compile (char *arg)
|
||||
{
|
||||
return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_routemap_rule_set_metric_type_free (void *rule)
|
||||
{
|
||||
XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||
}
|
||||
|
||||
struct route_map_rule_cmd
|
||||
ospf6_routemap_rule_set_metric_type_cmd =
|
||||
{
|
||||
"metric-type",
|
||||
ospf6_routemap_rule_set_metric_type,
|
||||
ospf6_routemap_rule_set_metric_type_compile,
|
||||
ospf6_routemap_rule_set_metric_type_free,
|
||||
};
|
||||
|
||||
route_map_result_t
|
||||
ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix,
|
||||
route_map_object_t type, void *object)
|
||||
{
|
||||
char *metric = rule;
|
||||
struct ospf6_external_info *info = object;
|
||||
|
||||
if (type != RMAP_OSPF6)
|
||||
return RMAP_OKAY;
|
||||
|
||||
info->metric = atoi (metric);
|
||||
return RMAP_OKAY;
|
||||
}
|
||||
|
||||
void *
|
||||
ospf6_routemap_rule_set_metric_compile (char *arg)
|
||||
{
|
||||
return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_routemap_rule_set_metric_free (void *rule)
|
||||
{
|
||||
XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||
}
|
||||
|
||||
struct route_map_rule_cmd
|
||||
ospf6_routemap_rule_set_metric_cmd =
|
||||
{
|
||||
"metric",
|
||||
ospf6_routemap_rule_set_metric,
|
||||
ospf6_routemap_rule_set_metric_compile,
|
||||
ospf6_routemap_rule_set_metric_free,
|
||||
};
|
||||
|
||||
route_map_result_t
|
||||
ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix,
|
||||
route_map_object_t type, void *object)
|
||||
{
|
||||
char *forwarding = rule;
|
||||
struct ospf6_external_info *info = object;
|
||||
|
||||
if (type != RMAP_OSPF6)
|
||||
return RMAP_OKAY;
|
||||
|
||||
if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1)
|
||||
{
|
||||
memset (&info->forwarding, 0, sizeof (struct in6_addr));
|
||||
return RMAP_ERROR;
|
||||
}
|
||||
|
||||
return RMAP_OKAY;
|
||||
}
|
||||
|
||||
void *
|
||||
ospf6_routemap_rule_set_forwarding_compile (char *arg)
|
||||
{
|
||||
return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_routemap_rule_set_forwarding_free (void *rule)
|
||||
{
|
||||
XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
|
||||
}
|
||||
|
||||
struct route_map_rule_cmd
|
||||
ospf6_routemap_rule_set_forwarding_cmd =
|
||||
{
|
||||
"forwarding-address",
|
||||
ospf6_routemap_rule_set_forwarding,
|
||||
ospf6_routemap_rule_set_forwarding_compile,
|
||||
ospf6_routemap_rule_set_forwarding_free,
|
||||
};
|
||||
|
||||
int
|
||||
route_map_command_status (struct vty *vty, int ret)
|
||||
{
|
||||
if (! ret)
|
||||
return CMD_SUCCESS;
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
case RMAP_RULE_MISSING:
|
||||
vty_out (vty, "Can't find rule.%s", VTY_NEWLINE);
|
||||
break;
|
||||
case RMAP_COMPILE_ERROR:
|
||||
vty_out (vty, "Argument is malformed.%s", VTY_NEWLINE);
|
||||
break;
|
||||
default:
|
||||
vty_out (vty, "route-map add set failed.%s", VTY_NEWLINE);
|
||||
break;
|
||||
}
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
/* add "match address" */
|
||||
DEFUN (match_ipv6_address_prefix_list,
|
||||
match_ipv6_address_prefix_list_cmd,
|
||||
"match ipv6 address prefix-list WORD",
|
||||
MATCH_STR
|
||||
IPV6_STR
|
||||
"Match address of route\n"
|
||||
"Match entries of prefix-lists\n"
|
||||
"IP prefix-list name\n")
|
||||
{
|
||||
int ret = route_map_add_match ((struct route_map_index *) vty->index,
|
||||
"ipv6 address prefix-list", argv[0]);
|
||||
return route_map_command_status (vty, ret);
|
||||
}
|
||||
|
||||
/* delete "match address" */
|
||||
DEFUN (no_match_ipv6_address_prefix_list,
|
||||
no_match_ipv6_address_prefix_list_cmd,
|
||||
"no match ipv6 address prefix-list WORD",
|
||||
NO_STR
|
||||
MATCH_STR
|
||||
IPV6_STR
|
||||
"Match address of route\n"
|
||||
"Match entries of prefix-lists\n"
|
||||
"IP prefix-list name\n")
|
||||
{
|
||||
int ret = route_map_delete_match ((struct route_map_index *) vty->index,
|
||||
"ipv6 address prefix-list", argv[0]);
|
||||
return route_map_command_status (vty, ret);
|
||||
}
|
||||
|
||||
/* add "set metric-type" */
|
||||
DEFUN (set_metric_type,
|
||||
set_metric_type_cmd,
|
||||
"set metric-type (type-1|type-2)",
|
||||
SET_STR
|
||||
"Type of metric for destination routing protocol\n"
|
||||
"OSPF[6] external type 1 metric\n"
|
||||
"OSPF[6] external type 2 metric\n")
|
||||
{
|
||||
int ret = route_map_add_set ((struct route_map_index *) vty->index,
|
||||
"metric-type", argv[0]);
|
||||
return route_map_command_status (vty, ret);
|
||||
}
|
||||
|
||||
/* delete "set metric-type" */
|
||||
DEFUN (no_set_metric_type,
|
||||
no_set_metric_type_cmd,
|
||||
"no set metric-type",
|
||||
NO_STR
|
||||
SET_STR
|
||||
"Type of metric for destination routing protocol\n")
|
||||
{
|
||||
int ret;
|
||||
if (argc == 0)
|
||||
ret = route_map_delete_set ((struct route_map_index *) vty->index,
|
||||
"metric-type", NULL);
|
||||
else
|
||||
ret = route_map_delete_set ((struct route_map_index *) vty->index,
|
||||
"metric-type", argv[0]);
|
||||
return route_map_command_status (vty, ret);
|
||||
}
|
||||
|
||||
ALIAS (no_set_metric_type,
|
||||
no_set_metric_type_val_cmd,
|
||||
"no set metric-type (type-1|type-2)",
|
||||
NO_STR
|
||||
SET_STR
|
||||
"Type of metric for destination routing protocol\n"
|
||||
"OSPF[6] external type 1 metric\n"
|
||||
"OSPF[6] external type 2 metric\n")
|
||||
|
||||
/* add "set metric" */
|
||||
DEFUN (set_metric,
|
||||
set_metric_cmd,
|
||||
"set metric <0-4294967295>",
|
||||
SET_STR
|
||||
"Metric value for destination routing protocol\n"
|
||||
"Metric value\n")
|
||||
{
|
||||
int ret = route_map_add_set ((struct route_map_index *) vty->index,
|
||||
"metric", argv[0]);
|
||||
return route_map_command_status (vty, ret);
|
||||
}
|
||||
|
||||
/* delete "set metric" */
|
||||
DEFUN (no_set_metric,
|
||||
no_set_metric_cmd,
|
||||
"no set metric",
|
||||
NO_STR
|
||||
SET_STR
|
||||
"Metric value for destination routing protocol\n")
|
||||
{
|
||||
int ret;
|
||||
if (argc == 0)
|
||||
ret = route_map_delete_set ((struct route_map_index *) vty->index,
|
||||
"metric", NULL);
|
||||
else
|
||||
ret = route_map_delete_set ((struct route_map_index *) vty->index,
|
||||
"metric", argv[0]);
|
||||
return route_map_command_status (vty, ret);
|
||||
}
|
||||
|
||||
ALIAS (no_set_metric,
|
||||
no_set_metric_val_cmd,
|
||||
"no set metric <0-4294967295>",
|
||||
NO_STR
|
||||
SET_STR
|
||||
"Metric value for destination routing protocol\n"
|
||||
"Metric value\n")
|
||||
|
||||
/* add "set forwarding-address" */
|
||||
DEFUN (ospf6_routemap_set_forwarding,
|
||||
ospf6_routemap_set_forwarding_cmd,
|
||||
"set forwarding-address X:X::X:X",
|
||||
"Set value\n"
|
||||
"Forwarding Address\n"
|
||||
"IPv6 Address\n")
|
||||
{
|
||||
int ret = route_map_add_set ((struct route_map_index *) vty->index,
|
||||
"forwarding-address", argv[0]);
|
||||
return route_map_command_status (vty, ret);
|
||||
}
|
||||
|
||||
/* delete "set forwarding-address" */
|
||||
DEFUN (ospf6_routemap_no_set_forwarding,
|
||||
ospf6_routemap_no_set_forwarding_cmd,
|
||||
"no set forwarding-address X:X::X:X",
|
||||
NO_STR
|
||||
"Set value\n"
|
||||
"Forwarding Address\n"
|
||||
"IPv6 Address\n")
|
||||
{
|
||||
int ret = route_map_delete_set ((struct route_map_index *) vty->index,
|
||||
"forwarding-address", argv[0]);
|
||||
return route_map_command_status (vty, ret);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_routemap_init ()
|
||||
{
|
||||
route_map_init ();
|
||||
route_map_init_vty ();
|
||||
route_map_add_hook (ospf6_asbr_routemap_update);
|
||||
route_map_delete_hook (ospf6_asbr_routemap_update);
|
||||
|
||||
route_map_install_match (&ospf6_routemap_rule_match_address_prefixlist_cmd);
|
||||
route_map_install_set (&ospf6_routemap_rule_set_metric_type_cmd);
|
||||
route_map_install_set (&ospf6_routemap_rule_set_metric_cmd);
|
||||
route_map_install_set (&ospf6_routemap_rule_set_forwarding_cmd);
|
||||
|
||||
/* Match address prefix-list */
|
||||
install_element (RMAP_NODE, &match_ipv6_address_prefix_list_cmd);
|
||||
install_element (RMAP_NODE, &no_match_ipv6_address_prefix_list_cmd);
|
||||
|
||||
/* ASE Metric Type (e.g. Type-1/Type-2) */
|
||||
install_element (RMAP_NODE, &set_metric_type_cmd);
|
||||
install_element (RMAP_NODE, &no_set_metric_type_cmd);
|
||||
install_element (RMAP_NODE, &no_set_metric_type_val_cmd);
|
||||
|
||||
/* ASE Metric */
|
||||
install_element (RMAP_NODE, &set_metric_cmd);
|
||||
install_element (RMAP_NODE, &no_set_metric_cmd);
|
||||
install_element (RMAP_NODE, &no_set_metric_val_cmd);
|
||||
|
||||
/* ASE Metric */
|
||||
install_element (RMAP_NODE, &ospf6_routemap_set_forwarding_cmd);
|
||||
install_element (RMAP_NODE, &ospf6_routemap_no_set_forwarding_cmd);
|
||||
}
|
||||
|
@ -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 */
|
1820
ospf6d/ospf6_spf.c
1820
ospf6d/ospf6_spf.c
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
void ospf6_spf_table_finish (struct ospf6_route_table *result_table);
|
||||
void ospf6_spf_calculation (u_int32_t router_id,
|
||||
struct ospf6_route_table *result_table,
|
||||
struct ospf6_area *oa);
|
||||
void ospf6_spf_schedule (struct ospf6_area *oa);
|
||||
|
||||
/* root of this tree */
|
||||
struct ospf6_vertex *root;
|
||||
|
||||
/* list for search */
|
||||
list list;
|
||||
|
||||
/* statistics */
|
||||
u_int32_t timerun;
|
||||
|
||||
struct timeval runtime_total;
|
||||
struct timeval runtime_min;
|
||||
struct timeval runtime_max;
|
||||
|
||||
struct timeval updated_time;
|
||||
struct timeval interval_total;
|
||||
struct timeval interval_min;
|
||||
struct timeval interval_max;
|
||||
};
|
||||
|
||||
int ospf6_spf_calculate_route (void *);
|
||||
|
||||
void
|
||||
ospf6_spf_calculation_schedule (u_int32_t area_id);
|
||||
struct ospf6_spftree *ospf6_spftree_create ();
|
||||
void
|
||||
ospf6_spf_statistics_show (struct vty *vty, struct ospf6_spftree *spf_tree);
|
||||
void ospf6_spftree_delete (struct ospf6_spftree *spf_tree);
|
||||
|
||||
void ospf6_spf_database_hook (struct ospf6_lsa *old, struct ospf6_lsa *new);
|
||||
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 */
|
||||
|
@ -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 *))
|
||||
{
|
||||
listnode node;
|
||||
struct ospf6_area *o6a;
|
||||
|
||||
for (node = listhead (o6->area_list); node; nextnode (node))
|
||||
{
|
||||
o6a = (struct ospf6_area *) getdata (node);
|
||||
(*func) (arg, val, o6a);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ospf6_top_foreach_interface (struct ospf6 *o6, void *arg, int val,
|
||||
void (*func) (void *, int, void *))
|
||||
{
|
||||
listnode node;
|
||||
struct ospf6_area *o6a;
|
||||
|
||||
for (node = listhead (o6->area_list); node; nextnode (node))
|
||||
{
|
||||
o6a = (struct ospf6_area *) getdata (node);
|
||||
(*o6a->foreach_if) (o6a, arg, val, func);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ospf6_top_foreach_neighbor (struct ospf6 *o6, void *arg, int val,
|
||||
void (*func) (void *, int, void *))
|
||||
{
|
||||
listnode node;
|
||||
struct ospf6_area *o6a;
|
||||
|
||||
for (node = listhead (o6->area_list); node; nextnode (node))
|
||||
{
|
||||
o6a = (struct ospf6_area *) getdata (node);
|
||||
(*o6a->foreach_nei) (o6a, arg, val, func);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ospf6_top_maxage_remover (struct thread *t)
|
||||
{
|
||||
int count;
|
||||
struct ospf6 *o6 = (struct ospf6 *) THREAD_ARG (t);
|
||||
|
||||
o6->maxage_remover = (struct thread *) NULL;
|
||||
|
||||
count = 0;
|
||||
o6->foreach_nei (o6, &count, NBS_EXCHANGE, ospf6_count_state);
|
||||
o6->foreach_nei (o6, &count, NBS_LOADING, ospf6_count_state);
|
||||
if (count != 0)
|
||||
return 0;
|
||||
|
||||
ospf6_lsdb_remove_maxage (o6->lsdb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_top_schedule_maxage_remover (void *arg, int val, struct ospf6 *o6)
|
||||
ospf6_top_lsdb_hook_add (struct ospf6_lsa *lsa)
|
||||
{
|
||||
if (o6->maxage_remover != NULL)
|
||||
return;
|
||||
|
||||
o6->maxage_remover =
|
||||
thread_add_event (master, ospf6_top_maxage_remover, o6, 0);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_show (struct vty *vty)
|
||||
{
|
||||
listnode n;
|
||||
struct ospf6_area *area;
|
||||
char id_string[32];
|
||||
unsigned long day, hour, min, sec;
|
||||
struct timeval now, running;
|
||||
|
||||
/* process id, router id */
|
||||
inet_ntop (AF_INET, &ospf6->router_id, id_string, sizeof (id_string));
|
||||
vty_out (vty, " Routing Process (%lu) with ID %s%s",
|
||||
ospf6->process_id, id_string, VTY_NEWLINE);
|
||||
|
||||
/* 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);
|
||||
|
||||
vty_out (vty, " Supports only single TOS(TOS0) routes%s", VTY_NEWLINE);
|
||||
|
||||
/* Redistribute config */
|
||||
ospf6_redistribute_show_config (vty);
|
||||
|
||||
/* LSAs */
|
||||
vty_out (vty, " Number of AS scoped LSAs is %u%s",
|
||||
ospf6->lsdb->count, VTY_NEWLINE);
|
||||
vty_out (vty, " Route calculation executed %d times%s",
|
||||
ospf6->stat_route_calculation_execed, VTY_NEWLINE);
|
||||
|
||||
/* Route Statistics */
|
||||
#if 0
|
||||
ospf6_route_statistics_show (vty, ospf6->route_table);
|
||||
#endif
|
||||
|
||||
/* 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))
|
||||
switch (ntohs (lsa->header->type))
|
||||
{
|
||||
area = (struct ospf6_area *) getdata (n);
|
||||
ospf6_area_show (vty, area);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_statistics_show (struct vty *vty, struct ospf6 *o6)
|
||||
ospf6_top_lsdb_hook_remove (struct ospf6_lsa *lsa)
|
||||
{
|
||||
listnode node;
|
||||
struct ospf6_area *o6a;
|
||||
char running_time[128];
|
||||
struct timeval now, running;
|
||||
|
||||
gettimeofday (&now, (struct timezone *) NULL);
|
||||
ospf6_timeval_sub (&now, &o6->starttime, &running);
|
||||
ospf6_timeval_string (&running, running_time, sizeof (running_time));
|
||||
|
||||
vty_out (vty, "Statistics of OSPF process %ld%s",
|
||||
o6->process_id, VTY_NEWLINE);
|
||||
vty_out (vty, " Running: %s%s", running_time, VTY_NEWLINE);
|
||||
|
||||
#if 0
|
||||
ospf6_route_statistics_show (vty, o6->route_table);
|
||||
#endif
|
||||
|
||||
for (node = listhead (o6->area_list); node; nextnode (node))
|
||||
switch (ntohs (lsa->header->type))
|
||||
{
|
||||
o6a = (struct ospf6_area *) getdata (node);
|
||||
ospf6_area_statistics_show (vty, o6a);
|
||||
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 struct ospf6 *
|
||||
ospf6_new ()
|
||||
{
|
||||
struct ospf6 *new;
|
||||
new = XMALLOC (MTYPE_OSPF6_TOP, sizeof (struct ospf6));
|
||||
if (new)
|
||||
memset (new, 0, sizeof (struct ospf6));
|
||||
return new;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_free (struct ospf6 *ospf6)
|
||||
{
|
||||
XFREE (MTYPE_OSPF6_TOP, ospf6);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_top_topology_add (struct ospf6_route_req *request)
|
||||
{
|
||||
assert (request->route.type == OSPF6_DEST_TYPE_ROUTER);
|
||||
if (CHECK_FLAG (request->path.router_bits, OSPF6_ROUTER_LSA_BIT_E))
|
||||
ospf6_asbr_asbr_entry_add (request);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_top_topology_remove (struct ospf6_route_req *request)
|
||||
{
|
||||
assert (request->route.type == OSPF6_DEST_TYPE_ROUTER);
|
||||
if (CHECK_FLAG (request->path.router_bits, OSPF6_ROUTER_LSA_BIT_E))
|
||||
ospf6_asbr_asbr_entry_remove (request);
|
||||
}
|
||||
|
||||
struct ospf6 *
|
||||
ospf6_create (unsigned long process_id)
|
||||
ospf6_create ()
|
||||
{
|
||||
struct ospf6 *o6;
|
||||
char namebuf[64];
|
||||
struct ospf6 *o;
|
||||
|
||||
o6 = ospf6_new ();
|
||||
o = XMALLOC (MTYPE_OSPF6_TOP, sizeof (struct ospf6));
|
||||
memset (o, 0, sizeof (struct ospf6));
|
||||
|
||||
/* initialize */
|
||||
gettimeofday (&o6->starttime, (struct timezone *)NULL);
|
||||
o6->process_id = process_id;
|
||||
o6->version = OSPF6_VERSION;
|
||||
o6->area_list = list_new ();
|
||||
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->lsdb = ospf6_lsdb_create ();
|
||||
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;
|
||||
|
||||
o6->foreach_area = ospf6_top_foreach_area;
|
||||
o6->foreach_if = ospf6_top_foreach_interface;
|
||||
o6->foreach_nei = ospf6_top_foreach_neighbor;
|
||||
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;
|
||||
|
||||
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);
|
||||
o->external_table = ospf6_route_table_create ();
|
||||
o->external_id_table = route_table_init ();
|
||||
|
||||
#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;
|
||||
return o;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_delete (struct ospf6 *ospf6)
|
||||
ospf6_delete (struct ospf6 *o)
|
||||
{
|
||||
if (!ospf6)
|
||||
return;
|
||||
listnode i;
|
||||
struct ospf6_area *oa;
|
||||
|
||||
ospf6_route_remove_all (ospf6->route_table);
|
||||
ospf6_free (ospf6);
|
||||
}
|
||||
for (i = listhead (o->area_list); i; nextnode (i))
|
||||
{
|
||||
oa = (struct ospf6_area *) getdata (i);
|
||||
ospf6_area_delete (oa);
|
||||
}
|
||||
|
||||
struct ospf6 *
|
||||
ospf6_start ()
|
||||
{
|
||||
if (ospf6)
|
||||
return ospf6;
|
||||
ospf6_lsdb_delete (o->lsdb);
|
||||
|
||||
ospf6 = ospf6_create (0);
|
||||
return ospf6;
|
||||
ospf6_route_table_delete (o->route_table);
|
||||
ospf6_route_table_delete (o->asbr_table);
|
||||
|
||||
ospf6_route_table_delete (o->external_table);
|
||||
route_table_finish (o->external_id_table);
|
||||
|
||||
XFREE (MTYPE_OSPF6_TOP, o);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_stop ()
|
||||
ospf6_enable (struct ospf6 *o)
|
||||
{
|
||||
if (!ospf6)
|
||||
return;
|
||||
listnode i;
|
||||
struct ospf6_area *oa;
|
||||
|
||||
ospf6_delete (ospf6);
|
||||
ospf6 = NULL;
|
||||
if (CHECK_FLAG (o->flag, OSPF6_DISABLED))
|
||||
{
|
||||
UNSET_FLAG (o->flag, OSPF6_DISABLED);
|
||||
for (i = listhead (o->area_list); i; nextnode (i))
|
||||
{
|
||||
oa = (struct ospf6_area *) getdata (i);
|
||||
ospf6_area_enable (oa);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_disable (struct ospf6 *o)
|
||||
{
|
||||
listnode i;
|
||||
struct ospf6_area *oa;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ospf6_is_asbr (struct ospf6 *o6)
|
||||
ospf6_maxage_remover (struct thread *thread)
|
||||
{
|
||||
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);
|
||||
struct ospf6 *o = (struct ospf6 *) THREAD_ARG (thread);
|
||||
struct ospf6_area *oa;
|
||||
struct ospf6_interface *oi;
|
||||
struct ospf6_neighbor *on;
|
||||
listnode i, j, k;
|
||||
|
||||
o->maxage_remover = (struct thread *) NULL;
|
||||
if (IS_OSPF6_DEBUG_LSA (TIMER))
|
||||
zlog_info ("Maxage Remover");
|
||||
|
||||
for (i = listhead (o->area_list); i; nextnode (i))
|
||||
{
|
||||
oa = (struct ospf6_area *) getdata (i);
|
||||
for (j = listhead (oa->if_list); j; nextnode (j))
|
||||
{
|
||||
oi = (struct ospf6_interface *) getdata (j);
|
||||
for (k = listhead (oi->neighbor_list); k; nextnode (k))
|
||||
{
|
||||
on = (struct ospf6_neighbor *) getdata (k);
|
||||
if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
|
||||
on->state != OSPF6_NEIGHBOR_LOADING)
|
||||
continue;
|
||||
|
||||
if (IS_OSPF6_DEBUG_LSA (TIMER))
|
||||
zlog_info ("Maxage Remover End: %s exchange or loading",
|
||||
on->name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = listhead (o->area_list); i; nextnode (i))
|
||||
{
|
||||
oa = (struct ospf6_area *) getdata (i);
|
||||
for (j = listhead (oa->if_list); j; nextnode (j))
|
||||
{
|
||||
oi = (struct ospf6_interface *) getdata (j);
|
||||
OSPF6_LSDB_MAXAGE_REMOVER (oi->lsdb);
|
||||
}
|
||||
OSPF6_LSDB_MAXAGE_REMOVER (oa->lsdb);
|
||||
}
|
||||
OSPF6_LSDB_MAXAGE_REMOVER (o->lsdb);
|
||||
|
||||
if (IS_OSPF6_DEBUG_LSA (TIMER))
|
||||
zlog_info ("Maxage Remover End");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_maxage_remove (struct ospf6 *o)
|
||||
{
|
||||
if (o && ! o->maxage_remover)
|
||||
o->maxage_remover = thread_add_event (master, ospf6_maxage_remover, o, 0);
|
||||
}
|
||||
|
||||
/* start ospf6 */
|
||||
DEFUN (router_ospf6,
|
||||
router_ospf6_cmd,
|
||||
"router ospf6",
|
||||
ROUTER_STR
|
||||
OSPF6_STR)
|
||||
{
|
||||
if (ospf6 == NULL)
|
||||
ospf6 = ospf6_create ();
|
||||
if (CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
|
||||
ospf6_enable (ospf6);
|
||||
|
||||
/* set current ospf point. */
|
||||
vty->node = OSPF6_NODE;
|
||||
vty->index = ospf6;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* stop ospf6 */
|
||||
DEFUN (no_router_ospf6,
|
||||
no_router_ospf6_cmd,
|
||||
"no router ospf6",
|
||||
NO_STR
|
||||
OSPF6_ROUTER_STR)
|
||||
{
|
||||
if (ospf6 == NULL || CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
|
||||
vty_out (vty, "OSPFv3 is not running%s", VTY_NEWLINE);
|
||||
else
|
||||
ospf6_disable (ospf6);
|
||||
|
||||
/* return to config node . */
|
||||
vty->node = CONFIG_NODE;
|
||||
vty->index = NULL;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* change Router_ID commands. */
|
||||
DEFUN (ospf6_router_id,
|
||||
ospf6_router_id_cmd,
|
||||
"router-id A.B.C.D",
|
||||
"Configure OSPF Router-ID\n"
|
||||
V4NOTATION_STR)
|
||||
{
|
||||
int ret;
|
||||
u_int32_t router_id;
|
||||
struct ospf6 *o;
|
||||
|
||||
o = (struct ospf6 *) vty->index;
|
||||
|
||||
ret = inet_pton (AF_INET, argv[0], &router_id);
|
||||
if (ret == 0)
|
||||
{
|
||||
vty_out (vty, "malformed OSPF Router-ID: %s%s", argv[0], VTY_NEWLINE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
o->router_id = router_id;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ospf6_interface_area,
|
||||
ospf6_interface_area_cmd,
|
||||
"interface IFNAME area A.B.C.D",
|
||||
"Enable routing on an IPv6 interface\n"
|
||||
IFNAME_STR
|
||||
"Specify the OSPF6 area ID\n"
|
||||
"OSPF6 area ID in IPv4 address notation\n"
|
||||
)
|
||||
{
|
||||
struct ospf6 *o;
|
||||
struct ospf6_area *oa;
|
||||
struct ospf6_interface *oi;
|
||||
struct interface *ifp;
|
||||
u_int32_t area_id;
|
||||
|
||||
o = (struct ospf6 *) vty->index;
|
||||
|
||||
/* find/create ospf6 interface */
|
||||
ifp = if_get_by_name (argv[0]);
|
||||
oi = (struct ospf6_interface *) ifp->info;
|
||||
if (oi == NULL)
|
||||
oi = ospf6_interface_create (ifp);
|
||||
if (oi->area)
|
||||
{
|
||||
vty_out (vty, "%s already attached to Area %s%s",
|
||||
oi->interface->name, oi->area->name, VTY_NEWLINE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* parse Area-ID */
|
||||
if (inet_pton (AF_INET, argv[1], &area_id) != 1)
|
||||
{
|
||||
vty_out (vty, "Invalid Area-ID: %s%s", argv[1], VTY_NEWLINE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* find/create ospf6 area */
|
||||
oa = ospf6_area_lookup (area_id, o);
|
||||
if (oa == NULL)
|
||||
oa = ospf6_area_create (area_id, o);
|
||||
|
||||
/* attach interface to area */
|
||||
listnode_add (oa->if_list, oi); /* sort ?? */
|
||||
oi->area = oa;
|
||||
|
||||
/* start up */
|
||||
thread_add_event (master, interface_up, oi, 0);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_ospf6_interface_area,
|
||||
no_ospf6_interface_area_cmd,
|
||||
"no interface IFNAME area A.B.C.D",
|
||||
NO_STR
|
||||
"Disable routing on an IPv6 interface\n"
|
||||
IFNAME_STR
|
||||
"Specify the OSPF6 area ID\n"
|
||||
"OSPF6 area ID in IPv4 address notation\n"
|
||||
)
|
||||
{
|
||||
struct ospf6 *o;
|
||||
struct ospf6_interface *oi;
|
||||
struct interface *ifp;
|
||||
u_int32_t area_id;
|
||||
|
||||
o = (struct ospf6 *) vty->index;
|
||||
|
||||
ifp = if_lookup_by_name (argv[0]);
|
||||
if (ifp == NULL)
|
||||
{
|
||||
vty_out (vty, "No such interface %s%s", argv[0], VTY_NEWLINE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
oi = (struct ospf6_interface *) ifp->info;
|
||||
if (oi == NULL)
|
||||
{
|
||||
vty_out (vty, "Interface %s not enabled%s", ifp->name, VTY_NEWLINE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/* parse Area-ID */
|
||||
if (inet_pton (AF_INET, argv[1], &area_id) != 1)
|
||||
{
|
||||
vty_out (vty, "Invalid Area-ID: %s%s", argv[1], VTY_NEWLINE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
if (oi->area->area_id != area_id)
|
||||
{
|
||||
vty_out (vty, "Wrong Area-ID: %s is attached to area %s%s",
|
||||
oi->interface->name, oi->area->name, VTY_NEWLINE);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
thread_execute (master, interface_down, oi, 0);
|
||||
|
||||
listnode_delete (oi->area->if_list, oi);
|
||||
oi->area = (struct ospf6_area *) NULL;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_show (struct vty *vty, struct ospf6 *o)
|
||||
{
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/* show top level structures */
|
||||
DEFUN (show_ipv6_ospf6,
|
||||
show_ipv6_ospf6_cmd,
|
||||
"show ipv6 ospf6",
|
||||
SHOW_STR
|
||||
IP6_STR
|
||||
OSPF6_STR)
|
||||
{
|
||||
OSPF6_CMD_CHECK_RUNNING ();
|
||||
|
||||
ospf6_show (vty, 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;
|
||||
|
||||
ALIAS (show_ipv6_ospf6_topology,
|
||||
show_ipv6_ospf6_topology_router_lsid_cmd,
|
||||
"show ipv6 ospf6 topology (A.B.C.D|<0-4294967295>) (A.B.C.D|<0-4294967295>)",
|
||||
SHOW_STR
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"Inter Area topology information\n"
|
||||
OSPF6_ROUTER_ID_STR
|
||||
OSPF6_ROUTER_ID_STR
|
||||
OSPF6_LS_ID_STR
|
||||
OSPF6_LS_ID_STR
|
||||
)
|
||||
/* copy argv to sargv and then append "match" and "detail" */
|
||||
for (i = 0; i < argc; i++)
|
||||
sargv[i] = argv[i];
|
||||
sargc = argc;
|
||||
sargv[sargc++] = "match";
|
||||
sargv[sargc++] = "detail";
|
||||
sargv[sargc] = NULL;
|
||||
|
||||
ospf6_route_table_show (vty, sargc, sargv, ospf6->route_table);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* OSPF configuration write function. */
|
||||
int
|
||||
config_write_ospf6 (struct vty *vty)
|
||||
{
|
||||
char router_id[16];
|
||||
listnode j, k;
|
||||
struct ospf6_area *oa;
|
||||
struct ospf6_interface *oi;
|
||||
|
||||
/* OSPFv6 configuration. */
|
||||
if (ospf6 == NULL)
|
||||
return CMD_SUCCESS;
|
||||
if (CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
|
||||
return CMD_SUCCESS;
|
||||
|
||||
inet_ntop (AF_INET, &ospf6->router_id, router_id, sizeof (router_id));
|
||||
vty_out (vty, "router ospf6%s", VTY_NEWLINE);
|
||||
vty_out (vty, " router-id %s%s", router_id, VTY_NEWLINE);
|
||||
|
||||
ospf6_redistribute_config_write (vty);
|
||||
|
||||
for (j = listhead (ospf6->area_list); j; nextnode (j))
|
||||
{
|
||||
oa = (struct ospf6_area *) getdata (j);
|
||||
for (k = listhead (oa->if_list); k; nextnode (k))
|
||||
{
|
||||
oi = (struct ospf6_interface *) getdata (k);
|
||||
vty_out (vty, " interface %s area %s%s",
|
||||
oi->interface->name, oa->name, VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
vty_out (vty, "!%s", VTY_NEWLINE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* OSPF6 node structure. */
|
||||
struct cmd_node ospf6_node =
|
||||
{
|
||||
OSPF6_NODE,
|
||||
"%s(config-ospf6)# ",
|
||||
};
|
||||
|
||||
/* Install ospf related commands. */
|
||||
void
|
||||
ospf6_top_init ()
|
||||
{
|
||||
/* Install ospf6 top node. */
|
||||
install_node (&ospf6_node, config_write_ospf6);
|
||||
|
||||
install_element (VIEW_NODE, &show_ipv6_ospf6_cmd);
|
||||
install_element (ENABLE_NODE, &show_ipv6_ospf6_cmd);
|
||||
install_element (CONFIG_NODE, &router_ospf6_cmd);
|
||||
|
||||
install_element (VIEW_NODE, &show_ipv6_ospf6_route_cmd);
|
||||
install_element (VIEW_NODE, &show_ipv6_ospf6_route_prefix_cmd);
|
||||
install_element (VIEW_NODE, &show_ipv6_ospf6_topology_cmd);
|
||||
install_element (VIEW_NODE, &show_ipv6_ospf6_topology_router_cmd);
|
||||
install_element (VIEW_NODE, &show_ipv6_ospf6_topology_router_lsid_cmd);
|
||||
install_element (VIEW_NODE, &show_ipv6_ospf6_route_detail_cmd);
|
||||
install_element (VIEW_NODE, &show_ipv6_ospf6_route_match_cmd);
|
||||
install_element (VIEW_NODE, &show_ipv6_ospf6_route_match_detail_cmd);
|
||||
install_element (ENABLE_NODE, &show_ipv6_ospf6_route_cmd);
|
||||
install_element (ENABLE_NODE, &show_ipv6_ospf6_route_prefix_cmd);
|
||||
install_element (ENABLE_NODE, &show_ipv6_ospf6_topology_cmd);
|
||||
install_element (ENABLE_NODE, &show_ipv6_ospf6_topology_router_cmd);
|
||||
install_element (ENABLE_NODE, &show_ipv6_ospf6_topology_router_lsid_cmd);
|
||||
install_element (ENABLE_NODE, &show_ipv6_ospf6_route_detail_cmd);
|
||||
install_element (ENABLE_NODE, &show_ipv6_ospf6_route_match_cmd);
|
||||
install_element (ENABLE_NODE, &show_ipv6_ospf6_route_match_detail_cmd);
|
||||
|
||||
install_default (OSPF6_NODE);
|
||||
install_element (OSPF6_NODE, &ospf6_router_id_cmd);
|
||||
install_element (OSPF6_NODE, &ospf6_interface_area_cmd);
|
||||
install_element (OSPF6_NODE, &no_ospf6_interface_area_cmd);
|
||||
install_element (OSPF6_NODE, &no_router_ospf6_cmd);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
#define OSPF6_DISABLED 0x01
|
||||
|
||||
/* global pointer for OSPF top data structure */
|
||||
extern struct ospf6 *ospf6;
|
||||
|
||||
/* prototypes */
|
||||
int
|
||||
ospf6_top_count_neighbor_in_state (u_char state, struct ospf6 *o6);
|
||||
|
||||
void
|
||||
ospf6_top_schedule_maxage_remover (void *arg, int val, struct ospf6 *o6);
|
||||
|
||||
void ospf6_show (struct vty *);
|
||||
void ospf6_statistics_show (struct vty *vty, struct ospf6 *o6);
|
||||
|
||||
struct ospf6 *ospf6_start ();
|
||||
void ospf6_stop ();
|
||||
|
||||
void ospf6_delete (struct ospf6 *);
|
||||
int ospf6_is_asbr (struct ospf6 *);
|
||||
|
||||
void ospf6_top_init ();
|
||||
|
||||
void ospf6_maxage_remove (struct ospf6 *o);
|
||||
|
||||
#endif /* OSPF6_TOP_H */
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 1999 Yasuhiro Ohara
|
||||
* Copyright (C) 2003 Yasuhiro Ohara
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
@ -19,12 +19,26 @@
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <zebra.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "vty.h"
|
||||
#include "command.h"
|
||||
#include "prefix.h"
|
||||
#include "stream.h"
|
||||
#include "zclient.h"
|
||||
#include "memory.h"
|
||||
|
||||
#include "ospf6d.h"
|
||||
|
||||
#include "ospf6_proto.h"
|
||||
#include "ospf6_top.h"
|
||||
#include "ospf6_interface.h"
|
||||
#include "ospf6_route.h"
|
||||
#include "ospf6_lsa.h"
|
||||
#include "ospf6_asbr.h"
|
||||
#include "ospf6_zebra.h"
|
||||
|
||||
#include "ospf6_linklist.h"
|
||||
unsigned char conf_debug_ospf6_zebra = 0;
|
||||
|
||||
/* information about zebra. */
|
||||
struct zclient *zclient = NULL;
|
||||
@ -33,50 +47,23 @@ 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);
|
||||
@ -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,
|
||||
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)
|
||||
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))
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_ZEBRA (SEND))
|
||||
zlog_info (" Best-path removal resulted Sencondary addition");
|
||||
type = ADD;
|
||||
request = request->next;
|
||||
}
|
||||
|
||||
/* Only the best path will be sent to zebra. */
|
||||
if (! ospf6_route_is_best (request))
|
||||
{
|
||||
/* this is not preferred best route, ignore */
|
||||
if (IS_OSPF6_DUMP_ZEBRA)
|
||||
zlog_info ("ZEBRA: not best path, ignore");
|
||||
if (IS_OSPF6_DEBUG_ZEBRA (SEND))
|
||||
zlog_info (" Ignore non-best route");
|
||||
return;
|
||||
}
|
||||
|
||||
nexthop_list = linklist_create ();
|
||||
nhcount = 0;
|
||||
for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
|
||||
if (ospf6_nexthop_is_set (&request->nexthop[i]))
|
||||
nhcount++;
|
||||
|
||||
/* for each nexthop */
|
||||
for (ospf6_route_lookup (&route, &request->route.prefix, request->table);
|
||||
! ospf6_route_end (&route); ospf6_route_next (&route))
|
||||
if (nhcount == 0)
|
||||
{
|
||||
if (memcmp (&route.path, &request->path, sizeof (route.path)))
|
||||
break;
|
||||
|
||||
#define IN6_IS_ILLEGAL_NEXTHOP(a)\
|
||||
((*(u_int32_t *)(void *)(&(a)->s6_addr[0]) == 0xffffffff) &&\
|
||||
(*(u_int32_t *)(void *)(&(a)->s6_addr[4]) == 0xffffffff) &&\
|
||||
(*(u_int32_t *)(void *)(&(a)->s6_addr[8]) == 0xffffffff) &&\
|
||||
(*(u_int32_t *)(void *)(&(a)->s6_addr[12]) == 0xffffffff))
|
||||
if (IN6_IS_ILLEGAL_NEXTHOP (&route.nexthop.address))
|
||||
{
|
||||
zlog_warn ("ZEBRA: Illegal nexthop");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type == REMOVE && ! memcmp (&route.nexthop, &request->nexthop,
|
||||
sizeof (struct ospf6_nexthop)))
|
||||
continue;
|
||||
|
||||
nexthop = XCALLOC (MTYPE_OSPF6_OTHER, sizeof (struct ospf6_nexthop));
|
||||
if (! nexthop)
|
||||
{
|
||||
zlog_warn ("ZEBRA: Can't update nexthop: malloc failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy (nexthop, &route.nexthop, sizeof (struct ospf6_nexthop));
|
||||
linklist_add (nexthop, nexthop_list);
|
||||
}
|
||||
|
||||
if (type == REMOVE && nexthop_list->count != 0)
|
||||
type = ADD;
|
||||
else if (type == REMOVE && nexthop_list->count == 0)
|
||||
{
|
||||
if (IS_OSPF6_DUMP_ZEBRA)
|
||||
zlog_info ("ZEBRA: all nexthop with the selected path has gone");
|
||||
|
||||
if (! memcmp (&request->route, &route.route,
|
||||
sizeof (struct ospf6_route)))
|
||||
{
|
||||
/* send 'add' of alternative route */
|
||||
struct ospf6_path seconde_path;
|
||||
|
||||
if (IS_OSPF6_DUMP_ZEBRA)
|
||||
zlog_info ("ZEBRA: found alternative path to add");
|
||||
|
||||
memcpy (&seconde_path, &route.path, sizeof (struct ospf6_path));
|
||||
type = ADD;
|
||||
|
||||
while (! memcmp (&seconde_path, &route.path,
|
||||
sizeof (struct ospf6_path)))
|
||||
{
|
||||
nexthop = XCALLOC (MTYPE_OSPF6_OTHER,
|
||||
sizeof (struct ospf6_nexthop));
|
||||
if (! nexthop)
|
||||
zlog_warn ("ZEBRA: Can't update nexthop: malloc failed");
|
||||
else
|
||||
{
|
||||
memcpy (nexthop, &route.nexthop,
|
||||
sizeof (struct ospf6_nexthop));
|
||||
linklist_add (nexthop, nexthop_list);
|
||||
}
|
||||
|
||||
ospf6_route_next (&route);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* there is no alternative route. send 'remove' to zebra for
|
||||
requested route */
|
||||
if (IS_OSPF6_DUMP_ZEBRA)
|
||||
zlog_info ("ZEBRA: can't find alternative path, remove");
|
||||
|
||||
if (IS_OSPF6_DUMP_ZEBRA)
|
||||
{
|
||||
zlog_info ("ZEBRA: Debug: walk over the route ?");
|
||||
ospf6_route_log_request ("Debug route", "***", &route);
|
||||
ospf6_route_log_request ("Debug request", "***", request);
|
||||
}
|
||||
|
||||
nexthop = XCALLOC (MTYPE_OSPF6_OTHER,
|
||||
sizeof (struct ospf6_nexthop));
|
||||
if (! nexthop)
|
||||
zlog_warn ("ZEBRA: Can't update nexthop: malloc failed");
|
||||
else
|
||||
{
|
||||
memcpy (nexthop, &request->nexthop,
|
||||
sizeof (struct ospf6_nexthop));
|
||||
linklist_add (nexthop, nexthop_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nexthop_list->count == 0)
|
||||
{
|
||||
if (IS_OSPF6_DUMP_ZEBRA)
|
||||
zlog_info ("ZEBRA: no nexthop, ignore");
|
||||
linklist_delete (nexthop_list);
|
||||
if (IS_OSPF6_DEBUG_ZEBRA (SEND))
|
||||
zlog_info (" No nexthop, ignore");
|
||||
return;
|
||||
}
|
||||
|
||||
/* allocate memory for nexthop_list */
|
||||
nexthops = XCALLOC (MTYPE_OSPF6_OTHER,
|
||||
nexthop_list->count * sizeof (struct in6_addr *));
|
||||
if (! nexthops)
|
||||
nhcount * sizeof (struct in6_addr *));
|
||||
if (nexthops == NULL)
|
||||
{
|
||||
zlog_warn ("ZEBRA: Can't update zebra route: malloc failed");
|
||||
for (linklist_head (nexthop_list, &node); !linklist_end (&node);
|
||||
linklist_next (&node))
|
||||
XFREE (MTYPE_OSPF6_OTHER, node.data);
|
||||
linklist_delete (nexthop_list);
|
||||
zlog_warn ("Can't send route to zebra: malloc failed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* allocate memory for ifindex_list */
|
||||
ifindexes = XCALLOC (MTYPE_OSPF6_OTHER,
|
||||
nexthop_list->count * sizeof (unsigned int));
|
||||
if (! ifindexes)
|
||||
nhcount * sizeof (unsigned int));
|
||||
if (ifindexes == NULL)
|
||||
{
|
||||
zlog_warn ("ZEBRA: Can't update zebra route: malloc failed");
|
||||
for (linklist_head (nexthop_list, &node); !linklist_end (&node);
|
||||
linklist_next (&node))
|
||||
XFREE (MTYPE_OSPF6_OTHER, node.data);
|
||||
linklist_delete (nexthop_list);
|
||||
zlog_warn ("Can't send route to zebra: malloc failed");
|
||||
XFREE (MTYPE_OSPF6_OTHER, nexthops);
|
||||
return;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for (linklist_head (nexthop_list, &node); ! linklist_end (&node);
|
||||
linklist_next (&node))
|
||||
for (i = 0; i < nhcount; i++)
|
||||
{
|
||||
nexthop = node.data;
|
||||
if (IS_OSPF6_DUMP_ZEBRA)
|
||||
if (IS_OSPF6_DEBUG_ZEBRA (SEND))
|
||||
{
|
||||
inet_ntop (AF_INET6, &nexthop->address, buf, sizeof (buf));
|
||||
if_indextoname (nexthop->ifindex, ifname);
|
||||
zlog_info ("ZEBRA: nexthop: %s%%%s(%d)",
|
||||
buf, ifname, nexthop->ifindex);
|
||||
inet_ntop (AF_INET6, &request->nexthop[i].address,
|
||||
buf, sizeof (buf));
|
||||
if_indextoname (request->nexthop[i].ifindex, ifname);
|
||||
zlog_info (" nexthop: %s%%%s(%d)", buf, ifname,
|
||||
request->nexthop[i].ifindex);
|
||||
}
|
||||
nexthops[i] = &nexthop->address;
|
||||
ifindexes[i] = nexthop->ifindex;
|
||||
i++;
|
||||
nexthops[i] = &request->nexthop[i].address;
|
||||
ifindexes[i] = request->nexthop[i].ifindex;
|
||||
}
|
||||
|
||||
api.type = ZEBRA_ROUTE_OSPF6;
|
||||
api.flags = 0;
|
||||
api.message = 0;
|
||||
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
|
||||
SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
|
||||
api.nexthop_num = nexthop_list->count;
|
||||
api.nexthop_num = nhcount;
|
||||
api.nexthop = nexthops;
|
||||
api.ifindex_num = nexthop_list->count;
|
||||
SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
|
||||
api.ifindex_num = nhcount;
|
||||
api.ifindex = ifindexes;
|
||||
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
|
||||
api.metric = (request->path.metric_type == 2 ?
|
||||
request->path.cost_e2 : request->path.cost);
|
||||
|
||||
p = (struct prefix_ipv6 *) &request->route.prefix;
|
||||
if (type == REMOVE && nexthop_list->count == 1)
|
||||
ret = zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, p, &api);
|
||||
dest = (struct prefix_ipv6 *) &request->prefix;
|
||||
if (type == REM)
|
||||
ret = zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, dest, &api);
|
||||
else
|
||||
ret = zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, p, &api);
|
||||
ret = zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, dest, &api);
|
||||
|
||||
if (ret < 0)
|
||||
zlog_err ("ZEBRA: zapi_ipv6_route () failed: %s", strerror (errno));
|
||||
zlog_err ("zapi_ipv6_route() %s failed: %s",
|
||||
(type == REM ? "delete" : "add"), strerror (errno));
|
||||
|
||||
for (linklist_head (nexthop_list, &node); !linklist_end (&node);
|
||||
linklist_next (&node))
|
||||
XFREE (MTYPE_OSPF6_OTHER, node.data);
|
||||
linklist_delete (nexthop_list);
|
||||
XFREE (MTYPE_OSPF6_OTHER, nexthops);
|
||||
XFREE (MTYPE_OSPF6_OTHER, ifindexes);
|
||||
|
||||
@ -586,64 +450,52 @@ 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)
|
||||
{
|
||||
if (! zclient->redist[ZEBRA_ROUTE_OSPF6])
|
||||
{
|
||||
ospf6->route_table->hook_add = NULL;
|
||||
ospf6->route_table->hook_remove = NULL;
|
||||
return;
|
||||
}
|
||||
ospf6_zebra_route_update (ADD, request);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_zebra_route_update_remove (struct ospf6_route_req *request)
|
||||
ospf6_zebra_route_update_remove (struct ospf6_route *request)
|
||||
{
|
||||
ospf6_zebra_route_update (REMOVE, request);
|
||||
}
|
||||
|
||||
static void
|
||||
ospf6_zebra_redistribute_ospf6 ()
|
||||
{
|
||||
struct route_node *node;
|
||||
|
||||
for (node = route_top (ospf6->route_table->table); node;
|
||||
node = route_next (node))
|
||||
if (! zclient->redist[ZEBRA_ROUTE_OSPF6])
|
||||
{
|
||||
if (! node || ! node->info)
|
||||
continue;
|
||||
ospf6_zebra_route_update_add (node->info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ospf6_zebra_no_redistribute_ospf6 ()
|
||||
{
|
||||
struct route_node *node;
|
||||
|
||||
if (! ospf6)
|
||||
ospf6->route_table->hook_add = NULL;
|
||||
ospf6->route_table->hook_remove = NULL;
|
||||
return;
|
||||
|
||||
for (node = route_top (ospf6->route_table->table); node;
|
||||
node = route_next (node))
|
||||
{
|
||||
if (! node || ! node->info)
|
||||
continue;
|
||||
|
||||
ospf6_zebra_route_update_remove (node->info);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_zebra_finish ()
|
||||
/* Debug */
|
||||
|
||||
DEFUN (debug_ospf6_zebra_sendrecv,
|
||||
debug_ospf6_zebra_sendrecv_cmd,
|
||||
"debug ospf6 zebra (send|recv)",
|
||||
DEBUG_STR
|
||||
OSPF6_STR
|
||||
"Debug connection between zebra\n"
|
||||
"Debug Sending zebra\n"
|
||||
"Debug Receiving zebra\n"
|
||||
)
|
||||
{
|
||||
zclient_stop (zclient);
|
||||
zclient_free (zclient);
|
||||
zclient = (struct zclient *) NULL;
|
||||
unsigned char level = 0;
|
||||
|
||||
if (argc)
|
||||
{
|
||||
if (! strncmp (argv[0], "s", 1))
|
||||
level = OSPF6_DEBUG_ZEBRA_SEND;
|
||||
else if (! strncmp (argv[0], "r", 1))
|
||||
level = OSPF6_DEBUG_ZEBRA_RECV;
|
||||
}
|
||||
else
|
||||
level = OSPF6_DEBUG_ZEBRA_SEND | OSPF6_DEBUG_ZEBRA_RECV;
|
||||
|
||||
OSPF6_DEBUG_ZEBRA_ON (level);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
ALIAS (debug_ospf6_zebra_sendrecv,
|
||||
debug_ospf6_zebra_cmd,
|
||||
"debug ospf6 zebra",
|
||||
DEBUG_STR
|
||||
OSPF6_STR
|
||||
"Debug connection between zebra\n"
|
||||
);
|
||||
|
||||
|
||||
DEFUN (no_debug_ospf6_zebra_sendrecv,
|
||||
no_debug_ospf6_zebra_sendrecv_cmd,
|
||||
"no debug ospf6 zebra (send|recv)",
|
||||
NO_STR
|
||||
DEBUG_STR
|
||||
OSPF6_STR
|
||||
"Debug connection between zebra\n"
|
||||
"Debug Sending zebra\n"
|
||||
"Debug Receiving zebra\n"
|
||||
)
|
||||
{
|
||||
unsigned char level = 0;
|
||||
|
||||
if (argc)
|
||||
{
|
||||
if (! strncmp (argv[0], "s", 1))
|
||||
level = OSPF6_DEBUG_ZEBRA_SEND;
|
||||
else if (! strncmp (argv[0], "r", 1))
|
||||
level = OSPF6_DEBUG_ZEBRA_RECV;
|
||||
}
|
||||
else
|
||||
level = OSPF6_DEBUG_ZEBRA_SEND | OSPF6_DEBUG_ZEBRA_RECV;
|
||||
|
||||
OSPF6_DEBUG_ZEBRA_OFF (level);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
ALIAS (no_debug_ospf6_zebra_sendrecv,
|
||||
no_debug_ospf6_zebra_cmd,
|
||||
"no debug ospf6 zebra",
|
||||
NO_STR
|
||||
DEBUG_STR
|
||||
OSPF6_STR
|
||||
"Debug connection between zebra\n"
|
||||
);
|
||||
|
||||
int
|
||||
config_write_ospf6_debug_zebra (struct vty *vty)
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_ZEBRA (SEND) && IS_OSPF6_DEBUG_ZEBRA (RECV))
|
||||
vty_out (vty, "debug ospf6 zebra%s", VTY_NEWLINE);
|
||||
else
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_ZEBRA (SEND))
|
||||
vty_out (vty, "debug ospf6 zebra send%s", VTY_NEWLINE);
|
||||
if (IS_OSPF6_DEBUG_ZEBRA (RECV))
|
||||
vty_out (vty, "debug ospf6 zebra recv%s", VTY_NEWLINE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
install_element_ospf6_debug_zebra ()
|
||||
{
|
||||
install_element (ENABLE_NODE, &debug_ospf6_zebra_cmd);
|
||||
install_element (ENABLE_NODE, &no_debug_ospf6_zebra_cmd);
|
||||
install_element (ENABLE_NODE, &debug_ospf6_zebra_sendrecv_cmd);
|
||||
install_element (ENABLE_NODE, &no_debug_ospf6_zebra_sendrecv_cmd);
|
||||
install_element (CONFIG_NODE, &debug_ospf6_zebra_cmd);
|
||||
install_element (CONFIG_NODE, &no_debug_ospf6_zebra_cmd);
|
||||
install_element (CONFIG_NODE, &debug_ospf6_zebra_sendrecv_cmd);
|
||||
install_element (CONFIG_NODE, &no_debug_ospf6_zebra_sendrecv_cmd);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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*/
|
||||
|
||||
|
1945
ospf6d/ospf6d.c
1945
ospf6d/ospf6d.c
File diff suppressed because it is too large
Load Diff
@ -1,32 +1,20 @@
|
||||
!
|
||||
! Zebra configuration saved from vty
|
||||
! 2000/05/11 02:09:37
|
||||
! 2003/11/28 00:49:49
|
||||
!
|
||||
hostname ospf6d@yasu3380
|
||||
hostname ospf6d@plant
|
||||
password zebra
|
||||
log file /var/log/zebra-ospf6d.log
|
||||
log stdout
|
||||
service advanced-vty
|
||||
!
|
||||
debug ospf6 message dbdesc
|
||||
debug ospf6 message lsreq
|
||||
debug ospf6 message lsupdate
|
||||
debug ospf6 message lsack
|
||||
debug ospf6 neighbor
|
||||
debug ospf6 spf
|
||||
debug ospf6 interface
|
||||
debug ospf6 area
|
||||
debug ospf6 lsa
|
||||
debug ospf6 zebra
|
||||
debug ospf6 config
|
||||
debug ospf6 dbex
|
||||
debug ospf6 route
|
||||
debug ospf6 neighbor state
|
||||
!
|
||||
interface ed0
|
||||
interface fxp0
|
||||
ipv6 ospf6 cost 1
|
||||
ipv6 ospf6 hello-interval 10
|
||||
ipv6 ospf6 dead-interval 40
|
||||
ipv6 ospf6 retransmit-interval 5
|
||||
ipv6 ospf6 priority 1
|
||||
ipv6 ospf6 priority 0
|
||||
ipv6 ospf6 transmit-delay 1
|
||||
ipv6 ospf6 instance-id 0
|
||||
!
|
||||
@ -40,15 +28,25 @@ 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
|
||||
!
|
||||
ipv6 prefix-list hostroute seq 10 permit 3ffe:501:100c:4380::/60 le 128 ge 128
|
||||
access-list access4 permit 127.0.0.1/32
|
||||
!
|
||||
route-map static-ospf6 permit 50
|
||||
match ipv6 address prefix-list hostroute
|
||||
ipv6 access-list access6 permit 3ffe:501::/32
|
||||
ipv6 access-list access6 permit 2001:200::/48
|
||||
ipv6 access-list access6 permit ::1/128
|
||||
!
|
||||
ipv6 prefix-list test-prefix seq 1000 deny any
|
||||
!
|
||||
route-map static-ospf6 permit 10
|
||||
match ipv6 address prefix-list test-prefix
|
||||
set metric-type type-2
|
||||
set metric 30
|
||||
set metric 2000
|
||||
!
|
||||
line vty
|
||||
access-class access4
|
||||
ipv6 access-class access6
|
||||
exec-timeout 0 0
|
||||
!
|
||||
|
164
ospf6d/ospf6d.h
164
ospf6d/ospf6d.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 1999 Yasuhiro Ohara
|
||||
* Copyright (C) 2003 Yasuhiro Ohara
|
||||
*
|
||||
* This file is part of GNU Zebra.
|
||||
*
|
||||
@ -22,78 +22,11 @@
|
||||
#ifndef OSPF6D_H
|
||||
#define OSPF6D_H
|
||||
|
||||
#include <zebra.h>
|
||||
#include "linklist.h"
|
||||
|
||||
#ifndef HEADER_DEPENDENCY
|
||||
/* Include other stuffs */
|
||||
#include <lib/version.h>
|
||||
#include "log.h"
|
||||
#include "getopt.h"
|
||||
#include "thread.h"
|
||||
#include "command.h"
|
||||
#include "memory.h"
|
||||
#include "sockunion.h"
|
||||
#include "if.h"
|
||||
#include "prefix.h"
|
||||
#include "stream.h"
|
||||
#include "thread.h"
|
||||
#include "filter.h"
|
||||
#include "zclient.h"
|
||||
#include "table.h"
|
||||
#include "plist.h"
|
||||
|
||||
/* OSPF stuffs */
|
||||
#include "ospf6_hook.h"
|
||||
#include "ospf6_types.h"
|
||||
#include "ospf6_prefix.h"
|
||||
#include "ospf6_lsa.h"
|
||||
#include "ospf6_lsdb.h"
|
||||
|
||||
#include "ospf6_message.h"
|
||||
#include "ospf6_proto.h"
|
||||
#include "ospf6_spf.h"
|
||||
#include "ospf6_top.h"
|
||||
#include "ospf6_area.h"
|
||||
#include "ospf6_interface.h"
|
||||
#include "ospf6_neighbor.h"
|
||||
#include "ospf6_ism.h"
|
||||
#include "ospf6_nsm.h"
|
||||
#include "ospf6_route.h"
|
||||
#include "ospf6_dbex.h"
|
||||
#include "ospf6_network.h"
|
||||
#include "ospf6_zebra.h"
|
||||
#include "ospf6_dump.h"
|
||||
#include "ospf6_routemap.h"
|
||||
#include "ospf6_asbr.h"
|
||||
#include "ospf6_abr.h"
|
||||
#include "ospf6_intra.h"
|
||||
#endif /*HEADER_DEPENDENCY*/
|
||||
|
||||
#define HASHVAL 64
|
||||
#define MAXIOVLIST 1024
|
||||
|
||||
#define OSPF6_DAEMON_VERSION "0.9.6p"
|
||||
|
||||
#define AF_LINKSTATE 0xff
|
||||
#define OSPF6_DAEMON_VERSION "0.9.7a"
|
||||
|
||||
/* global variables */
|
||||
extern char *progname;
|
||||
extern int errno;
|
||||
extern int daemon_mode;
|
||||
extern struct thread_master *master;
|
||||
extern list iflist;
|
||||
extern list nexthoplist;
|
||||
extern struct sockaddr_in6 allspfrouters6;
|
||||
extern struct sockaddr_in6 alldrouters6;
|
||||
extern int ospf6_sock;
|
||||
extern char *recent_reason;
|
||||
|
||||
/* Default configuration file name for ospfd. */
|
||||
#define OSPF6_DEFAULT_CONFIG "ospf6d.conf"
|
||||
|
||||
/* Default port values. */
|
||||
#define OSPF6_VTY_PORT 2606
|
||||
|
||||
#ifdef INRIA_IPV6
|
||||
#ifndef IPV6_PKTINFO
|
||||
@ -101,7 +34,7 @@ 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 */
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user