Ospf6d merge from Zebra repository with added privs stuff and merged

zclient changes.
This commit is contained in:
hasso 2004-05-18 18:57:06 +00:00
parent 6708fa3c3e
commit 508e53e2ee
59 changed files with 12250 additions and 17260 deletions

View File

@ -1,5 +1,4 @@
Makefile
Makefile.in
*.o
*.patch
ospf6d

View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -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 ();
}

View File

@ -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

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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);
}

View File

@ -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_*/

View File

@ -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 */

View File

@ -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 ();

View File

@ -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);
}
}

View File

@ -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 */

View File

@ -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");
}

View File

@ -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 */

View File

@ -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";
}

View File

@ -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

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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_*/

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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));
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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));
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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);
}

View File

@ -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*/

File diff suppressed because it is too large Load Diff

View File

@ -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
!

View File

@ -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 */