freebsd-ports/net/zebra/files/patch-ospf6d
Munechika SUMIKAWA 57848a7fcc Upgrade to ospf6d to 0.9.6p to fix the critical bug on AS-External
LSA refreshing.

Obtained from:	zebra cvs
2003-04-26 23:40:59 +00:00

3427 lines
101 KiB
Text
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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