diff options
author | sumikawa <sumikawa@FreeBSD.org> | 2003-04-27 07:40:59 +0800 |
---|---|---|
committer | sumikawa <sumikawa@FreeBSD.org> | 2003-04-27 07:40:59 +0800 |
commit | b7dfdcbf94327b265fc18b434f0902a7659023ba (patch) | |
tree | cf43791872767ac0671c2c500eb022fe4b01fa7b /net | |
parent | 59fb21f4a775e174f7f6b962e39ebe690786f812 (diff) | |
download | freebsd-ports-gnome-b7dfdcbf94327b265fc18b434f0902a7659023ba.tar.gz freebsd-ports-gnome-b7dfdcbf94327b265fc18b434f0902a7659023ba.tar.zst freebsd-ports-gnome-b7dfdcbf94327b265fc18b434f0902a7659023ba.zip |
Upgrade to ospf6d to 0.9.6p to fix the critical bug on AS-External
LSA refreshing.
Obtained from: zebra cvs
Diffstat (limited to 'net')
-rw-r--r-- | net/zebra-devel/Makefile | 14 | ||||
-rw-r--r-- | net/zebra-devel/files/patch-ospf6d | 3427 | ||||
-rw-r--r-- | net/zebra-devel/pkg-plist | 2 | ||||
-rw-r--r-- | net/zebra-devel/pkg-plist.v6 | 2 | ||||
-rw-r--r-- | net/zebra-pj/Makefile | 14 | ||||
-rw-r--r-- | net/zebra-pj/files/patch-ospf6d | 3427 | ||||
-rw-r--r-- | net/zebra-pj/pkg-plist | 2 | ||||
-rw-r--r-- | net/zebra-pj/pkg-plist.v6 | 2 | ||||
-rw-r--r-- | net/zebra/Makefile | 14 | ||||
-rw-r--r-- | net/zebra/files/patch-ospf6d | 3427 | ||||
-rw-r--r-- | net/zebra/pkg-plist | 2 | ||||
-rw-r--r-- | net/zebra/pkg-plist.v6 | 2 |
12 files changed, 10293 insertions, 42 deletions
diff --git a/net/zebra-devel/Makefile b/net/zebra-devel/Makefile index b5fc2c0e79bc..5751661f153e 100644 --- a/net/zebra-devel/Makefile +++ b/net/zebra-devel/Makefile @@ -7,7 +7,7 @@ PORTNAME= zebra PORTVERSION= 0.93b -PORTREVISION= 4 +PORTREVISION= 5 CATEGORIES= net ipv6 MASTER_SITES= ftp://ftp.zebra.org/pub/zebra/ \ ftp://ftp.ripe.net/mirrors/sites/ftp.zebra.org/pub/zebra/ \ @@ -40,16 +40,6 @@ post-clean: .endif .endif -.include <bsd.port.pre.mk> - -.if ${OSVERSION} >= 400014 -PLIST:= ${WRKDIR}/PLIST -pre-install: - @${CAT} ${PKGDIR}/pkg-plist.v6 ${PKGDIR}/pkg-plist > ${PLIST} -.else -CONFIGURE_ARGS+=--disable-ospf6d --disable-ripngd -.endif - post-install: @( cd ${WRKSRC}/doc; rm -f zebra*info*; ${MAKE} zebra.info install ) @${ECHO} "===> installing zebra startup file..." @@ -64,4 +54,4 @@ post-install: @${ECHO} "router_flags=\"start\"" @${ECHO} "done." -.include <bsd.port.post.mk> +.include <bsd.port.mk> diff --git a/net/zebra-devel/files/patch-ospf6d b/net/zebra-devel/files/patch-ospf6d new file mode 100644 index 000000000000..8dce08ba2c3e --- /dev/null +++ b/net/zebra-devel/files/patch-ospf6d @@ -0,0 +1,3427 @@ +diff -x CVS -urN ospf6d.old/ChangeLog ospf6d/ChangeLog +--- ospf6d.old/ChangeLog Sat Apr 26 23:17:47 2003 ++++ ospf6d/ChangeLog Fri Apr 25 11:40:31 2003 +@@ -1,3 +1,36 @@ ++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 ++ ++2002-11-09 Vincent Jardin <jardin@6wind.com> ++ ++ * ospf6_interface.c: update link-local address on interface creation. ++ ++2002-11-09 Yasuhiro Ohara <yasu@sfc.wide.ad.jp> ++ ++ * ospf6_asbr.c: apply MinLSInterval to AS-External-LSA origination. ++ * ospf6_lsa.c: change not to issue flooding caused by expire event ++ when the received LSA is (already) MaxAge. ++ * ospf6_spf.c: fix a bug which is that ospf6d calculates ++ wrong nexthop when failed to find Link-LSA for the neighbor. ++ * ospf6_damp.c ospf6_dbex.c ospf6_neighbor.c ospf6_spf.c: ++ some clean up ++ * version: 0.9.6o ++ ++2002-10-04 Yasuhiro Ohara <yasu@sfc.wide.ad.jp> ++ ++ * ospf6_asbr.c: bug of failing ASE lsa refresh fixed. ++ * version: 0.9.6n ++ ++2002-10-01 Yasuhiro Ohara <yasu@sfc.wide.ad.jp> ++ ++ * ospf6_asbr.c: AS-External-LSA origination function ++ is re-written. ++ * ospf6_damp.[ch]: New feature that damps flaps is added. ++ * version: 0.9.6m ++ + 2002-07-14 Yasuhiro Ohara <yasu@sfc.wide.ad.jp> + + * ospf6_spf.c: unwanted assert() in ospf6_spf_nexthop_calculation() +diff -x CVS -urN ospf6d.old/Makefile.in ospf6d/Makefile.in +--- ospf6d.old/Makefile.in Sat Apr 26 23:17:47 2003 ++++ ospf6d/Makefile.in Thu Feb 20 01:31:12 2003 +@@ -1,4 +1,4 @@ +-# Makefile.in generated by automake 1.6.2 from Makefile.am. ++# Makefile.in generated by automake 1.6.3 from Makefile.am. + # @configure_input@ + + # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +@@ -111,9 +111,9 @@ + 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_redistribute.c ospf6_routemap.c ospf6_proto.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_abr.c ospf6_intra.c ospf6_damp.c + + + noinst_HEADERS = \ +@@ -121,9 +121,9 @@ + 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_redistribute.h ospf6_routemap.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_abr.h ospf6_intra.h ospf6_damp.h + + + ospf6d_SOURCES = \ +@@ -150,10 +150,10 @@ + ospf6_zebra.$(OBJEXT) ospf6_ism.$(OBJEXT) ospf6_dbex.$(OBJEXT) \ + ospf6_lsdb.$(OBJEXT) ospf6_prefix.$(OBJEXT) ospf6_top.$(OBJEXT) \ + ospf6_area.$(OBJEXT) ospf6_nsm.$(OBJEXT) \ +- ospf6_redistribute.$(OBJEXT) ospf6_routemap.$(OBJEXT) \ +- ospf6_proto.$(OBJEXT) ospf6_hook.$(OBJEXT) ospf6_asbr.$(OBJEXT) \ ++ ospf6_routemap.$(OBJEXT) ospf6_proto.$(OBJEXT) \ ++ ospf6_hook.$(OBJEXT) ospf6_asbr.$(OBJEXT) \ + ospf6_bintree.$(OBJEXT) ospf6_linklist.$(OBJEXT) \ +- ospf6_abr.$(OBJEXT) ospf6_intra.$(OBJEXT) ++ ospf6_abr.$(OBJEXT) ospf6_intra.$(OBJEXT) ospf6_damp.$(OBJEXT) + libospf6_a_OBJECTS = $(am_libospf6_a_OBJECTS) + sbin_PROGRAMS = ospf6d$(EXEEXT) + PROGRAMS = $(sbin_PROGRAMS) +@@ -165,10 +165,10 @@ + ospf6_zebra.$(OBJEXT) ospf6_ism.$(OBJEXT) ospf6_dbex.$(OBJEXT) \ + ospf6_lsdb.$(OBJEXT) ospf6_prefix.$(OBJEXT) ospf6_top.$(OBJEXT) \ + ospf6_area.$(OBJEXT) ospf6_nsm.$(OBJEXT) \ +- ospf6_redistribute.$(OBJEXT) ospf6_routemap.$(OBJEXT) \ +- ospf6_proto.$(OBJEXT) ospf6_hook.$(OBJEXT) ospf6_asbr.$(OBJEXT) \ ++ ospf6_routemap.$(OBJEXT) ospf6_proto.$(OBJEXT) \ ++ ospf6_hook.$(OBJEXT) ospf6_asbr.$(OBJEXT) \ + ospf6_bintree.$(OBJEXT) ospf6_linklist.$(OBJEXT) \ +- ospf6_abr.$(OBJEXT) ospf6_intra.$(OBJEXT) ++ ospf6_abr.$(OBJEXT) ospf6_intra.$(OBJEXT) ospf6_damp.$(OBJEXT) + am_ospf6d_OBJECTS = ospf6_main.$(OBJEXT) $(am__objects_1) + ospf6d_OBJECTS = $(am_ospf6d_OBJECTS) + ospf6d_DEPENDENCIES = ../lib/libzebra.a +@@ -182,8 +182,8 @@ + @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/ospf6_abr.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_area.Po ./$(DEPDIR)/ospf6_asbr.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_bintree.Po \ +-@AMDEP_TRUE@ ./$(DEPDIR)/ospf6_dbex.Po ./$(DEPDIR)/ospf6_dump.Po \ +-@AMDEP_TRUE@ ./$(DEPDIR)/ospf6_hook.Po \ ++@AMDEP_TRUE@ ./$(DEPDIR)/ospf6_damp.Po ./$(DEPDIR)/ospf6_dbex.Po \ ++@AMDEP_TRUE@ ./$(DEPDIR)/ospf6_dump.Po ./$(DEPDIR)/ospf6_hook.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_interface.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_intra.Po ./$(DEPDIR)/ospf6_ism.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_linklist.Po \ +@@ -195,7 +195,6 @@ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_nsm.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_prefix.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_proto.Po \ +-@AMDEP_TRUE@ ./$(DEPDIR)/ospf6_redistribute.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_route.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_routemap.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_spf.Po ./$(DEPDIR)/ospf6_top.Po \ +@@ -218,7 +217,7 @@ + + .SUFFIXES: + .SUFFIXES: .c .o .obj +-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) ++$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign ospf6d/Makefile + Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status +@@ -238,8 +237,7 @@ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + ; then \ +- p1=`echo "$$p1" | sed -e 's,^.*/,,'`; \ +- f=`echo $$p1|sed '$(transform);s/$$/$(EXEEXT)/'`; \ ++ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f"; \ + $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f; \ + else :; fi; \ +@@ -248,8 +246,7 @@ + uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ +- f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ +- f=`echo "$$f" | sed -e 's,^.*/,,'`; \ ++ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \ + rm -f $(DESTDIR)$(sbindir)/$$f; \ + done +@@ -270,6 +267,7 @@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_area.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_asbr.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_bintree.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_damp.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_dbex.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_dump.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_hook.Po@am__quote@ +@@ -286,7 +284,6 @@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_nsm.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_prefix.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_proto.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_redistribute.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_route.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_routemap.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_spf.Po@am__quote@ +diff -x CVS -urN ospf6d.old/ospf6_abr.c ospf6d/ospf6_abr.c +--- ospf6d.old/ospf6_abr.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_abr.c Tue Oct 1 10:28:07 2002 +@@ -42,7 +42,7 @@ + + inet_ntop (AF_INET, &router_id, router_string, sizeof (router_string)); + +- zlog_info ("ABR: Finding router %s in area %s", router_string, area->str); ++ //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; +diff -x CVS -urN ospf6d.old/ospf6_area.h ospf6d/ospf6_area.h +--- ospf6d.old/ospf6_area.h Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_area.h Sat Nov 9 11:25:30 2002 +@@ -62,6 +62,8 @@ + void (*func) (void *, int, void *)); + + struct thread *maxage_remover; ++ ++ struct thread *thread_router_lsa; + }; + + +diff -x CVS -urN ospf6d.old/ospf6_asbr.c ospf6d/ospf6_asbr.c +--- ospf6d.old/ospf6_asbr.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_asbr.c Fri Apr 25 11:40:31 2003 +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2001 Yasuhiro Ohara ++ * Copyright (C) 2001-2002 Yasuhiro Ohara + * + * This file is part of GNU Zebra. + * +@@ -19,108 +19,641 @@ + * Boston, MA 02111-1307, USA. + */ + +-#include "ospf6d.h" ++#include <zebra.h> ++ ++#include "log.h" ++#include "memory.h" ++#include "prefix.h" ++#include "command.h" ++#include "vty.h" ++#include "routemap.h" ++#include "table.h" ++#include "plist.h" ++#include "thread.h" ++ ++#include "ospf6_prefix.h" /* xxx for ospf6_asbr.h */ ++#include "ospf6_lsa.h" /* xxx for ospf6_asbr.h */ ++#include "ospf6_route.h" /* xxx for ospf6_asbr.h, ospf6_zebra.h */ ++#include "ospf6_zebra.h" ++#include "ospf6_asbr.h" ++#include "ospf6_damp.h" ++#include "ospf6_top.h" ++#include "ospf6_lsdb.h" ++#include "ospf6_proto.h" ++ ++extern struct thread_master *master; ++ ++struct route_table *external_table; ++struct ++{ ++ char *name; ++ struct route_map *map; ++} rmap [ZEBRA_ROUTE_MAX]; ++ ++static u_int32_t link_state_id = 0; ++ ++char * ++zroute_name[] = ++{ ++ "system", "kernel", "connected", "static", ++ "rip", "ripng", "ospf", "ospf6", "bgp", "unknown" ++}; ++char * ++zroute_abname[] = ++{ ++ "X", "K", "C", "S", "R", "R", "O", "O", "B", "?" ++}; ++ ++#define ZROUTE_NAME(x) \ ++ (0 < (x) && (x) < ZEBRA_ROUTE_MAX ? \ ++ zroute_name[(x)] : zroute_name[ZEBRA_ROUTE_MAX]) ++ ++#define ZROUTE_ABNAME(x) \ ++ (0 < (x) && (x) < ZEBRA_ROUTE_MAX ? \ ++ zroute_abname[(x)] : zroute_abname[ZEBRA_ROUTE_MAX]) ++ ++/* redistribute function */ ++void ++ospf6_asbr_routemap_set (int type, char *mapname) ++{ ++ if (rmap[type].name) ++ free (rmap[type].name); ++ ++ rmap[type].name = strdup (mapname); ++ rmap[type].map = route_map_lookup_by_name (mapname); ++} ++ ++void ++ospf6_asbr_routemap_unset (int type) ++{ ++ if (rmap[type].name) ++ free (rmap[type].name); ++ rmap[type].name = NULL; ++ rmap[type].map = NULL; ++} ++ ++void ++ospf6_asbr_routemap_update () ++{ ++ int i; ++ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) ++ { ++ if (rmap[i].name) ++ rmap[i].map = route_map_lookup_by_name (rmap[i].name); ++ else ++ rmap[i].map = NULL; ++ } ++} ++ ++DEFUN (ospf6_redistribute, ++ ospf6_redistribute_cmd, ++ "redistribute (static|kernel|connected|ripng|bgp)", ++ "Redistribute\n" ++ "Static route\n" ++ "Kernel route\n" ++ "Connected route\n" ++ "RIPng route\n" ++ "BGP route\n" ++ ) ++{ ++ int type = 0; ++ ++ if (strncmp (argv[0], "sta", 3) == 0) ++ type = ZEBRA_ROUTE_STATIC; ++ else if (strncmp (argv[0], "ker", 3) == 0) ++ type = ZEBRA_ROUTE_KERNEL; ++ else if (strncmp (argv[0], "con", 3) == 0) ++ type = ZEBRA_ROUTE_CONNECT; ++ else if (strncmp (argv[0], "rip", 3) == 0) ++ type = ZEBRA_ROUTE_RIPNG; ++ else if (strncmp (argv[0], "bgp", 3) == 0) ++ type = ZEBRA_ROUTE_BGP; ++ ++ ospf6_zebra_no_redistribute (type); ++ ospf6_asbr_routemap_unset (type); ++ ospf6_zebra_redistribute (type); ++ return CMD_SUCCESS; ++} ++ ++DEFUN (ospf6_redistribute_routemap, ++ ospf6_redistribute_routemap_cmd, ++ "redistribute (static|kernel|connected|ripng|bgp) route-map WORD", ++ "Redistribute\n" ++ "Static routes\n" ++ "Kernel route\n" ++ "Connected route\n" ++ "RIPng route\n" ++ "BGP route\n" ++ "Route map reference\n" ++ "Route map name\n" ++ ) ++{ ++ int type = 0; ++ ++ if (strncmp (argv[0], "sta", 3) == 0) ++ type = ZEBRA_ROUTE_STATIC; ++ else if (strncmp (argv[0], "ker", 3) == 0) ++ type = ZEBRA_ROUTE_KERNEL; ++ else if (strncmp (argv[0], "con", 3) == 0) ++ type = ZEBRA_ROUTE_CONNECT; ++ else if (strncmp (argv[0], "rip", 3) == 0) ++ type = ZEBRA_ROUTE_RIPNG; ++ else if (strncmp (argv[0], "bgp", 3) == 0) ++ type = ZEBRA_ROUTE_BGP; ++ ++ ospf6_zebra_no_redistribute (type); ++ ospf6_asbr_routemap_set (type, argv[1]); ++ ospf6_zebra_redistribute (type); ++ return CMD_SUCCESS; ++} ++ ++DEFUN (no_ospf6_redistribute, ++ no_ospf6_redistribute_cmd, ++ "no redistribute (static|kernel|connected|ripng|bgp)", ++ NO_STR ++ "Redistribute\n" ++ "Static route\n" ++ "Kernel route\n" ++ "Connected route\n" ++ "RIPng route\n" ++ "BGP route\n" ++ ) ++{ ++ int type = 0; ++ struct route_node *node; ++ struct ospf6_external_route *route; ++ struct ospf6_external_info *info, *info_next = NULL; ++ ++ if (strncmp (argv[0], "sta", 3) == 0) ++ type = ZEBRA_ROUTE_STATIC; ++ else if (strncmp (argv[0], "ker", 3) == 0) ++ type = ZEBRA_ROUTE_KERNEL; ++ else if (strncmp (argv[0], "con", 3) == 0) ++ type = ZEBRA_ROUTE_CONNECT; ++ else if (strncmp (argv[0], "rip", 3) == 0) ++ type = ZEBRA_ROUTE_RIPNG; ++ else if (strncmp (argv[0], "bgp", 3) == 0) ++ type = ZEBRA_ROUTE_BGP; ++ ++ ospf6_zebra_no_redistribute (type); ++ ospf6_asbr_routemap_unset (type); ++ ++ /* remove redistributed route */ ++ for (node = route_top (external_table); node; node = route_next (node)) ++ { ++ route = node->info; ++ if (! route) ++ continue; ++ for (info = route->info_head; info; info = info_next) ++ { ++ info_next = info->next; ++ if (info->type != type) ++ continue; ++ ospf6_asbr_route_remove (info->type, info->ifindex, ++ &route->prefix); ++ } ++ } ++ ++ return CMD_SUCCESS; ++} ++ ++ ++int ++ospf6_redistribute_config_write (struct vty *vty) ++{ ++ int i; ++ ++ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) ++ { ++ if (i == ZEBRA_ROUTE_OSPF6) ++ continue; ++ ++ if (! ospf6_zebra_is_redistribute (i)) ++ continue; ++ ++ if (rmap[i].map) ++ vty_out (vty, " redistribute %s route-map %s%s", ++ ZROUTE_NAME(i), rmap[i].name, VTY_NEWLINE); ++ else ++ vty_out (vty, " redistribute %s%s", ++ ZROUTE_NAME(i), VTY_NEWLINE); ++ } ++ ++ return 0; ++} + + void +-ospf6_asbr_external_lsa_update (struct ospf6_route_req *request) ++ospf6_redistribute_show_config (struct vty *vty) + { ++ int i; ++ ++ if (! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_SYSTEM) && ++ ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_KERNEL) && ++ ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_STATIC) && ++ ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_RIPNG) && ++ ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_BGP)) ++ return; ++ ++ vty_out (vty, " Redistributing External Routes from,%s", VTY_NEWLINE); ++ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) ++ { ++ if (i == ZEBRA_ROUTE_OSPF6) ++ continue; ++ if (! ospf6_zebra_is_redistribute (i)) ++ continue; ++ ++ if (rmap[i].map) ++ vty_out (vty, " %s with route-map %s%s", ++ ZROUTE_NAME(i), rmap[i].name, VTY_NEWLINE); ++ else ++ vty_out (vty, " %s%s", ZROUTE_NAME(i), VTY_NEWLINE); ++ } ++} ++ ++/* AS External LSA origination */ ++int ++ospf6_asbr_external_lsa_originate (struct thread *thread) ++{ ++ struct ospf6_external_info *info; + char buffer [MAXLSASIZE]; +- u_int16_t size; +- struct ospf6_lsa_as_external *external; ++ struct ospf6_lsa_as_external *e; + char *p; +- struct ospf6_route_req route; +- char pbuf[BUFSIZ]; + +- /* 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; ++ info = THREAD_ARG (thread); + +- if (IS_OSPF6_DUMP_LSA) +- zlog_info ("Update AS-External: ID: %lu", +- (u_long) ntohl (request->path.origin.id)); ++ /* clear thread */ ++ info->thread_originate = NULL; ++ ++ if (info->is_removed) ++ { ++ if (IS_OSPF6_DUMP_ASBR) ++ { ++ char pbuf[64]; ++ prefix2str (&info->route->prefix, pbuf, sizeof (pbuf)); ++ zlog_info ("ASBR: quit redistribution %s: state is down", ++ pbuf); ++ } ++ return 0; ++ } + + /* prepare buffer */ + memset (buffer, 0, sizeof (buffer)); +- size = sizeof (struct ospf6_lsa_as_external); +- external = (struct ospf6_lsa_as_external *) buffer; +- p = (char *) (external + 1); ++ e = (struct ospf6_lsa_as_external *) buffer; ++ p = (char *) (e + 1); + +- if (route.path.metric_type == 2) +- SET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E); /* type2 */ ++ if (info->metric_type == 2) ++ SET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_E); /* type2 */ + else +- UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E); /* type1 */ ++ UNSET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_E); /* type1, default */ + + /* forwarding address */ +- if (! IN6_IS_ADDR_UNSPECIFIED (&route.nexthop.address)) +- SET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F); ++ if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding)) ++ SET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_F); + else +- UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F); ++ UNSET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_F); + + /* external route tag */ +- UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T); ++ UNSET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_T); + + /* set metric. note: related to E bit */ +- OSPF6_ASBR_METRIC_SET (external, route.path.cost); ++ OSPF6_ASBR_METRIC_SET (e, info->metric); + + /* prefixlen */ +- external->prefix.prefix_length = route.route.prefix.prefixlen; ++ e->prefix.prefix_length = info->route->prefix.prefixlen; + + /* PrefixOptions */ +- external->prefix.prefix_options = route.path.prefix_options; ++ e->prefix.prefix_options = info->prefix_options; + + /* don't use refer LS-type */ +- external->prefix.prefix_refer_lstype = htons (0); +- +- if (IS_OSPF6_DUMP_LSA) +- { +- prefix2str (&route.route.prefix, pbuf, sizeof (pbuf)); +- zlog_info (" Prefix: %s", pbuf); +- } ++ e->prefix.prefix_refer_lstype = htons (0); + + /* set Prefix */ +- memcpy (p, &route.route.prefix.u.prefix6, +- OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen)); +- ospf6_prefix_apply_mask (&external->prefix); +- size += OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen); +- p += OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen); ++ memcpy (p, &info->route->prefix.u.prefix6, ++ OSPF6_PREFIX_SPACE (info->route->prefix.prefixlen)); ++ ospf6_prefix_apply_mask (&e->prefix); ++ p += OSPF6_PREFIX_SPACE (info->route->prefix.prefixlen); + + /* Forwarding address */ +- if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F)) ++ if (CHECK_FLAG (e->bits_metric, OSPF6_ASBR_BIT_F)) + { +- memcpy (p, &route.nexthop.address, sizeof (struct in6_addr)); +- size += sizeof (struct in6_addr); ++ memcpy (p, &info->forwarding, sizeof (struct in6_addr)); + p += sizeof (struct in6_addr); + } + + /* External Route Tag */ +- if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T)) ++ if (CHECK_FLAG (e->bits_metric, OSPF6_ASBR_BIT_T)) + { + /* xxx */ + } + + ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_AS_EXTERNAL), +- route.path.origin.id, ospf6->router_id, +- (char *) external, size, ospf6); +- return; ++ htonl (info->id), ospf6->router_id, ++ (char *) buffer, p - buffer, ospf6); ++ return 0; ++} ++ ++int ++ospf6_asbr_schedule_external (void *data) ++{ ++ struct ospf6_external_info *info = data; ++ u_long elasped_time, time = 0; ++ ++ if (info->thread_originate) ++ { ++ if (IS_OSPF6_DUMP_ASBR) ++ { ++ char pbuf[64]; ++ prefix2str (&info->route->prefix, pbuf, sizeof (pbuf)); ++ zlog_info ("ASBR: schedule redistribution %s: another thread", ++ pbuf); ++ } ++ return 0; ++ } ++ ++ elasped_time = ++ ospf6_lsa_has_elasped (htons (OSPF6_LSA_TYPE_AS_EXTERNAL), ++ htonl (info->id), ospf6->router_id, ospf6); ++ if (elasped_time < OSPF6_MIN_LS_INTERVAL) ++ time = OSPF6_MIN_LS_INTERVAL - elasped_time; ++ else ++ time = 0; ++ ++ //if (IS_OSPF6_DUMP_ASBR) ++ { ++ char pbuf[64]; ++ prefix2str (&info->route->prefix, pbuf, sizeof (pbuf)); ++ zlog_info ("ASBR: schedule redistribution %s as LS-ID %ld after %lu sec", ++ pbuf, (u_long) info->id, time); ++ } ++ ++ if (time) ++ info->thread_originate = ++ thread_add_timer (master, ospf6_asbr_external_lsa_originate, info, time); ++ else ++ info->thread_originate = ++ thread_add_timer (master, ospf6_asbr_external_lsa_originate, info, 0); ++ ++ return 0; ++} ++ ++int ++ospf6_asbr_external_lsa_flush (void *data) ++{ ++ struct ospf6_lsa *lsa = data; ++ if (lsa) ++ ospf6_lsa_premature_aging (lsa); ++ return 0; ++} ++ ++int ++ospf6_asbr_external_lsa_refresh (void *data) ++{ ++ struct ospf6_lsa *lsa = data; ++ struct ospf6_lsa_as_external *e; ++ struct prefix prefix; ++ struct route_node *node; ++ struct ospf6_external_route *route = NULL; ++ struct ospf6_external_info *info = NULL; ++ struct ospf6_external_info *match = NULL; ++ ++ if (IS_OSPF6_DUMP_ASBR) ++ zlog_info ("ASBR: refresh %s", lsa->str); ++ ++ e = (struct ospf6_lsa_as_external *) (lsa->header + 1); ++ ospf6_prefix_in6_addr (&e->prefix, &prefix.u.prefix6); ++ prefix.prefixlen = e->prefix.prefix_length; ++ prefix.family = AF_INET6; ++ apply_mask_ipv6 ((struct prefix_ipv6 *) &prefix); ++ ++ for (node = route_top (external_table); node; node = route_next (node)) ++ { ++ route = node->info; ++ if (route == NULL) ++ continue; ++ ++ for (info = route->info_head; info; info = info->next) ++ { ++ if (lsa->header->id == htonl (info->id)) ++ match = info; ++ } ++ } ++ ++ if (match == NULL) ++ { ++ ospf6_lsa_premature_aging (lsa); ++ return 0; ++ } ++ ++ ospf6_asbr_schedule_external (match); ++ return 0; ++ ++#if 0 ++ node = route_node_lookup (external_table, &prefix); ++ if (! node || ! node->info) ++ { ++ char pname[64]; ++ ++ prefix2str (&prefix, pname, sizeof (pname)); ++ if (IS_OSPF6_DUMP_ASBR) ++ zlog_info ("ASBR: could not find %s: premature age", pname); ++ ospf6_lsa_premature_aging (lsa); ++ return 0; ++ } ++ ++ /* find external_info */ ++ route = node->info; ++ for (info = route->info_head; info; info = info->next) ++ { ++ if (lsa->header->id == htonl (info->id)) ++ break; ++ } ++ ++ if (info) ++ ospf6_asbr_schedule_external (info); ++ else ++ ospf6_lsa_premature_aging (lsa); ++ ++ return 0; ++#endif + } + + void +-ospf6_asbr_external_route_add (struct ospf6_route_req *route) ++ospf6_asbr_route_add (int type, int ifindex, struct prefix *prefix, ++ u_int nexthop_num, struct in6_addr *nexthop) + { +- ospf6_asbr_external_lsa_update (route); ++ int ret; ++ struct route_node *node; ++ struct ospf6_external_route *route; ++ struct ospf6_external_info *info, tinfo; ++ ++ if (! ospf6_zebra_is_redistribute (type)) ++ return; ++ ++ /* apply route-map */ ++ memset (&tinfo, 0, sizeof (struct ospf6_external_info)); ++ if (rmap[type].map) ++ { ++ ret = route_map_apply (rmap[type].map, prefix, RMAP_OSPF6, &tinfo); ++ if (ret == RMAP_DENYMATCH) ++ { ++ if (IS_OSPF6_DUMP_ASBR) ++ zlog_info ("ASBR: denied by route-map %s", rmap[type].name); ++ return; ++ } ++ } ++ ++ node = route_node_get (external_table, prefix); ++ route = node->info; ++ ++ if (! route) ++ { ++ route = XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO, ++ sizeof (struct ospf6_external_route)); ++ memset (route, 0, sizeof (struct ospf6_external_route)); ++ ++ memcpy (&route->prefix, prefix, sizeof (struct prefix)); ++ ++ node->info = route; ++ route->node = node; ++ } ++ ++ for (info = route->info_head; info; info = info->next) ++ { ++ if (info->type == type && info->ifindex == ifindex) ++ break; ++ } ++ ++ if (! info) ++ { ++ info = XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO, ++ sizeof (struct ospf6_external_info)); ++ memset (info, 0, sizeof (struct ospf6_external_info)); ++ ++ info->route = route; ++ /* add tail */ ++ info->prev = route->info_tail; ++ if (route->info_tail) ++ route->info_tail->next = info; ++ else ++ route->info_head = info; ++ route->info_tail = info; ++ ++ info->id = link_state_id++; ++ } ++ ++ /* copy result of route-map */ ++ info->metric_type = tinfo.metric_type; ++ info->metric = tinfo.metric; ++ memcpy (&info->forwarding, &tinfo.forwarding, ++ sizeof (struct in6_addr)); ++ ++ info->type = type; ++ info->ifindex = ifindex; ++ ++ if (nexthop_num && nexthop) ++ { ++ info->nexthop_num = nexthop_num; ++ ++ if (info->nexthop) ++ XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info->nexthop); ++ ++ info->nexthop = (struct in6_addr *) ++ XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO, ++ nexthop_num * sizeof (struct in6_addr)); ++ memcpy (info->nexthop, nexthop, ++ nexthop_num * sizeof (struct in6_addr)); ++ } ++ ++ info->is_removed = 0; ++ ++ //if (IS_OSPF6_DUMP_ASBR) ++ { ++ char pbuf[64]; ++ struct timeval now; ++ prefix2str (&info->route->prefix, pbuf, sizeof (pbuf)); ++ gettimeofday (&now, NULL); ++ zlog_info ("ASBR: start redistributing %s as LS-ID %ld: %ld.%06ld", ++ pbuf, (u_long) info->id, now.tv_sec, now.tv_usec); ++ } ++ ++#ifdef HAVE_OSPF6_DAMP ++ ospf6_damp_event_up (OSPF6_DAMP_TYPE_ROUTE, prefix, ++ ospf6_asbr_schedule_external, info); ++#else /*HAVE_OSPF6_DAMP*/ ++ ospf6_asbr_schedule_external (info); ++#endif /*HAVE_OSPF6_DAMP*/ + } + + void +-ospf6_asbr_external_route_remove (struct ospf6_route_req *route) ++ospf6_asbr_route_remove (int type, int ifindex, struct prefix *prefix) + { ++ struct route_node *node; ++ struct ospf6_external_route *route; ++ struct ospf6_external_info *info; + struct ospf6_lsa *lsa; + +- lsa = ospf6_lsdb_lookup_lsdb (htons (OSPF6_LSA_TYPE_AS_EXTERNAL), +- route->path.origin.id, +- ospf6->router_id, ospf6->lsdb); +- if (lsa) +- ospf6_lsa_premature_aging (lsa); ++ node = route_node_get (external_table, prefix); ++ route = node->info; ++ ++ if (! route) ++ return; ++ ++ for (info = route->info_head; info; info = info->next) ++ { ++ if (info->type == type && info->ifindex == ifindex) ++ break; ++ } ++ ++ if (! info) ++ return; ++ ++ //if (IS_OSPF6_DUMP_ASBR) ++ { ++ char pbuf[64]; ++ struct timeval now; ++ prefix2str (&info->route->prefix, pbuf, sizeof (pbuf)); ++ gettimeofday (&now, NULL); ++ zlog_info ("ASBR: quit redistributing %s as LS-ID %ld: %ld.%06ld", ++ pbuf, (u_long) info->id, now.tv_sec, now.tv_usec); ++ } ++ ++ if (info->thread_originate) ++ thread_cancel (info->thread_originate); ++ info->thread_originate = NULL; ++ ++ lsa = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_AS_EXTERNAL), ++ htonl (info->id), ospf6->router_id, ospf6); ++#ifdef HAVE_OSPF6_DAMP ++ ospf6_damp_event_down (OSPF6_DAMP_TYPE_ROUTE, &info->route->prefix, ++ ospf6_asbr_external_lsa_flush, lsa); ++#else /*HAVE_OSPF6_DAMP*/ ++ ospf6_asbr_external_lsa_flush (lsa); ++#endif /*HAVE_OSPF6_DAMP*/ ++ ++#if 1 ++ info->is_removed = 1; ++#else ++ /* remove from route */ ++ if (info->prev) ++ info->prev->next = info->next; ++ else ++ info->route->info_head = info->next; ++ if (info->next) ++ info->next->prev = info->prev; ++ else ++ info->route->info_tail = info->prev; ++ ++ /* if no info, free route */ ++ if (! info->route->info_head && ! info->route->info_tail) ++ { ++ info->route->node->info = NULL; ++ free (info->route); ++ } ++ ++ if (info->nexthop) ++ free (info->nexthop); ++ free (info); ++#endif /*0*/ + } + + void +@@ -134,22 +667,29 @@ + external = OSPF6_LSA_HEADER_END (lsa->header); + + if (IS_LSA_MAXAGE (lsa)) +- return; ++ { ++ if (IS_OSPF6_DUMP_ASBR) ++ zlog_info ("ASBR: maxage external lsa: %s seq: %lx", ++ lsa->str, (u_long)ntohl (lsa->header->seqnum)); ++ ospf6_asbr_external_lsa_remove (lsa); ++ return; ++ } + + if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: Calculate %s", lsa->str); ++ zlog_info ("ASBR: new external lsa: %s seq: %lx", ++ lsa->str, (u_long)ntohl (lsa->header->seqnum)); + + if (lsa->header->adv_router == ospf6->router_id) + { + if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: Self-originated, ignore"); ++ zlog_info ("ASBR: my external LSA, ignore"); + return; + } + + if (OSPF6_ASBR_METRIC (external) == LS_INFINITY) + { + if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: Metric is Infinity, ignore"); ++ zlog_info ("ASBR: metric is infinity, ignore"); + return; + } + +@@ -167,7 +707,7 @@ + { + char buf[64]; + inet_ntop (AF_INET, &asbr_id.adv_router, buf, sizeof (buf)); +- zlog_info ("ASBR: ASBR %s not found, ignore", buf); ++ zlog_info ("ASBR: router %s not found, ignore", buf); + } + return; + } +@@ -206,6 +746,14 @@ + { + memcpy (&request.nexthop, &asbr_entry.nexthop, + sizeof (struct ospf6_nexthop)); ++ if (IS_OSPF6_DUMP_ASBR) ++ { ++ char buf[64], nhop[64], ifname[IFNAMSIZ]; ++ prefix2str (&request.route.prefix, buf, sizeof (buf)); ++ inet_ntop (AF_INET6, &request.nexthop.address, nhop, sizeof (nhop)); ++ if_indextoname (request.nexthop.ifindex, ifname); ++ zlog_info ("ASBR: add route: %s %s%%%s", buf, nhop, ifname); ++ } + ospf6_route_add (&request, ospf6->route_table); + ospf6_route_next (&asbr_entry); + } +@@ -220,12 +768,13 @@ + struct ospf6_route_req request; + + if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: Withdraw route of %s", lsa->str); ++ zlog_info ("ASBR: withdraw external lsa: %s seq: %lx", ++ lsa->str, (u_long)ntohl (lsa->header->seqnum)); + + if (lsa->header->adv_router == ospf6->router_id) + { + if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: Self-originated, ignore"); ++ zlog_info ("ASBR: my external LSA, ignore"); + return; + } + +@@ -236,14 +785,14 @@ + memcpy (&dest.u.prefix6, (char *)(external + 1), + OSPF6_PREFIX_SPACE (dest.prefixlen)); + +- prefix2str (&dest, buf, sizeof (buf)); +- if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: route: %s", buf); +- + ospf6_route_lookup (&request, &dest, ospf6->route_table); + if (ospf6_route_end (&request)) + { +- zlog_info ("ASBR: route not found"); ++ if (IS_OSPF6_DUMP_ASBR) ++ { ++ prefix2str (&dest, buf, sizeof (buf)); ++ zlog_info ("ASBR: %s not found", buf); ++ } + return; + } + +@@ -252,7 +801,8 @@ + { + if (prefix_same (&request.route.prefix, &dest) != 1) + { +- zlog_info ("ASBR: Can't find the entry matches the origin"); ++ if (IS_OSPF6_DUMP_ASBR) ++ zlog_info ("ASBR: Can't find the entry matches the origin"); + return; + } + ospf6_route_next (&request); +@@ -264,6 +814,15 @@ + request.path.origin.adv_router == lsa->header->adv_router && + prefix_same (&request.route.prefix, &dest) == 1) + { ++ if (IS_OSPF6_DUMP_ASBR) ++ { ++ char nhop[64], ifname[IFNAMSIZ]; ++ prefix2str (&dest, buf, sizeof (buf)); ++ inet_ntop (AF_INET6, &request.nexthop.address, nhop, sizeof (nhop)); ++ if_indextoname (request.nexthop.ifindex, ifname); ++ zlog_info ("ASBR: remove route: %s %s%%%s", buf, nhop, ifname); ++ } ++ + ospf6_route_remove (&request, ospf6->route_table); + ospf6_route_next (&request); + } +@@ -303,7 +862,7 @@ + { + char buf[64]; + inet_ntop (AF_INET, &inter_router->adv_router, buf, sizeof (buf)); +- zlog_info ("ASBR: New router found: %s", buf); ++ zlog_info ("ASBR: new router found: %s", buf); + } + + if (ntohl (id) != 0 || +@@ -335,7 +894,7 @@ + { + char buf[64]; + inet_ntop (AF_INET, &inter_router->adv_router, buf, sizeof (buf)); +- zlog_info ("ASBR: Router disappearing: %s", buf); ++ zlog_info ("ASBR: router disappearing: %s", buf); + } + + if (ntohl (id) != 0 || +@@ -410,37 +969,6 @@ + return 0; + } + +-int +-ospf6_asbr_external_refresh (void *old) +-{ +- struct ospf6_lsa *lsa = old; +- struct ospf6_route_req route, *target; +- +- assert (ospf6); +- +- if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: refresh %s", lsa->str); +- +- target = NULL; +- for (ospf6_route_head (&route, ospf6->external_table); +- ! ospf6_route_end (&route); +- ospf6_route_next (&route)) +- { +- if (route.path.origin.id == lsa->header->id) +- { +- target = &route; +- break; +- } +- } +- +- if (target) +- ospf6_asbr_external_lsa_update (target); +- else +- ospf6_lsa_premature_aging (lsa); +- +- return 0; +-} +- + void + ospf6_asbr_database_hook (struct ospf6_lsa *old, struct ospf6_lsa *new) + { +@@ -459,7 +987,7 @@ + slot.type = htons (OSPF6_LSA_TYPE_AS_EXTERNAL); + slot.name = "AS-External"; + slot.func_show = ospf6_asbr_external_show; +- slot.func_refresh = ospf6_asbr_external_refresh; ++ slot.func_refresh = ospf6_asbr_external_lsa_refresh; + ospf6_lsa_slot_register (&slot); + + ospf6_lsdb_hook[OSPF6_LSA_TYPE_AS_EXTERNAL & OSPF6_LSTYPE_CODE_MASK].hook = +@@ -467,9 +995,71 @@ + } + + void ++ospf6_asbr_external_info_show (struct vty *vty, ++ struct ospf6_external_info *info) ++{ ++ char prefix_buf[64], id_buf[16]; ++ struct in_addr id; ++ ++ if (info->is_removed) ++ return; ++ ++ id.s_addr = ntohl (info->id); ++ inet_ntop (AF_INET, &id, id_buf, sizeof (id_buf)); ++ prefix2str (&info->route->prefix, prefix_buf, sizeof (prefix_buf)); ++ vty_out (vty, "%s %-32s %3d %-15s %3d %lu(type-%d)%s", ++ ZROUTE_ABNAME(info->type), prefix_buf, info->ifindex, id_buf, ++ info->nexthop_num, (u_long) info->metric, info->metric_type, ++ VTY_NEWLINE); ++} ++ ++void ++ospf6_asbr_external_route_show (struct vty *vty, ++ struct ospf6_external_route *route) ++{ ++ struct ospf6_external_info *info; ++ for (info = route->info_head; info; info = info->next) ++ ospf6_asbr_external_info_show (vty, info); ++} ++ ++DEFUN (show_ipv6_route_ospf6_external, ++ show_ipv6_route_ospf6_external_cmd, ++ "show ipv6 ospf6 route redistribute", ++ SHOW_STR ++ IP6_STR ++ ROUTE_STR ++ OSPF6_STR ++ "redistributing External information\n" ++ ) ++{ ++ struct route_node *node; ++ struct ospf6_external_route *route; ++ ++ vty_out (vty, "%s %-32s %3s %-15s %3s %s%s", ++ " ", "Prefix", "I/F", "LS-Id", "#NH", "Metric", ++ VTY_NEWLINE); ++ for (node = route_top (external_table); node; node = route_next (node)) ++ { ++ route = node->info; ++ if (route) ++ ospf6_asbr_external_route_show (vty, route); ++ } ++ return CMD_SUCCESS; ++} ++ ++void + ospf6_asbr_init () + { ++ external_table = route_table_init (); ++ link_state_id = 0; ++ + ospf6_asbr_register_as_external (); ++ ++ install_element (VIEW_NODE, &show_ipv6_route_ospf6_external_cmd); ++ install_element (ENABLE_NODE, &show_ipv6_route_ospf6_external_cmd); ++ install_element (OSPF6_NODE, &ospf6_redistribute_cmd); ++ install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd); ++ install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd); + } + + +diff -x CVS -urN ospf6d.old/ospf6_asbr.h ospf6d/ospf6_asbr.h +--- ospf6d.old/ospf6_asbr.h Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_asbr.h Sat Nov 9 11:25:30 2002 +@@ -22,6 +22,51 @@ + #ifndef OSPF6_ASBR_H + #define OSPF6_ASBR_H + ++#include "thread.h" ++ ++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 */ ++ int type; ++ ++ /* external route ifindex */ ++ int ifindex; ++ ++ /* LS-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 + { +@@ -42,8 +87,16 @@ + { (E)->bits_metric &= htonl (0xff000000); \ + (E)->bits_metric |= htonl (0x00ffffff) & htonl (C); } + +-void ospf6_asbr_external_route_add (struct ospf6_route_req *route); +-void ospf6_asbr_external_route_remove (struct ospf6_route_req *route); ++void ospf6_asbr_routemap_update (); ++ ++int ospf6_redistribute_config_write (struct vty *vty); ++void ospf6_redistribute_show_config (struct vty *vty); ++ ++void ++ospf6_asbr_route_add (int type, int ifindex, struct prefix *prefix, ++ u_int nexthop_num, struct in6_addr *nexthop); ++void ++ospf6_asbr_route_remove (int type, int ifindex, struct prefix *prefix); + + void ospf6_asbr_external_lsa_add (struct ospf6_lsa *lsa); + void ospf6_asbr_external_lsa_remove (struct ospf6_lsa *lsa); +diff -x CVS -urN ospf6d.old/ospf6_damp.c ospf6d/ospf6_damp.c +--- ospf6d.old/ospf6_damp.c Thu Jan 1 01:00:00 1970 ++++ ospf6d/ospf6_damp.c Sat Nov 9 11:25:30 2002 +@@ -0,0 +1,748 @@ ++/* ++ * 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, ++ 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, ++ 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, ++ 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, ++ 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 (flap_damping_route, ++ 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, &flap_damping_route_cmd); ++ ++ install_element (ENABLE_NODE, &show_debug_ospf6_damp_cmd); ++ install_element (CONFIG_NODE, &debug_ospf6_damp_cmd); ++ install_element (CONFIG_NODE, &no_debug_ospf6_damp_cmd); ++ ++ thread_add_event (master, ospf6_damp_debug_thread, NULL, 0); ++} ++ ++#endif /* HAVE_OSPF6_DAMP */ ++ ++ +diff -x CVS -urN ospf6d.old/ospf6_damp.h ospf6d/ospf6_damp.h +--- ospf6d.old/ospf6_damp.h Thu Jan 1 01:00:00 1970 ++++ ospf6d/ospf6_damp.h Tue Oct 1 00:41:10 2002 +@@ -0,0 +1,109 @@ ++/* ++ * OSPF flap dampening by Manav Bhatia ++ * Copyright (C) 2002 ++ * ++ * This file is part of GNU Zebra. ++ * ++ * GNU Zebra is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2, or (at your option) any ++ * later version. ++ * ++ * GNU Zebra is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GNU Zebra; see the file COPYING. If not, write to the Free ++ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ++ * 02111-1307, USA. ++ */ ++ ++/* ++ * Flap Damping (target e.g. link/route) ++ */ ++ ++#define HAVE_OSPF6_DAMP ++ ++typedef enum ++{ ++ OFF, ++ ON, ++} onoff_t; ++ ++typedef enum ++{ ++ event_none, ++ event_up, ++ event_down, ++} damp_event_t; ++ ++/* Structure maintained per target basis */ ++struct ospf6_damp_info ++{ ++ /* identifier to decide which target */ ++ u_short type; ++ struct prefix name; ++ ++ /* do we damping this info */ ++ onoff_t damping; ++ ++ u_int penalty; ++ u_int flap; ++ time_t t_start; /* First flap (down event) time */ ++ time_t t_updated; /* Last time the penalty was updated */ ++ ++ /* index and double-link for reuse list */ ++ int index; ++ struct ospf6_damp_info *next; ++ struct ospf6_damp_info *prev; ++ ++ /* the last event that we are avoiding */ ++ int (*event) (void *target); ++ void *target; ++ damp_event_t event_type; ++ damp_event_t target_status; ++}; ++ ++#define OSPF6_DAMP_TYPE_ROUTE 0 ++#define OSPF6_DAMP_TYPE_MAX 1 ++ ++/* Global Configuration Parameters */ ++struct ospf6_damp_config ++{ ++ /* is damping enabled ? */ ++ onoff_t enabled; ++ ++ /* configurable parameters */ ++ u_int half_life; ++ u_int suppress; ++ u_int reuse; ++ u_int t_hold; /* Maximum hold down time */ ++ ++ /* Non configurable parameters */ ++ u_int delta_t; ++ u_int delta_reuse; ++ u_int default_penalty; ++ u_int ceiling; /* Max value a penalty can attain */ ++ double scale_factor; ++ ++ int decay_array_size; /* Calculated using config parameters */ ++ double *decay_array; /* Storage for decay values */ ++ ++ int reuse_index_array_size; /* Size of reuse index array */ ++ int *reuse_index_array; ++ ++ int reuse_list_size; /* Number of reuse lists */ ++ struct ospf6_damp_info **reuse_list_array; ++}; ++ ++int ospf6_damp_reuse_timer (struct thread *); ++void ospf6_damp_event_up (u_short type, struct prefix *name, ++ int (*exec_up) (void *), void *target); ++void ospf6_damp_event_down (u_short type, struct prefix *name, ++ int (*exec_down) (void *), void *target); ++ ++void ospf6_damp_config_write (struct vty *); ++void ospf6_damp_init (); ++ +diff -x CVS -urN ospf6d.old/ospf6_dbex.c ospf6d/ospf6_dbex.c +--- ospf6d.old/ospf6_dbex.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_dbex.c Sat Nov 9 11:25:30 2002 +@@ -230,12 +230,11 @@ + 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); + +- if (IS_OSPF6_DUMP_DBEX) +- zlog_info ("Receive %s from %s", received->str, from->str); +- + /* set LSA scope */ + if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (htons (lsa_header->type))) + received->scope = from->ospf6_interface; +@@ -248,27 +247,24 @@ + cksum = ntohs (lsa_header->checksum); + if (ntohs (ospf6_lsa_checksum (lsa_header)) != cksum) + { +- zlog_warn ("DBEX: LSA cksum wrong: %s checksum %#hx should be %#hx", +- received->str, cksum, ntohs (ospf6_lsa_checksum (lsa_header))); ++ 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; + } + +-#if 0 +- /* (2) warn if unknown */ +- if (! ospf6_lsa_is_known_type (lsa_header)) +- zlog_warn ("[%s:%s] receive LSA unknown: %#x", +- from->str, from->ospf6_interface->interface->name, +- ntohs (lsa_header->type)); +-#endif /*0*/ +- + /* (3) Ebit Missmatch: AS-External-LSA */ + if (lsa_header->type == htons (OSPF6_LSA_TYPE_AS_EXTERNAL) && + ospf6_area_is_stub (from->ospf6_interface->area)) + { +- zlog_err ("DBEX: [%s:%s] receive LSA E-bit mismatch: %s", +- from->str, from->ospf6_interface->interface->name, +- received->str); ++ 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; + } +@@ -279,8 +275,10 @@ + { + /* log */ + if (IS_OSPF6_DUMP_DBEX) +- zlog_info ("Drop MaxAge LSA: no instance, no neighbor " +- "exchanging DB: %s", received->str); ++ 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 */ +@@ -312,18 +310,29 @@ + + /* (a) MinLSArrival check */ + gettimeofday (&now, (struct timezone *)NULL); +- if (have && now.tv_sec - have->installed.tv_sec <= OSPF6_MIN_LS_ARRIVAL) ++ if (have && SEC_TVDIFF (&now, &have->installed) < OSPF6_MIN_LS_ARRIVAL) + { +- if (IS_OSPF6_DUMP_DBEX) +- zlog_info ("DBEX: [%s:%s] received LSA too soon: %s", +- from->str, from->ospf6_interface->interface->name, +- received->str); ++ //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); + +@@ -344,18 +353,20 @@ + 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: [%s:%s] don't ack %s", +- from->str, from->ospf6_interface->interface->name, +- received->str); ++ zlog_info ("DBEX: No Ack to %s", from->str); + } + + /* (f) */ +@@ -413,6 +424,9 @@ + 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); + } +@@ -421,18 +435,20 @@ + 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: [%s:%s] will no ack %s", +- from->str, from->ospf6_interface->interface->name, +- received->str); ++ zlog_info ("DBEX: No Ack to %s", from->str); + } + ospf6_lsa_delete (received); + } +@@ -443,6 +459,9 @@ + 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); +@@ -455,83 +474,52 @@ + struct ospf6_neighbor *from) + { + struct ospf6_interface *ospf6_interface; +- struct ospf6_neighbor *nbr; +- listnode n, m; ++ 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; + } +- else if (ismore_recent < 0 && +- ! CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_FLOODBACK)) +- { +- if (ospf6_interface->state == IFS_BDR) +- { +- if (ospf6_interface->dr == from->router_id) +- { +- return DELAYED_ACK; +- } +- else +- { +- return NO_ACK; +- } +- } +- else +- { +- return DELAYED_ACK; +- } +- } +- else if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_DUPLICATE) && +- CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_IMPLIEDACK)) +- { +- if (ospf6_interface->state == IFS_BDR) +- { +- if (ospf6_interface->dr == from->router_id) +- { +- return DELAYED_ACK; +- } +- else +- { +- return NO_ACK; +- } +- } +- else +- { +- return NO_ACK; +- } +- } +- else if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_DUPLICATE) && +- ! CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_IMPLIEDACK)) +- { +- return DIRECT_ACK; +- } +- else if (IS_LSA_MAXAGE (newp)) ++ ++ if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_DUPLICATE) && ++ CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_IMPLIEDACK)) + { +- if (! ospf6_lsdb_lookup (newp->header->type, newp->header->id, +- newp->header->adv_router, +- ospf6_lsa_get_scope (newp->header->type, +- from->ospf6_interface))) +- { +- for (n = listhead (from->ospf6_interface->area->if_list); +- n; nextnode (n)) +- { +- ospf6_interface = (struct ospf6_interface *) getdata (n); +- for (m = listhead (ospf6_interface->neighbor_list); +- m; nextnode (m)) +- { +- nbr = (struct ospf6_neighbor *) getdata (m); +- if (nbr->state == NBS_EXCHANGE || nbr->state == NBS_LOADING) +- { +- return NO_ACK; +- } +- } +- } +- return DIRECT_ACK; +- } ++ 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; + } +@@ -600,11 +588,13 @@ + + /* (2) */ + if (addretrans == 0) ++ return; /* examin next interface */ ++ ++ if (from && from->ospf6_interface == o6i) + { +- return; /* examin next interface */ +- } +- else 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); + } +@@ -624,7 +614,7 @@ + return; /* examin next interface */ + + if (IS_OSPF6_DUMP_DBEX) +- zlog_info (" Flood to interface %s", o6i->interface->name); ++ zlog_info ("Flood to interface %s", o6i->interface->name); + + /* (5) send LinkState Update */ + ospf6_send_lsupdate_flood (lsa, o6i); +@@ -678,14 +668,13 @@ + + lsa_header = (struct ospf6_lsa_header *) lsa->lsa_hdr; + +- if (IS_OSPF6_DUMP_DBEX) +- zlog_info ("Flood: %s", lsa->str); +- + 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))) +@@ -693,6 +682,8 @@ + 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))) +@@ -700,6 +691,8 @@ + o6 = (struct ospf6 *) lsa->scope; + assert (o6); + ++ if (IS_OSPF6_DUMP_DBEX) ++ zlog_info ("Flood AS"); + ospf6_dbex_flood_as (lsa, o6, from); + } + else +diff -x CVS -urN ospf6d.old/ospf6_interface.c ospf6d/ospf6_interface.c +--- ospf6d.old/ospf6_interface.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_interface.c Sat Nov 9 13:26:03 2002 +@@ -126,6 +126,9 @@ + + CALL_ADD_HOOK (&interface_hook, o6i); + ++ /* Get the interface's link-local if any */ ++ ospf6_interface_address_update(ifp); ++ + return o6i; + } + +diff -x CVS -urN ospf6d.old/ospf6_lsa.c ospf6d/ospf6_lsa.c +--- ospf6d.old/ospf6_lsa.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_lsa.c Sat Nov 9 11:25:30 2002 +@@ -51,7 +51,6 @@ + #include "ospf6_area.h" + #include "ospf6_interface.h" + #include "ospf6_neighbor.h" +-#include "ospf6_redistribute.h" + #include "ospf6_ism.h" + #include "ospf6_nsm.h" + #include "ospf6_dbex.h" +@@ -142,8 +141,11 @@ + + lsa->birth.tv_sec = now.tv_sec - ntohs (lsa->header->age); + lsa->birth.tv_usec = now.tv_usec; +- lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa, +- lsa->birth.tv_sec + MAXAGE - now.tv_sec); ++ if (ntohs (lsa->header->age) != MAXAGE) ++ lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa, ++ lsa->birth.tv_sec + MAXAGE - now.tv_sec); ++ else ++ lsa->expire = NULL; + return; + } + +@@ -692,38 +694,6 @@ + ospf6_lsa_delete (lsa); + } + +-/* check necessity to update LSA: +- returns 1 if it's necessary to reoriginate */ +-static int +-ospf6_lsa_is_really_reoriginate (struct ospf6_lsa *new) +-{ +- struct ospf6_lsa *old; +- int diff; +- +- /* find previous LSA */ +- old = ospf6_lsdb_lookup (new->header->type, new->header->id, +- new->header->adv_router, new->scope); +- if (! old) +- return 1; +- +- /* Check if this is refresh */ +- if (CHECK_FLAG (old->flag, OSPF6_LSA_FLAG_REFRESH)) +- { +- zlog_warn ("LSA: reoriginate: %s: Refresh", new->str); +- return 1; +- } +- +- /* Are these contents different ? */ +- diff = ospf6_lsa_differ (new, old); +- +- if (diff) +- return 1; +- +- if (IS_OSPF6_DUMP_LSA) +- zlog_info ("LSA: Suppress updating %s", new->str); +- return 0; +-} +- + void + ospf6_lsa_originate (u_int16_t type, u_int32_t id, u_int32_t adv_router, + char *data, int data_len, void *scope) +@@ -731,6 +701,7 @@ + char buffer[MAXLSASIZE]; + struct ospf6_lsa_header *lsa_header; + struct ospf6_lsa *lsa; ++ struct ospf6_lsa *old; + + assert (data_len <= sizeof (buffer) - sizeof (struct ospf6_lsa_header)); + +@@ -754,18 +725,37 @@ + + /* create LSA */ + lsa = ospf6_lsa_create ((struct ospf6_lsa_header *) buffer); +- lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa, +- OSPF6_LS_REFRESH_TIME); + lsa->scope = scope; + +- if (ospf6_lsa_is_really_reoriginate (lsa)) +- { +- ospf6_dbex_remove_from_all_retrans_list (lsa); +- ospf6_dbex_flood (lsa, NULL); +- ospf6_lsdb_install (lsa); ++ /* find previous LSA */ ++ old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, ++ lsa->header->adv_router, lsa->scope); ++ if (old) ++ { ++ /* Check if this is neither different instance nor refresh, return */ ++ if (! CHECK_FLAG (old->flag, OSPF6_LSA_FLAG_REFRESH) && ++ ! ospf6_lsa_differ (lsa, old)) ++ { ++ if (IS_OSPF6_DUMP_LSA) ++ zlog_info ("LSA: Suppress updating %s", lsa->str); ++ ospf6_lsa_delete (lsa); ++ return; ++ } + } +- else +- ospf6_lsa_delete (lsa); ++ ++ lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa, ++ OSPF6_LS_REFRESH_TIME); ++ gettimeofday (&lsa->originated, NULL); ++ ++ //if (IS_OSPF6_DUMP_LSA) ++ zlog_info ("LSA: originate %s seq: %#x age: %hu %ld.%06ld", ++ lsa->str, ntohl (lsa->header->seqnum), ++ ospf6_lsa_age_current (lsa), ++ lsa->originated.tv_sec, lsa->originated.tv_usec); ++ ++ ospf6_dbex_remove_from_all_retrans_list (lsa); ++ ospf6_dbex_flood (lsa, NULL); ++ ospf6_lsdb_install (lsa); + } + + +@@ -1130,14 +1120,32 @@ + return 0; + } + +-void +-ospf6_lsa_router_update (u_int32_t area_id) ++u_long ++ospf6_lsa_has_elasped (u_int16_t type, u_int32_t id, ++ u_int32_t adv_router, void *scope) ++{ ++ struct ospf6_lsa *old; ++ struct timeval now; ++ ++ if (adv_router != ospf6->router_id) ++ zlog_info ("LSA: Router-ID changed ?"); ++ ++ old = ospf6_lsdb_lookup (type, id, adv_router, scope); ++ if (! old) ++ return OSPF6_LSA_MAXAGE; ++ ++ gettimeofday (&now, NULL); ++ return ((u_long) SEC_TVDIFF (&now, &old->originated)); ++} ++ ++int ++ospf6_lsa_originate_router (struct thread *thread) + { + char buffer [MAXLSASIZE]; + u_int16_t size; +- struct ospf6_lsa *old; + struct ospf6_area *o6a; + int count; ++ u_int32_t area_id; + + struct ospf6_router_lsa *router_lsa; + struct ospf6_router_lsd *router_lsd; +@@ -1145,22 +1153,22 @@ + struct ospf6_interface *o6i; + struct ospf6_neighbor *o6n = NULL; + ++ area_id = (u_int32_t) THREAD_ARG (thread); ++ + o6a = ospf6_area_lookup (area_id, ospf6); + if (! o6a) + { + inet_ntop (AF_INET, &area_id, buffer, sizeof (buffer)); + if (IS_OSPF6_DUMP_LSA) +- zlog_warn ("Update Router-LSA: No such area: %s", buffer); +- return; ++ zlog_info ("LSA: Update Router-LSA: No such area: %s", buffer); ++ return 0; + } + +- if (IS_OSPF6_DUMP_LSA) +- zlog_info ("Update Router-LSA: for Area %s", o6a->str); ++ /* clear thread */ ++ o6a->thread_router_lsa = NULL; + +- /* find previous LSA */ +- /* xxx, there may be multiple Router-LSAs */ +- old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_ROUTER), +- htonl (0), o6a->ospf6->router_id, o6a); ++ if (IS_OSPF6_DUMP_LSA) ++ zlog_info ("LSA: originate Router-LSA for Area %s", o6a->str); + + size = sizeof (struct ospf6_router_lsa); + memset (buffer, 0, sizeof (buffer)); +@@ -1277,6 +1285,42 @@ + ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_ROUTER), + htonl (0), o6a->ospf6->router_id, + (char *) router_lsa, size, o6a); ++ return 0; ++} ++ ++void ++ospf6_lsa_schedule_router (struct ospf6_area *area) ++{ ++ u_long elasped_time, time = 0; ++ ++ if (area->thread_router_lsa) ++ { ++ if (IS_OSPF6_DUMP_LSA) ++ zlog_info ("LSA: schedule: Router-LSA for Area %s: another thread", ++ area->str); ++ return; ++ } ++ ++ elasped_time = ++ ospf6_lsa_has_elasped (htons (OSPF6_LSA_TYPE_ROUTER), htonl (0), ++ area->ospf6->router_id, area); ++ if (elasped_time < OSPF6_MIN_LS_INTERVAL) ++ time = (u_long) (OSPF6_MIN_LS_INTERVAL - elasped_time); ++ else ++ time = 0; ++ ++ if (IS_OSPF6_DUMP_LSA) ++ zlog_info ("LSA: schedule: Router-LSA for Area %s after %lu sec", ++ area->str, time); ++ ++ if (time) ++ area->thread_router_lsa = ++ thread_add_timer (master, ospf6_lsa_originate_router, ++ (void *) area->area_id, time); ++ else ++ area->thread_router_lsa = ++ thread_add_event (master, ospf6_lsa_originate_router, ++ (void *) area->area_id, 0); + } + + int +@@ -1284,7 +1328,7 @@ + { + struct ospf6_neighbor *o6n = neighbor; + if (o6n->ospf6_interface->area) +- ospf6_lsa_router_update (o6n->ospf6_interface->area->area_id); ++ ospf6_lsa_schedule_router (o6n->ospf6_interface->area); + return 0; + } + +@@ -1293,7 +1337,7 @@ + { + struct ospf6_interface *o6i = interface; + if (o6i->area) +- ospf6_lsa_router_update (o6i->area->area_id); ++ ospf6_lsa_schedule_router (o6i->area); + return 0; + } + +@@ -1301,7 +1345,7 @@ + ospf6_lsa_router_hook_area (void *area) + { + struct ospf6_area *o6a = area; +- ospf6_lsa_router_update (o6a->area_id); ++ ospf6_lsa_schedule_router (o6a); + return 0; + } + +@@ -1315,7 +1359,7 @@ + for (node = listhead (o6->area_list); node; nextnode (node)) + { + o6a = getdata (node); +- ospf6_lsa_router_update (o6a->area_id); ++ ospf6_lsa_schedule_router (o6a); + } + return 0; + } +@@ -1327,7 +1371,7 @@ + struct ospf6_area *o6a; + + o6a = lsa->scope; +- ospf6_lsa_router_update (o6a->area_id); ++ ospf6_lsa_schedule_router (o6a); + return 0; + } + +diff -x CVS -urN ospf6d.old/ospf6_lsa.h ospf6d/ospf6_lsa.h +--- ospf6d.old/ospf6_lsa.h Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_lsa.h Sat Nov 9 11:25:30 2002 +@@ -25,6 +25,13 @@ + + #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) ++ + /* LSA definition */ + + #define MAXLSASIZE 1024 +@@ -211,6 +218,7 @@ + unsigned char flag; /* to decide ack type and refresh */ + struct timeval birth; /* tv_sec when LS age 0 */ + struct timeval installed; /* installed time */ ++ struct timeval originated; /* installed time */ + struct thread *expire; + struct thread *refresh; /* For self-originated LSA */ + u_int32_t from; /* from which neighbor */ +@@ -397,22 +405,22 @@ + + u_short ospf6_lsa_checksum (struct ospf6_lsa_header *); + +-void ospf6_lsa_update_router (u_int32_t area_id); + 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_reoriginate (struct ospf6_lsa *); +-void +-ospf6_lsa_originate (u_int16_t, u_int32_t, u_int32_t, char *, int, void *); +- + 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 *); + + #endif /* OSPF6_LSA_H */ + +diff -x CVS -urN ospf6d.old/ospf6_message.c ospf6d/ospf6_message.c +--- ospf6d.old/ospf6_message.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_message.c Sat Nov 9 11:25:30 2002 +@@ -1108,14 +1108,14 @@ + if (!o6n) + { + if (IS_OSPF6_DUMP_LSACK) +- zlog_info (" neighbor not found, reject"); ++ zlog_info ("LSACK: neighbor not found, reject"); + return; + } + + if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr))) + { +- if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) +- zlog_info ("From Secondary I/F of the neighbor: ignore"); ++ if (IS_OSPF6_DUMP_LSACK) ++ zlog_info ("LSACK: From Secondary I/F of the neighbor: ignore"); + return; + } + +@@ -1123,7 +1123,7 @@ + if (o6n->state < NBS_EXCHANGE) + { + if (IS_OSPF6_DUMP_LSACK) +- zlog_info (" neighbor state less than Exchange, reject"); ++ zlog_info ("LSACK: neighbor state less than Exchange, reject"); + return; + } + +@@ -1141,7 +1141,7 @@ + if (!copy) + { + if (IS_OSPF6_DUMP_LSACK) +- zlog_info ("no database copy, ignore"); ++ zlog_info ("LSACK: no database copy, ignore"); + continue; + } + +@@ -1152,7 +1152,7 @@ + if (rem == NULL) + { + if (IS_OSPF6_DUMP_LSACK) +- zlog_info ("not on %s's retranslist, ignore", o6n->str); ++ zlog_info ("LSACK: not on %s's retranslist, ignore", o6n->str); + continue; + } + +@@ -1167,7 +1167,13 @@ + { + /* Log the questionable acknowledgement, + and examine the next one. */ +- zlog_warn ("LSAck: questionable acknowledge: LSAs differ"); ++ zlog_info ("LSACK: questionable acknowledge: %s", copy->str); ++ zlog_info ("LSACK: received: seq: %#x age: %hu", ++ ntohl (lsa->header->seqnum), ++ ntohs (lsa->header->age)); ++ zlog_info ("LSACK: instance: seq: %#x age: %hu", ++ ntohl (copy->header->seqnum), ++ ospf6_lsa_age_current (copy)); + } + + /* release temporary LSA from Ack message */ +@@ -1242,6 +1248,22 @@ + return; + } + ++ /* message type check */ ++ type = (ospf6_header->type >= OSPF6_MESSAGE_TYPE_MAX ? ++ OSPF6_MESSAGE_TYPE_UNKNOWN : ospf6_header->type); ++ ++ /* log */ ++ if (IS_OSPF6_DUMP_MESSAGE (type)) ++ { ++ char srcname[64], dstname[64]; ++ inet_ntop (AF_INET6, dst, dstname, sizeof (dstname)); ++ inet_ntop (AF_INET6, src, srcname, sizeof (srcname)); ++ zlog_info ("Receive %s on %s", ++ ospf6_message_type_string[type], o6i->interface->name); ++ zlog_info (" %s -> %s", srcname, dstname); ++ ospf6_message_log (message); ++ } ++ + /* router id check */ + router_id = ospf6_header->router_id; + if (ospf6_header->router_id == o6i->area->ospf6->router_id) +@@ -1252,10 +1274,6 @@ + return; + } + +- /* message type check */ +- type = (ospf6_header->type >= OSPF6_MESSAGE_TYPE_MAX ? +- OSPF6_MESSAGE_TYPE_UNKNOWN : ospf6_header->type); +- + /* octet statistics relies on some asumption: + on ethernet, no IPv6 Extention header, etc */ + #define OSPF6_IP6_HEADER_SIZE 40 +@@ -1280,12 +1298,14 @@ + struct ospf6_header ospf6_header; + char buffer[OSPF6_MESSAGE_RECEIVE_BUFSIZE]; + struct ospf6_interface *o6i; +- char srcname[64], dstname[64]; + unsigned char type; + + /* get socket */ + sockfd = THREAD_FD (thread); + ++ /* add next read thread */ ++ thread_add_read (master, ospf6_receive, NULL, sockfd); ++ + /* initialize */ + OSPF6_MESSAGE_CLEAR (message); + memset (&ospf6_header, 0, sizeof (struct ospf6_header)); +@@ -1302,22 +1322,10 @@ + o6i = ospf6_interface_lookup_by_index (ifindex); + if (!o6i || !o6i->area) + { +- zlog_warn ("*** received interface ospf6 disabled"); +- thread_add_read (master, ospf6_receive, NULL, sockfd); ++ //zlog_warn ("*** received interface ospf6 disabled"); + return 0; + } + +- /* log */ +- if (IS_OSPF6_DUMP_MESSAGE (type)) +- { +- inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname)); +- inet_ntop (AF_INET6, &src, srcname, sizeof (srcname)); +- zlog_info ("Receive %s on %s", +- ospf6_message_type_string[type], o6i->interface->name); +- zlog_info (" %s -> %s", srcname, dstname); +- ospf6_message_log (message); +- } +- + /* if not passive, process message */ + if (! CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE)) + ospf6_message_process (message, &src, &dst, o6i); +@@ -1325,9 +1333,6 @@ + zlog_info ("Ignore message on passive interface %s", + o6i->interface->name); + +- /* add next read thread */ +- thread_add_read (master, ospf6_receive, NULL, sockfd); +- + return 0; + } + +@@ -1828,6 +1833,9 @@ + return 0; + lsupdate.lsupdate_num = htonl (lsupdate.lsupdate_num); + ++ if (IS_OSPF6_DUMP_LSUPDATE) ++ zlog_info ("MESSAGE: retrsnsmit LSUpdate to %s", o6n->str); ++ + /* statistics */ + o6n->ospf6_stat_retrans_lsupdate++; + +@@ -1915,6 +1923,9 @@ + + o6i = THREAD_ARG (thread); + assert (o6i); ++ ++ if (IS_OSPF6_DUMP_LSACK) ++ zlog_info ("LSACK: Delayed LSAck for %s\n", o6i->interface->name); + + o6i->thread_send_lsack_delayed = (struct thread *) NULL; + +diff -x CVS -urN ospf6d.old/ospf6_neighbor.c ospf6d/ospf6_neighbor.c +--- ospf6d.old/ospf6_neighbor.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_neighbor.c Sat Nov 9 11:25:30 2002 +@@ -179,6 +179,13 @@ + } + + ospf6_lsdb_remove (lsa, nei->retrans_list); ++ ++ if (nei->retrans_list->count == 0) ++ { ++ if (nei->send_update) ++ thread_cancel (nei->send_update); ++ nei->send_update = NULL; ++ } + } + + void +diff -x CVS -urN ospf6d.old/ospf6_network.c ospf6d/ospf6_network.c +--- ospf6d.old/ospf6_network.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_network.c Tue Oct 1 10:28:08 2002 +@@ -255,8 +255,10 @@ + &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 +@@ -273,8 +275,10 @@ + &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 +@@ -290,8 +294,10 @@ + if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, + &mreq6, sizeof (mreq6)) < 0) + zlog_warn ("Network: Leave AllDRouters on ifindex %d Failed", ifindex); ++#if 0 + else + zlog_info ("Network: Leave AllDRouters on ifindex %d", ifindex); ++#endif + } + + /* setsockopt ReUseAddr to on */ +diff -x CVS -urN ospf6d.old/ospf6_route.h ospf6d/ospf6_route.h +--- ospf6d.old/ospf6_route.h Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_route.h Tue Oct 1 00:41:10 2002 +@@ -186,6 +186,9 @@ + 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 *), +diff -x CVS -urN ospf6d.old/ospf6_routemap.c ospf6d/ospf6_routemap.c +--- ospf6d.old/ospf6_routemap.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_routemap.c Tue Oct 1 00:41:10 2002 +@@ -22,9 +22,6 @@ + + #include <zebra.h> + +-#if 1 +-#include "ospf6d.h" +-#else + #include "log.h" + #include "memory.h" + #include "linklist.h" +@@ -32,11 +29,13 @@ + #include "command.h" + #include "vty.h" + #include "routemap.h" ++#include "table.h" + #include "plist.h" + +-#include "ospf6_top.h" +-#include "ospf6_redistribute.h" +-#endif ++#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, +@@ -70,7 +69,8 @@ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + } + +-struct route_map_rule_cmd ospf6_routemap_rule_match_address_prefixlist_cmd = ++struct route_map_rule_cmd ++ospf6_routemap_rule_match_address_prefixlist_cmd = + { + "ipv6 address prefix-list", + ospf6_routemap_rule_match_address_prefixlist, +@@ -83,15 +83,15 @@ + route_map_object_t type, void *object) + { + char *metric_type = rule; +- struct ospf6_route_req *route = object; ++ struct ospf6_external_info *info = object; + + if (type != RMAP_OSPF6) + return RMAP_OKAY; + + if (strcmp (metric_type, "type-2") == 0) +- route->path.metric_type = 2; ++ info->metric_type = 2; + else +- route->path.metric_type = 1; ++ info->metric_type = 1; + + return RMAP_OKAY; + } +@@ -108,7 +108,8 @@ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + } + +-struct route_map_rule_cmd ospf6_routemap_rule_set_metric_type_cmd = ++struct route_map_rule_cmd ++ospf6_routemap_rule_set_metric_type_cmd = + { + "metric-type", + ospf6_routemap_rule_set_metric_type, +@@ -121,14 +122,12 @@ + route_map_object_t type, void *object) + { + char *metric = rule; +- struct ospf6_route_req *route = object; ++ struct ospf6_external_info *info = object; + + if (type != RMAP_OSPF6) + return RMAP_OKAY; + +- route->path.cost = atoi (metric); +- route->path.cost_e2 = atoi (metric); +- ++ info->metric = atoi (metric); + return RMAP_OKAY; + } + +@@ -144,7 +143,8 @@ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + } + +-struct route_map_rule_cmd ospf6_routemap_rule_set_metric_cmd = ++struct route_map_rule_cmd ++ospf6_routemap_rule_set_metric_cmd = + { + "metric", + ospf6_routemap_rule_set_metric, +@@ -157,14 +157,14 @@ + route_map_object_t type, void *object) + { + char *forwarding = rule; +- struct ospf6_route_req *route = object; ++ struct ospf6_external_info *info = object; + + if (type != RMAP_OSPF6) + return RMAP_OKAY; + +- if (inet_pton (AF_INET6, forwarding, &route->nexthop.address) != 1) ++ if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1) + { +- memset (&route->nexthop.address, 0, sizeof (struct in6_addr)); ++ memset (&info->forwarding, 0, sizeof (struct in6_addr)); + return RMAP_ERROR; + } + +@@ -183,7 +183,8 @@ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + } + +-struct route_map_rule_cmd ospf6_routemap_rule_set_forwarding_cmd = ++struct route_map_rule_cmd ++ospf6_routemap_rule_set_forwarding_cmd = + { + "forwarding-address", + ospf6_routemap_rule_set_forwarding, +@@ -331,8 +332,8 @@ + { + route_map_init (); + route_map_init_vty (); +- route_map_add_hook (ospf6_redistribute_routemap_update); +- route_map_delete_hook (ospf6_redistribute_routemap_update); ++ 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); +diff -x CVS -urN ospf6d.old/ospf6_spf.c ospf6d/ospf6_spf.c +--- ospf6d.old/ospf6_spf.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_spf.c Sat Nov 9 11:25:30 2002 +@@ -281,7 +281,7 @@ + static struct in6_addr * + ospf6_spf_get_ipaddr (u_int32_t id, u_int32_t adv_router, u_int32_t ifindex) + { +- char buf[64]; ++ char buf[64], nhbuf[64]; + struct ospf6_interface *o6i; + struct ospf6_neighbor *o6n; + struct ospf6_lsa *lsa; +@@ -303,26 +303,30 @@ + lsa = node.lsa; + + /* return Linklocal Address field if the Link-LSA exists */ +- if (lsa) ++ if (lsa && lsa->header->adv_router == adv_router) + { + struct ospf6_link_lsa *link_lsa; + link_lsa = (struct ospf6_link_lsa *) (lsa->header + 1); + return &link_lsa->llsa_linklocal; + } + +- zlog_warn ("SPF: Can't find Link-LSA for %s, " +- "use source address from his packet", ++ zlog_warn ("SPF: Can't find Link-LSA for %s", + inet_ntop (AF_INET, &adv_router, buf, sizeof (buf))); + + o6n = ospf6_neighbor_lookup (adv_router, o6i); + if (! o6n) + { + inet_ntop (AF_INET, &adv_router, buf, sizeof (buf)); +- zlog_err ("SPF: Can't find neighbor %s in %s", ++ zlog_err ("SPF: Can't find neighbor %s in %s, " ++ "unable to find his linklocal address", + buf, o6i->interface->name); + return (struct in6_addr *) NULL; + } + ++ zlog_warn ("SPF: use packet's source address for %s's nexthop: %s", ++ inet_ntop (AF_INET, &adv_router, buf, sizeof (buf)), ++ inet_ntop (AF_INET6, &o6n->hisaddr, nhbuf, sizeof (nhbuf))); ++ + return &o6n->hisaddr; + } + +@@ -478,18 +482,22 @@ + inet_ntop (AF_INET, &adv_router, buf_router, sizeof (buf_router)); + inet_ntop (AF_INET, &id, buf_id, sizeof (buf_id)); + +- if (type == htons (OSPF6_LSA_TYPE_ROUTER)) +- zlog_err ("SPF: Can't find LSA for W (%s *): not found", +- buf_router); +- else +- zlog_err ("SPF: Can't find LSA for W (%s %s): not found", +- buf_router, buf_id); ++ if (IS_OSPF6_DUMP_SPF) ++ { ++ if (type == htons (OSPF6_LSA_TYPE_ROUTER)) ++ zlog_info ("SPF: Can't find LSA for W (%s *): not found", ++ buf_router); ++ else ++ zlog_info ("SPF: Can't find LSA for W (%s %s): not found", ++ buf_router, buf_id); ++ } + return (struct ospf6_vertex *) NULL; + } + + if (IS_LSA_MAXAGE (lsa)) + { +- zlog_err ("SPF: Associated LSA for W is MaxAge: %s", lsa->str); ++ if (IS_OSPF6_DUMP_SPF) ++ zlog_info ("SPF: Associated LSA for W is MaxAge: %s", lsa->str); + return (struct ospf6_vertex *) NULL; + } + +@@ -504,8 +512,9 @@ + } + if (! backreference) + { +- zlog_err ("SPF: Back reference failed: V: %s, W: %s", +- V->lsa->str, lsa->str); ++ if (IS_OSPF6_DUMP_SPF) ++ zlog_info ("SPF: Back reference failed: V: %s, W: %s", ++ V->lsa->str, lsa->str); + return (struct ospf6_vertex *) NULL; + } + +diff -x CVS -urN ospf6d.old/ospf6_top.c ospf6d/ospf6_top.c +--- ospf6d.old/ospf6_top.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_top.c Tue Oct 1 00:51:40 2002 +@@ -43,7 +43,6 @@ + #include "ospf6_area.h" + #include "ospf6_top.h" + +-#include "ospf6_redistribute.h" + #include "ospf6_route.h" + #include "ospf6_zebra.h" + +@@ -152,7 +151,7 @@ + vty_out (vty, " Supports only single TOS(TOS0) routes%s", VTY_NEWLINE); + + /* Redistribute config */ +- ospf6_redistribute_show_config (vty, ospf6); ++ ospf6_redistribute_show_config (vty); + + /* LSAs */ + vty_out (vty, " Number of AS scoped LSAs is %u%s", +@@ -250,9 +249,6 @@ + + o6->lsdb = ospf6_lsdb_create (); + +- /* route table init */ +- ospf6_redistribute_init (o6); +- + o6->foreach_area = ospf6_top_foreach_area; + o6->foreach_if = ospf6_top_foreach_interface; + o6->foreach_nei = ospf6_top_foreach_neighbor; +@@ -264,12 +260,14 @@ + ospf6_top_topology_remove, + o6->topology_table); + ++#if 0 + snprintf (namebuf, sizeof (namebuf), "External table"); + o6->external_table = ospf6_route_table_create (namebuf); + ospf6_route_hook_register (ospf6_asbr_external_route_add, + ospf6_asbr_external_route_add, + ospf6_asbr_external_route_remove, + o6->external_table); ++#endif /*0*/ + + snprintf (namebuf, sizeof (namebuf), "Top route table"); + o6->route_table = ospf6_route_table_create (namebuf); +diff -x CVS -urN ospf6d.old/ospf6_zebra.c ospf6d/ospf6_zebra.c +--- ospf6d.old/ospf6_zebra.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_zebra.c Wed Oct 2 17:16:56 2002 +@@ -22,7 +22,7 @@ + #include "ospf6d.h" + + #include "ospf6_interface.h" +-#include "ospf6_redistribute.h" ++#include "ospf6_asbr.h" + + #include "ospf6_linklist.h" + +@@ -202,13 +202,14 @@ + struct stream *s; + struct zapi_ipv6 api; + unsigned long ifindex; +- struct in6_addr nexthop; + struct prefix_ipv6 p; ++ struct in6_addr *nexthop; + char prefixstr[128], nexthopstr[128]; + + s = zclient->ibuf; + ifindex = 0; +- memset (&nexthop, 0, sizeof (struct in6_addr)); ++ nexthop = NULL; ++ memset (&api, 0, sizeof (api)); + + /* Type, flags, message. */ + api.type = stream_getc (s); +@@ -225,7 +226,9 @@ + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) + { + api.nexthop_num = stream_getc (s); +- stream_get (&nexthop, s, 16); ++ nexthop = (struct in6_addr *) ++ malloc (api.nexthop_num * sizeof (struct in6_addr)); ++ stream_get (nexthop, s, api.nexthop_num * sizeof (struct in6_addr)); + } + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) + { +@@ -256,11 +259,15 @@ + zebra_route_name [api.type], prefixstr, + nexthopstr, ifindex); + } +- ++ + if (command == ZEBRA_IPV6_ROUTE_ADD) +- ospf6_redistribute_route_add (api.type, ifindex, &p); ++ ospf6_asbr_route_add (api.type, ifindex, (struct prefix *) &p, ++ api.nexthop_num, nexthop); + else +- ospf6_redistribute_route_remove (api.type, ifindex, &p); ++ ospf6_asbr_route_remove (api.type, ifindex, (struct prefix *) &p); ++ ++ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) ++ free (nexthop); + + return 0; + } +@@ -448,10 +455,6 @@ + + if (IS_OSPF6_DUMP_ZEBRA) + zlog_info ("ZEBRA: found alternative path to add"); +- +- linklist_remove (nexthop, nexthop_list); +- XFREE (MTYPE_OSPF6_OTHER, nexthop); +- assert (nexthop_list->count == 0); + + memcpy (&seconde_path, &route.path, sizeof (struct ospf6_path)); + type = ADD; +diff -x CVS -urN ospf6d.old/ospf6d.c ospf6d/ospf6d.c +--- ospf6d.old/ospf6d.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6d.c Mon Mar 24 17:45:16 2003 +@@ -21,6 +21,8 @@ + + #include "ospf6d.h" + ++#include "ospf6_damp.h" ++ + /* global ospf6d variable */ + int ospf6_sock; + list iflist; +@@ -536,8 +538,8 @@ + return CMD_SUCCESS; + } + +-DEFUN (area_range, +- area_range_cmd, ++DEFUN (ospf6_area_range, ++ ospf6_area_range_cmd, + "area A.B.C.D range X:X::X:X/M", + "OSPFv3 area parameters\n" + "OSPFv3 area ID in IPv4 address format\n" +@@ -689,6 +691,7 @@ + vty_out (vty, " router-id %s%s", buf, VTY_NEWLINE); + + ospf6_redistribute_config_write (vty); ++ ospf6_damp_config_write (vty); + + for (j = listhead (ospf6->area_list); j; nextnode (j)) + { +@@ -745,7 +748,7 @@ + install_element (OSPF6_NODE, &no_interface_area_cmd); + install_element (OSPF6_NODE, &passive_interface_cmd); + install_element (OSPF6_NODE, &no_passive_interface_cmd); +- install_element (OSPF6_NODE, &area_range_cmd); ++ install_element (OSPF6_NODE, &ospf6_area_range_cmd); + + /* Make empty list of top list. */ + if_init (); +@@ -757,6 +760,10 @@ + prefix_list_init (); + + ospf6_dump_init (); ++ ++#ifdef HAVE_OSPF6_DAMP ++ ospf6_damp_init (); ++#endif /*HAVE_OSPF6_DAMP*/ + + ospf6_hook_init (); + ospf6_lsa_init (); +diff -x CVS -urN ospf6d.old/ospf6d.h ospf6d/ospf6d.h +--- ospf6d.old/ospf6d.h Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6d.h Fri Apr 25 11:40:31 2003 +@@ -59,7 +59,6 @@ + #include "ospf6_neighbor.h" + #include "ospf6_ism.h" + #include "ospf6_nsm.h" +-#include "ospf6_redistribute.h" + #include "ospf6_route.h" + #include "ospf6_dbex.h" + #include "ospf6_network.h" +@@ -74,7 +73,7 @@ + #define HASHVAL 64 + #define MAXIOVLIST 1024 + +-#define OSPF6_DAEMON_VERSION "0.9.6l" ++#define OSPF6_DAEMON_VERSION "0.9.6p" + + #define AF_LINKSTATE 0xff + diff --git a/net/zebra-devel/pkg-plist b/net/zebra-devel/pkg-plist index 08c293d29b50..c8ec32930086 100644 --- a/net/zebra-devel/pkg-plist +++ b/net/zebra-devel/pkg-plist @@ -1,4 +1,5 @@ sbin/bgpd +sbin/ospf6d sbin/ospfd sbin/ripd sbin/ripngd @@ -7,6 +8,7 @@ sbin/zebractl bin/vtysh etc/zebra/bgpd.conf.sample etc/zebra/bgpd.conf.sample2 +etc/zebra/ospf6d.conf.sample etc/zebra/ospfd.conf.sample etc/zebra/ripd.conf.sample etc/zebra/ripngd.conf.sample diff --git a/net/zebra-devel/pkg-plist.v6 b/net/zebra-devel/pkg-plist.v6 deleted file mode 100644 index a8519a7a98c9..000000000000 --- a/net/zebra-devel/pkg-plist.v6 +++ /dev/null @@ -1,2 +0,0 @@ -sbin/ospf6d -etc/zebra/ospf6d.conf.sample diff --git a/net/zebra-pj/Makefile b/net/zebra-pj/Makefile index b5fc2c0e79bc..5751661f153e 100644 --- a/net/zebra-pj/Makefile +++ b/net/zebra-pj/Makefile @@ -7,7 +7,7 @@ PORTNAME= zebra PORTVERSION= 0.93b -PORTREVISION= 4 +PORTREVISION= 5 CATEGORIES= net ipv6 MASTER_SITES= ftp://ftp.zebra.org/pub/zebra/ \ ftp://ftp.ripe.net/mirrors/sites/ftp.zebra.org/pub/zebra/ \ @@ -40,16 +40,6 @@ post-clean: .endif .endif -.include <bsd.port.pre.mk> - -.if ${OSVERSION} >= 400014 -PLIST:= ${WRKDIR}/PLIST -pre-install: - @${CAT} ${PKGDIR}/pkg-plist.v6 ${PKGDIR}/pkg-plist > ${PLIST} -.else -CONFIGURE_ARGS+=--disable-ospf6d --disable-ripngd -.endif - post-install: @( cd ${WRKSRC}/doc; rm -f zebra*info*; ${MAKE} zebra.info install ) @${ECHO} "===> installing zebra startup file..." @@ -64,4 +54,4 @@ post-install: @${ECHO} "router_flags=\"start\"" @${ECHO} "done." -.include <bsd.port.post.mk> +.include <bsd.port.mk> diff --git a/net/zebra-pj/files/patch-ospf6d b/net/zebra-pj/files/patch-ospf6d new file mode 100644 index 000000000000..8dce08ba2c3e --- /dev/null +++ b/net/zebra-pj/files/patch-ospf6d @@ -0,0 +1,3427 @@ +diff -x CVS -urN ospf6d.old/ChangeLog ospf6d/ChangeLog +--- ospf6d.old/ChangeLog Sat Apr 26 23:17:47 2003 ++++ ospf6d/ChangeLog Fri Apr 25 11:40:31 2003 +@@ -1,3 +1,36 @@ ++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 ++ ++2002-11-09 Vincent Jardin <jardin@6wind.com> ++ ++ * ospf6_interface.c: update link-local address on interface creation. ++ ++2002-11-09 Yasuhiro Ohara <yasu@sfc.wide.ad.jp> ++ ++ * ospf6_asbr.c: apply MinLSInterval to AS-External-LSA origination. ++ * ospf6_lsa.c: change not to issue flooding caused by expire event ++ when the received LSA is (already) MaxAge. ++ * ospf6_spf.c: fix a bug which is that ospf6d calculates ++ wrong nexthop when failed to find Link-LSA for the neighbor. ++ * ospf6_damp.c ospf6_dbex.c ospf6_neighbor.c ospf6_spf.c: ++ some clean up ++ * version: 0.9.6o ++ ++2002-10-04 Yasuhiro Ohara <yasu@sfc.wide.ad.jp> ++ ++ * ospf6_asbr.c: bug of failing ASE lsa refresh fixed. ++ * version: 0.9.6n ++ ++2002-10-01 Yasuhiro Ohara <yasu@sfc.wide.ad.jp> ++ ++ * ospf6_asbr.c: AS-External-LSA origination function ++ is re-written. ++ * ospf6_damp.[ch]: New feature that damps flaps is added. ++ * version: 0.9.6m ++ + 2002-07-14 Yasuhiro Ohara <yasu@sfc.wide.ad.jp> + + * ospf6_spf.c: unwanted assert() in ospf6_spf_nexthop_calculation() +diff -x CVS -urN ospf6d.old/Makefile.in ospf6d/Makefile.in +--- ospf6d.old/Makefile.in Sat Apr 26 23:17:47 2003 ++++ ospf6d/Makefile.in Thu Feb 20 01:31:12 2003 +@@ -1,4 +1,4 @@ +-# Makefile.in generated by automake 1.6.2 from Makefile.am. ++# Makefile.in generated by automake 1.6.3 from Makefile.am. + # @configure_input@ + + # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +@@ -111,9 +111,9 @@ + 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_redistribute.c ospf6_routemap.c ospf6_proto.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_abr.c ospf6_intra.c ospf6_damp.c + + + noinst_HEADERS = \ +@@ -121,9 +121,9 @@ + 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_redistribute.h ospf6_routemap.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_abr.h ospf6_intra.h ospf6_damp.h + + + ospf6d_SOURCES = \ +@@ -150,10 +150,10 @@ + ospf6_zebra.$(OBJEXT) ospf6_ism.$(OBJEXT) ospf6_dbex.$(OBJEXT) \ + ospf6_lsdb.$(OBJEXT) ospf6_prefix.$(OBJEXT) ospf6_top.$(OBJEXT) \ + ospf6_area.$(OBJEXT) ospf6_nsm.$(OBJEXT) \ +- ospf6_redistribute.$(OBJEXT) ospf6_routemap.$(OBJEXT) \ +- ospf6_proto.$(OBJEXT) ospf6_hook.$(OBJEXT) ospf6_asbr.$(OBJEXT) \ ++ ospf6_routemap.$(OBJEXT) ospf6_proto.$(OBJEXT) \ ++ ospf6_hook.$(OBJEXT) ospf6_asbr.$(OBJEXT) \ + ospf6_bintree.$(OBJEXT) ospf6_linklist.$(OBJEXT) \ +- ospf6_abr.$(OBJEXT) ospf6_intra.$(OBJEXT) ++ ospf6_abr.$(OBJEXT) ospf6_intra.$(OBJEXT) ospf6_damp.$(OBJEXT) + libospf6_a_OBJECTS = $(am_libospf6_a_OBJECTS) + sbin_PROGRAMS = ospf6d$(EXEEXT) + PROGRAMS = $(sbin_PROGRAMS) +@@ -165,10 +165,10 @@ + ospf6_zebra.$(OBJEXT) ospf6_ism.$(OBJEXT) ospf6_dbex.$(OBJEXT) \ + ospf6_lsdb.$(OBJEXT) ospf6_prefix.$(OBJEXT) ospf6_top.$(OBJEXT) \ + ospf6_area.$(OBJEXT) ospf6_nsm.$(OBJEXT) \ +- ospf6_redistribute.$(OBJEXT) ospf6_routemap.$(OBJEXT) \ +- ospf6_proto.$(OBJEXT) ospf6_hook.$(OBJEXT) ospf6_asbr.$(OBJEXT) \ ++ ospf6_routemap.$(OBJEXT) ospf6_proto.$(OBJEXT) \ ++ ospf6_hook.$(OBJEXT) ospf6_asbr.$(OBJEXT) \ + ospf6_bintree.$(OBJEXT) ospf6_linklist.$(OBJEXT) \ +- ospf6_abr.$(OBJEXT) ospf6_intra.$(OBJEXT) ++ ospf6_abr.$(OBJEXT) ospf6_intra.$(OBJEXT) ospf6_damp.$(OBJEXT) + am_ospf6d_OBJECTS = ospf6_main.$(OBJEXT) $(am__objects_1) + ospf6d_OBJECTS = $(am_ospf6d_OBJECTS) + ospf6d_DEPENDENCIES = ../lib/libzebra.a +@@ -182,8 +182,8 @@ + @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/ospf6_abr.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_area.Po ./$(DEPDIR)/ospf6_asbr.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_bintree.Po \ +-@AMDEP_TRUE@ ./$(DEPDIR)/ospf6_dbex.Po ./$(DEPDIR)/ospf6_dump.Po \ +-@AMDEP_TRUE@ ./$(DEPDIR)/ospf6_hook.Po \ ++@AMDEP_TRUE@ ./$(DEPDIR)/ospf6_damp.Po ./$(DEPDIR)/ospf6_dbex.Po \ ++@AMDEP_TRUE@ ./$(DEPDIR)/ospf6_dump.Po ./$(DEPDIR)/ospf6_hook.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_interface.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_intra.Po ./$(DEPDIR)/ospf6_ism.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_linklist.Po \ +@@ -195,7 +195,6 @@ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_nsm.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_prefix.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_proto.Po \ +-@AMDEP_TRUE@ ./$(DEPDIR)/ospf6_redistribute.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_route.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_routemap.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_spf.Po ./$(DEPDIR)/ospf6_top.Po \ +@@ -218,7 +217,7 @@ + + .SUFFIXES: + .SUFFIXES: .c .o .obj +-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) ++$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign ospf6d/Makefile + Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status +@@ -238,8 +237,7 @@ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + ; then \ +- p1=`echo "$$p1" | sed -e 's,^.*/,,'`; \ +- f=`echo $$p1|sed '$(transform);s/$$/$(EXEEXT)/'`; \ ++ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f"; \ + $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f; \ + else :; fi; \ +@@ -248,8 +246,7 @@ + uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ +- f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ +- f=`echo "$$f" | sed -e 's,^.*/,,'`; \ ++ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \ + rm -f $(DESTDIR)$(sbindir)/$$f; \ + done +@@ -270,6 +267,7 @@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_area.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_asbr.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_bintree.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_damp.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_dbex.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_dump.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_hook.Po@am__quote@ +@@ -286,7 +284,6 @@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_nsm.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_prefix.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_proto.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_redistribute.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_route.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_routemap.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_spf.Po@am__quote@ +diff -x CVS -urN ospf6d.old/ospf6_abr.c ospf6d/ospf6_abr.c +--- ospf6d.old/ospf6_abr.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_abr.c Tue Oct 1 10:28:07 2002 +@@ -42,7 +42,7 @@ + + inet_ntop (AF_INET, &router_id, router_string, sizeof (router_string)); + +- zlog_info ("ABR: Finding router %s in area %s", router_string, area->str); ++ //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; +diff -x CVS -urN ospf6d.old/ospf6_area.h ospf6d/ospf6_area.h +--- ospf6d.old/ospf6_area.h Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_area.h Sat Nov 9 11:25:30 2002 +@@ -62,6 +62,8 @@ + void (*func) (void *, int, void *)); + + struct thread *maxage_remover; ++ ++ struct thread *thread_router_lsa; + }; + + +diff -x CVS -urN ospf6d.old/ospf6_asbr.c ospf6d/ospf6_asbr.c +--- ospf6d.old/ospf6_asbr.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_asbr.c Fri Apr 25 11:40:31 2003 +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2001 Yasuhiro Ohara ++ * Copyright (C) 2001-2002 Yasuhiro Ohara + * + * This file is part of GNU Zebra. + * +@@ -19,108 +19,641 @@ + * Boston, MA 02111-1307, USA. + */ + +-#include "ospf6d.h" ++#include <zebra.h> ++ ++#include "log.h" ++#include "memory.h" ++#include "prefix.h" ++#include "command.h" ++#include "vty.h" ++#include "routemap.h" ++#include "table.h" ++#include "plist.h" ++#include "thread.h" ++ ++#include "ospf6_prefix.h" /* xxx for ospf6_asbr.h */ ++#include "ospf6_lsa.h" /* xxx for ospf6_asbr.h */ ++#include "ospf6_route.h" /* xxx for ospf6_asbr.h, ospf6_zebra.h */ ++#include "ospf6_zebra.h" ++#include "ospf6_asbr.h" ++#include "ospf6_damp.h" ++#include "ospf6_top.h" ++#include "ospf6_lsdb.h" ++#include "ospf6_proto.h" ++ ++extern struct thread_master *master; ++ ++struct route_table *external_table; ++struct ++{ ++ char *name; ++ struct route_map *map; ++} rmap [ZEBRA_ROUTE_MAX]; ++ ++static u_int32_t link_state_id = 0; ++ ++char * ++zroute_name[] = ++{ ++ "system", "kernel", "connected", "static", ++ "rip", "ripng", "ospf", "ospf6", "bgp", "unknown" ++}; ++char * ++zroute_abname[] = ++{ ++ "X", "K", "C", "S", "R", "R", "O", "O", "B", "?" ++}; ++ ++#define ZROUTE_NAME(x) \ ++ (0 < (x) && (x) < ZEBRA_ROUTE_MAX ? \ ++ zroute_name[(x)] : zroute_name[ZEBRA_ROUTE_MAX]) ++ ++#define ZROUTE_ABNAME(x) \ ++ (0 < (x) && (x) < ZEBRA_ROUTE_MAX ? \ ++ zroute_abname[(x)] : zroute_abname[ZEBRA_ROUTE_MAX]) ++ ++/* redistribute function */ ++void ++ospf6_asbr_routemap_set (int type, char *mapname) ++{ ++ if (rmap[type].name) ++ free (rmap[type].name); ++ ++ rmap[type].name = strdup (mapname); ++ rmap[type].map = route_map_lookup_by_name (mapname); ++} ++ ++void ++ospf6_asbr_routemap_unset (int type) ++{ ++ if (rmap[type].name) ++ free (rmap[type].name); ++ rmap[type].name = NULL; ++ rmap[type].map = NULL; ++} ++ ++void ++ospf6_asbr_routemap_update () ++{ ++ int i; ++ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) ++ { ++ if (rmap[i].name) ++ rmap[i].map = route_map_lookup_by_name (rmap[i].name); ++ else ++ rmap[i].map = NULL; ++ } ++} ++ ++DEFUN (ospf6_redistribute, ++ ospf6_redistribute_cmd, ++ "redistribute (static|kernel|connected|ripng|bgp)", ++ "Redistribute\n" ++ "Static route\n" ++ "Kernel route\n" ++ "Connected route\n" ++ "RIPng route\n" ++ "BGP route\n" ++ ) ++{ ++ int type = 0; ++ ++ if (strncmp (argv[0], "sta", 3) == 0) ++ type = ZEBRA_ROUTE_STATIC; ++ else if (strncmp (argv[0], "ker", 3) == 0) ++ type = ZEBRA_ROUTE_KERNEL; ++ else if (strncmp (argv[0], "con", 3) == 0) ++ type = ZEBRA_ROUTE_CONNECT; ++ else if (strncmp (argv[0], "rip", 3) == 0) ++ type = ZEBRA_ROUTE_RIPNG; ++ else if (strncmp (argv[0], "bgp", 3) == 0) ++ type = ZEBRA_ROUTE_BGP; ++ ++ ospf6_zebra_no_redistribute (type); ++ ospf6_asbr_routemap_unset (type); ++ ospf6_zebra_redistribute (type); ++ return CMD_SUCCESS; ++} ++ ++DEFUN (ospf6_redistribute_routemap, ++ ospf6_redistribute_routemap_cmd, ++ "redistribute (static|kernel|connected|ripng|bgp) route-map WORD", ++ "Redistribute\n" ++ "Static routes\n" ++ "Kernel route\n" ++ "Connected route\n" ++ "RIPng route\n" ++ "BGP route\n" ++ "Route map reference\n" ++ "Route map name\n" ++ ) ++{ ++ int type = 0; ++ ++ if (strncmp (argv[0], "sta", 3) == 0) ++ type = ZEBRA_ROUTE_STATIC; ++ else if (strncmp (argv[0], "ker", 3) == 0) ++ type = ZEBRA_ROUTE_KERNEL; ++ else if (strncmp (argv[0], "con", 3) == 0) ++ type = ZEBRA_ROUTE_CONNECT; ++ else if (strncmp (argv[0], "rip", 3) == 0) ++ type = ZEBRA_ROUTE_RIPNG; ++ else if (strncmp (argv[0], "bgp", 3) == 0) ++ type = ZEBRA_ROUTE_BGP; ++ ++ ospf6_zebra_no_redistribute (type); ++ ospf6_asbr_routemap_set (type, argv[1]); ++ ospf6_zebra_redistribute (type); ++ return CMD_SUCCESS; ++} ++ ++DEFUN (no_ospf6_redistribute, ++ no_ospf6_redistribute_cmd, ++ "no redistribute (static|kernel|connected|ripng|bgp)", ++ NO_STR ++ "Redistribute\n" ++ "Static route\n" ++ "Kernel route\n" ++ "Connected route\n" ++ "RIPng route\n" ++ "BGP route\n" ++ ) ++{ ++ int type = 0; ++ struct route_node *node; ++ struct ospf6_external_route *route; ++ struct ospf6_external_info *info, *info_next = NULL; ++ ++ if (strncmp (argv[0], "sta", 3) == 0) ++ type = ZEBRA_ROUTE_STATIC; ++ else if (strncmp (argv[0], "ker", 3) == 0) ++ type = ZEBRA_ROUTE_KERNEL; ++ else if (strncmp (argv[0], "con", 3) == 0) ++ type = ZEBRA_ROUTE_CONNECT; ++ else if (strncmp (argv[0], "rip", 3) == 0) ++ type = ZEBRA_ROUTE_RIPNG; ++ else if (strncmp (argv[0], "bgp", 3) == 0) ++ type = ZEBRA_ROUTE_BGP; ++ ++ ospf6_zebra_no_redistribute (type); ++ ospf6_asbr_routemap_unset (type); ++ ++ /* remove redistributed route */ ++ for (node = route_top (external_table); node; node = route_next (node)) ++ { ++ route = node->info; ++ if (! route) ++ continue; ++ for (info = route->info_head; info; info = info_next) ++ { ++ info_next = info->next; ++ if (info->type != type) ++ continue; ++ ospf6_asbr_route_remove (info->type, info->ifindex, ++ &route->prefix); ++ } ++ } ++ ++ return CMD_SUCCESS; ++} ++ ++ ++int ++ospf6_redistribute_config_write (struct vty *vty) ++{ ++ int i; ++ ++ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) ++ { ++ if (i == ZEBRA_ROUTE_OSPF6) ++ continue; ++ ++ if (! ospf6_zebra_is_redistribute (i)) ++ continue; ++ ++ if (rmap[i].map) ++ vty_out (vty, " redistribute %s route-map %s%s", ++ ZROUTE_NAME(i), rmap[i].name, VTY_NEWLINE); ++ else ++ vty_out (vty, " redistribute %s%s", ++ ZROUTE_NAME(i), VTY_NEWLINE); ++ } ++ ++ return 0; ++} + + void +-ospf6_asbr_external_lsa_update (struct ospf6_route_req *request) ++ospf6_redistribute_show_config (struct vty *vty) + { ++ int i; ++ ++ if (! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_SYSTEM) && ++ ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_KERNEL) && ++ ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_STATIC) && ++ ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_RIPNG) && ++ ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_BGP)) ++ return; ++ ++ vty_out (vty, " Redistributing External Routes from,%s", VTY_NEWLINE); ++ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) ++ { ++ if (i == ZEBRA_ROUTE_OSPF6) ++ continue; ++ if (! ospf6_zebra_is_redistribute (i)) ++ continue; ++ ++ if (rmap[i].map) ++ vty_out (vty, " %s with route-map %s%s", ++ ZROUTE_NAME(i), rmap[i].name, VTY_NEWLINE); ++ else ++ vty_out (vty, " %s%s", ZROUTE_NAME(i), VTY_NEWLINE); ++ } ++} ++ ++/* AS External LSA origination */ ++int ++ospf6_asbr_external_lsa_originate (struct thread *thread) ++{ ++ struct ospf6_external_info *info; + char buffer [MAXLSASIZE]; +- u_int16_t size; +- struct ospf6_lsa_as_external *external; ++ struct ospf6_lsa_as_external *e; + char *p; +- struct ospf6_route_req route; +- char pbuf[BUFSIZ]; + +- /* 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; ++ info = THREAD_ARG (thread); + +- if (IS_OSPF6_DUMP_LSA) +- zlog_info ("Update AS-External: ID: %lu", +- (u_long) ntohl (request->path.origin.id)); ++ /* clear thread */ ++ info->thread_originate = NULL; ++ ++ if (info->is_removed) ++ { ++ if (IS_OSPF6_DUMP_ASBR) ++ { ++ char pbuf[64]; ++ prefix2str (&info->route->prefix, pbuf, sizeof (pbuf)); ++ zlog_info ("ASBR: quit redistribution %s: state is down", ++ pbuf); ++ } ++ return 0; ++ } + + /* prepare buffer */ + memset (buffer, 0, sizeof (buffer)); +- size = sizeof (struct ospf6_lsa_as_external); +- external = (struct ospf6_lsa_as_external *) buffer; +- p = (char *) (external + 1); ++ e = (struct ospf6_lsa_as_external *) buffer; ++ p = (char *) (e + 1); + +- if (route.path.metric_type == 2) +- SET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E); /* type2 */ ++ if (info->metric_type == 2) ++ SET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_E); /* type2 */ + else +- UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E); /* type1 */ ++ UNSET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_E); /* type1, default */ + + /* forwarding address */ +- if (! IN6_IS_ADDR_UNSPECIFIED (&route.nexthop.address)) +- SET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F); ++ if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding)) ++ SET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_F); + else +- UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F); ++ UNSET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_F); + + /* external route tag */ +- UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T); ++ UNSET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_T); + + /* set metric. note: related to E bit */ +- OSPF6_ASBR_METRIC_SET (external, route.path.cost); ++ OSPF6_ASBR_METRIC_SET (e, info->metric); + + /* prefixlen */ +- external->prefix.prefix_length = route.route.prefix.prefixlen; ++ e->prefix.prefix_length = info->route->prefix.prefixlen; + + /* PrefixOptions */ +- external->prefix.prefix_options = route.path.prefix_options; ++ e->prefix.prefix_options = info->prefix_options; + + /* don't use refer LS-type */ +- external->prefix.prefix_refer_lstype = htons (0); +- +- if (IS_OSPF6_DUMP_LSA) +- { +- prefix2str (&route.route.prefix, pbuf, sizeof (pbuf)); +- zlog_info (" Prefix: %s", pbuf); +- } ++ e->prefix.prefix_refer_lstype = htons (0); + + /* set Prefix */ +- memcpy (p, &route.route.prefix.u.prefix6, +- OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen)); +- ospf6_prefix_apply_mask (&external->prefix); +- size += OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen); +- p += OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen); ++ memcpy (p, &info->route->prefix.u.prefix6, ++ OSPF6_PREFIX_SPACE (info->route->prefix.prefixlen)); ++ ospf6_prefix_apply_mask (&e->prefix); ++ p += OSPF6_PREFIX_SPACE (info->route->prefix.prefixlen); + + /* Forwarding address */ +- if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F)) ++ if (CHECK_FLAG (e->bits_metric, OSPF6_ASBR_BIT_F)) + { +- memcpy (p, &route.nexthop.address, sizeof (struct in6_addr)); +- size += sizeof (struct in6_addr); ++ memcpy (p, &info->forwarding, sizeof (struct in6_addr)); + p += sizeof (struct in6_addr); + } + + /* External Route Tag */ +- if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T)) ++ if (CHECK_FLAG (e->bits_metric, OSPF6_ASBR_BIT_T)) + { + /* xxx */ + } + + ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_AS_EXTERNAL), +- route.path.origin.id, ospf6->router_id, +- (char *) external, size, ospf6); +- return; ++ htonl (info->id), ospf6->router_id, ++ (char *) buffer, p - buffer, ospf6); ++ return 0; ++} ++ ++int ++ospf6_asbr_schedule_external (void *data) ++{ ++ struct ospf6_external_info *info = data; ++ u_long elasped_time, time = 0; ++ ++ if (info->thread_originate) ++ { ++ if (IS_OSPF6_DUMP_ASBR) ++ { ++ char pbuf[64]; ++ prefix2str (&info->route->prefix, pbuf, sizeof (pbuf)); ++ zlog_info ("ASBR: schedule redistribution %s: another thread", ++ pbuf); ++ } ++ return 0; ++ } ++ ++ elasped_time = ++ ospf6_lsa_has_elasped (htons (OSPF6_LSA_TYPE_AS_EXTERNAL), ++ htonl (info->id), ospf6->router_id, ospf6); ++ if (elasped_time < OSPF6_MIN_LS_INTERVAL) ++ time = OSPF6_MIN_LS_INTERVAL - elasped_time; ++ else ++ time = 0; ++ ++ //if (IS_OSPF6_DUMP_ASBR) ++ { ++ char pbuf[64]; ++ prefix2str (&info->route->prefix, pbuf, sizeof (pbuf)); ++ zlog_info ("ASBR: schedule redistribution %s as LS-ID %ld after %lu sec", ++ pbuf, (u_long) info->id, time); ++ } ++ ++ if (time) ++ info->thread_originate = ++ thread_add_timer (master, ospf6_asbr_external_lsa_originate, info, time); ++ else ++ info->thread_originate = ++ thread_add_timer (master, ospf6_asbr_external_lsa_originate, info, 0); ++ ++ return 0; ++} ++ ++int ++ospf6_asbr_external_lsa_flush (void *data) ++{ ++ struct ospf6_lsa *lsa = data; ++ if (lsa) ++ ospf6_lsa_premature_aging (lsa); ++ return 0; ++} ++ ++int ++ospf6_asbr_external_lsa_refresh (void *data) ++{ ++ struct ospf6_lsa *lsa = data; ++ struct ospf6_lsa_as_external *e; ++ struct prefix prefix; ++ struct route_node *node; ++ struct ospf6_external_route *route = NULL; ++ struct ospf6_external_info *info = NULL; ++ struct ospf6_external_info *match = NULL; ++ ++ if (IS_OSPF6_DUMP_ASBR) ++ zlog_info ("ASBR: refresh %s", lsa->str); ++ ++ e = (struct ospf6_lsa_as_external *) (lsa->header + 1); ++ ospf6_prefix_in6_addr (&e->prefix, &prefix.u.prefix6); ++ prefix.prefixlen = e->prefix.prefix_length; ++ prefix.family = AF_INET6; ++ apply_mask_ipv6 ((struct prefix_ipv6 *) &prefix); ++ ++ for (node = route_top (external_table); node; node = route_next (node)) ++ { ++ route = node->info; ++ if (route == NULL) ++ continue; ++ ++ for (info = route->info_head; info; info = info->next) ++ { ++ if (lsa->header->id == htonl (info->id)) ++ match = info; ++ } ++ } ++ ++ if (match == NULL) ++ { ++ ospf6_lsa_premature_aging (lsa); ++ return 0; ++ } ++ ++ ospf6_asbr_schedule_external (match); ++ return 0; ++ ++#if 0 ++ node = route_node_lookup (external_table, &prefix); ++ if (! node || ! node->info) ++ { ++ char pname[64]; ++ ++ prefix2str (&prefix, pname, sizeof (pname)); ++ if (IS_OSPF6_DUMP_ASBR) ++ zlog_info ("ASBR: could not find %s: premature age", pname); ++ ospf6_lsa_premature_aging (lsa); ++ return 0; ++ } ++ ++ /* find external_info */ ++ route = node->info; ++ for (info = route->info_head; info; info = info->next) ++ { ++ if (lsa->header->id == htonl (info->id)) ++ break; ++ } ++ ++ if (info) ++ ospf6_asbr_schedule_external (info); ++ else ++ ospf6_lsa_premature_aging (lsa); ++ ++ return 0; ++#endif + } + + void +-ospf6_asbr_external_route_add (struct ospf6_route_req *route) ++ospf6_asbr_route_add (int type, int ifindex, struct prefix *prefix, ++ u_int nexthop_num, struct in6_addr *nexthop) + { +- ospf6_asbr_external_lsa_update (route); ++ int ret; ++ struct route_node *node; ++ struct ospf6_external_route *route; ++ struct ospf6_external_info *info, tinfo; ++ ++ if (! ospf6_zebra_is_redistribute (type)) ++ return; ++ ++ /* apply route-map */ ++ memset (&tinfo, 0, sizeof (struct ospf6_external_info)); ++ if (rmap[type].map) ++ { ++ ret = route_map_apply (rmap[type].map, prefix, RMAP_OSPF6, &tinfo); ++ if (ret == RMAP_DENYMATCH) ++ { ++ if (IS_OSPF6_DUMP_ASBR) ++ zlog_info ("ASBR: denied by route-map %s", rmap[type].name); ++ return; ++ } ++ } ++ ++ node = route_node_get (external_table, prefix); ++ route = node->info; ++ ++ if (! route) ++ { ++ route = XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO, ++ sizeof (struct ospf6_external_route)); ++ memset (route, 0, sizeof (struct ospf6_external_route)); ++ ++ memcpy (&route->prefix, prefix, sizeof (struct prefix)); ++ ++ node->info = route; ++ route->node = node; ++ } ++ ++ for (info = route->info_head; info; info = info->next) ++ { ++ if (info->type == type && info->ifindex == ifindex) ++ break; ++ } ++ ++ if (! info) ++ { ++ info = XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO, ++ sizeof (struct ospf6_external_info)); ++ memset (info, 0, sizeof (struct ospf6_external_info)); ++ ++ info->route = route; ++ /* add tail */ ++ info->prev = route->info_tail; ++ if (route->info_tail) ++ route->info_tail->next = info; ++ else ++ route->info_head = info; ++ route->info_tail = info; ++ ++ info->id = link_state_id++; ++ } ++ ++ /* copy result of route-map */ ++ info->metric_type = tinfo.metric_type; ++ info->metric = tinfo.metric; ++ memcpy (&info->forwarding, &tinfo.forwarding, ++ sizeof (struct in6_addr)); ++ ++ info->type = type; ++ info->ifindex = ifindex; ++ ++ if (nexthop_num && nexthop) ++ { ++ info->nexthop_num = nexthop_num; ++ ++ if (info->nexthop) ++ XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info->nexthop); ++ ++ info->nexthop = (struct in6_addr *) ++ XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO, ++ nexthop_num * sizeof (struct in6_addr)); ++ memcpy (info->nexthop, nexthop, ++ nexthop_num * sizeof (struct in6_addr)); ++ } ++ ++ info->is_removed = 0; ++ ++ //if (IS_OSPF6_DUMP_ASBR) ++ { ++ char pbuf[64]; ++ struct timeval now; ++ prefix2str (&info->route->prefix, pbuf, sizeof (pbuf)); ++ gettimeofday (&now, NULL); ++ zlog_info ("ASBR: start redistributing %s as LS-ID %ld: %ld.%06ld", ++ pbuf, (u_long) info->id, now.tv_sec, now.tv_usec); ++ } ++ ++#ifdef HAVE_OSPF6_DAMP ++ ospf6_damp_event_up (OSPF6_DAMP_TYPE_ROUTE, prefix, ++ ospf6_asbr_schedule_external, info); ++#else /*HAVE_OSPF6_DAMP*/ ++ ospf6_asbr_schedule_external (info); ++#endif /*HAVE_OSPF6_DAMP*/ + } + + void +-ospf6_asbr_external_route_remove (struct ospf6_route_req *route) ++ospf6_asbr_route_remove (int type, int ifindex, struct prefix *prefix) + { ++ struct route_node *node; ++ struct ospf6_external_route *route; ++ struct ospf6_external_info *info; + struct ospf6_lsa *lsa; + +- lsa = ospf6_lsdb_lookup_lsdb (htons (OSPF6_LSA_TYPE_AS_EXTERNAL), +- route->path.origin.id, +- ospf6->router_id, ospf6->lsdb); +- if (lsa) +- ospf6_lsa_premature_aging (lsa); ++ node = route_node_get (external_table, prefix); ++ route = node->info; ++ ++ if (! route) ++ return; ++ ++ for (info = route->info_head; info; info = info->next) ++ { ++ if (info->type == type && info->ifindex == ifindex) ++ break; ++ } ++ ++ if (! info) ++ return; ++ ++ //if (IS_OSPF6_DUMP_ASBR) ++ { ++ char pbuf[64]; ++ struct timeval now; ++ prefix2str (&info->route->prefix, pbuf, sizeof (pbuf)); ++ gettimeofday (&now, NULL); ++ zlog_info ("ASBR: quit redistributing %s as LS-ID %ld: %ld.%06ld", ++ pbuf, (u_long) info->id, now.tv_sec, now.tv_usec); ++ } ++ ++ if (info->thread_originate) ++ thread_cancel (info->thread_originate); ++ info->thread_originate = NULL; ++ ++ lsa = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_AS_EXTERNAL), ++ htonl (info->id), ospf6->router_id, ospf6); ++#ifdef HAVE_OSPF6_DAMP ++ ospf6_damp_event_down (OSPF6_DAMP_TYPE_ROUTE, &info->route->prefix, ++ ospf6_asbr_external_lsa_flush, lsa); ++#else /*HAVE_OSPF6_DAMP*/ ++ ospf6_asbr_external_lsa_flush (lsa); ++#endif /*HAVE_OSPF6_DAMP*/ ++ ++#if 1 ++ info->is_removed = 1; ++#else ++ /* remove from route */ ++ if (info->prev) ++ info->prev->next = info->next; ++ else ++ info->route->info_head = info->next; ++ if (info->next) ++ info->next->prev = info->prev; ++ else ++ info->route->info_tail = info->prev; ++ ++ /* if no info, free route */ ++ if (! info->route->info_head && ! info->route->info_tail) ++ { ++ info->route->node->info = NULL; ++ free (info->route); ++ } ++ ++ if (info->nexthop) ++ free (info->nexthop); ++ free (info); ++#endif /*0*/ + } + + void +@@ -134,22 +667,29 @@ + external = OSPF6_LSA_HEADER_END (lsa->header); + + if (IS_LSA_MAXAGE (lsa)) +- return; ++ { ++ if (IS_OSPF6_DUMP_ASBR) ++ zlog_info ("ASBR: maxage external lsa: %s seq: %lx", ++ lsa->str, (u_long)ntohl (lsa->header->seqnum)); ++ ospf6_asbr_external_lsa_remove (lsa); ++ return; ++ } + + if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: Calculate %s", lsa->str); ++ zlog_info ("ASBR: new external lsa: %s seq: %lx", ++ lsa->str, (u_long)ntohl (lsa->header->seqnum)); + + if (lsa->header->adv_router == ospf6->router_id) + { + if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: Self-originated, ignore"); ++ zlog_info ("ASBR: my external LSA, ignore"); + return; + } + + if (OSPF6_ASBR_METRIC (external) == LS_INFINITY) + { + if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: Metric is Infinity, ignore"); ++ zlog_info ("ASBR: metric is infinity, ignore"); + return; + } + +@@ -167,7 +707,7 @@ + { + char buf[64]; + inet_ntop (AF_INET, &asbr_id.adv_router, buf, sizeof (buf)); +- zlog_info ("ASBR: ASBR %s not found, ignore", buf); ++ zlog_info ("ASBR: router %s not found, ignore", buf); + } + return; + } +@@ -206,6 +746,14 @@ + { + memcpy (&request.nexthop, &asbr_entry.nexthop, + sizeof (struct ospf6_nexthop)); ++ if (IS_OSPF6_DUMP_ASBR) ++ { ++ char buf[64], nhop[64], ifname[IFNAMSIZ]; ++ prefix2str (&request.route.prefix, buf, sizeof (buf)); ++ inet_ntop (AF_INET6, &request.nexthop.address, nhop, sizeof (nhop)); ++ if_indextoname (request.nexthop.ifindex, ifname); ++ zlog_info ("ASBR: add route: %s %s%%%s", buf, nhop, ifname); ++ } + ospf6_route_add (&request, ospf6->route_table); + ospf6_route_next (&asbr_entry); + } +@@ -220,12 +768,13 @@ + struct ospf6_route_req request; + + if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: Withdraw route of %s", lsa->str); ++ zlog_info ("ASBR: withdraw external lsa: %s seq: %lx", ++ lsa->str, (u_long)ntohl (lsa->header->seqnum)); + + if (lsa->header->adv_router == ospf6->router_id) + { + if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: Self-originated, ignore"); ++ zlog_info ("ASBR: my external LSA, ignore"); + return; + } + +@@ -236,14 +785,14 @@ + memcpy (&dest.u.prefix6, (char *)(external + 1), + OSPF6_PREFIX_SPACE (dest.prefixlen)); + +- prefix2str (&dest, buf, sizeof (buf)); +- if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: route: %s", buf); +- + ospf6_route_lookup (&request, &dest, ospf6->route_table); + if (ospf6_route_end (&request)) + { +- zlog_info ("ASBR: route not found"); ++ if (IS_OSPF6_DUMP_ASBR) ++ { ++ prefix2str (&dest, buf, sizeof (buf)); ++ zlog_info ("ASBR: %s not found", buf); ++ } + return; + } + +@@ -252,7 +801,8 @@ + { + if (prefix_same (&request.route.prefix, &dest) != 1) + { +- zlog_info ("ASBR: Can't find the entry matches the origin"); ++ if (IS_OSPF6_DUMP_ASBR) ++ zlog_info ("ASBR: Can't find the entry matches the origin"); + return; + } + ospf6_route_next (&request); +@@ -264,6 +814,15 @@ + request.path.origin.adv_router == lsa->header->adv_router && + prefix_same (&request.route.prefix, &dest) == 1) + { ++ if (IS_OSPF6_DUMP_ASBR) ++ { ++ char nhop[64], ifname[IFNAMSIZ]; ++ prefix2str (&dest, buf, sizeof (buf)); ++ inet_ntop (AF_INET6, &request.nexthop.address, nhop, sizeof (nhop)); ++ if_indextoname (request.nexthop.ifindex, ifname); ++ zlog_info ("ASBR: remove route: %s %s%%%s", buf, nhop, ifname); ++ } ++ + ospf6_route_remove (&request, ospf6->route_table); + ospf6_route_next (&request); + } +@@ -303,7 +862,7 @@ + { + char buf[64]; + inet_ntop (AF_INET, &inter_router->adv_router, buf, sizeof (buf)); +- zlog_info ("ASBR: New router found: %s", buf); ++ zlog_info ("ASBR: new router found: %s", buf); + } + + if (ntohl (id) != 0 || +@@ -335,7 +894,7 @@ + { + char buf[64]; + inet_ntop (AF_INET, &inter_router->adv_router, buf, sizeof (buf)); +- zlog_info ("ASBR: Router disappearing: %s", buf); ++ zlog_info ("ASBR: router disappearing: %s", buf); + } + + if (ntohl (id) != 0 || +@@ -410,37 +969,6 @@ + return 0; + } + +-int +-ospf6_asbr_external_refresh (void *old) +-{ +- struct ospf6_lsa *lsa = old; +- struct ospf6_route_req route, *target; +- +- assert (ospf6); +- +- if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: refresh %s", lsa->str); +- +- target = NULL; +- for (ospf6_route_head (&route, ospf6->external_table); +- ! ospf6_route_end (&route); +- ospf6_route_next (&route)) +- { +- if (route.path.origin.id == lsa->header->id) +- { +- target = &route; +- break; +- } +- } +- +- if (target) +- ospf6_asbr_external_lsa_update (target); +- else +- ospf6_lsa_premature_aging (lsa); +- +- return 0; +-} +- + void + ospf6_asbr_database_hook (struct ospf6_lsa *old, struct ospf6_lsa *new) + { +@@ -459,7 +987,7 @@ + slot.type = htons (OSPF6_LSA_TYPE_AS_EXTERNAL); + slot.name = "AS-External"; + slot.func_show = ospf6_asbr_external_show; +- slot.func_refresh = ospf6_asbr_external_refresh; ++ slot.func_refresh = ospf6_asbr_external_lsa_refresh; + ospf6_lsa_slot_register (&slot); + + ospf6_lsdb_hook[OSPF6_LSA_TYPE_AS_EXTERNAL & OSPF6_LSTYPE_CODE_MASK].hook = +@@ -467,9 +995,71 @@ + } + + void ++ospf6_asbr_external_info_show (struct vty *vty, ++ struct ospf6_external_info *info) ++{ ++ char prefix_buf[64], id_buf[16]; ++ struct in_addr id; ++ ++ if (info->is_removed) ++ return; ++ ++ id.s_addr = ntohl (info->id); ++ inet_ntop (AF_INET, &id, id_buf, sizeof (id_buf)); ++ prefix2str (&info->route->prefix, prefix_buf, sizeof (prefix_buf)); ++ vty_out (vty, "%s %-32s %3d %-15s %3d %lu(type-%d)%s", ++ ZROUTE_ABNAME(info->type), prefix_buf, info->ifindex, id_buf, ++ info->nexthop_num, (u_long) info->metric, info->metric_type, ++ VTY_NEWLINE); ++} ++ ++void ++ospf6_asbr_external_route_show (struct vty *vty, ++ struct ospf6_external_route *route) ++{ ++ struct ospf6_external_info *info; ++ for (info = route->info_head; info; info = info->next) ++ ospf6_asbr_external_info_show (vty, info); ++} ++ ++DEFUN (show_ipv6_route_ospf6_external, ++ show_ipv6_route_ospf6_external_cmd, ++ "show ipv6 ospf6 route redistribute", ++ SHOW_STR ++ IP6_STR ++ ROUTE_STR ++ OSPF6_STR ++ "redistributing External information\n" ++ ) ++{ ++ struct route_node *node; ++ struct ospf6_external_route *route; ++ ++ vty_out (vty, "%s %-32s %3s %-15s %3s %s%s", ++ " ", "Prefix", "I/F", "LS-Id", "#NH", "Metric", ++ VTY_NEWLINE); ++ for (node = route_top (external_table); node; node = route_next (node)) ++ { ++ route = node->info; ++ if (route) ++ ospf6_asbr_external_route_show (vty, route); ++ } ++ return CMD_SUCCESS; ++} ++ ++void + ospf6_asbr_init () + { ++ external_table = route_table_init (); ++ link_state_id = 0; ++ + ospf6_asbr_register_as_external (); ++ ++ install_element (VIEW_NODE, &show_ipv6_route_ospf6_external_cmd); ++ install_element (ENABLE_NODE, &show_ipv6_route_ospf6_external_cmd); ++ install_element (OSPF6_NODE, &ospf6_redistribute_cmd); ++ install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd); ++ install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd); + } + + +diff -x CVS -urN ospf6d.old/ospf6_asbr.h ospf6d/ospf6_asbr.h +--- ospf6d.old/ospf6_asbr.h Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_asbr.h Sat Nov 9 11:25:30 2002 +@@ -22,6 +22,51 @@ + #ifndef OSPF6_ASBR_H + #define OSPF6_ASBR_H + ++#include "thread.h" ++ ++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 */ ++ int type; ++ ++ /* external route ifindex */ ++ int ifindex; ++ ++ /* LS-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 + { +@@ -42,8 +87,16 @@ + { (E)->bits_metric &= htonl (0xff000000); \ + (E)->bits_metric |= htonl (0x00ffffff) & htonl (C); } + +-void ospf6_asbr_external_route_add (struct ospf6_route_req *route); +-void ospf6_asbr_external_route_remove (struct ospf6_route_req *route); ++void ospf6_asbr_routemap_update (); ++ ++int ospf6_redistribute_config_write (struct vty *vty); ++void ospf6_redistribute_show_config (struct vty *vty); ++ ++void ++ospf6_asbr_route_add (int type, int ifindex, struct prefix *prefix, ++ u_int nexthop_num, struct in6_addr *nexthop); ++void ++ospf6_asbr_route_remove (int type, int ifindex, struct prefix *prefix); + + void ospf6_asbr_external_lsa_add (struct ospf6_lsa *lsa); + void ospf6_asbr_external_lsa_remove (struct ospf6_lsa *lsa); +diff -x CVS -urN ospf6d.old/ospf6_damp.c ospf6d/ospf6_damp.c +--- ospf6d.old/ospf6_damp.c Thu Jan 1 01:00:00 1970 ++++ ospf6d/ospf6_damp.c Sat Nov 9 11:25:30 2002 +@@ -0,0 +1,748 @@ ++/* ++ * 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, ++ 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, ++ 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, ++ 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, ++ 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 (flap_damping_route, ++ 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, &flap_damping_route_cmd); ++ ++ install_element (ENABLE_NODE, &show_debug_ospf6_damp_cmd); ++ install_element (CONFIG_NODE, &debug_ospf6_damp_cmd); ++ install_element (CONFIG_NODE, &no_debug_ospf6_damp_cmd); ++ ++ thread_add_event (master, ospf6_damp_debug_thread, NULL, 0); ++} ++ ++#endif /* HAVE_OSPF6_DAMP */ ++ ++ +diff -x CVS -urN ospf6d.old/ospf6_damp.h ospf6d/ospf6_damp.h +--- ospf6d.old/ospf6_damp.h Thu Jan 1 01:00:00 1970 ++++ ospf6d/ospf6_damp.h Tue Oct 1 00:41:10 2002 +@@ -0,0 +1,109 @@ ++/* ++ * OSPF flap dampening by Manav Bhatia ++ * Copyright (C) 2002 ++ * ++ * This file is part of GNU Zebra. ++ * ++ * GNU Zebra is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2, or (at your option) any ++ * later version. ++ * ++ * GNU Zebra is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GNU Zebra; see the file COPYING. If not, write to the Free ++ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ++ * 02111-1307, USA. ++ */ ++ ++/* ++ * Flap Damping (target e.g. link/route) ++ */ ++ ++#define HAVE_OSPF6_DAMP ++ ++typedef enum ++{ ++ OFF, ++ ON, ++} onoff_t; ++ ++typedef enum ++{ ++ event_none, ++ event_up, ++ event_down, ++} damp_event_t; ++ ++/* Structure maintained per target basis */ ++struct ospf6_damp_info ++{ ++ /* identifier to decide which target */ ++ u_short type; ++ struct prefix name; ++ ++ /* do we damping this info */ ++ onoff_t damping; ++ ++ u_int penalty; ++ u_int flap; ++ time_t t_start; /* First flap (down event) time */ ++ time_t t_updated; /* Last time the penalty was updated */ ++ ++ /* index and double-link for reuse list */ ++ int index; ++ struct ospf6_damp_info *next; ++ struct ospf6_damp_info *prev; ++ ++ /* the last event that we are avoiding */ ++ int (*event) (void *target); ++ void *target; ++ damp_event_t event_type; ++ damp_event_t target_status; ++}; ++ ++#define OSPF6_DAMP_TYPE_ROUTE 0 ++#define OSPF6_DAMP_TYPE_MAX 1 ++ ++/* Global Configuration Parameters */ ++struct ospf6_damp_config ++{ ++ /* is damping enabled ? */ ++ onoff_t enabled; ++ ++ /* configurable parameters */ ++ u_int half_life; ++ u_int suppress; ++ u_int reuse; ++ u_int t_hold; /* Maximum hold down time */ ++ ++ /* Non configurable parameters */ ++ u_int delta_t; ++ u_int delta_reuse; ++ u_int default_penalty; ++ u_int ceiling; /* Max value a penalty can attain */ ++ double scale_factor; ++ ++ int decay_array_size; /* Calculated using config parameters */ ++ double *decay_array; /* Storage for decay values */ ++ ++ int reuse_index_array_size; /* Size of reuse index array */ ++ int *reuse_index_array; ++ ++ int reuse_list_size; /* Number of reuse lists */ ++ struct ospf6_damp_info **reuse_list_array; ++}; ++ ++int ospf6_damp_reuse_timer (struct thread *); ++void ospf6_damp_event_up (u_short type, struct prefix *name, ++ int (*exec_up) (void *), void *target); ++void ospf6_damp_event_down (u_short type, struct prefix *name, ++ int (*exec_down) (void *), void *target); ++ ++void ospf6_damp_config_write (struct vty *); ++void ospf6_damp_init (); ++ +diff -x CVS -urN ospf6d.old/ospf6_dbex.c ospf6d/ospf6_dbex.c +--- ospf6d.old/ospf6_dbex.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_dbex.c Sat Nov 9 11:25:30 2002 +@@ -230,12 +230,11 @@ + 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); + +- if (IS_OSPF6_DUMP_DBEX) +- zlog_info ("Receive %s from %s", received->str, from->str); +- + /* set LSA scope */ + if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (htons (lsa_header->type))) + received->scope = from->ospf6_interface; +@@ -248,27 +247,24 @@ + cksum = ntohs (lsa_header->checksum); + if (ntohs (ospf6_lsa_checksum (lsa_header)) != cksum) + { +- zlog_warn ("DBEX: LSA cksum wrong: %s checksum %#hx should be %#hx", +- received->str, cksum, ntohs (ospf6_lsa_checksum (lsa_header))); ++ 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; + } + +-#if 0 +- /* (2) warn if unknown */ +- if (! ospf6_lsa_is_known_type (lsa_header)) +- zlog_warn ("[%s:%s] receive LSA unknown: %#x", +- from->str, from->ospf6_interface->interface->name, +- ntohs (lsa_header->type)); +-#endif /*0*/ +- + /* (3) Ebit Missmatch: AS-External-LSA */ + if (lsa_header->type == htons (OSPF6_LSA_TYPE_AS_EXTERNAL) && + ospf6_area_is_stub (from->ospf6_interface->area)) + { +- zlog_err ("DBEX: [%s:%s] receive LSA E-bit mismatch: %s", +- from->str, from->ospf6_interface->interface->name, +- received->str); ++ 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; + } +@@ -279,8 +275,10 @@ + { + /* log */ + if (IS_OSPF6_DUMP_DBEX) +- zlog_info ("Drop MaxAge LSA: no instance, no neighbor " +- "exchanging DB: %s", received->str); ++ 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 */ +@@ -312,18 +310,29 @@ + + /* (a) MinLSArrival check */ + gettimeofday (&now, (struct timezone *)NULL); +- if (have && now.tv_sec - have->installed.tv_sec <= OSPF6_MIN_LS_ARRIVAL) ++ if (have && SEC_TVDIFF (&now, &have->installed) < OSPF6_MIN_LS_ARRIVAL) + { +- if (IS_OSPF6_DUMP_DBEX) +- zlog_info ("DBEX: [%s:%s] received LSA too soon: %s", +- from->str, from->ospf6_interface->interface->name, +- received->str); ++ //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); + +@@ -344,18 +353,20 @@ + 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: [%s:%s] don't ack %s", +- from->str, from->ospf6_interface->interface->name, +- received->str); ++ zlog_info ("DBEX: No Ack to %s", from->str); + } + + /* (f) */ +@@ -413,6 +424,9 @@ + 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); + } +@@ -421,18 +435,20 @@ + 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: [%s:%s] will no ack %s", +- from->str, from->ospf6_interface->interface->name, +- received->str); ++ zlog_info ("DBEX: No Ack to %s", from->str); + } + ospf6_lsa_delete (received); + } +@@ -443,6 +459,9 @@ + 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); +@@ -455,83 +474,52 @@ + struct ospf6_neighbor *from) + { + struct ospf6_interface *ospf6_interface; +- struct ospf6_neighbor *nbr; +- listnode n, m; ++ 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; + } +- else if (ismore_recent < 0 && +- ! CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_FLOODBACK)) +- { +- if (ospf6_interface->state == IFS_BDR) +- { +- if (ospf6_interface->dr == from->router_id) +- { +- return DELAYED_ACK; +- } +- else +- { +- return NO_ACK; +- } +- } +- else +- { +- return DELAYED_ACK; +- } +- } +- else if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_DUPLICATE) && +- CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_IMPLIEDACK)) +- { +- if (ospf6_interface->state == IFS_BDR) +- { +- if (ospf6_interface->dr == from->router_id) +- { +- return DELAYED_ACK; +- } +- else +- { +- return NO_ACK; +- } +- } +- else +- { +- return NO_ACK; +- } +- } +- else if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_DUPLICATE) && +- ! CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_IMPLIEDACK)) +- { +- return DIRECT_ACK; +- } +- else if (IS_LSA_MAXAGE (newp)) ++ ++ if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_DUPLICATE) && ++ CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_IMPLIEDACK)) + { +- if (! ospf6_lsdb_lookup (newp->header->type, newp->header->id, +- newp->header->adv_router, +- ospf6_lsa_get_scope (newp->header->type, +- from->ospf6_interface))) +- { +- for (n = listhead (from->ospf6_interface->area->if_list); +- n; nextnode (n)) +- { +- ospf6_interface = (struct ospf6_interface *) getdata (n); +- for (m = listhead (ospf6_interface->neighbor_list); +- m; nextnode (m)) +- { +- nbr = (struct ospf6_neighbor *) getdata (m); +- if (nbr->state == NBS_EXCHANGE || nbr->state == NBS_LOADING) +- { +- return NO_ACK; +- } +- } +- } +- return DIRECT_ACK; +- } ++ 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; + } +@@ -600,11 +588,13 @@ + + /* (2) */ + if (addretrans == 0) ++ return; /* examin next interface */ ++ ++ if (from && from->ospf6_interface == o6i) + { +- return; /* examin next interface */ +- } +- else 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); + } +@@ -624,7 +614,7 @@ + return; /* examin next interface */ + + if (IS_OSPF6_DUMP_DBEX) +- zlog_info (" Flood to interface %s", o6i->interface->name); ++ zlog_info ("Flood to interface %s", o6i->interface->name); + + /* (5) send LinkState Update */ + ospf6_send_lsupdate_flood (lsa, o6i); +@@ -678,14 +668,13 @@ + + lsa_header = (struct ospf6_lsa_header *) lsa->lsa_hdr; + +- if (IS_OSPF6_DUMP_DBEX) +- zlog_info ("Flood: %s", lsa->str); +- + 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))) +@@ -693,6 +682,8 @@ + 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))) +@@ -700,6 +691,8 @@ + o6 = (struct ospf6 *) lsa->scope; + assert (o6); + ++ if (IS_OSPF6_DUMP_DBEX) ++ zlog_info ("Flood AS"); + ospf6_dbex_flood_as (lsa, o6, from); + } + else +diff -x CVS -urN ospf6d.old/ospf6_interface.c ospf6d/ospf6_interface.c +--- ospf6d.old/ospf6_interface.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_interface.c Sat Nov 9 13:26:03 2002 +@@ -126,6 +126,9 @@ + + CALL_ADD_HOOK (&interface_hook, o6i); + ++ /* Get the interface's link-local if any */ ++ ospf6_interface_address_update(ifp); ++ + return o6i; + } + +diff -x CVS -urN ospf6d.old/ospf6_lsa.c ospf6d/ospf6_lsa.c +--- ospf6d.old/ospf6_lsa.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_lsa.c Sat Nov 9 11:25:30 2002 +@@ -51,7 +51,6 @@ + #include "ospf6_area.h" + #include "ospf6_interface.h" + #include "ospf6_neighbor.h" +-#include "ospf6_redistribute.h" + #include "ospf6_ism.h" + #include "ospf6_nsm.h" + #include "ospf6_dbex.h" +@@ -142,8 +141,11 @@ + + lsa->birth.tv_sec = now.tv_sec - ntohs (lsa->header->age); + lsa->birth.tv_usec = now.tv_usec; +- lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa, +- lsa->birth.tv_sec + MAXAGE - now.tv_sec); ++ if (ntohs (lsa->header->age) != MAXAGE) ++ lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa, ++ lsa->birth.tv_sec + MAXAGE - now.tv_sec); ++ else ++ lsa->expire = NULL; + return; + } + +@@ -692,38 +694,6 @@ + ospf6_lsa_delete (lsa); + } + +-/* check necessity to update LSA: +- returns 1 if it's necessary to reoriginate */ +-static int +-ospf6_lsa_is_really_reoriginate (struct ospf6_lsa *new) +-{ +- struct ospf6_lsa *old; +- int diff; +- +- /* find previous LSA */ +- old = ospf6_lsdb_lookup (new->header->type, new->header->id, +- new->header->adv_router, new->scope); +- if (! old) +- return 1; +- +- /* Check if this is refresh */ +- if (CHECK_FLAG (old->flag, OSPF6_LSA_FLAG_REFRESH)) +- { +- zlog_warn ("LSA: reoriginate: %s: Refresh", new->str); +- return 1; +- } +- +- /* Are these contents different ? */ +- diff = ospf6_lsa_differ (new, old); +- +- if (diff) +- return 1; +- +- if (IS_OSPF6_DUMP_LSA) +- zlog_info ("LSA: Suppress updating %s", new->str); +- return 0; +-} +- + void + ospf6_lsa_originate (u_int16_t type, u_int32_t id, u_int32_t adv_router, + char *data, int data_len, void *scope) +@@ -731,6 +701,7 @@ + char buffer[MAXLSASIZE]; + struct ospf6_lsa_header *lsa_header; + struct ospf6_lsa *lsa; ++ struct ospf6_lsa *old; + + assert (data_len <= sizeof (buffer) - sizeof (struct ospf6_lsa_header)); + +@@ -754,18 +725,37 @@ + + /* create LSA */ + lsa = ospf6_lsa_create ((struct ospf6_lsa_header *) buffer); +- lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa, +- OSPF6_LS_REFRESH_TIME); + lsa->scope = scope; + +- if (ospf6_lsa_is_really_reoriginate (lsa)) +- { +- ospf6_dbex_remove_from_all_retrans_list (lsa); +- ospf6_dbex_flood (lsa, NULL); +- ospf6_lsdb_install (lsa); ++ /* find previous LSA */ ++ old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, ++ lsa->header->adv_router, lsa->scope); ++ if (old) ++ { ++ /* Check if this is neither different instance nor refresh, return */ ++ if (! CHECK_FLAG (old->flag, OSPF6_LSA_FLAG_REFRESH) && ++ ! ospf6_lsa_differ (lsa, old)) ++ { ++ if (IS_OSPF6_DUMP_LSA) ++ zlog_info ("LSA: Suppress updating %s", lsa->str); ++ ospf6_lsa_delete (lsa); ++ return; ++ } + } +- else +- ospf6_lsa_delete (lsa); ++ ++ lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa, ++ OSPF6_LS_REFRESH_TIME); ++ gettimeofday (&lsa->originated, NULL); ++ ++ //if (IS_OSPF6_DUMP_LSA) ++ zlog_info ("LSA: originate %s seq: %#x age: %hu %ld.%06ld", ++ lsa->str, ntohl (lsa->header->seqnum), ++ ospf6_lsa_age_current (lsa), ++ lsa->originated.tv_sec, lsa->originated.tv_usec); ++ ++ ospf6_dbex_remove_from_all_retrans_list (lsa); ++ ospf6_dbex_flood (lsa, NULL); ++ ospf6_lsdb_install (lsa); + } + + +@@ -1130,14 +1120,32 @@ + return 0; + } + +-void +-ospf6_lsa_router_update (u_int32_t area_id) ++u_long ++ospf6_lsa_has_elasped (u_int16_t type, u_int32_t id, ++ u_int32_t adv_router, void *scope) ++{ ++ struct ospf6_lsa *old; ++ struct timeval now; ++ ++ if (adv_router != ospf6->router_id) ++ zlog_info ("LSA: Router-ID changed ?"); ++ ++ old = ospf6_lsdb_lookup (type, id, adv_router, scope); ++ if (! old) ++ return OSPF6_LSA_MAXAGE; ++ ++ gettimeofday (&now, NULL); ++ return ((u_long) SEC_TVDIFF (&now, &old->originated)); ++} ++ ++int ++ospf6_lsa_originate_router (struct thread *thread) + { + char buffer [MAXLSASIZE]; + u_int16_t size; +- struct ospf6_lsa *old; + struct ospf6_area *o6a; + int count; ++ u_int32_t area_id; + + struct ospf6_router_lsa *router_lsa; + struct ospf6_router_lsd *router_lsd; +@@ -1145,22 +1153,22 @@ + struct ospf6_interface *o6i; + struct ospf6_neighbor *o6n = NULL; + ++ area_id = (u_int32_t) THREAD_ARG (thread); ++ + o6a = ospf6_area_lookup (area_id, ospf6); + if (! o6a) + { + inet_ntop (AF_INET, &area_id, buffer, sizeof (buffer)); + if (IS_OSPF6_DUMP_LSA) +- zlog_warn ("Update Router-LSA: No such area: %s", buffer); +- return; ++ zlog_info ("LSA: Update Router-LSA: No such area: %s", buffer); ++ return 0; + } + +- if (IS_OSPF6_DUMP_LSA) +- zlog_info ("Update Router-LSA: for Area %s", o6a->str); ++ /* clear thread */ ++ o6a->thread_router_lsa = NULL; + +- /* find previous LSA */ +- /* xxx, there may be multiple Router-LSAs */ +- old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_ROUTER), +- htonl (0), o6a->ospf6->router_id, o6a); ++ if (IS_OSPF6_DUMP_LSA) ++ zlog_info ("LSA: originate Router-LSA for Area %s", o6a->str); + + size = sizeof (struct ospf6_router_lsa); + memset (buffer, 0, sizeof (buffer)); +@@ -1277,6 +1285,42 @@ + ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_ROUTER), + htonl (0), o6a->ospf6->router_id, + (char *) router_lsa, size, o6a); ++ return 0; ++} ++ ++void ++ospf6_lsa_schedule_router (struct ospf6_area *area) ++{ ++ u_long elasped_time, time = 0; ++ ++ if (area->thread_router_lsa) ++ { ++ if (IS_OSPF6_DUMP_LSA) ++ zlog_info ("LSA: schedule: Router-LSA for Area %s: another thread", ++ area->str); ++ return; ++ } ++ ++ elasped_time = ++ ospf6_lsa_has_elasped (htons (OSPF6_LSA_TYPE_ROUTER), htonl (0), ++ area->ospf6->router_id, area); ++ if (elasped_time < OSPF6_MIN_LS_INTERVAL) ++ time = (u_long) (OSPF6_MIN_LS_INTERVAL - elasped_time); ++ else ++ time = 0; ++ ++ if (IS_OSPF6_DUMP_LSA) ++ zlog_info ("LSA: schedule: Router-LSA for Area %s after %lu sec", ++ area->str, time); ++ ++ if (time) ++ area->thread_router_lsa = ++ thread_add_timer (master, ospf6_lsa_originate_router, ++ (void *) area->area_id, time); ++ else ++ area->thread_router_lsa = ++ thread_add_event (master, ospf6_lsa_originate_router, ++ (void *) area->area_id, 0); + } + + int +@@ -1284,7 +1328,7 @@ + { + struct ospf6_neighbor *o6n = neighbor; + if (o6n->ospf6_interface->area) +- ospf6_lsa_router_update (o6n->ospf6_interface->area->area_id); ++ ospf6_lsa_schedule_router (o6n->ospf6_interface->area); + return 0; + } + +@@ -1293,7 +1337,7 @@ + { + struct ospf6_interface *o6i = interface; + if (o6i->area) +- ospf6_lsa_router_update (o6i->area->area_id); ++ ospf6_lsa_schedule_router (o6i->area); + return 0; + } + +@@ -1301,7 +1345,7 @@ + ospf6_lsa_router_hook_area (void *area) + { + struct ospf6_area *o6a = area; +- ospf6_lsa_router_update (o6a->area_id); ++ ospf6_lsa_schedule_router (o6a); + return 0; + } + +@@ -1315,7 +1359,7 @@ + for (node = listhead (o6->area_list); node; nextnode (node)) + { + o6a = getdata (node); +- ospf6_lsa_router_update (o6a->area_id); ++ ospf6_lsa_schedule_router (o6a); + } + return 0; + } +@@ -1327,7 +1371,7 @@ + struct ospf6_area *o6a; + + o6a = lsa->scope; +- ospf6_lsa_router_update (o6a->area_id); ++ ospf6_lsa_schedule_router (o6a); + return 0; + } + +diff -x CVS -urN ospf6d.old/ospf6_lsa.h ospf6d/ospf6_lsa.h +--- ospf6d.old/ospf6_lsa.h Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_lsa.h Sat Nov 9 11:25:30 2002 +@@ -25,6 +25,13 @@ + + #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) ++ + /* LSA definition */ + + #define MAXLSASIZE 1024 +@@ -211,6 +218,7 @@ + unsigned char flag; /* to decide ack type and refresh */ + struct timeval birth; /* tv_sec when LS age 0 */ + struct timeval installed; /* installed time */ ++ struct timeval originated; /* installed time */ + struct thread *expire; + struct thread *refresh; /* For self-originated LSA */ + u_int32_t from; /* from which neighbor */ +@@ -397,22 +405,22 @@ + + u_short ospf6_lsa_checksum (struct ospf6_lsa_header *); + +-void ospf6_lsa_update_router (u_int32_t area_id); + 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_reoriginate (struct ospf6_lsa *); +-void +-ospf6_lsa_originate (u_int16_t, u_int32_t, u_int32_t, char *, int, void *); +- + 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 *); + + #endif /* OSPF6_LSA_H */ + +diff -x CVS -urN ospf6d.old/ospf6_message.c ospf6d/ospf6_message.c +--- ospf6d.old/ospf6_message.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_message.c Sat Nov 9 11:25:30 2002 +@@ -1108,14 +1108,14 @@ + if (!o6n) + { + if (IS_OSPF6_DUMP_LSACK) +- zlog_info (" neighbor not found, reject"); ++ zlog_info ("LSACK: neighbor not found, reject"); + return; + } + + if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr))) + { +- if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) +- zlog_info ("From Secondary I/F of the neighbor: ignore"); ++ if (IS_OSPF6_DUMP_LSACK) ++ zlog_info ("LSACK: From Secondary I/F of the neighbor: ignore"); + return; + } + +@@ -1123,7 +1123,7 @@ + if (o6n->state < NBS_EXCHANGE) + { + if (IS_OSPF6_DUMP_LSACK) +- zlog_info (" neighbor state less than Exchange, reject"); ++ zlog_info ("LSACK: neighbor state less than Exchange, reject"); + return; + } + +@@ -1141,7 +1141,7 @@ + if (!copy) + { + if (IS_OSPF6_DUMP_LSACK) +- zlog_info ("no database copy, ignore"); ++ zlog_info ("LSACK: no database copy, ignore"); + continue; + } + +@@ -1152,7 +1152,7 @@ + if (rem == NULL) + { + if (IS_OSPF6_DUMP_LSACK) +- zlog_info ("not on %s's retranslist, ignore", o6n->str); ++ zlog_info ("LSACK: not on %s's retranslist, ignore", o6n->str); + continue; + } + +@@ -1167,7 +1167,13 @@ + { + /* Log the questionable acknowledgement, + and examine the next one. */ +- zlog_warn ("LSAck: questionable acknowledge: LSAs differ"); ++ zlog_info ("LSACK: questionable acknowledge: %s", copy->str); ++ zlog_info ("LSACK: received: seq: %#x age: %hu", ++ ntohl (lsa->header->seqnum), ++ ntohs (lsa->header->age)); ++ zlog_info ("LSACK: instance: seq: %#x age: %hu", ++ ntohl (copy->header->seqnum), ++ ospf6_lsa_age_current (copy)); + } + + /* release temporary LSA from Ack message */ +@@ -1242,6 +1248,22 @@ + return; + } + ++ /* message type check */ ++ type = (ospf6_header->type >= OSPF6_MESSAGE_TYPE_MAX ? ++ OSPF6_MESSAGE_TYPE_UNKNOWN : ospf6_header->type); ++ ++ /* log */ ++ if (IS_OSPF6_DUMP_MESSAGE (type)) ++ { ++ char srcname[64], dstname[64]; ++ inet_ntop (AF_INET6, dst, dstname, sizeof (dstname)); ++ inet_ntop (AF_INET6, src, srcname, sizeof (srcname)); ++ zlog_info ("Receive %s on %s", ++ ospf6_message_type_string[type], o6i->interface->name); ++ zlog_info (" %s -> %s", srcname, dstname); ++ ospf6_message_log (message); ++ } ++ + /* router id check */ + router_id = ospf6_header->router_id; + if (ospf6_header->router_id == o6i->area->ospf6->router_id) +@@ -1252,10 +1274,6 @@ + return; + } + +- /* message type check */ +- type = (ospf6_header->type >= OSPF6_MESSAGE_TYPE_MAX ? +- OSPF6_MESSAGE_TYPE_UNKNOWN : ospf6_header->type); +- + /* octet statistics relies on some asumption: + on ethernet, no IPv6 Extention header, etc */ + #define OSPF6_IP6_HEADER_SIZE 40 +@@ -1280,12 +1298,14 @@ + struct ospf6_header ospf6_header; + char buffer[OSPF6_MESSAGE_RECEIVE_BUFSIZE]; + struct ospf6_interface *o6i; +- char srcname[64], dstname[64]; + unsigned char type; + + /* get socket */ + sockfd = THREAD_FD (thread); + ++ /* add next read thread */ ++ thread_add_read (master, ospf6_receive, NULL, sockfd); ++ + /* initialize */ + OSPF6_MESSAGE_CLEAR (message); + memset (&ospf6_header, 0, sizeof (struct ospf6_header)); +@@ -1302,22 +1322,10 @@ + o6i = ospf6_interface_lookup_by_index (ifindex); + if (!o6i || !o6i->area) + { +- zlog_warn ("*** received interface ospf6 disabled"); +- thread_add_read (master, ospf6_receive, NULL, sockfd); ++ //zlog_warn ("*** received interface ospf6 disabled"); + return 0; + } + +- /* log */ +- if (IS_OSPF6_DUMP_MESSAGE (type)) +- { +- inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname)); +- inet_ntop (AF_INET6, &src, srcname, sizeof (srcname)); +- zlog_info ("Receive %s on %s", +- ospf6_message_type_string[type], o6i->interface->name); +- zlog_info (" %s -> %s", srcname, dstname); +- ospf6_message_log (message); +- } +- + /* if not passive, process message */ + if (! CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE)) + ospf6_message_process (message, &src, &dst, o6i); +@@ -1325,9 +1333,6 @@ + zlog_info ("Ignore message on passive interface %s", + o6i->interface->name); + +- /* add next read thread */ +- thread_add_read (master, ospf6_receive, NULL, sockfd); +- + return 0; + } + +@@ -1828,6 +1833,9 @@ + return 0; + lsupdate.lsupdate_num = htonl (lsupdate.lsupdate_num); + ++ if (IS_OSPF6_DUMP_LSUPDATE) ++ zlog_info ("MESSAGE: retrsnsmit LSUpdate to %s", o6n->str); ++ + /* statistics */ + o6n->ospf6_stat_retrans_lsupdate++; + +@@ -1915,6 +1923,9 @@ + + o6i = THREAD_ARG (thread); + assert (o6i); ++ ++ if (IS_OSPF6_DUMP_LSACK) ++ zlog_info ("LSACK: Delayed LSAck for %s\n", o6i->interface->name); + + o6i->thread_send_lsack_delayed = (struct thread *) NULL; + +diff -x CVS -urN ospf6d.old/ospf6_neighbor.c ospf6d/ospf6_neighbor.c +--- ospf6d.old/ospf6_neighbor.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_neighbor.c Sat Nov 9 11:25:30 2002 +@@ -179,6 +179,13 @@ + } + + ospf6_lsdb_remove (lsa, nei->retrans_list); ++ ++ if (nei->retrans_list->count == 0) ++ { ++ if (nei->send_update) ++ thread_cancel (nei->send_update); ++ nei->send_update = NULL; ++ } + } + + void +diff -x CVS -urN ospf6d.old/ospf6_network.c ospf6d/ospf6_network.c +--- ospf6d.old/ospf6_network.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_network.c Tue Oct 1 10:28:08 2002 +@@ -255,8 +255,10 @@ + &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 +@@ -273,8 +275,10 @@ + &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 +@@ -290,8 +294,10 @@ + if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, + &mreq6, sizeof (mreq6)) < 0) + zlog_warn ("Network: Leave AllDRouters on ifindex %d Failed", ifindex); ++#if 0 + else + zlog_info ("Network: Leave AllDRouters on ifindex %d", ifindex); ++#endif + } + + /* setsockopt ReUseAddr to on */ +diff -x CVS -urN ospf6d.old/ospf6_route.h ospf6d/ospf6_route.h +--- ospf6d.old/ospf6_route.h Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_route.h Tue Oct 1 00:41:10 2002 +@@ -186,6 +186,9 @@ + 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 *), +diff -x CVS -urN ospf6d.old/ospf6_routemap.c ospf6d/ospf6_routemap.c +--- ospf6d.old/ospf6_routemap.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_routemap.c Tue Oct 1 00:41:10 2002 +@@ -22,9 +22,6 @@ + + #include <zebra.h> + +-#if 1 +-#include "ospf6d.h" +-#else + #include "log.h" + #include "memory.h" + #include "linklist.h" +@@ -32,11 +29,13 @@ + #include "command.h" + #include "vty.h" + #include "routemap.h" ++#include "table.h" + #include "plist.h" + +-#include "ospf6_top.h" +-#include "ospf6_redistribute.h" +-#endif ++#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, +@@ -70,7 +69,8 @@ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + } + +-struct route_map_rule_cmd ospf6_routemap_rule_match_address_prefixlist_cmd = ++struct route_map_rule_cmd ++ospf6_routemap_rule_match_address_prefixlist_cmd = + { + "ipv6 address prefix-list", + ospf6_routemap_rule_match_address_prefixlist, +@@ -83,15 +83,15 @@ + route_map_object_t type, void *object) + { + char *metric_type = rule; +- struct ospf6_route_req *route = object; ++ struct ospf6_external_info *info = object; + + if (type != RMAP_OSPF6) + return RMAP_OKAY; + + if (strcmp (metric_type, "type-2") == 0) +- route->path.metric_type = 2; ++ info->metric_type = 2; + else +- route->path.metric_type = 1; ++ info->metric_type = 1; + + return RMAP_OKAY; + } +@@ -108,7 +108,8 @@ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + } + +-struct route_map_rule_cmd ospf6_routemap_rule_set_metric_type_cmd = ++struct route_map_rule_cmd ++ospf6_routemap_rule_set_metric_type_cmd = + { + "metric-type", + ospf6_routemap_rule_set_metric_type, +@@ -121,14 +122,12 @@ + route_map_object_t type, void *object) + { + char *metric = rule; +- struct ospf6_route_req *route = object; ++ struct ospf6_external_info *info = object; + + if (type != RMAP_OSPF6) + return RMAP_OKAY; + +- route->path.cost = atoi (metric); +- route->path.cost_e2 = atoi (metric); +- ++ info->metric = atoi (metric); + return RMAP_OKAY; + } + +@@ -144,7 +143,8 @@ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + } + +-struct route_map_rule_cmd ospf6_routemap_rule_set_metric_cmd = ++struct route_map_rule_cmd ++ospf6_routemap_rule_set_metric_cmd = + { + "metric", + ospf6_routemap_rule_set_metric, +@@ -157,14 +157,14 @@ + route_map_object_t type, void *object) + { + char *forwarding = rule; +- struct ospf6_route_req *route = object; ++ struct ospf6_external_info *info = object; + + if (type != RMAP_OSPF6) + return RMAP_OKAY; + +- if (inet_pton (AF_INET6, forwarding, &route->nexthop.address) != 1) ++ if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1) + { +- memset (&route->nexthop.address, 0, sizeof (struct in6_addr)); ++ memset (&info->forwarding, 0, sizeof (struct in6_addr)); + return RMAP_ERROR; + } + +@@ -183,7 +183,8 @@ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + } + +-struct route_map_rule_cmd ospf6_routemap_rule_set_forwarding_cmd = ++struct route_map_rule_cmd ++ospf6_routemap_rule_set_forwarding_cmd = + { + "forwarding-address", + ospf6_routemap_rule_set_forwarding, +@@ -331,8 +332,8 @@ + { + route_map_init (); + route_map_init_vty (); +- route_map_add_hook (ospf6_redistribute_routemap_update); +- route_map_delete_hook (ospf6_redistribute_routemap_update); ++ 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); +diff -x CVS -urN ospf6d.old/ospf6_spf.c ospf6d/ospf6_spf.c +--- ospf6d.old/ospf6_spf.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_spf.c Sat Nov 9 11:25:30 2002 +@@ -281,7 +281,7 @@ + static struct in6_addr * + ospf6_spf_get_ipaddr (u_int32_t id, u_int32_t adv_router, u_int32_t ifindex) + { +- char buf[64]; ++ char buf[64], nhbuf[64]; + struct ospf6_interface *o6i; + struct ospf6_neighbor *o6n; + struct ospf6_lsa *lsa; +@@ -303,26 +303,30 @@ + lsa = node.lsa; + + /* return Linklocal Address field if the Link-LSA exists */ +- if (lsa) ++ if (lsa && lsa->header->adv_router == adv_router) + { + struct ospf6_link_lsa *link_lsa; + link_lsa = (struct ospf6_link_lsa *) (lsa->header + 1); + return &link_lsa->llsa_linklocal; + } + +- zlog_warn ("SPF: Can't find Link-LSA for %s, " +- "use source address from his packet", ++ zlog_warn ("SPF: Can't find Link-LSA for %s", + inet_ntop (AF_INET, &adv_router, buf, sizeof (buf))); + + o6n = ospf6_neighbor_lookup (adv_router, o6i); + if (! o6n) + { + inet_ntop (AF_INET, &adv_router, buf, sizeof (buf)); +- zlog_err ("SPF: Can't find neighbor %s in %s", ++ zlog_err ("SPF: Can't find neighbor %s in %s, " ++ "unable to find his linklocal address", + buf, o6i->interface->name); + return (struct in6_addr *) NULL; + } + ++ zlog_warn ("SPF: use packet's source address for %s's nexthop: %s", ++ inet_ntop (AF_INET, &adv_router, buf, sizeof (buf)), ++ inet_ntop (AF_INET6, &o6n->hisaddr, nhbuf, sizeof (nhbuf))); ++ + return &o6n->hisaddr; + } + +@@ -478,18 +482,22 @@ + inet_ntop (AF_INET, &adv_router, buf_router, sizeof (buf_router)); + inet_ntop (AF_INET, &id, buf_id, sizeof (buf_id)); + +- if (type == htons (OSPF6_LSA_TYPE_ROUTER)) +- zlog_err ("SPF: Can't find LSA for W (%s *): not found", +- buf_router); +- else +- zlog_err ("SPF: Can't find LSA for W (%s %s): not found", +- buf_router, buf_id); ++ if (IS_OSPF6_DUMP_SPF) ++ { ++ if (type == htons (OSPF6_LSA_TYPE_ROUTER)) ++ zlog_info ("SPF: Can't find LSA for W (%s *): not found", ++ buf_router); ++ else ++ zlog_info ("SPF: Can't find LSA for W (%s %s): not found", ++ buf_router, buf_id); ++ } + return (struct ospf6_vertex *) NULL; + } + + if (IS_LSA_MAXAGE (lsa)) + { +- zlog_err ("SPF: Associated LSA for W is MaxAge: %s", lsa->str); ++ if (IS_OSPF6_DUMP_SPF) ++ zlog_info ("SPF: Associated LSA for W is MaxAge: %s", lsa->str); + return (struct ospf6_vertex *) NULL; + } + +@@ -504,8 +512,9 @@ + } + if (! backreference) + { +- zlog_err ("SPF: Back reference failed: V: %s, W: %s", +- V->lsa->str, lsa->str); ++ if (IS_OSPF6_DUMP_SPF) ++ zlog_info ("SPF: Back reference failed: V: %s, W: %s", ++ V->lsa->str, lsa->str); + return (struct ospf6_vertex *) NULL; + } + +diff -x CVS -urN ospf6d.old/ospf6_top.c ospf6d/ospf6_top.c +--- ospf6d.old/ospf6_top.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_top.c Tue Oct 1 00:51:40 2002 +@@ -43,7 +43,6 @@ + #include "ospf6_area.h" + #include "ospf6_top.h" + +-#include "ospf6_redistribute.h" + #include "ospf6_route.h" + #include "ospf6_zebra.h" + +@@ -152,7 +151,7 @@ + vty_out (vty, " Supports only single TOS(TOS0) routes%s", VTY_NEWLINE); + + /* Redistribute config */ +- ospf6_redistribute_show_config (vty, ospf6); ++ ospf6_redistribute_show_config (vty); + + /* LSAs */ + vty_out (vty, " Number of AS scoped LSAs is %u%s", +@@ -250,9 +249,6 @@ + + o6->lsdb = ospf6_lsdb_create (); + +- /* route table init */ +- ospf6_redistribute_init (o6); +- + o6->foreach_area = ospf6_top_foreach_area; + o6->foreach_if = ospf6_top_foreach_interface; + o6->foreach_nei = ospf6_top_foreach_neighbor; +@@ -264,12 +260,14 @@ + ospf6_top_topology_remove, + o6->topology_table); + ++#if 0 + snprintf (namebuf, sizeof (namebuf), "External table"); + o6->external_table = ospf6_route_table_create (namebuf); + ospf6_route_hook_register (ospf6_asbr_external_route_add, + ospf6_asbr_external_route_add, + ospf6_asbr_external_route_remove, + o6->external_table); ++#endif /*0*/ + + snprintf (namebuf, sizeof (namebuf), "Top route table"); + o6->route_table = ospf6_route_table_create (namebuf); +diff -x CVS -urN ospf6d.old/ospf6_zebra.c ospf6d/ospf6_zebra.c +--- ospf6d.old/ospf6_zebra.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_zebra.c Wed Oct 2 17:16:56 2002 +@@ -22,7 +22,7 @@ + #include "ospf6d.h" + + #include "ospf6_interface.h" +-#include "ospf6_redistribute.h" ++#include "ospf6_asbr.h" + + #include "ospf6_linklist.h" + +@@ -202,13 +202,14 @@ + struct stream *s; + struct zapi_ipv6 api; + unsigned long ifindex; +- struct in6_addr nexthop; + struct prefix_ipv6 p; ++ struct in6_addr *nexthop; + char prefixstr[128], nexthopstr[128]; + + s = zclient->ibuf; + ifindex = 0; +- memset (&nexthop, 0, sizeof (struct in6_addr)); ++ nexthop = NULL; ++ memset (&api, 0, sizeof (api)); + + /* Type, flags, message. */ + api.type = stream_getc (s); +@@ -225,7 +226,9 @@ + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) + { + api.nexthop_num = stream_getc (s); +- stream_get (&nexthop, s, 16); ++ nexthop = (struct in6_addr *) ++ malloc (api.nexthop_num * sizeof (struct in6_addr)); ++ stream_get (nexthop, s, api.nexthop_num * sizeof (struct in6_addr)); + } + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) + { +@@ -256,11 +259,15 @@ + zebra_route_name [api.type], prefixstr, + nexthopstr, ifindex); + } +- ++ + if (command == ZEBRA_IPV6_ROUTE_ADD) +- ospf6_redistribute_route_add (api.type, ifindex, &p); ++ ospf6_asbr_route_add (api.type, ifindex, (struct prefix *) &p, ++ api.nexthop_num, nexthop); + else +- ospf6_redistribute_route_remove (api.type, ifindex, &p); ++ ospf6_asbr_route_remove (api.type, ifindex, (struct prefix *) &p); ++ ++ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) ++ free (nexthop); + + return 0; + } +@@ -448,10 +455,6 @@ + + if (IS_OSPF6_DUMP_ZEBRA) + zlog_info ("ZEBRA: found alternative path to add"); +- +- linklist_remove (nexthop, nexthop_list); +- XFREE (MTYPE_OSPF6_OTHER, nexthop); +- assert (nexthop_list->count == 0); + + memcpy (&seconde_path, &route.path, sizeof (struct ospf6_path)); + type = ADD; +diff -x CVS -urN ospf6d.old/ospf6d.c ospf6d/ospf6d.c +--- ospf6d.old/ospf6d.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6d.c Mon Mar 24 17:45:16 2003 +@@ -21,6 +21,8 @@ + + #include "ospf6d.h" + ++#include "ospf6_damp.h" ++ + /* global ospf6d variable */ + int ospf6_sock; + list iflist; +@@ -536,8 +538,8 @@ + return CMD_SUCCESS; + } + +-DEFUN (area_range, +- area_range_cmd, ++DEFUN (ospf6_area_range, ++ ospf6_area_range_cmd, + "area A.B.C.D range X:X::X:X/M", + "OSPFv3 area parameters\n" + "OSPFv3 area ID in IPv4 address format\n" +@@ -689,6 +691,7 @@ + vty_out (vty, " router-id %s%s", buf, VTY_NEWLINE); + + ospf6_redistribute_config_write (vty); ++ ospf6_damp_config_write (vty); + + for (j = listhead (ospf6->area_list); j; nextnode (j)) + { +@@ -745,7 +748,7 @@ + install_element (OSPF6_NODE, &no_interface_area_cmd); + install_element (OSPF6_NODE, &passive_interface_cmd); + install_element (OSPF6_NODE, &no_passive_interface_cmd); +- install_element (OSPF6_NODE, &area_range_cmd); ++ install_element (OSPF6_NODE, &ospf6_area_range_cmd); + + /* Make empty list of top list. */ + if_init (); +@@ -757,6 +760,10 @@ + prefix_list_init (); + + ospf6_dump_init (); ++ ++#ifdef HAVE_OSPF6_DAMP ++ ospf6_damp_init (); ++#endif /*HAVE_OSPF6_DAMP*/ + + ospf6_hook_init (); + ospf6_lsa_init (); +diff -x CVS -urN ospf6d.old/ospf6d.h ospf6d/ospf6d.h +--- ospf6d.old/ospf6d.h Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6d.h Fri Apr 25 11:40:31 2003 +@@ -59,7 +59,6 @@ + #include "ospf6_neighbor.h" + #include "ospf6_ism.h" + #include "ospf6_nsm.h" +-#include "ospf6_redistribute.h" + #include "ospf6_route.h" + #include "ospf6_dbex.h" + #include "ospf6_network.h" +@@ -74,7 +73,7 @@ + #define HASHVAL 64 + #define MAXIOVLIST 1024 + +-#define OSPF6_DAEMON_VERSION "0.9.6l" ++#define OSPF6_DAEMON_VERSION "0.9.6p" + + #define AF_LINKSTATE 0xff + diff --git a/net/zebra-pj/pkg-plist b/net/zebra-pj/pkg-plist index 08c293d29b50..c8ec32930086 100644 --- a/net/zebra-pj/pkg-plist +++ b/net/zebra-pj/pkg-plist @@ -1,4 +1,5 @@ sbin/bgpd +sbin/ospf6d sbin/ospfd sbin/ripd sbin/ripngd @@ -7,6 +8,7 @@ sbin/zebractl bin/vtysh etc/zebra/bgpd.conf.sample etc/zebra/bgpd.conf.sample2 +etc/zebra/ospf6d.conf.sample etc/zebra/ospfd.conf.sample etc/zebra/ripd.conf.sample etc/zebra/ripngd.conf.sample diff --git a/net/zebra-pj/pkg-plist.v6 b/net/zebra-pj/pkg-plist.v6 deleted file mode 100644 index a8519a7a98c9..000000000000 --- a/net/zebra-pj/pkg-plist.v6 +++ /dev/null @@ -1,2 +0,0 @@ -sbin/ospf6d -etc/zebra/ospf6d.conf.sample diff --git a/net/zebra/Makefile b/net/zebra/Makefile index b5fc2c0e79bc..5751661f153e 100644 --- a/net/zebra/Makefile +++ b/net/zebra/Makefile @@ -7,7 +7,7 @@ PORTNAME= zebra PORTVERSION= 0.93b -PORTREVISION= 4 +PORTREVISION= 5 CATEGORIES= net ipv6 MASTER_SITES= ftp://ftp.zebra.org/pub/zebra/ \ ftp://ftp.ripe.net/mirrors/sites/ftp.zebra.org/pub/zebra/ \ @@ -40,16 +40,6 @@ post-clean: .endif .endif -.include <bsd.port.pre.mk> - -.if ${OSVERSION} >= 400014 -PLIST:= ${WRKDIR}/PLIST -pre-install: - @${CAT} ${PKGDIR}/pkg-plist.v6 ${PKGDIR}/pkg-plist > ${PLIST} -.else -CONFIGURE_ARGS+=--disable-ospf6d --disable-ripngd -.endif - post-install: @( cd ${WRKSRC}/doc; rm -f zebra*info*; ${MAKE} zebra.info install ) @${ECHO} "===> installing zebra startup file..." @@ -64,4 +54,4 @@ post-install: @${ECHO} "router_flags=\"start\"" @${ECHO} "done." -.include <bsd.port.post.mk> +.include <bsd.port.mk> diff --git a/net/zebra/files/patch-ospf6d b/net/zebra/files/patch-ospf6d new file mode 100644 index 000000000000..8dce08ba2c3e --- /dev/null +++ b/net/zebra/files/patch-ospf6d @@ -0,0 +1,3427 @@ +diff -x CVS -urN ospf6d.old/ChangeLog ospf6d/ChangeLog +--- ospf6d.old/ChangeLog Sat Apr 26 23:17:47 2003 ++++ ospf6d/ChangeLog Fri Apr 25 11:40:31 2003 +@@ -1,3 +1,36 @@ ++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 ++ ++2002-11-09 Vincent Jardin <jardin@6wind.com> ++ ++ * ospf6_interface.c: update link-local address on interface creation. ++ ++2002-11-09 Yasuhiro Ohara <yasu@sfc.wide.ad.jp> ++ ++ * ospf6_asbr.c: apply MinLSInterval to AS-External-LSA origination. ++ * ospf6_lsa.c: change not to issue flooding caused by expire event ++ when the received LSA is (already) MaxAge. ++ * ospf6_spf.c: fix a bug which is that ospf6d calculates ++ wrong nexthop when failed to find Link-LSA for the neighbor. ++ * ospf6_damp.c ospf6_dbex.c ospf6_neighbor.c ospf6_spf.c: ++ some clean up ++ * version: 0.9.6o ++ ++2002-10-04 Yasuhiro Ohara <yasu@sfc.wide.ad.jp> ++ ++ * ospf6_asbr.c: bug of failing ASE lsa refresh fixed. ++ * version: 0.9.6n ++ ++2002-10-01 Yasuhiro Ohara <yasu@sfc.wide.ad.jp> ++ ++ * ospf6_asbr.c: AS-External-LSA origination function ++ is re-written. ++ * ospf6_damp.[ch]: New feature that damps flaps is added. ++ * version: 0.9.6m ++ + 2002-07-14 Yasuhiro Ohara <yasu@sfc.wide.ad.jp> + + * ospf6_spf.c: unwanted assert() in ospf6_spf_nexthop_calculation() +diff -x CVS -urN ospf6d.old/Makefile.in ospf6d/Makefile.in +--- ospf6d.old/Makefile.in Sat Apr 26 23:17:47 2003 ++++ ospf6d/Makefile.in Thu Feb 20 01:31:12 2003 +@@ -1,4 +1,4 @@ +-# Makefile.in generated by automake 1.6.2 from Makefile.am. ++# Makefile.in generated by automake 1.6.3 from Makefile.am. + # @configure_input@ + + # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +@@ -111,9 +111,9 @@ + 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_redistribute.c ospf6_routemap.c ospf6_proto.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_abr.c ospf6_intra.c ospf6_damp.c + + + noinst_HEADERS = \ +@@ -121,9 +121,9 @@ + 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_redistribute.h ospf6_routemap.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_abr.h ospf6_intra.h ospf6_damp.h + + + ospf6d_SOURCES = \ +@@ -150,10 +150,10 @@ + ospf6_zebra.$(OBJEXT) ospf6_ism.$(OBJEXT) ospf6_dbex.$(OBJEXT) \ + ospf6_lsdb.$(OBJEXT) ospf6_prefix.$(OBJEXT) ospf6_top.$(OBJEXT) \ + ospf6_area.$(OBJEXT) ospf6_nsm.$(OBJEXT) \ +- ospf6_redistribute.$(OBJEXT) ospf6_routemap.$(OBJEXT) \ +- ospf6_proto.$(OBJEXT) ospf6_hook.$(OBJEXT) ospf6_asbr.$(OBJEXT) \ ++ ospf6_routemap.$(OBJEXT) ospf6_proto.$(OBJEXT) \ ++ ospf6_hook.$(OBJEXT) ospf6_asbr.$(OBJEXT) \ + ospf6_bintree.$(OBJEXT) ospf6_linklist.$(OBJEXT) \ +- ospf6_abr.$(OBJEXT) ospf6_intra.$(OBJEXT) ++ ospf6_abr.$(OBJEXT) ospf6_intra.$(OBJEXT) ospf6_damp.$(OBJEXT) + libospf6_a_OBJECTS = $(am_libospf6_a_OBJECTS) + sbin_PROGRAMS = ospf6d$(EXEEXT) + PROGRAMS = $(sbin_PROGRAMS) +@@ -165,10 +165,10 @@ + ospf6_zebra.$(OBJEXT) ospf6_ism.$(OBJEXT) ospf6_dbex.$(OBJEXT) \ + ospf6_lsdb.$(OBJEXT) ospf6_prefix.$(OBJEXT) ospf6_top.$(OBJEXT) \ + ospf6_area.$(OBJEXT) ospf6_nsm.$(OBJEXT) \ +- ospf6_redistribute.$(OBJEXT) ospf6_routemap.$(OBJEXT) \ +- ospf6_proto.$(OBJEXT) ospf6_hook.$(OBJEXT) ospf6_asbr.$(OBJEXT) \ ++ ospf6_routemap.$(OBJEXT) ospf6_proto.$(OBJEXT) \ ++ ospf6_hook.$(OBJEXT) ospf6_asbr.$(OBJEXT) \ + ospf6_bintree.$(OBJEXT) ospf6_linklist.$(OBJEXT) \ +- ospf6_abr.$(OBJEXT) ospf6_intra.$(OBJEXT) ++ ospf6_abr.$(OBJEXT) ospf6_intra.$(OBJEXT) ospf6_damp.$(OBJEXT) + am_ospf6d_OBJECTS = ospf6_main.$(OBJEXT) $(am__objects_1) + ospf6d_OBJECTS = $(am_ospf6d_OBJECTS) + ospf6d_DEPENDENCIES = ../lib/libzebra.a +@@ -182,8 +182,8 @@ + @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/ospf6_abr.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_area.Po ./$(DEPDIR)/ospf6_asbr.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_bintree.Po \ +-@AMDEP_TRUE@ ./$(DEPDIR)/ospf6_dbex.Po ./$(DEPDIR)/ospf6_dump.Po \ +-@AMDEP_TRUE@ ./$(DEPDIR)/ospf6_hook.Po \ ++@AMDEP_TRUE@ ./$(DEPDIR)/ospf6_damp.Po ./$(DEPDIR)/ospf6_dbex.Po \ ++@AMDEP_TRUE@ ./$(DEPDIR)/ospf6_dump.Po ./$(DEPDIR)/ospf6_hook.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_interface.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_intra.Po ./$(DEPDIR)/ospf6_ism.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_linklist.Po \ +@@ -195,7 +195,6 @@ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_nsm.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_prefix.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_proto.Po \ +-@AMDEP_TRUE@ ./$(DEPDIR)/ospf6_redistribute.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_route.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_routemap.Po \ + @AMDEP_TRUE@ ./$(DEPDIR)/ospf6_spf.Po ./$(DEPDIR)/ospf6_top.Po \ +@@ -218,7 +217,7 @@ + + .SUFFIXES: + .SUFFIXES: .c .o .obj +-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) ++$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign ospf6d/Makefile + Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status +@@ -238,8 +237,7 @@ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + ; then \ +- p1=`echo "$$p1" | sed -e 's,^.*/,,'`; \ +- f=`echo $$p1|sed '$(transform);s/$$/$(EXEEXT)/'`; \ ++ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f"; \ + $(INSTALL_PROGRAM_ENV) $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f; \ + else :; fi; \ +@@ -248,8 +246,7 @@ + uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ +- f=`echo $$p|sed 's/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ +- f=`echo "$$f" | sed -e 's,^.*/,,'`; \ ++ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \ + rm -f $(DESTDIR)$(sbindir)/$$f; \ + done +@@ -270,6 +267,7 @@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_area.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_asbr.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_bintree.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_damp.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_dbex.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_dump.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_hook.Po@am__quote@ +@@ -286,7 +284,6 @@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_nsm.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_prefix.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_proto.Po@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_redistribute.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_route.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_routemap.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_spf.Po@am__quote@ +diff -x CVS -urN ospf6d.old/ospf6_abr.c ospf6d/ospf6_abr.c +--- ospf6d.old/ospf6_abr.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_abr.c Tue Oct 1 10:28:07 2002 +@@ -42,7 +42,7 @@ + + inet_ntop (AF_INET, &router_id, router_string, sizeof (router_string)); + +- zlog_info ("ABR: Finding router %s in area %s", router_string, area->str); ++ //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; +diff -x CVS -urN ospf6d.old/ospf6_area.h ospf6d/ospf6_area.h +--- ospf6d.old/ospf6_area.h Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_area.h Sat Nov 9 11:25:30 2002 +@@ -62,6 +62,8 @@ + void (*func) (void *, int, void *)); + + struct thread *maxage_remover; ++ ++ struct thread *thread_router_lsa; + }; + + +diff -x CVS -urN ospf6d.old/ospf6_asbr.c ospf6d/ospf6_asbr.c +--- ospf6d.old/ospf6_asbr.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_asbr.c Fri Apr 25 11:40:31 2003 +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2001 Yasuhiro Ohara ++ * Copyright (C) 2001-2002 Yasuhiro Ohara + * + * This file is part of GNU Zebra. + * +@@ -19,108 +19,641 @@ + * Boston, MA 02111-1307, USA. + */ + +-#include "ospf6d.h" ++#include <zebra.h> ++ ++#include "log.h" ++#include "memory.h" ++#include "prefix.h" ++#include "command.h" ++#include "vty.h" ++#include "routemap.h" ++#include "table.h" ++#include "plist.h" ++#include "thread.h" ++ ++#include "ospf6_prefix.h" /* xxx for ospf6_asbr.h */ ++#include "ospf6_lsa.h" /* xxx for ospf6_asbr.h */ ++#include "ospf6_route.h" /* xxx for ospf6_asbr.h, ospf6_zebra.h */ ++#include "ospf6_zebra.h" ++#include "ospf6_asbr.h" ++#include "ospf6_damp.h" ++#include "ospf6_top.h" ++#include "ospf6_lsdb.h" ++#include "ospf6_proto.h" ++ ++extern struct thread_master *master; ++ ++struct route_table *external_table; ++struct ++{ ++ char *name; ++ struct route_map *map; ++} rmap [ZEBRA_ROUTE_MAX]; ++ ++static u_int32_t link_state_id = 0; ++ ++char * ++zroute_name[] = ++{ ++ "system", "kernel", "connected", "static", ++ "rip", "ripng", "ospf", "ospf6", "bgp", "unknown" ++}; ++char * ++zroute_abname[] = ++{ ++ "X", "K", "C", "S", "R", "R", "O", "O", "B", "?" ++}; ++ ++#define ZROUTE_NAME(x) \ ++ (0 < (x) && (x) < ZEBRA_ROUTE_MAX ? \ ++ zroute_name[(x)] : zroute_name[ZEBRA_ROUTE_MAX]) ++ ++#define ZROUTE_ABNAME(x) \ ++ (0 < (x) && (x) < ZEBRA_ROUTE_MAX ? \ ++ zroute_abname[(x)] : zroute_abname[ZEBRA_ROUTE_MAX]) ++ ++/* redistribute function */ ++void ++ospf6_asbr_routemap_set (int type, char *mapname) ++{ ++ if (rmap[type].name) ++ free (rmap[type].name); ++ ++ rmap[type].name = strdup (mapname); ++ rmap[type].map = route_map_lookup_by_name (mapname); ++} ++ ++void ++ospf6_asbr_routemap_unset (int type) ++{ ++ if (rmap[type].name) ++ free (rmap[type].name); ++ rmap[type].name = NULL; ++ rmap[type].map = NULL; ++} ++ ++void ++ospf6_asbr_routemap_update () ++{ ++ int i; ++ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) ++ { ++ if (rmap[i].name) ++ rmap[i].map = route_map_lookup_by_name (rmap[i].name); ++ else ++ rmap[i].map = NULL; ++ } ++} ++ ++DEFUN (ospf6_redistribute, ++ ospf6_redistribute_cmd, ++ "redistribute (static|kernel|connected|ripng|bgp)", ++ "Redistribute\n" ++ "Static route\n" ++ "Kernel route\n" ++ "Connected route\n" ++ "RIPng route\n" ++ "BGP route\n" ++ ) ++{ ++ int type = 0; ++ ++ if (strncmp (argv[0], "sta", 3) == 0) ++ type = ZEBRA_ROUTE_STATIC; ++ else if (strncmp (argv[0], "ker", 3) == 0) ++ type = ZEBRA_ROUTE_KERNEL; ++ else if (strncmp (argv[0], "con", 3) == 0) ++ type = ZEBRA_ROUTE_CONNECT; ++ else if (strncmp (argv[0], "rip", 3) == 0) ++ type = ZEBRA_ROUTE_RIPNG; ++ else if (strncmp (argv[0], "bgp", 3) == 0) ++ type = ZEBRA_ROUTE_BGP; ++ ++ ospf6_zebra_no_redistribute (type); ++ ospf6_asbr_routemap_unset (type); ++ ospf6_zebra_redistribute (type); ++ return CMD_SUCCESS; ++} ++ ++DEFUN (ospf6_redistribute_routemap, ++ ospf6_redistribute_routemap_cmd, ++ "redistribute (static|kernel|connected|ripng|bgp) route-map WORD", ++ "Redistribute\n" ++ "Static routes\n" ++ "Kernel route\n" ++ "Connected route\n" ++ "RIPng route\n" ++ "BGP route\n" ++ "Route map reference\n" ++ "Route map name\n" ++ ) ++{ ++ int type = 0; ++ ++ if (strncmp (argv[0], "sta", 3) == 0) ++ type = ZEBRA_ROUTE_STATIC; ++ else if (strncmp (argv[0], "ker", 3) == 0) ++ type = ZEBRA_ROUTE_KERNEL; ++ else if (strncmp (argv[0], "con", 3) == 0) ++ type = ZEBRA_ROUTE_CONNECT; ++ else if (strncmp (argv[0], "rip", 3) == 0) ++ type = ZEBRA_ROUTE_RIPNG; ++ else if (strncmp (argv[0], "bgp", 3) == 0) ++ type = ZEBRA_ROUTE_BGP; ++ ++ ospf6_zebra_no_redistribute (type); ++ ospf6_asbr_routemap_set (type, argv[1]); ++ ospf6_zebra_redistribute (type); ++ return CMD_SUCCESS; ++} ++ ++DEFUN (no_ospf6_redistribute, ++ no_ospf6_redistribute_cmd, ++ "no redistribute (static|kernel|connected|ripng|bgp)", ++ NO_STR ++ "Redistribute\n" ++ "Static route\n" ++ "Kernel route\n" ++ "Connected route\n" ++ "RIPng route\n" ++ "BGP route\n" ++ ) ++{ ++ int type = 0; ++ struct route_node *node; ++ struct ospf6_external_route *route; ++ struct ospf6_external_info *info, *info_next = NULL; ++ ++ if (strncmp (argv[0], "sta", 3) == 0) ++ type = ZEBRA_ROUTE_STATIC; ++ else if (strncmp (argv[0], "ker", 3) == 0) ++ type = ZEBRA_ROUTE_KERNEL; ++ else if (strncmp (argv[0], "con", 3) == 0) ++ type = ZEBRA_ROUTE_CONNECT; ++ else if (strncmp (argv[0], "rip", 3) == 0) ++ type = ZEBRA_ROUTE_RIPNG; ++ else if (strncmp (argv[0], "bgp", 3) == 0) ++ type = ZEBRA_ROUTE_BGP; ++ ++ ospf6_zebra_no_redistribute (type); ++ ospf6_asbr_routemap_unset (type); ++ ++ /* remove redistributed route */ ++ for (node = route_top (external_table); node; node = route_next (node)) ++ { ++ route = node->info; ++ if (! route) ++ continue; ++ for (info = route->info_head; info; info = info_next) ++ { ++ info_next = info->next; ++ if (info->type != type) ++ continue; ++ ospf6_asbr_route_remove (info->type, info->ifindex, ++ &route->prefix); ++ } ++ } ++ ++ return CMD_SUCCESS; ++} ++ ++ ++int ++ospf6_redistribute_config_write (struct vty *vty) ++{ ++ int i; ++ ++ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) ++ { ++ if (i == ZEBRA_ROUTE_OSPF6) ++ continue; ++ ++ if (! ospf6_zebra_is_redistribute (i)) ++ continue; ++ ++ if (rmap[i].map) ++ vty_out (vty, " redistribute %s route-map %s%s", ++ ZROUTE_NAME(i), rmap[i].name, VTY_NEWLINE); ++ else ++ vty_out (vty, " redistribute %s%s", ++ ZROUTE_NAME(i), VTY_NEWLINE); ++ } ++ ++ return 0; ++} + + void +-ospf6_asbr_external_lsa_update (struct ospf6_route_req *request) ++ospf6_redistribute_show_config (struct vty *vty) + { ++ int i; ++ ++ if (! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_SYSTEM) && ++ ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_KERNEL) && ++ ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_STATIC) && ++ ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_RIPNG) && ++ ! ospf6_zebra_is_redistribute(ZEBRA_ROUTE_BGP)) ++ return; ++ ++ vty_out (vty, " Redistributing External Routes from,%s", VTY_NEWLINE); ++ for (i = 0; i < ZEBRA_ROUTE_MAX; i++) ++ { ++ if (i == ZEBRA_ROUTE_OSPF6) ++ continue; ++ if (! ospf6_zebra_is_redistribute (i)) ++ continue; ++ ++ if (rmap[i].map) ++ vty_out (vty, " %s with route-map %s%s", ++ ZROUTE_NAME(i), rmap[i].name, VTY_NEWLINE); ++ else ++ vty_out (vty, " %s%s", ZROUTE_NAME(i), VTY_NEWLINE); ++ } ++} ++ ++/* AS External LSA origination */ ++int ++ospf6_asbr_external_lsa_originate (struct thread *thread) ++{ ++ struct ospf6_external_info *info; + char buffer [MAXLSASIZE]; +- u_int16_t size; +- struct ospf6_lsa_as_external *external; ++ struct ospf6_lsa_as_external *e; + char *p; +- struct ospf6_route_req route; +- char pbuf[BUFSIZ]; + +- /* 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; ++ info = THREAD_ARG (thread); + +- if (IS_OSPF6_DUMP_LSA) +- zlog_info ("Update AS-External: ID: %lu", +- (u_long) ntohl (request->path.origin.id)); ++ /* clear thread */ ++ info->thread_originate = NULL; ++ ++ if (info->is_removed) ++ { ++ if (IS_OSPF6_DUMP_ASBR) ++ { ++ char pbuf[64]; ++ prefix2str (&info->route->prefix, pbuf, sizeof (pbuf)); ++ zlog_info ("ASBR: quit redistribution %s: state is down", ++ pbuf); ++ } ++ return 0; ++ } + + /* prepare buffer */ + memset (buffer, 0, sizeof (buffer)); +- size = sizeof (struct ospf6_lsa_as_external); +- external = (struct ospf6_lsa_as_external *) buffer; +- p = (char *) (external + 1); ++ e = (struct ospf6_lsa_as_external *) buffer; ++ p = (char *) (e + 1); + +- if (route.path.metric_type == 2) +- SET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E); /* type2 */ ++ if (info->metric_type == 2) ++ SET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_E); /* type2 */ + else +- UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E); /* type1 */ ++ UNSET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_E); /* type1, default */ + + /* forwarding address */ +- if (! IN6_IS_ADDR_UNSPECIFIED (&route.nexthop.address)) +- SET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F); ++ if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding)) ++ SET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_F); + else +- UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F); ++ UNSET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_F); + + /* external route tag */ +- UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T); ++ UNSET_FLAG (e->bits_metric, OSPF6_ASBR_BIT_T); + + /* set metric. note: related to E bit */ +- OSPF6_ASBR_METRIC_SET (external, route.path.cost); ++ OSPF6_ASBR_METRIC_SET (e, info->metric); + + /* prefixlen */ +- external->prefix.prefix_length = route.route.prefix.prefixlen; ++ e->prefix.prefix_length = info->route->prefix.prefixlen; + + /* PrefixOptions */ +- external->prefix.prefix_options = route.path.prefix_options; ++ e->prefix.prefix_options = info->prefix_options; + + /* don't use refer LS-type */ +- external->prefix.prefix_refer_lstype = htons (0); +- +- if (IS_OSPF6_DUMP_LSA) +- { +- prefix2str (&route.route.prefix, pbuf, sizeof (pbuf)); +- zlog_info (" Prefix: %s", pbuf); +- } ++ e->prefix.prefix_refer_lstype = htons (0); + + /* set Prefix */ +- memcpy (p, &route.route.prefix.u.prefix6, +- OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen)); +- ospf6_prefix_apply_mask (&external->prefix); +- size += OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen); +- p += OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen); ++ memcpy (p, &info->route->prefix.u.prefix6, ++ OSPF6_PREFIX_SPACE (info->route->prefix.prefixlen)); ++ ospf6_prefix_apply_mask (&e->prefix); ++ p += OSPF6_PREFIX_SPACE (info->route->prefix.prefixlen); + + /* Forwarding address */ +- if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F)) ++ if (CHECK_FLAG (e->bits_metric, OSPF6_ASBR_BIT_F)) + { +- memcpy (p, &route.nexthop.address, sizeof (struct in6_addr)); +- size += sizeof (struct in6_addr); ++ memcpy (p, &info->forwarding, sizeof (struct in6_addr)); + p += sizeof (struct in6_addr); + } + + /* External Route Tag */ +- if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T)) ++ if (CHECK_FLAG (e->bits_metric, OSPF6_ASBR_BIT_T)) + { + /* xxx */ + } + + ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_AS_EXTERNAL), +- route.path.origin.id, ospf6->router_id, +- (char *) external, size, ospf6); +- return; ++ htonl (info->id), ospf6->router_id, ++ (char *) buffer, p - buffer, ospf6); ++ return 0; ++} ++ ++int ++ospf6_asbr_schedule_external (void *data) ++{ ++ struct ospf6_external_info *info = data; ++ u_long elasped_time, time = 0; ++ ++ if (info->thread_originate) ++ { ++ if (IS_OSPF6_DUMP_ASBR) ++ { ++ char pbuf[64]; ++ prefix2str (&info->route->prefix, pbuf, sizeof (pbuf)); ++ zlog_info ("ASBR: schedule redistribution %s: another thread", ++ pbuf); ++ } ++ return 0; ++ } ++ ++ elasped_time = ++ ospf6_lsa_has_elasped (htons (OSPF6_LSA_TYPE_AS_EXTERNAL), ++ htonl (info->id), ospf6->router_id, ospf6); ++ if (elasped_time < OSPF6_MIN_LS_INTERVAL) ++ time = OSPF6_MIN_LS_INTERVAL - elasped_time; ++ else ++ time = 0; ++ ++ //if (IS_OSPF6_DUMP_ASBR) ++ { ++ char pbuf[64]; ++ prefix2str (&info->route->prefix, pbuf, sizeof (pbuf)); ++ zlog_info ("ASBR: schedule redistribution %s as LS-ID %ld after %lu sec", ++ pbuf, (u_long) info->id, time); ++ } ++ ++ if (time) ++ info->thread_originate = ++ thread_add_timer (master, ospf6_asbr_external_lsa_originate, info, time); ++ else ++ info->thread_originate = ++ thread_add_timer (master, ospf6_asbr_external_lsa_originate, info, 0); ++ ++ return 0; ++} ++ ++int ++ospf6_asbr_external_lsa_flush (void *data) ++{ ++ struct ospf6_lsa *lsa = data; ++ if (lsa) ++ ospf6_lsa_premature_aging (lsa); ++ return 0; ++} ++ ++int ++ospf6_asbr_external_lsa_refresh (void *data) ++{ ++ struct ospf6_lsa *lsa = data; ++ struct ospf6_lsa_as_external *e; ++ struct prefix prefix; ++ struct route_node *node; ++ struct ospf6_external_route *route = NULL; ++ struct ospf6_external_info *info = NULL; ++ struct ospf6_external_info *match = NULL; ++ ++ if (IS_OSPF6_DUMP_ASBR) ++ zlog_info ("ASBR: refresh %s", lsa->str); ++ ++ e = (struct ospf6_lsa_as_external *) (lsa->header + 1); ++ ospf6_prefix_in6_addr (&e->prefix, &prefix.u.prefix6); ++ prefix.prefixlen = e->prefix.prefix_length; ++ prefix.family = AF_INET6; ++ apply_mask_ipv6 ((struct prefix_ipv6 *) &prefix); ++ ++ for (node = route_top (external_table); node; node = route_next (node)) ++ { ++ route = node->info; ++ if (route == NULL) ++ continue; ++ ++ for (info = route->info_head; info; info = info->next) ++ { ++ if (lsa->header->id == htonl (info->id)) ++ match = info; ++ } ++ } ++ ++ if (match == NULL) ++ { ++ ospf6_lsa_premature_aging (lsa); ++ return 0; ++ } ++ ++ ospf6_asbr_schedule_external (match); ++ return 0; ++ ++#if 0 ++ node = route_node_lookup (external_table, &prefix); ++ if (! node || ! node->info) ++ { ++ char pname[64]; ++ ++ prefix2str (&prefix, pname, sizeof (pname)); ++ if (IS_OSPF6_DUMP_ASBR) ++ zlog_info ("ASBR: could not find %s: premature age", pname); ++ ospf6_lsa_premature_aging (lsa); ++ return 0; ++ } ++ ++ /* find external_info */ ++ route = node->info; ++ for (info = route->info_head; info; info = info->next) ++ { ++ if (lsa->header->id == htonl (info->id)) ++ break; ++ } ++ ++ if (info) ++ ospf6_asbr_schedule_external (info); ++ else ++ ospf6_lsa_premature_aging (lsa); ++ ++ return 0; ++#endif + } + + void +-ospf6_asbr_external_route_add (struct ospf6_route_req *route) ++ospf6_asbr_route_add (int type, int ifindex, struct prefix *prefix, ++ u_int nexthop_num, struct in6_addr *nexthop) + { +- ospf6_asbr_external_lsa_update (route); ++ int ret; ++ struct route_node *node; ++ struct ospf6_external_route *route; ++ struct ospf6_external_info *info, tinfo; ++ ++ if (! ospf6_zebra_is_redistribute (type)) ++ return; ++ ++ /* apply route-map */ ++ memset (&tinfo, 0, sizeof (struct ospf6_external_info)); ++ if (rmap[type].map) ++ { ++ ret = route_map_apply (rmap[type].map, prefix, RMAP_OSPF6, &tinfo); ++ if (ret == RMAP_DENYMATCH) ++ { ++ if (IS_OSPF6_DUMP_ASBR) ++ zlog_info ("ASBR: denied by route-map %s", rmap[type].name); ++ return; ++ } ++ } ++ ++ node = route_node_get (external_table, prefix); ++ route = node->info; ++ ++ if (! route) ++ { ++ route = XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO, ++ sizeof (struct ospf6_external_route)); ++ memset (route, 0, sizeof (struct ospf6_external_route)); ++ ++ memcpy (&route->prefix, prefix, sizeof (struct prefix)); ++ ++ node->info = route; ++ route->node = node; ++ } ++ ++ for (info = route->info_head; info; info = info->next) ++ { ++ if (info->type == type && info->ifindex == ifindex) ++ break; ++ } ++ ++ if (! info) ++ { ++ info = XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO, ++ sizeof (struct ospf6_external_info)); ++ memset (info, 0, sizeof (struct ospf6_external_info)); ++ ++ info->route = route; ++ /* add tail */ ++ info->prev = route->info_tail; ++ if (route->info_tail) ++ route->info_tail->next = info; ++ else ++ route->info_head = info; ++ route->info_tail = info; ++ ++ info->id = link_state_id++; ++ } ++ ++ /* copy result of route-map */ ++ info->metric_type = tinfo.metric_type; ++ info->metric = tinfo.metric; ++ memcpy (&info->forwarding, &tinfo.forwarding, ++ sizeof (struct in6_addr)); ++ ++ info->type = type; ++ info->ifindex = ifindex; ++ ++ if (nexthop_num && nexthop) ++ { ++ info->nexthop_num = nexthop_num; ++ ++ if (info->nexthop) ++ XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info->nexthop); ++ ++ info->nexthop = (struct in6_addr *) ++ XMALLOC (MTYPE_OSPF6_EXTERNAL_INFO, ++ nexthop_num * sizeof (struct in6_addr)); ++ memcpy (info->nexthop, nexthop, ++ nexthop_num * sizeof (struct in6_addr)); ++ } ++ ++ info->is_removed = 0; ++ ++ //if (IS_OSPF6_DUMP_ASBR) ++ { ++ char pbuf[64]; ++ struct timeval now; ++ prefix2str (&info->route->prefix, pbuf, sizeof (pbuf)); ++ gettimeofday (&now, NULL); ++ zlog_info ("ASBR: start redistributing %s as LS-ID %ld: %ld.%06ld", ++ pbuf, (u_long) info->id, now.tv_sec, now.tv_usec); ++ } ++ ++#ifdef HAVE_OSPF6_DAMP ++ ospf6_damp_event_up (OSPF6_DAMP_TYPE_ROUTE, prefix, ++ ospf6_asbr_schedule_external, info); ++#else /*HAVE_OSPF6_DAMP*/ ++ ospf6_asbr_schedule_external (info); ++#endif /*HAVE_OSPF6_DAMP*/ + } + + void +-ospf6_asbr_external_route_remove (struct ospf6_route_req *route) ++ospf6_asbr_route_remove (int type, int ifindex, struct prefix *prefix) + { ++ struct route_node *node; ++ struct ospf6_external_route *route; ++ struct ospf6_external_info *info; + struct ospf6_lsa *lsa; + +- lsa = ospf6_lsdb_lookup_lsdb (htons (OSPF6_LSA_TYPE_AS_EXTERNAL), +- route->path.origin.id, +- ospf6->router_id, ospf6->lsdb); +- if (lsa) +- ospf6_lsa_premature_aging (lsa); ++ node = route_node_get (external_table, prefix); ++ route = node->info; ++ ++ if (! route) ++ return; ++ ++ for (info = route->info_head; info; info = info->next) ++ { ++ if (info->type == type && info->ifindex == ifindex) ++ break; ++ } ++ ++ if (! info) ++ return; ++ ++ //if (IS_OSPF6_DUMP_ASBR) ++ { ++ char pbuf[64]; ++ struct timeval now; ++ prefix2str (&info->route->prefix, pbuf, sizeof (pbuf)); ++ gettimeofday (&now, NULL); ++ zlog_info ("ASBR: quit redistributing %s as LS-ID %ld: %ld.%06ld", ++ pbuf, (u_long) info->id, now.tv_sec, now.tv_usec); ++ } ++ ++ if (info->thread_originate) ++ thread_cancel (info->thread_originate); ++ info->thread_originate = NULL; ++ ++ lsa = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_AS_EXTERNAL), ++ htonl (info->id), ospf6->router_id, ospf6); ++#ifdef HAVE_OSPF6_DAMP ++ ospf6_damp_event_down (OSPF6_DAMP_TYPE_ROUTE, &info->route->prefix, ++ ospf6_asbr_external_lsa_flush, lsa); ++#else /*HAVE_OSPF6_DAMP*/ ++ ospf6_asbr_external_lsa_flush (lsa); ++#endif /*HAVE_OSPF6_DAMP*/ ++ ++#if 1 ++ info->is_removed = 1; ++#else ++ /* remove from route */ ++ if (info->prev) ++ info->prev->next = info->next; ++ else ++ info->route->info_head = info->next; ++ if (info->next) ++ info->next->prev = info->prev; ++ else ++ info->route->info_tail = info->prev; ++ ++ /* if no info, free route */ ++ if (! info->route->info_head && ! info->route->info_tail) ++ { ++ info->route->node->info = NULL; ++ free (info->route); ++ } ++ ++ if (info->nexthop) ++ free (info->nexthop); ++ free (info); ++#endif /*0*/ + } + + void +@@ -134,22 +667,29 @@ + external = OSPF6_LSA_HEADER_END (lsa->header); + + if (IS_LSA_MAXAGE (lsa)) +- return; ++ { ++ if (IS_OSPF6_DUMP_ASBR) ++ zlog_info ("ASBR: maxage external lsa: %s seq: %lx", ++ lsa->str, (u_long)ntohl (lsa->header->seqnum)); ++ ospf6_asbr_external_lsa_remove (lsa); ++ return; ++ } + + if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: Calculate %s", lsa->str); ++ zlog_info ("ASBR: new external lsa: %s seq: %lx", ++ lsa->str, (u_long)ntohl (lsa->header->seqnum)); + + if (lsa->header->adv_router == ospf6->router_id) + { + if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: Self-originated, ignore"); ++ zlog_info ("ASBR: my external LSA, ignore"); + return; + } + + if (OSPF6_ASBR_METRIC (external) == LS_INFINITY) + { + if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: Metric is Infinity, ignore"); ++ zlog_info ("ASBR: metric is infinity, ignore"); + return; + } + +@@ -167,7 +707,7 @@ + { + char buf[64]; + inet_ntop (AF_INET, &asbr_id.adv_router, buf, sizeof (buf)); +- zlog_info ("ASBR: ASBR %s not found, ignore", buf); ++ zlog_info ("ASBR: router %s not found, ignore", buf); + } + return; + } +@@ -206,6 +746,14 @@ + { + memcpy (&request.nexthop, &asbr_entry.nexthop, + sizeof (struct ospf6_nexthop)); ++ if (IS_OSPF6_DUMP_ASBR) ++ { ++ char buf[64], nhop[64], ifname[IFNAMSIZ]; ++ prefix2str (&request.route.prefix, buf, sizeof (buf)); ++ inet_ntop (AF_INET6, &request.nexthop.address, nhop, sizeof (nhop)); ++ if_indextoname (request.nexthop.ifindex, ifname); ++ zlog_info ("ASBR: add route: %s %s%%%s", buf, nhop, ifname); ++ } + ospf6_route_add (&request, ospf6->route_table); + ospf6_route_next (&asbr_entry); + } +@@ -220,12 +768,13 @@ + struct ospf6_route_req request; + + if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: Withdraw route of %s", lsa->str); ++ zlog_info ("ASBR: withdraw external lsa: %s seq: %lx", ++ lsa->str, (u_long)ntohl (lsa->header->seqnum)); + + if (lsa->header->adv_router == ospf6->router_id) + { + if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: Self-originated, ignore"); ++ zlog_info ("ASBR: my external LSA, ignore"); + return; + } + +@@ -236,14 +785,14 @@ + memcpy (&dest.u.prefix6, (char *)(external + 1), + OSPF6_PREFIX_SPACE (dest.prefixlen)); + +- prefix2str (&dest, buf, sizeof (buf)); +- if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: route: %s", buf); +- + ospf6_route_lookup (&request, &dest, ospf6->route_table); + if (ospf6_route_end (&request)) + { +- zlog_info ("ASBR: route not found"); ++ if (IS_OSPF6_DUMP_ASBR) ++ { ++ prefix2str (&dest, buf, sizeof (buf)); ++ zlog_info ("ASBR: %s not found", buf); ++ } + return; + } + +@@ -252,7 +801,8 @@ + { + if (prefix_same (&request.route.prefix, &dest) != 1) + { +- zlog_info ("ASBR: Can't find the entry matches the origin"); ++ if (IS_OSPF6_DUMP_ASBR) ++ zlog_info ("ASBR: Can't find the entry matches the origin"); + return; + } + ospf6_route_next (&request); +@@ -264,6 +814,15 @@ + request.path.origin.adv_router == lsa->header->adv_router && + prefix_same (&request.route.prefix, &dest) == 1) + { ++ if (IS_OSPF6_DUMP_ASBR) ++ { ++ char nhop[64], ifname[IFNAMSIZ]; ++ prefix2str (&dest, buf, sizeof (buf)); ++ inet_ntop (AF_INET6, &request.nexthop.address, nhop, sizeof (nhop)); ++ if_indextoname (request.nexthop.ifindex, ifname); ++ zlog_info ("ASBR: remove route: %s %s%%%s", buf, nhop, ifname); ++ } ++ + ospf6_route_remove (&request, ospf6->route_table); + ospf6_route_next (&request); + } +@@ -303,7 +862,7 @@ + { + char buf[64]; + inet_ntop (AF_INET, &inter_router->adv_router, buf, sizeof (buf)); +- zlog_info ("ASBR: New router found: %s", buf); ++ zlog_info ("ASBR: new router found: %s", buf); + } + + if (ntohl (id) != 0 || +@@ -335,7 +894,7 @@ + { + char buf[64]; + inet_ntop (AF_INET, &inter_router->adv_router, buf, sizeof (buf)); +- zlog_info ("ASBR: Router disappearing: %s", buf); ++ zlog_info ("ASBR: router disappearing: %s", buf); + } + + if (ntohl (id) != 0 || +@@ -410,37 +969,6 @@ + return 0; + } + +-int +-ospf6_asbr_external_refresh (void *old) +-{ +- struct ospf6_lsa *lsa = old; +- struct ospf6_route_req route, *target; +- +- assert (ospf6); +- +- if (IS_OSPF6_DUMP_ASBR) +- zlog_info ("ASBR: refresh %s", lsa->str); +- +- target = NULL; +- for (ospf6_route_head (&route, ospf6->external_table); +- ! ospf6_route_end (&route); +- ospf6_route_next (&route)) +- { +- if (route.path.origin.id == lsa->header->id) +- { +- target = &route; +- break; +- } +- } +- +- if (target) +- ospf6_asbr_external_lsa_update (target); +- else +- ospf6_lsa_premature_aging (lsa); +- +- return 0; +-} +- + void + ospf6_asbr_database_hook (struct ospf6_lsa *old, struct ospf6_lsa *new) + { +@@ -459,7 +987,7 @@ + slot.type = htons (OSPF6_LSA_TYPE_AS_EXTERNAL); + slot.name = "AS-External"; + slot.func_show = ospf6_asbr_external_show; +- slot.func_refresh = ospf6_asbr_external_refresh; ++ slot.func_refresh = ospf6_asbr_external_lsa_refresh; + ospf6_lsa_slot_register (&slot); + + ospf6_lsdb_hook[OSPF6_LSA_TYPE_AS_EXTERNAL & OSPF6_LSTYPE_CODE_MASK].hook = +@@ -467,9 +995,71 @@ + } + + void ++ospf6_asbr_external_info_show (struct vty *vty, ++ struct ospf6_external_info *info) ++{ ++ char prefix_buf[64], id_buf[16]; ++ struct in_addr id; ++ ++ if (info->is_removed) ++ return; ++ ++ id.s_addr = ntohl (info->id); ++ inet_ntop (AF_INET, &id, id_buf, sizeof (id_buf)); ++ prefix2str (&info->route->prefix, prefix_buf, sizeof (prefix_buf)); ++ vty_out (vty, "%s %-32s %3d %-15s %3d %lu(type-%d)%s", ++ ZROUTE_ABNAME(info->type), prefix_buf, info->ifindex, id_buf, ++ info->nexthop_num, (u_long) info->metric, info->metric_type, ++ VTY_NEWLINE); ++} ++ ++void ++ospf6_asbr_external_route_show (struct vty *vty, ++ struct ospf6_external_route *route) ++{ ++ struct ospf6_external_info *info; ++ for (info = route->info_head; info; info = info->next) ++ ospf6_asbr_external_info_show (vty, info); ++} ++ ++DEFUN (show_ipv6_route_ospf6_external, ++ show_ipv6_route_ospf6_external_cmd, ++ "show ipv6 ospf6 route redistribute", ++ SHOW_STR ++ IP6_STR ++ ROUTE_STR ++ OSPF6_STR ++ "redistributing External information\n" ++ ) ++{ ++ struct route_node *node; ++ struct ospf6_external_route *route; ++ ++ vty_out (vty, "%s %-32s %3s %-15s %3s %s%s", ++ " ", "Prefix", "I/F", "LS-Id", "#NH", "Metric", ++ VTY_NEWLINE); ++ for (node = route_top (external_table); node; node = route_next (node)) ++ { ++ route = node->info; ++ if (route) ++ ospf6_asbr_external_route_show (vty, route); ++ } ++ return CMD_SUCCESS; ++} ++ ++void + ospf6_asbr_init () + { ++ external_table = route_table_init (); ++ link_state_id = 0; ++ + ospf6_asbr_register_as_external (); ++ ++ install_element (VIEW_NODE, &show_ipv6_route_ospf6_external_cmd); ++ install_element (ENABLE_NODE, &show_ipv6_route_ospf6_external_cmd); ++ install_element (OSPF6_NODE, &ospf6_redistribute_cmd); ++ install_element (OSPF6_NODE, &ospf6_redistribute_routemap_cmd); ++ install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd); + } + + +diff -x CVS -urN ospf6d.old/ospf6_asbr.h ospf6d/ospf6_asbr.h +--- ospf6d.old/ospf6_asbr.h Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_asbr.h Sat Nov 9 11:25:30 2002 +@@ -22,6 +22,51 @@ + #ifndef OSPF6_ASBR_H + #define OSPF6_ASBR_H + ++#include "thread.h" ++ ++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 */ ++ int type; ++ ++ /* external route ifindex */ ++ int ifindex; ++ ++ /* LS-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 + { +@@ -42,8 +87,16 @@ + { (E)->bits_metric &= htonl (0xff000000); \ + (E)->bits_metric |= htonl (0x00ffffff) & htonl (C); } + +-void ospf6_asbr_external_route_add (struct ospf6_route_req *route); +-void ospf6_asbr_external_route_remove (struct ospf6_route_req *route); ++void ospf6_asbr_routemap_update (); ++ ++int ospf6_redistribute_config_write (struct vty *vty); ++void ospf6_redistribute_show_config (struct vty *vty); ++ ++void ++ospf6_asbr_route_add (int type, int ifindex, struct prefix *prefix, ++ u_int nexthop_num, struct in6_addr *nexthop); ++void ++ospf6_asbr_route_remove (int type, int ifindex, struct prefix *prefix); + + void ospf6_asbr_external_lsa_add (struct ospf6_lsa *lsa); + void ospf6_asbr_external_lsa_remove (struct ospf6_lsa *lsa); +diff -x CVS -urN ospf6d.old/ospf6_damp.c ospf6d/ospf6_damp.c +--- ospf6d.old/ospf6_damp.c Thu Jan 1 01:00:00 1970 ++++ ospf6d/ospf6_damp.c Sat Nov 9 11:25:30 2002 +@@ -0,0 +1,748 @@ ++/* ++ * 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, ++ 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, ++ 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, ++ 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, ++ 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 (flap_damping_route, ++ 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, &flap_damping_route_cmd); ++ ++ install_element (ENABLE_NODE, &show_debug_ospf6_damp_cmd); ++ install_element (CONFIG_NODE, &debug_ospf6_damp_cmd); ++ install_element (CONFIG_NODE, &no_debug_ospf6_damp_cmd); ++ ++ thread_add_event (master, ospf6_damp_debug_thread, NULL, 0); ++} ++ ++#endif /* HAVE_OSPF6_DAMP */ ++ ++ +diff -x CVS -urN ospf6d.old/ospf6_damp.h ospf6d/ospf6_damp.h +--- ospf6d.old/ospf6_damp.h Thu Jan 1 01:00:00 1970 ++++ ospf6d/ospf6_damp.h Tue Oct 1 00:41:10 2002 +@@ -0,0 +1,109 @@ ++/* ++ * OSPF flap dampening by Manav Bhatia ++ * Copyright (C) 2002 ++ * ++ * This file is part of GNU Zebra. ++ * ++ * GNU Zebra is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2, or (at your option) any ++ * later version. ++ * ++ * GNU Zebra is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with GNU Zebra; see the file COPYING. If not, write to the Free ++ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ++ * 02111-1307, USA. ++ */ ++ ++/* ++ * Flap Damping (target e.g. link/route) ++ */ ++ ++#define HAVE_OSPF6_DAMP ++ ++typedef enum ++{ ++ OFF, ++ ON, ++} onoff_t; ++ ++typedef enum ++{ ++ event_none, ++ event_up, ++ event_down, ++} damp_event_t; ++ ++/* Structure maintained per target basis */ ++struct ospf6_damp_info ++{ ++ /* identifier to decide which target */ ++ u_short type; ++ struct prefix name; ++ ++ /* do we damping this info */ ++ onoff_t damping; ++ ++ u_int penalty; ++ u_int flap; ++ time_t t_start; /* First flap (down event) time */ ++ time_t t_updated; /* Last time the penalty was updated */ ++ ++ /* index and double-link for reuse list */ ++ int index; ++ struct ospf6_damp_info *next; ++ struct ospf6_damp_info *prev; ++ ++ /* the last event that we are avoiding */ ++ int (*event) (void *target); ++ void *target; ++ damp_event_t event_type; ++ damp_event_t target_status; ++}; ++ ++#define OSPF6_DAMP_TYPE_ROUTE 0 ++#define OSPF6_DAMP_TYPE_MAX 1 ++ ++/* Global Configuration Parameters */ ++struct ospf6_damp_config ++{ ++ /* is damping enabled ? */ ++ onoff_t enabled; ++ ++ /* configurable parameters */ ++ u_int half_life; ++ u_int suppress; ++ u_int reuse; ++ u_int t_hold; /* Maximum hold down time */ ++ ++ /* Non configurable parameters */ ++ u_int delta_t; ++ u_int delta_reuse; ++ u_int default_penalty; ++ u_int ceiling; /* Max value a penalty can attain */ ++ double scale_factor; ++ ++ int decay_array_size; /* Calculated using config parameters */ ++ double *decay_array; /* Storage for decay values */ ++ ++ int reuse_index_array_size; /* Size of reuse index array */ ++ int *reuse_index_array; ++ ++ int reuse_list_size; /* Number of reuse lists */ ++ struct ospf6_damp_info **reuse_list_array; ++}; ++ ++int ospf6_damp_reuse_timer (struct thread *); ++void ospf6_damp_event_up (u_short type, struct prefix *name, ++ int (*exec_up) (void *), void *target); ++void ospf6_damp_event_down (u_short type, struct prefix *name, ++ int (*exec_down) (void *), void *target); ++ ++void ospf6_damp_config_write (struct vty *); ++void ospf6_damp_init (); ++ +diff -x CVS -urN ospf6d.old/ospf6_dbex.c ospf6d/ospf6_dbex.c +--- ospf6d.old/ospf6_dbex.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_dbex.c Sat Nov 9 11:25:30 2002 +@@ -230,12 +230,11 @@ + 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); + +- if (IS_OSPF6_DUMP_DBEX) +- zlog_info ("Receive %s from %s", received->str, from->str); +- + /* set LSA scope */ + if (OSPF6_LSA_IS_SCOPE_LINKLOCAL (htons (lsa_header->type))) + received->scope = from->ospf6_interface; +@@ -248,27 +247,24 @@ + cksum = ntohs (lsa_header->checksum); + if (ntohs (ospf6_lsa_checksum (lsa_header)) != cksum) + { +- zlog_warn ("DBEX: LSA cksum wrong: %s checksum %#hx should be %#hx", +- received->str, cksum, ntohs (ospf6_lsa_checksum (lsa_header))); ++ 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; + } + +-#if 0 +- /* (2) warn if unknown */ +- if (! ospf6_lsa_is_known_type (lsa_header)) +- zlog_warn ("[%s:%s] receive LSA unknown: %#x", +- from->str, from->ospf6_interface->interface->name, +- ntohs (lsa_header->type)); +-#endif /*0*/ +- + /* (3) Ebit Missmatch: AS-External-LSA */ + if (lsa_header->type == htons (OSPF6_LSA_TYPE_AS_EXTERNAL) && + ospf6_area_is_stub (from->ospf6_interface->area)) + { +- zlog_err ("DBEX: [%s:%s] receive LSA E-bit mismatch: %s", +- from->str, from->ospf6_interface->interface->name, +- received->str); ++ 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; + } +@@ -279,8 +275,10 @@ + { + /* log */ + if (IS_OSPF6_DUMP_DBEX) +- zlog_info ("Drop MaxAge LSA: no instance, no neighbor " +- "exchanging DB: %s", received->str); ++ 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 */ +@@ -312,18 +310,29 @@ + + /* (a) MinLSArrival check */ + gettimeofday (&now, (struct timezone *)NULL); +- if (have && now.tv_sec - have->installed.tv_sec <= OSPF6_MIN_LS_ARRIVAL) ++ if (have && SEC_TVDIFF (&now, &have->installed) < OSPF6_MIN_LS_ARRIVAL) + { +- if (IS_OSPF6_DUMP_DBEX) +- zlog_info ("DBEX: [%s:%s] received LSA too soon: %s", +- from->str, from->ospf6_interface->interface->name, +- received->str); ++ //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); + +@@ -344,18 +353,20 @@ + 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: [%s:%s] don't ack %s", +- from->str, from->ospf6_interface->interface->name, +- received->str); ++ zlog_info ("DBEX: No Ack to %s", from->str); + } + + /* (f) */ +@@ -413,6 +424,9 @@ + 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); + } +@@ -421,18 +435,20 @@ + 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: [%s:%s] will no ack %s", +- from->str, from->ospf6_interface->interface->name, +- received->str); ++ zlog_info ("DBEX: No Ack to %s", from->str); + } + ospf6_lsa_delete (received); + } +@@ -443,6 +459,9 @@ + 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); +@@ -455,83 +474,52 @@ + struct ospf6_neighbor *from) + { + struct ospf6_interface *ospf6_interface; +- struct ospf6_neighbor *nbr; +- listnode n, m; ++ 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; + } +- else if (ismore_recent < 0 && +- ! CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_FLOODBACK)) +- { +- if (ospf6_interface->state == IFS_BDR) +- { +- if (ospf6_interface->dr == from->router_id) +- { +- return DELAYED_ACK; +- } +- else +- { +- return NO_ACK; +- } +- } +- else +- { +- return DELAYED_ACK; +- } +- } +- else if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_DUPLICATE) && +- CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_IMPLIEDACK)) +- { +- if (ospf6_interface->state == IFS_BDR) +- { +- if (ospf6_interface->dr == from->router_id) +- { +- return DELAYED_ACK; +- } +- else +- { +- return NO_ACK; +- } +- } +- else +- { +- return NO_ACK; +- } +- } +- else if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_DUPLICATE) && +- ! CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_IMPLIEDACK)) +- { +- return DIRECT_ACK; +- } +- else if (IS_LSA_MAXAGE (newp)) ++ ++ if (CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_DUPLICATE) && ++ CHECK_FLAG (newp->flag, OSPF6_LSA_FLAG_IMPLIEDACK)) + { +- if (! ospf6_lsdb_lookup (newp->header->type, newp->header->id, +- newp->header->adv_router, +- ospf6_lsa_get_scope (newp->header->type, +- from->ospf6_interface))) +- { +- for (n = listhead (from->ospf6_interface->area->if_list); +- n; nextnode (n)) +- { +- ospf6_interface = (struct ospf6_interface *) getdata (n); +- for (m = listhead (ospf6_interface->neighbor_list); +- m; nextnode (m)) +- { +- nbr = (struct ospf6_neighbor *) getdata (m); +- if (nbr->state == NBS_EXCHANGE || nbr->state == NBS_LOADING) +- { +- return NO_ACK; +- } +- } +- } +- return DIRECT_ACK; +- } ++ 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; + } +@@ -600,11 +588,13 @@ + + /* (2) */ + if (addretrans == 0) ++ return; /* examin next interface */ ++ ++ if (from && from->ospf6_interface == o6i) + { +- return; /* examin next interface */ +- } +- else 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); + } +@@ -624,7 +614,7 @@ + return; /* examin next interface */ + + if (IS_OSPF6_DUMP_DBEX) +- zlog_info (" Flood to interface %s", o6i->interface->name); ++ zlog_info ("Flood to interface %s", o6i->interface->name); + + /* (5) send LinkState Update */ + ospf6_send_lsupdate_flood (lsa, o6i); +@@ -678,14 +668,13 @@ + + lsa_header = (struct ospf6_lsa_header *) lsa->lsa_hdr; + +- if (IS_OSPF6_DUMP_DBEX) +- zlog_info ("Flood: %s", lsa->str); +- + 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))) +@@ -693,6 +682,8 @@ + 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))) +@@ -700,6 +691,8 @@ + o6 = (struct ospf6 *) lsa->scope; + assert (o6); + ++ if (IS_OSPF6_DUMP_DBEX) ++ zlog_info ("Flood AS"); + ospf6_dbex_flood_as (lsa, o6, from); + } + else +diff -x CVS -urN ospf6d.old/ospf6_interface.c ospf6d/ospf6_interface.c +--- ospf6d.old/ospf6_interface.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_interface.c Sat Nov 9 13:26:03 2002 +@@ -126,6 +126,9 @@ + + CALL_ADD_HOOK (&interface_hook, o6i); + ++ /* Get the interface's link-local if any */ ++ ospf6_interface_address_update(ifp); ++ + return o6i; + } + +diff -x CVS -urN ospf6d.old/ospf6_lsa.c ospf6d/ospf6_lsa.c +--- ospf6d.old/ospf6_lsa.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_lsa.c Sat Nov 9 11:25:30 2002 +@@ -51,7 +51,6 @@ + #include "ospf6_area.h" + #include "ospf6_interface.h" + #include "ospf6_neighbor.h" +-#include "ospf6_redistribute.h" + #include "ospf6_ism.h" + #include "ospf6_nsm.h" + #include "ospf6_dbex.h" +@@ -142,8 +141,11 @@ + + lsa->birth.tv_sec = now.tv_sec - ntohs (lsa->header->age); + lsa->birth.tv_usec = now.tv_usec; +- lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa, +- lsa->birth.tv_sec + MAXAGE - now.tv_sec); ++ if (ntohs (lsa->header->age) != MAXAGE) ++ lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa, ++ lsa->birth.tv_sec + MAXAGE - now.tv_sec); ++ else ++ lsa->expire = NULL; + return; + } + +@@ -692,38 +694,6 @@ + ospf6_lsa_delete (lsa); + } + +-/* check necessity to update LSA: +- returns 1 if it's necessary to reoriginate */ +-static int +-ospf6_lsa_is_really_reoriginate (struct ospf6_lsa *new) +-{ +- struct ospf6_lsa *old; +- int diff; +- +- /* find previous LSA */ +- old = ospf6_lsdb_lookup (new->header->type, new->header->id, +- new->header->adv_router, new->scope); +- if (! old) +- return 1; +- +- /* Check if this is refresh */ +- if (CHECK_FLAG (old->flag, OSPF6_LSA_FLAG_REFRESH)) +- { +- zlog_warn ("LSA: reoriginate: %s: Refresh", new->str); +- return 1; +- } +- +- /* Are these contents different ? */ +- diff = ospf6_lsa_differ (new, old); +- +- if (diff) +- return 1; +- +- if (IS_OSPF6_DUMP_LSA) +- zlog_info ("LSA: Suppress updating %s", new->str); +- return 0; +-} +- + void + ospf6_lsa_originate (u_int16_t type, u_int32_t id, u_int32_t adv_router, + char *data, int data_len, void *scope) +@@ -731,6 +701,7 @@ + char buffer[MAXLSASIZE]; + struct ospf6_lsa_header *lsa_header; + struct ospf6_lsa *lsa; ++ struct ospf6_lsa *old; + + assert (data_len <= sizeof (buffer) - sizeof (struct ospf6_lsa_header)); + +@@ -754,18 +725,37 @@ + + /* create LSA */ + lsa = ospf6_lsa_create ((struct ospf6_lsa_header *) buffer); +- lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa, +- OSPF6_LS_REFRESH_TIME); + lsa->scope = scope; + +- if (ospf6_lsa_is_really_reoriginate (lsa)) +- { +- ospf6_dbex_remove_from_all_retrans_list (lsa); +- ospf6_dbex_flood (lsa, NULL); +- ospf6_lsdb_install (lsa); ++ /* find previous LSA */ ++ old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, ++ lsa->header->adv_router, lsa->scope); ++ if (old) ++ { ++ /* Check if this is neither different instance nor refresh, return */ ++ if (! CHECK_FLAG (old->flag, OSPF6_LSA_FLAG_REFRESH) && ++ ! ospf6_lsa_differ (lsa, old)) ++ { ++ if (IS_OSPF6_DUMP_LSA) ++ zlog_info ("LSA: Suppress updating %s", lsa->str); ++ ospf6_lsa_delete (lsa); ++ return; ++ } + } +- else +- ospf6_lsa_delete (lsa); ++ ++ lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa, ++ OSPF6_LS_REFRESH_TIME); ++ gettimeofday (&lsa->originated, NULL); ++ ++ //if (IS_OSPF6_DUMP_LSA) ++ zlog_info ("LSA: originate %s seq: %#x age: %hu %ld.%06ld", ++ lsa->str, ntohl (lsa->header->seqnum), ++ ospf6_lsa_age_current (lsa), ++ lsa->originated.tv_sec, lsa->originated.tv_usec); ++ ++ ospf6_dbex_remove_from_all_retrans_list (lsa); ++ ospf6_dbex_flood (lsa, NULL); ++ ospf6_lsdb_install (lsa); + } + + +@@ -1130,14 +1120,32 @@ + return 0; + } + +-void +-ospf6_lsa_router_update (u_int32_t area_id) ++u_long ++ospf6_lsa_has_elasped (u_int16_t type, u_int32_t id, ++ u_int32_t adv_router, void *scope) ++{ ++ struct ospf6_lsa *old; ++ struct timeval now; ++ ++ if (adv_router != ospf6->router_id) ++ zlog_info ("LSA: Router-ID changed ?"); ++ ++ old = ospf6_lsdb_lookup (type, id, adv_router, scope); ++ if (! old) ++ return OSPF6_LSA_MAXAGE; ++ ++ gettimeofday (&now, NULL); ++ return ((u_long) SEC_TVDIFF (&now, &old->originated)); ++} ++ ++int ++ospf6_lsa_originate_router (struct thread *thread) + { + char buffer [MAXLSASIZE]; + u_int16_t size; +- struct ospf6_lsa *old; + struct ospf6_area *o6a; + int count; ++ u_int32_t area_id; + + struct ospf6_router_lsa *router_lsa; + struct ospf6_router_lsd *router_lsd; +@@ -1145,22 +1153,22 @@ + struct ospf6_interface *o6i; + struct ospf6_neighbor *o6n = NULL; + ++ area_id = (u_int32_t) THREAD_ARG (thread); ++ + o6a = ospf6_area_lookup (area_id, ospf6); + if (! o6a) + { + inet_ntop (AF_INET, &area_id, buffer, sizeof (buffer)); + if (IS_OSPF6_DUMP_LSA) +- zlog_warn ("Update Router-LSA: No such area: %s", buffer); +- return; ++ zlog_info ("LSA: Update Router-LSA: No such area: %s", buffer); ++ return 0; + } + +- if (IS_OSPF6_DUMP_LSA) +- zlog_info ("Update Router-LSA: for Area %s", o6a->str); ++ /* clear thread */ ++ o6a->thread_router_lsa = NULL; + +- /* find previous LSA */ +- /* xxx, there may be multiple Router-LSAs */ +- old = ospf6_lsdb_lookup (htons (OSPF6_LSA_TYPE_ROUTER), +- htonl (0), o6a->ospf6->router_id, o6a); ++ if (IS_OSPF6_DUMP_LSA) ++ zlog_info ("LSA: originate Router-LSA for Area %s", o6a->str); + + size = sizeof (struct ospf6_router_lsa); + memset (buffer, 0, sizeof (buffer)); +@@ -1277,6 +1285,42 @@ + ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_ROUTER), + htonl (0), o6a->ospf6->router_id, + (char *) router_lsa, size, o6a); ++ return 0; ++} ++ ++void ++ospf6_lsa_schedule_router (struct ospf6_area *area) ++{ ++ u_long elasped_time, time = 0; ++ ++ if (area->thread_router_lsa) ++ { ++ if (IS_OSPF6_DUMP_LSA) ++ zlog_info ("LSA: schedule: Router-LSA for Area %s: another thread", ++ area->str); ++ return; ++ } ++ ++ elasped_time = ++ ospf6_lsa_has_elasped (htons (OSPF6_LSA_TYPE_ROUTER), htonl (0), ++ area->ospf6->router_id, area); ++ if (elasped_time < OSPF6_MIN_LS_INTERVAL) ++ time = (u_long) (OSPF6_MIN_LS_INTERVAL - elasped_time); ++ else ++ time = 0; ++ ++ if (IS_OSPF6_DUMP_LSA) ++ zlog_info ("LSA: schedule: Router-LSA for Area %s after %lu sec", ++ area->str, time); ++ ++ if (time) ++ area->thread_router_lsa = ++ thread_add_timer (master, ospf6_lsa_originate_router, ++ (void *) area->area_id, time); ++ else ++ area->thread_router_lsa = ++ thread_add_event (master, ospf6_lsa_originate_router, ++ (void *) area->area_id, 0); + } + + int +@@ -1284,7 +1328,7 @@ + { + struct ospf6_neighbor *o6n = neighbor; + if (o6n->ospf6_interface->area) +- ospf6_lsa_router_update (o6n->ospf6_interface->area->area_id); ++ ospf6_lsa_schedule_router (o6n->ospf6_interface->area); + return 0; + } + +@@ -1293,7 +1337,7 @@ + { + struct ospf6_interface *o6i = interface; + if (o6i->area) +- ospf6_lsa_router_update (o6i->area->area_id); ++ ospf6_lsa_schedule_router (o6i->area); + return 0; + } + +@@ -1301,7 +1345,7 @@ + ospf6_lsa_router_hook_area (void *area) + { + struct ospf6_area *o6a = area; +- ospf6_lsa_router_update (o6a->area_id); ++ ospf6_lsa_schedule_router (o6a); + return 0; + } + +@@ -1315,7 +1359,7 @@ + for (node = listhead (o6->area_list); node; nextnode (node)) + { + o6a = getdata (node); +- ospf6_lsa_router_update (o6a->area_id); ++ ospf6_lsa_schedule_router (o6a); + } + return 0; + } +@@ -1327,7 +1371,7 @@ + struct ospf6_area *o6a; + + o6a = lsa->scope; +- ospf6_lsa_router_update (o6a->area_id); ++ ospf6_lsa_schedule_router (o6a); + return 0; + } + +diff -x CVS -urN ospf6d.old/ospf6_lsa.h ospf6d/ospf6_lsa.h +--- ospf6d.old/ospf6_lsa.h Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_lsa.h Sat Nov 9 11:25:30 2002 +@@ -25,6 +25,13 @@ + + #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) ++ + /* LSA definition */ + + #define MAXLSASIZE 1024 +@@ -211,6 +218,7 @@ + unsigned char flag; /* to decide ack type and refresh */ + struct timeval birth; /* tv_sec when LS age 0 */ + struct timeval installed; /* installed time */ ++ struct timeval originated; /* installed time */ + struct thread *expire; + struct thread *refresh; /* For self-originated LSA */ + u_int32_t from; /* from which neighbor */ +@@ -397,22 +405,22 @@ + + u_short ospf6_lsa_checksum (struct ospf6_lsa_header *); + +-void ospf6_lsa_update_router (u_int32_t area_id); + 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_reoriginate (struct ospf6_lsa *); +-void +-ospf6_lsa_originate (u_int16_t, u_int32_t, u_int32_t, char *, int, void *); +- + 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 *); + + #endif /* OSPF6_LSA_H */ + +diff -x CVS -urN ospf6d.old/ospf6_message.c ospf6d/ospf6_message.c +--- ospf6d.old/ospf6_message.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_message.c Sat Nov 9 11:25:30 2002 +@@ -1108,14 +1108,14 @@ + if (!o6n) + { + if (IS_OSPF6_DUMP_LSACK) +- zlog_info (" neighbor not found, reject"); ++ zlog_info ("LSACK: neighbor not found, reject"); + return; + } + + if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr))) + { +- if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) +- zlog_info ("From Secondary I/F of the neighbor: ignore"); ++ if (IS_OSPF6_DUMP_LSACK) ++ zlog_info ("LSACK: From Secondary I/F of the neighbor: ignore"); + return; + } + +@@ -1123,7 +1123,7 @@ + if (o6n->state < NBS_EXCHANGE) + { + if (IS_OSPF6_DUMP_LSACK) +- zlog_info (" neighbor state less than Exchange, reject"); ++ zlog_info ("LSACK: neighbor state less than Exchange, reject"); + return; + } + +@@ -1141,7 +1141,7 @@ + if (!copy) + { + if (IS_OSPF6_DUMP_LSACK) +- zlog_info ("no database copy, ignore"); ++ zlog_info ("LSACK: no database copy, ignore"); + continue; + } + +@@ -1152,7 +1152,7 @@ + if (rem == NULL) + { + if (IS_OSPF6_DUMP_LSACK) +- zlog_info ("not on %s's retranslist, ignore", o6n->str); ++ zlog_info ("LSACK: not on %s's retranslist, ignore", o6n->str); + continue; + } + +@@ -1167,7 +1167,13 @@ + { + /* Log the questionable acknowledgement, + and examine the next one. */ +- zlog_warn ("LSAck: questionable acknowledge: LSAs differ"); ++ zlog_info ("LSACK: questionable acknowledge: %s", copy->str); ++ zlog_info ("LSACK: received: seq: %#x age: %hu", ++ ntohl (lsa->header->seqnum), ++ ntohs (lsa->header->age)); ++ zlog_info ("LSACK: instance: seq: %#x age: %hu", ++ ntohl (copy->header->seqnum), ++ ospf6_lsa_age_current (copy)); + } + + /* release temporary LSA from Ack message */ +@@ -1242,6 +1248,22 @@ + return; + } + ++ /* message type check */ ++ type = (ospf6_header->type >= OSPF6_MESSAGE_TYPE_MAX ? ++ OSPF6_MESSAGE_TYPE_UNKNOWN : ospf6_header->type); ++ ++ /* log */ ++ if (IS_OSPF6_DUMP_MESSAGE (type)) ++ { ++ char srcname[64], dstname[64]; ++ inet_ntop (AF_INET6, dst, dstname, sizeof (dstname)); ++ inet_ntop (AF_INET6, src, srcname, sizeof (srcname)); ++ zlog_info ("Receive %s on %s", ++ ospf6_message_type_string[type], o6i->interface->name); ++ zlog_info (" %s -> %s", srcname, dstname); ++ ospf6_message_log (message); ++ } ++ + /* router id check */ + router_id = ospf6_header->router_id; + if (ospf6_header->router_id == o6i->area->ospf6->router_id) +@@ -1252,10 +1274,6 @@ + return; + } + +- /* message type check */ +- type = (ospf6_header->type >= OSPF6_MESSAGE_TYPE_MAX ? +- OSPF6_MESSAGE_TYPE_UNKNOWN : ospf6_header->type); +- + /* octet statistics relies on some asumption: + on ethernet, no IPv6 Extention header, etc */ + #define OSPF6_IP6_HEADER_SIZE 40 +@@ -1280,12 +1298,14 @@ + struct ospf6_header ospf6_header; + char buffer[OSPF6_MESSAGE_RECEIVE_BUFSIZE]; + struct ospf6_interface *o6i; +- char srcname[64], dstname[64]; + unsigned char type; + + /* get socket */ + sockfd = THREAD_FD (thread); + ++ /* add next read thread */ ++ thread_add_read (master, ospf6_receive, NULL, sockfd); ++ + /* initialize */ + OSPF6_MESSAGE_CLEAR (message); + memset (&ospf6_header, 0, sizeof (struct ospf6_header)); +@@ -1302,22 +1322,10 @@ + o6i = ospf6_interface_lookup_by_index (ifindex); + if (!o6i || !o6i->area) + { +- zlog_warn ("*** received interface ospf6 disabled"); +- thread_add_read (master, ospf6_receive, NULL, sockfd); ++ //zlog_warn ("*** received interface ospf6 disabled"); + return 0; + } + +- /* log */ +- if (IS_OSPF6_DUMP_MESSAGE (type)) +- { +- inet_ntop (AF_INET6, &dst, dstname, sizeof (dstname)); +- inet_ntop (AF_INET6, &src, srcname, sizeof (srcname)); +- zlog_info ("Receive %s on %s", +- ospf6_message_type_string[type], o6i->interface->name); +- zlog_info (" %s -> %s", srcname, dstname); +- ospf6_message_log (message); +- } +- + /* if not passive, process message */ + if (! CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE)) + ospf6_message_process (message, &src, &dst, o6i); +@@ -1325,9 +1333,6 @@ + zlog_info ("Ignore message on passive interface %s", + o6i->interface->name); + +- /* add next read thread */ +- thread_add_read (master, ospf6_receive, NULL, sockfd); +- + return 0; + } + +@@ -1828,6 +1833,9 @@ + return 0; + lsupdate.lsupdate_num = htonl (lsupdate.lsupdate_num); + ++ if (IS_OSPF6_DUMP_LSUPDATE) ++ zlog_info ("MESSAGE: retrsnsmit LSUpdate to %s", o6n->str); ++ + /* statistics */ + o6n->ospf6_stat_retrans_lsupdate++; + +@@ -1915,6 +1923,9 @@ + + o6i = THREAD_ARG (thread); + assert (o6i); ++ ++ if (IS_OSPF6_DUMP_LSACK) ++ zlog_info ("LSACK: Delayed LSAck for %s\n", o6i->interface->name); + + o6i->thread_send_lsack_delayed = (struct thread *) NULL; + +diff -x CVS -urN ospf6d.old/ospf6_neighbor.c ospf6d/ospf6_neighbor.c +--- ospf6d.old/ospf6_neighbor.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_neighbor.c Sat Nov 9 11:25:30 2002 +@@ -179,6 +179,13 @@ + } + + ospf6_lsdb_remove (lsa, nei->retrans_list); ++ ++ if (nei->retrans_list->count == 0) ++ { ++ if (nei->send_update) ++ thread_cancel (nei->send_update); ++ nei->send_update = NULL; ++ } + } + + void +diff -x CVS -urN ospf6d.old/ospf6_network.c ospf6d/ospf6_network.c +--- ospf6d.old/ospf6_network.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_network.c Tue Oct 1 10:28:08 2002 +@@ -255,8 +255,10 @@ + &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 +@@ -273,8 +275,10 @@ + &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 +@@ -290,8 +294,10 @@ + if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, + &mreq6, sizeof (mreq6)) < 0) + zlog_warn ("Network: Leave AllDRouters on ifindex %d Failed", ifindex); ++#if 0 + else + zlog_info ("Network: Leave AllDRouters on ifindex %d", ifindex); ++#endif + } + + /* setsockopt ReUseAddr to on */ +diff -x CVS -urN ospf6d.old/ospf6_route.h ospf6d/ospf6_route.h +--- ospf6d.old/ospf6_route.h Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_route.h Tue Oct 1 00:41:10 2002 +@@ -186,6 +186,9 @@ + 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 *), +diff -x CVS -urN ospf6d.old/ospf6_routemap.c ospf6d/ospf6_routemap.c +--- ospf6d.old/ospf6_routemap.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_routemap.c Tue Oct 1 00:41:10 2002 +@@ -22,9 +22,6 @@ + + #include <zebra.h> + +-#if 1 +-#include "ospf6d.h" +-#else + #include "log.h" + #include "memory.h" + #include "linklist.h" +@@ -32,11 +29,13 @@ + #include "command.h" + #include "vty.h" + #include "routemap.h" ++#include "table.h" + #include "plist.h" + +-#include "ospf6_top.h" +-#include "ospf6_redistribute.h" +-#endif ++#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, +@@ -70,7 +69,8 @@ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + } + +-struct route_map_rule_cmd ospf6_routemap_rule_match_address_prefixlist_cmd = ++struct route_map_rule_cmd ++ospf6_routemap_rule_match_address_prefixlist_cmd = + { + "ipv6 address prefix-list", + ospf6_routemap_rule_match_address_prefixlist, +@@ -83,15 +83,15 @@ + route_map_object_t type, void *object) + { + char *metric_type = rule; +- struct ospf6_route_req *route = object; ++ struct ospf6_external_info *info = object; + + if (type != RMAP_OSPF6) + return RMAP_OKAY; + + if (strcmp (metric_type, "type-2") == 0) +- route->path.metric_type = 2; ++ info->metric_type = 2; + else +- route->path.metric_type = 1; ++ info->metric_type = 1; + + return RMAP_OKAY; + } +@@ -108,7 +108,8 @@ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + } + +-struct route_map_rule_cmd ospf6_routemap_rule_set_metric_type_cmd = ++struct route_map_rule_cmd ++ospf6_routemap_rule_set_metric_type_cmd = + { + "metric-type", + ospf6_routemap_rule_set_metric_type, +@@ -121,14 +122,12 @@ + route_map_object_t type, void *object) + { + char *metric = rule; +- struct ospf6_route_req *route = object; ++ struct ospf6_external_info *info = object; + + if (type != RMAP_OSPF6) + return RMAP_OKAY; + +- route->path.cost = atoi (metric); +- route->path.cost_e2 = atoi (metric); +- ++ info->metric = atoi (metric); + return RMAP_OKAY; + } + +@@ -144,7 +143,8 @@ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + } + +-struct route_map_rule_cmd ospf6_routemap_rule_set_metric_cmd = ++struct route_map_rule_cmd ++ospf6_routemap_rule_set_metric_cmd = + { + "metric", + ospf6_routemap_rule_set_metric, +@@ -157,14 +157,14 @@ + route_map_object_t type, void *object) + { + char *forwarding = rule; +- struct ospf6_route_req *route = object; ++ struct ospf6_external_info *info = object; + + if (type != RMAP_OSPF6) + return RMAP_OKAY; + +- if (inet_pton (AF_INET6, forwarding, &route->nexthop.address) != 1) ++ if (inet_pton (AF_INET6, forwarding, &info->forwarding) != 1) + { +- memset (&route->nexthop.address, 0, sizeof (struct in6_addr)); ++ memset (&info->forwarding, 0, sizeof (struct in6_addr)); + return RMAP_ERROR; + } + +@@ -183,7 +183,8 @@ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); + } + +-struct route_map_rule_cmd ospf6_routemap_rule_set_forwarding_cmd = ++struct route_map_rule_cmd ++ospf6_routemap_rule_set_forwarding_cmd = + { + "forwarding-address", + ospf6_routemap_rule_set_forwarding, +@@ -331,8 +332,8 @@ + { + route_map_init (); + route_map_init_vty (); +- route_map_add_hook (ospf6_redistribute_routemap_update); +- route_map_delete_hook (ospf6_redistribute_routemap_update); ++ 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); +diff -x CVS -urN ospf6d.old/ospf6_spf.c ospf6d/ospf6_spf.c +--- ospf6d.old/ospf6_spf.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_spf.c Sat Nov 9 11:25:30 2002 +@@ -281,7 +281,7 @@ + static struct in6_addr * + ospf6_spf_get_ipaddr (u_int32_t id, u_int32_t adv_router, u_int32_t ifindex) + { +- char buf[64]; ++ char buf[64], nhbuf[64]; + struct ospf6_interface *o6i; + struct ospf6_neighbor *o6n; + struct ospf6_lsa *lsa; +@@ -303,26 +303,30 @@ + lsa = node.lsa; + + /* return Linklocal Address field if the Link-LSA exists */ +- if (lsa) ++ if (lsa && lsa->header->adv_router == adv_router) + { + struct ospf6_link_lsa *link_lsa; + link_lsa = (struct ospf6_link_lsa *) (lsa->header + 1); + return &link_lsa->llsa_linklocal; + } + +- zlog_warn ("SPF: Can't find Link-LSA for %s, " +- "use source address from his packet", ++ zlog_warn ("SPF: Can't find Link-LSA for %s", + inet_ntop (AF_INET, &adv_router, buf, sizeof (buf))); + + o6n = ospf6_neighbor_lookup (adv_router, o6i); + if (! o6n) + { + inet_ntop (AF_INET, &adv_router, buf, sizeof (buf)); +- zlog_err ("SPF: Can't find neighbor %s in %s", ++ zlog_err ("SPF: Can't find neighbor %s in %s, " ++ "unable to find his linklocal address", + buf, o6i->interface->name); + return (struct in6_addr *) NULL; + } + ++ zlog_warn ("SPF: use packet's source address for %s's nexthop: %s", ++ inet_ntop (AF_INET, &adv_router, buf, sizeof (buf)), ++ inet_ntop (AF_INET6, &o6n->hisaddr, nhbuf, sizeof (nhbuf))); ++ + return &o6n->hisaddr; + } + +@@ -478,18 +482,22 @@ + inet_ntop (AF_INET, &adv_router, buf_router, sizeof (buf_router)); + inet_ntop (AF_INET, &id, buf_id, sizeof (buf_id)); + +- if (type == htons (OSPF6_LSA_TYPE_ROUTER)) +- zlog_err ("SPF: Can't find LSA for W (%s *): not found", +- buf_router); +- else +- zlog_err ("SPF: Can't find LSA for W (%s %s): not found", +- buf_router, buf_id); ++ if (IS_OSPF6_DUMP_SPF) ++ { ++ if (type == htons (OSPF6_LSA_TYPE_ROUTER)) ++ zlog_info ("SPF: Can't find LSA for W (%s *): not found", ++ buf_router); ++ else ++ zlog_info ("SPF: Can't find LSA for W (%s %s): not found", ++ buf_router, buf_id); ++ } + return (struct ospf6_vertex *) NULL; + } + + if (IS_LSA_MAXAGE (lsa)) + { +- zlog_err ("SPF: Associated LSA for W is MaxAge: %s", lsa->str); ++ if (IS_OSPF6_DUMP_SPF) ++ zlog_info ("SPF: Associated LSA for W is MaxAge: %s", lsa->str); + return (struct ospf6_vertex *) NULL; + } + +@@ -504,8 +512,9 @@ + } + if (! backreference) + { +- zlog_err ("SPF: Back reference failed: V: %s, W: %s", +- V->lsa->str, lsa->str); ++ if (IS_OSPF6_DUMP_SPF) ++ zlog_info ("SPF: Back reference failed: V: %s, W: %s", ++ V->lsa->str, lsa->str); + return (struct ospf6_vertex *) NULL; + } + +diff -x CVS -urN ospf6d.old/ospf6_top.c ospf6d/ospf6_top.c +--- ospf6d.old/ospf6_top.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_top.c Tue Oct 1 00:51:40 2002 +@@ -43,7 +43,6 @@ + #include "ospf6_area.h" + #include "ospf6_top.h" + +-#include "ospf6_redistribute.h" + #include "ospf6_route.h" + #include "ospf6_zebra.h" + +@@ -152,7 +151,7 @@ + vty_out (vty, " Supports only single TOS(TOS0) routes%s", VTY_NEWLINE); + + /* Redistribute config */ +- ospf6_redistribute_show_config (vty, ospf6); ++ ospf6_redistribute_show_config (vty); + + /* LSAs */ + vty_out (vty, " Number of AS scoped LSAs is %u%s", +@@ -250,9 +249,6 @@ + + o6->lsdb = ospf6_lsdb_create (); + +- /* route table init */ +- ospf6_redistribute_init (o6); +- + o6->foreach_area = ospf6_top_foreach_area; + o6->foreach_if = ospf6_top_foreach_interface; + o6->foreach_nei = ospf6_top_foreach_neighbor; +@@ -264,12 +260,14 @@ + ospf6_top_topology_remove, + o6->topology_table); + ++#if 0 + snprintf (namebuf, sizeof (namebuf), "External table"); + o6->external_table = ospf6_route_table_create (namebuf); + ospf6_route_hook_register (ospf6_asbr_external_route_add, + ospf6_asbr_external_route_add, + ospf6_asbr_external_route_remove, + o6->external_table); ++#endif /*0*/ + + snprintf (namebuf, sizeof (namebuf), "Top route table"); + o6->route_table = ospf6_route_table_create (namebuf); +diff -x CVS -urN ospf6d.old/ospf6_zebra.c ospf6d/ospf6_zebra.c +--- ospf6d.old/ospf6_zebra.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6_zebra.c Wed Oct 2 17:16:56 2002 +@@ -22,7 +22,7 @@ + #include "ospf6d.h" + + #include "ospf6_interface.h" +-#include "ospf6_redistribute.h" ++#include "ospf6_asbr.h" + + #include "ospf6_linklist.h" + +@@ -202,13 +202,14 @@ + struct stream *s; + struct zapi_ipv6 api; + unsigned long ifindex; +- struct in6_addr nexthop; + struct prefix_ipv6 p; ++ struct in6_addr *nexthop; + char prefixstr[128], nexthopstr[128]; + + s = zclient->ibuf; + ifindex = 0; +- memset (&nexthop, 0, sizeof (struct in6_addr)); ++ nexthop = NULL; ++ memset (&api, 0, sizeof (api)); + + /* Type, flags, message. */ + api.type = stream_getc (s); +@@ -225,7 +226,9 @@ + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) + { + api.nexthop_num = stream_getc (s); +- stream_get (&nexthop, s, 16); ++ nexthop = (struct in6_addr *) ++ malloc (api.nexthop_num * sizeof (struct in6_addr)); ++ stream_get (nexthop, s, api.nexthop_num * sizeof (struct in6_addr)); + } + if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) + { +@@ -256,11 +259,15 @@ + zebra_route_name [api.type], prefixstr, + nexthopstr, ifindex); + } +- ++ + if (command == ZEBRA_IPV6_ROUTE_ADD) +- ospf6_redistribute_route_add (api.type, ifindex, &p); ++ ospf6_asbr_route_add (api.type, ifindex, (struct prefix *) &p, ++ api.nexthop_num, nexthop); + else +- ospf6_redistribute_route_remove (api.type, ifindex, &p); ++ ospf6_asbr_route_remove (api.type, ifindex, (struct prefix *) &p); ++ ++ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) ++ free (nexthop); + + return 0; + } +@@ -448,10 +455,6 @@ + + if (IS_OSPF6_DUMP_ZEBRA) + zlog_info ("ZEBRA: found alternative path to add"); +- +- linklist_remove (nexthop, nexthop_list); +- XFREE (MTYPE_OSPF6_OTHER, nexthop); +- assert (nexthop_list->count == 0); + + memcpy (&seconde_path, &route.path, sizeof (struct ospf6_path)); + type = ADD; +diff -x CVS -urN ospf6d.old/ospf6d.c ospf6d/ospf6d.c +--- ospf6d.old/ospf6d.c Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6d.c Mon Mar 24 17:45:16 2003 +@@ -21,6 +21,8 @@ + + #include "ospf6d.h" + ++#include "ospf6_damp.h" ++ + /* global ospf6d variable */ + int ospf6_sock; + list iflist; +@@ -536,8 +538,8 @@ + return CMD_SUCCESS; + } + +-DEFUN (area_range, +- area_range_cmd, ++DEFUN (ospf6_area_range, ++ ospf6_area_range_cmd, + "area A.B.C.D range X:X::X:X/M", + "OSPFv3 area parameters\n" + "OSPFv3 area ID in IPv4 address format\n" +@@ -689,6 +691,7 @@ + vty_out (vty, " router-id %s%s", buf, VTY_NEWLINE); + + ospf6_redistribute_config_write (vty); ++ ospf6_damp_config_write (vty); + + for (j = listhead (ospf6->area_list); j; nextnode (j)) + { +@@ -745,7 +748,7 @@ + install_element (OSPF6_NODE, &no_interface_area_cmd); + install_element (OSPF6_NODE, &passive_interface_cmd); + install_element (OSPF6_NODE, &no_passive_interface_cmd); +- install_element (OSPF6_NODE, &area_range_cmd); ++ install_element (OSPF6_NODE, &ospf6_area_range_cmd); + + /* Make empty list of top list. */ + if_init (); +@@ -757,6 +760,10 @@ + prefix_list_init (); + + ospf6_dump_init (); ++ ++#ifdef HAVE_OSPF6_DAMP ++ ospf6_damp_init (); ++#endif /*HAVE_OSPF6_DAMP*/ + + ospf6_hook_init (); + ospf6_lsa_init (); +diff -x CVS -urN ospf6d.old/ospf6d.h ospf6d/ospf6d.h +--- ospf6d.old/ospf6d.h Sat Apr 26 23:17:47 2003 ++++ ospf6d/ospf6d.h Fri Apr 25 11:40:31 2003 +@@ -59,7 +59,6 @@ + #include "ospf6_neighbor.h" + #include "ospf6_ism.h" + #include "ospf6_nsm.h" +-#include "ospf6_redistribute.h" + #include "ospf6_route.h" + #include "ospf6_dbex.h" + #include "ospf6_network.h" +@@ -74,7 +73,7 @@ + #define HASHVAL 64 + #define MAXIOVLIST 1024 + +-#define OSPF6_DAEMON_VERSION "0.9.6l" ++#define OSPF6_DAEMON_VERSION "0.9.6p" + + #define AF_LINKSTATE 0xff + diff --git a/net/zebra/pkg-plist b/net/zebra/pkg-plist index 08c293d29b50..c8ec32930086 100644 --- a/net/zebra/pkg-plist +++ b/net/zebra/pkg-plist @@ -1,4 +1,5 @@ sbin/bgpd +sbin/ospf6d sbin/ospfd sbin/ripd sbin/ripngd @@ -7,6 +8,7 @@ sbin/zebractl bin/vtysh etc/zebra/bgpd.conf.sample etc/zebra/bgpd.conf.sample2 +etc/zebra/ospf6d.conf.sample etc/zebra/ospfd.conf.sample etc/zebra/ripd.conf.sample etc/zebra/ripngd.conf.sample diff --git a/net/zebra/pkg-plist.v6 b/net/zebra/pkg-plist.v6 deleted file mode 100644 index a8519a7a98c9..000000000000 --- a/net/zebra/pkg-plist.v6 +++ /dev/null @@ -1,2 +0,0 @@ -sbin/ospf6d -etc/zebra/ospf6d.conf.sample |