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 + + * 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 + + * ospf6_interface.c: update link-local address on interface creation. + +2002-11-09 Yasuhiro Ohara + + * 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 + + * ospf6_asbr.c: bug of failing ASE lsa refresh fixed. + * version: 0.9.6n + +2002-10-01 Yasuhiro Ohara + + * 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 * 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 + +#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 +#include + +#include "log.h" +#include "prefix.h" +#include "thread.h" +#include "table.h" +#include "command.h" +#include "vty.h" + +extern struct thread_master *master; + +#include "ospf6_damp.h" + +#ifdef HAVE_OSPF6_DAMP + +#define DELTA_REUSE 10 /* Time granularity for reuse lists */ +#define DELTA_T 5 /* Time granularity for decay arrays */ +#define DEFAULT_HALF_LIFE 60 /* (sec) 1 min */ + +#define DEFAULT_PENALTY 1000 +#define DEFAULT_REUSE 750 +#define DEFAULT_SUPPRESS 2000 + +#define REUSE_LIST_SIZE 256 +#define REUSE_ARRAY_SIZE 1024 + +/* Global variable to access damping configuration */ +struct ospf6_damp_config damp_config; +struct ospf6_damp_config *dc = &damp_config; +u_int reuse_array_offset = 0; +struct route_table *damp_info_table[OSPF6_DAMP_TYPE_MAX]; +struct thread *ospf6_reuse_thread = NULL; + +int ospf6_damp_debug = 0; +#define IS_OSPF6_DEBUG_DAMP (ospf6_damp_debug) + +static struct ospf6_damp_info * +ospf6_damp_lookup (u_short type, struct prefix *name) +{ + struct route_node *node; + + node = route_node_lookup (damp_info_table[type], name); + if (node && node->info) + return (struct ospf6_damp_info *) node->info; + return NULL; +} + +static struct ospf6_damp_info * +ospf6_damp_create (u_short type, struct prefix *name) +{ + struct route_node *node; + struct ospf6_damp_info *di; + char namebuf[64]; + + di = ospf6_damp_lookup (type, name); + if (di) + return di; + + if (IS_OSPF6_DEBUG_DAMP) + { + prefix2str (name, namebuf, sizeof (namebuf)); + zlog_info ("DAMP: create: type: %d, name: %s", type, namebuf); + } + + di = (struct ospf6_damp_info *) + malloc (sizeof (struct ospf6_damp_info)); + memset (di, 0, sizeof (struct ospf6_damp_info)); + di->type = type; + prefix_copy (&di->name, name); + + node = route_node_get (damp_info_table[type], name); + node->info = di; + + return di; +} + +static void +ospf6_damp_delete (u_short type, struct prefix *name) +{ + struct route_node *node; + struct ospf6_damp_info *di; + char namebuf[64]; + + node = route_node_lookup (damp_info_table[type], name); + if (! node || ! node->info) + return; + + di = node->info; + + if (IS_OSPF6_DEBUG_DAMP) + { + prefix2str (&di->name, namebuf, sizeof (namebuf)); + zlog_info ("DAMP: delete: type: %d, name: %s", + di->type, namebuf); + } + + node->info = NULL; + free (di); +} + +/* compute and fill the configuration parameter */ +void +ospf6_damp_init_config (u_int half_life, u_int reuse, + u_int suppress, u_int t_hold) +{ + int i; + double max_ratio, max_ratio1, max_ratio2; + + dc->half_life = half_life ? half_life : DEFAULT_HALF_LIFE; + dc->reuse = reuse ? reuse : DEFAULT_REUSE; + dc->suppress = suppress ? suppress : DEFAULT_SUPPRESS; + dc->t_hold = t_hold ? t_hold : 4 * dc->half_life; + + /* Initialize system-wide params */ + dc->delta_t = DELTA_T; + dc->delta_reuse = DELTA_REUSE; + dc->default_penalty = DEFAULT_PENALTY; + dc->reuse_index_array_size = REUSE_ARRAY_SIZE; + + /* ceiling is the maximum penalty a route may attain */ + /* ceiling = reuse * 2^(T-hold/half-life) */ + dc->ceiling = (int) + (dc->reuse * (pow (2, (double) dc->t_hold / dc->half_life))); + + /* Decay-array computations */ + /* decay_array_size = decay memory/time granularity */ + dc->decay_array_size = ceil ((double) dc->t_hold / dc->delta_t); + dc->decay_array = malloc (sizeof (double) * (dc->decay_array_size)); + + /* Each i-th element is per tick delay raised to the i-th power */ + dc->decay_array[0] = 1.0; + dc->decay_array[1] = exp ((1.0 / (dc->half_life / dc->delta_t)) * log (0.5)); + for (i = 2; i < dc->decay_array_size; i++) + dc->decay_array[i] = dc->decay_array[i - 1] * dc->decay_array[1]; + + /* Reuse-list computations (reuse queue head array ?) */ + dc->reuse_list_size = ceil ((double) dc->t_hold / dc->delta_reuse) + 1; + if (dc->reuse_list_size == 0 || dc->reuse_list_size > REUSE_LIST_SIZE) + dc->reuse_list_size = REUSE_LIST_SIZE; + dc->reuse_list_array = (struct ospf6_damp_info **) + malloc (dc->reuse_list_size * sizeof (struct ospf6_reuse_list *)); + memset (dc->reuse_list_array, 0x00, + dc->reuse_list_size * sizeof (struct ospf6_reuse_list *)); + + /* Reuse-array computations */ + dc->reuse_index_array = malloc (sizeof (int) * dc->reuse_index_array_size); + + /* + * This is the maximum ratio between the current value of the penalty and + * the reuse value which can be indexed by the reuse array. It will be + * limited by the ceiling or by the amount of time that the reuse list + * covers + */ + max_ratio1 = (double) dc->ceiling / dc->reuse; + max_ratio2 = exp ((double) dc->t_hold / dc->half_life) * log10 (2.0); + max_ratio = (max_ratio2 != 0 && max_ratio2 < max_ratio1 ? + max_ratio2 : max_ratio1); + + /* + * reuse array is just an estimator and we need something + * to use the full array + */ + dc->scale_factor = (double) dc->reuse_index_array_size / (max_ratio - 1); + + for (i = 0; i < dc->reuse_index_array_size; i++) + { + dc->reuse_index_array[i] = (int) + (((double) dc->half_life / dc->delta_reuse) * + log10 (1.0 / (dc->reuse * (1.0 + ((double) i / dc->scale_factor)))) + / log10 (0.5)); + } + + dc->enabled = ON; +} + +static double +ospf6_damp_decay (time_t tdiff) +{ + int index = tdiff / dc->delta_t; + + if (index >= dc->decay_array_size) + return 0; + + return dc->decay_array[index]; +} + +static int +ospf6_damp_reuse_index (int penalty) +{ + int index; + + index = (int) (((double) penalty / dc->reuse - 1.0) * dc->scale_factor); + + if (index >= dc->reuse_index_array_size) + index = dc->reuse_index_array_size - 1; + + return (dc->reuse_index_array[index] - dc->reuse_index_array[0]); +} + +static int +ospf6_reuse_list_lookup (struct ospf6_damp_info *di) +{ + struct ospf6_damp_info *info; + + for (info = dc->reuse_list_array[di->index]; info; info = info->next) + { + if (info == di) + return 1; + } + return 0; +} + +static void +ospf6_reuse_list_remove (struct ospf6_damp_info *di) +{ + if (di->prev) + di->prev->next = di->next; + else + dc->reuse_list_array[di->index] = di->next; + if (di->next) + di->next->prev = di->prev; + + di->index = -1; + di->prev = NULL; + di->next = NULL; +} + +static void +ospf6_reuse_list_add (struct ospf6_damp_info *di) +{ + /* set the index of reuse-array */ + di->index = (reuse_array_offset + (ospf6_damp_reuse_index (di->penalty))) + % dc->reuse_list_size; + + /* insert to the head of the reuse list */ + di->next = dc->reuse_list_array[di->index]; + if (di->next) + di->next->prev = di; + di->prev = NULL; + dc->reuse_list_array[di->index] = di; +} + +/* When we quit damping for a target, we should execute proper event + which have been postponed during damping */ +static void +ospf6_damp_stop (struct ospf6_damp_info *di) +{ + time_t t_now; + char namebuf[64]; + struct timeval now; + + if (IS_OSPF6_DEBUG_DAMP) + { + t_now = time (NULL); + prefix2str (&di->name, namebuf, sizeof (namebuf)); + gettimeofday (&now, NULL); + zlog_info ("DAMP: %lu.%06lu stop damping: %ld: type: %d, name: %s", + now.tv_sec, now.tv_usec, + 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 -#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