diff -Naur quagga-0.98.5/configure quagga-0.98.5-manet/configure --- quagga-0.98.5/configure 2005-08-28 08:37:37.000000000 -0700 +++ quagga-0.98.5-manet/configure 2006-02-01 14:07:14.000000000 -0800 @@ -16334,7 +16334,7 @@ }' fi -DEFS=-DHAVE_CONFIG_H +DEFS="-DHAVE_CONFIG_H -DGTNETS -DBUGFIX -DOSPF6_CONFIG -DOSPF6_DELAYED_FLOOD -DOSPF6_MANET -DOSPF6_MANET_MPR_FLOOD -DOSPF6_MANET_MDR_FLOOD -DOSPF6_MANET_DIFF_HELLO -DUSER_CHECKSUM -DOSPF6_MANET_MDR_FLOOD_DD -DOSPF6_MANET_MPR_SP" ac_libobjs= ac_ltlibobjs= diff -Naur quagga-0.98.5/doc/defines.texi quagga-0.98.5-manet/doc/defines.texi --- quagga-0.98.5/doc/defines.texi 2005-08-28 08:39:49.000000000 -0700 +++ quagga-0.98.5-manet/doc/defines.texi 1969-12-31 16:00:00.000000000 -0800 @@ -1,13 +0,0 @@ -@c -*- texinfo -*- -@c doc/defines.texi. Generated from defines.texi.in by configure. - -@c Set variables -@set PACKAGE_NAME Quagga -@set AUTHORS Kunihiro Ishiguro, et al. -@set COPYRIGHT_YEAR 1999-2005 -@set COPYRIGHT_STR Copyright @copyright{} @value{COPYRIGHT_YEAR} @value{AUTHORS} - -@c These may vary with installation environment. -@set INSTALL_PREFIX_ETC /etc/quagga -@set INSTALL_PREFIX_SBIN /usr/sbin -@set INSTALL_PREFIX_STATE /var/run/quagga diff -Naur quagga-0.98.5/lib/linklist.h quagga-0.98.5-manet/lib/linklist.h --- quagga-0.98.5/lib/linklist.h 2005-06-27 10:06:48.000000000 -0700 +++ quagga-0.98.5-manet/lib/linklist.h 2006-02-01 14:02:42.000000000 -0800 @@ -22,6 +22,11 @@ #ifndef _ZEBRA_LINKLIST_H #define _ZEBRA_LINKLIST_H +#ifdef GTNETS +typedef struct list *pList; +typedef struct listnode *plistnode; +#endif //GTNETS + struct listnode { struct listnode *next; diff -Naur quagga-0.98.5/lib/vector.h quagga-0.98.5-manet/lib/vector.h --- quagga-0.98.5/lib/vector.h 2005-06-27 10:06:48.000000000 -0700 +++ quagga-0.98.5-manet/lib/vector.h 2006-02-01 14:09:21.000000000 -0800 @@ -23,6 +23,10 @@ #ifndef _ZEBRA_VECTOR_H #define _ZEBRA_VECTOR_H +#ifdef GTNETS +typedef struct _vector *pVector; +#endif //GTNETS + /* struct for vector */ struct _vector { diff -Naur quagga-0.98.5/lib/version.h quagga-0.98.5-manet/lib/version.h --- quagga-0.98.5/lib/version.h 2005-08-28 08:39:49.000000000 -0700 +++ quagga-0.98.5-manet/lib/version.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,43 +0,0 @@ -/* lib/version.h. Generated from version.h.in by configure. - * - * Quagga version - * Copyright (C) 1997, 1999 Kunihiro Ishiguro - * - * This file is part of GNU Zebra. - * - * GNU Zebra is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * GNU Zebra is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNU Zebra; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef _ZEBRA_VERSION_H -#define _ZEBRA_VERSION_H - -#define QUAGGA_PROGNAME "Quagga" - -#define QUAGGA_VERSION "0.98.5" - -#define ZEBRA_BUG_ADDRESS "http://bugzilla.quagga.net" - -#define QUAGGA_URL "http://www.quagga.net" - -#define QUAGGA_COPYRIGHT "Copyright 1996-2005 Kunihiro Ishiguro, et al." - -pid_t pid_output (const char *); - -#ifndef HAVE_DAEMON -int daemon(int, int); -#endif - -#endif /* _ZEBRA_VERSION_H */ diff -Naur quagga-0.98.5/ospf6d/Makefile.in quagga-0.98.5-manet/ospf6d/Makefile.in --- quagga-0.98.5/ospf6d/Makefile.in 2005-08-28 08:37:30.000000000 -0700 +++ quagga-0.98.5-manet/ospf6d/Makefile.in 2006-02-01 14:05:21.000000000 -0800 @@ -64,6 +64,7 @@ ospf6_flood.$(OBJEXT) ospf6_route.$(OBJEXT) \ ospf6_intra.$(OBJEXT) ospf6_zebra.$(OBJEXT) \ ospf6_spf.$(OBJEXT) ospf6_proto.$(OBJEXT) ospf6_asbr.$(OBJEXT) \ + ospf6_mdr.$(OBJEXT) ospf6_mpr.$(OBJEXT) \ ospf6_abr.$(OBJEXT) ospf6_snmp.$(OBJEXT) ospf6d.$(OBJEXT) libospf6_a_OBJECTS = $(am_libospf6_a_OBJECTS) am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(examplesdir)" @@ -75,6 +76,7 @@ ospf6_neighbor.$(OBJEXT) ospf6_flood.$(OBJEXT) \ ospf6_route.$(OBJEXT) ospf6_intra.$(OBJEXT) \ ospf6_zebra.$(OBJEXT) ospf6_spf.$(OBJEXT) \ + ospf6_mdr.$(OBJEXT) ospf6_mpr.$(OBJEXT) \ ospf6_proto.$(OBJEXT) ospf6_asbr.$(OBJEXT) ospf6_abr.$(OBJEXT) \ ospf6_snmp.$(OBJEXT) ospf6d.$(OBJEXT) am_ospf6d_OBJECTS = ospf6_main.$(OBJEXT) $(am__objects_1) @@ -241,14 +243,14 @@ ospf6_top.c ospf6_area.c ospf6_interface.c ospf6_neighbor.c \ ospf6_flood.c ospf6_route.c ospf6_intra.c ospf6_zebra.c \ ospf6_spf.c ospf6_proto.c ospf6_asbr.c ospf6_abr.c ospf6_snmp.c \ - ospf6d.c + ospf6_mdr.c ospf6_mpr.c ospf6d.c noinst_HEADERS = \ ospf6_network.h ospf6_message.h ospf6_lsa.h ospf6_lsdb.h \ ospf6_top.h ospf6_area.h ospf6_interface.h ospf6_neighbor.h \ ospf6_flood.h ospf6_route.h ospf6_intra.h ospf6_zebra.h \ ospf6_spf.h ospf6_proto.h ospf6_asbr.h ospf6_abr.h ospf6_snmp.h \ - ospf6d.h + ospf6_mdr.h ospf6_mpr.h ospf6d.h ospf6d_SOURCES = \ ospf6_main.c $(libospf6_a_SOURCES) @@ -350,6 +352,8 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_route.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_snmp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_spf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_mpr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_mdr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_top.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6_zebra.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ospf6d.Po@am__quote@ diff -Naur quagga-0.98.5/ospf6d/ospf6_abr.c quagga-0.98.5-manet/ospf6d/ospf6_abr.c --- quagga-0.98.5/ospf6d/ospf6_abr.c 2004-12-23 22:00:11.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_abr.c 2006-02-20 13:42:12.000000000 -0800 @@ -47,12 +47,16 @@ #include "ospf6_abr.h" #include "ospf6d.h" +#ifdef SIM +#include "sim.h" +#endif //SIM + unsigned char conf_debug_ospf6_abr; int ospf6_is_router_abr (struct ospf6 *o) { - struct listnode *node; + plistnode node; struct ospf6_area *oa; int area_count = 0; @@ -73,7 +77,7 @@ { struct ospf6_area *oa; struct ospf6_route *ro; - struct listnode *node; + plistnode node; for (node = listhead (area->ospf6->area_list); node; nextnode (node)) { @@ -111,7 +115,7 @@ struct ospf6_area *oa; struct ospf6_route *ro; struct ospf6_lsa *old; - struct listnode *node; + plistnode node; /* Withdraw all summary prefixes previously originated */ for (ro = ospf6_route_head (area->summary_prefix); ro; @@ -367,7 +371,11 @@ else { summary->type = route->type; +#ifdef SIM + gettimeofday_sim (&summary->changed, NULL); +#else gettimeofday (&summary->changed, NULL); +#endif //SIM } summary->path.router_bits = route->path.router_bits; @@ -470,7 +478,7 @@ void ospf6_abr_originate_summary (struct ospf6_route *route) { - struct listnode *node; + plistnode node; struct ospf6_area *oa; struct ospf6_route *range = NULL; @@ -656,7 +664,7 @@ { struct ospf6_lsa *lsa; struct ospf6_area *oa; - struct listnode *node; + plistnode node; u_int16_t type; type = htons (OSPF6_LSTYPE_INTER_ROUTER); diff -Naur quagga-0.98.5/ospf6d/ospf6_area.c quagga-0.98.5-manet/ospf6d/ospf6_area.c --- quagga-0.98.5/ospf6d/ospf6_area.c 2004-12-23 22:00:11.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_area.c 2006-02-20 13:42:12.000000000 -0800 @@ -27,7 +27,7 @@ #include "thread.h" #include "vty.h" #include "command.h" -#include "if.h" +#include "lib/if.h" #include "prefix.h" #include "table.h" @@ -136,7 +136,8 @@ struct ospf6_area *oa; struct ospf6_route *route; - oa = XCALLOC (MTYPE_OSPF6_AREA, sizeof (struct ospf6_area)); + oa = (struct ospf6_area *) + XCALLOC (MTYPE_OSPF6_AREA, sizeof (struct ospf6_area)); inet_ntop (AF_INET, &area_id, oa->name, sizeof (oa->name)); oa->area_id = area_id; @@ -148,6 +149,16 @@ oa->lsdb_self = ospf6_lsdb_create (oa); oa->spf_table = ospf6_route_table_create (); +#ifdef OSPF6_MANET_MPR_SP +//Changes by: Stan Ratliff +//Date: November 1st, 2005 +//Reason: Support for an unsynchronized adjacency SPF table +// Copyright (C) 2005 + + //Roy-01 4.1 + //create an unsynchronized adjacency SPF table + oa->spf_table_sync = ospf6_route_table_create (); +#endif //OSPF6_MANET_MPR_SP oa->route_table = ospf6_route_table_create (); oa->route_table->hook_add = ospf6_area_route_hook_add; oa->route_table->hook_remove = ospf6_area_route_hook_remove; @@ -157,9 +168,15 @@ oa->summary_router = ospf6_route_table_create (); /* set default options */ +#ifdef OSPF6_MANET + OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6, 2); + OSPF6_OPT_SET (oa->options, OSPF6_OPT_E, 2); + OSPF6_OPT_SET (oa->options, OSPF6_OPT_R, 2); +#else OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6); OSPF6_OPT_SET (oa->options, OSPF6_OPT_E); OSPF6_OPT_SET (oa->options, OSPF6_OPT_R); +#endif //OSPF6_MANET oa->ospf6 = o; listnode_add_sort (o->area_list, oa); @@ -543,7 +560,15 @@ conf_debug_ospf6_spf = 0; spf_table = ospf6_route_table_create (); +#ifdef OSPF6_MANET_MPR_SP +//Changes by: Stan Ratliff +//Date: November 1st, 2005 +//Reason: Support for an unsynchronized adjacency SPF table +// Copyright (C) 2005 + ospf6_spf_calculation (router_id, spf_table, oa, false); +#else ospf6_spf_calculation (router_id, spf_table, oa); +#endif //OSPF6_MANET_MPR_SP conf_debug_ospf6_spf = tmp_debug_ospf6_spf; diff -Naur quagga-0.98.5/ospf6d/ospf6_area.h quagga-0.98.5-manet/ospf6d/ospf6_area.h --- quagga-0.98.5/ospf6d/ospf6_area.h 2004-09-23 12:18:23.000000000 -0700 +++ quagga-0.98.5-manet/ospf6d/ospf6_area.h 2006-02-20 13:42:12.000000000 -0800 @@ -47,11 +47,15 @@ struct ospf6_route_table *summary_router; /* OSPF interface list */ - struct list *if_list; + pList if_list; struct ospf6_lsdb *lsdb; struct ospf6_lsdb *lsdb_self; +#ifdef OSPF6_MANET_MPR_SP + struct ospf6_route_table *spf_table_sync; +#endif //OSPF6_MANET_MPR_SP + struct ospf6_route_table *spf_table; struct ospf6_route_table *route_table; diff -Naur quagga-0.98.5/ospf6d/ospf6_asbr.c quagga-0.98.5-manet/ospf6d/ospf6_asbr.c --- quagga-0.98.5/ospf6d/ospf6_asbr.c 2004-12-23 22:00:11.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_asbr.c 2006-02-20 13:42:12.000000000 -0800 @@ -36,7 +36,9 @@ #include "ospf6_lsa.h" #include "ospf6_lsdb.h" #include "ospf6_route.h" +#ifndef SIM #include "ospf6_zebra.h" +#endif //SIM #include "ospf6_message.h" #include "ospf6_top.h" @@ -409,7 +411,9 @@ void ospf6_asbr_redistribute_set (int type) { +#ifndef SIM ospf6_zebra_redistribute (type); +#endif //SIM } void @@ -418,12 +422,14 @@ struct ospf6_route *route; struct ospf6_external_info *info; +#ifndef SIM ospf6_zebra_no_redistribute (type); +#endif //SIM for (route = ospf6_route_head (ospf6->external_table); route; route = ospf6_route_next (route)) { - info = route->route_option; + info = (struct ospf6_external_info *) route->route_option; if (info->type != type) continue; @@ -447,8 +453,10 @@ struct listnode *lnode; struct ospf6_area *oa; +#ifndef SIM if (! ospf6_zebra_is_redistribute (type)) return; +#endif //SIM if (IS_OSPF6_DEBUG_ASBR) { @@ -489,7 +497,7 @@ match = ospf6_route_lookup (prefix, ospf6->external_table); if (match) { - info = match->route_option; + info = (struct ospf6_external_info *) match->route_option; /* copy result of route-map */ if (ospf6->rmap[type].map) @@ -604,7 +612,7 @@ return; } - info = match->route_option; + info = (struct ospf6_external_info *) match->route_option; assert (info); if (info->type != type) @@ -751,8 +759,10 @@ { if (type == ZEBRA_ROUTE_OSPF6) continue; +#ifndef SIM if (! ospf6_zebra_is_redistribute (type)) continue; +#endif //SIM if (ospf6->rmap[type].name) vty_out (vty, " redistribute %s route-map %s%s", @@ -780,7 +790,7 @@ for (route = ospf6_route_head (ospf6->external_table); route; route = ospf6_route_next (route)) { - info = route->route_option; + info = (struct ospf6_external_info *) route->route_option; nroute[info->type]++; total++; } @@ -790,8 +800,10 @@ { if (type == ZEBRA_ROUTE_OSPF6) continue; +#ifndef SIM if (! ospf6_zebra_is_redistribute (type)) continue; +#endif //SIM if (ospf6->rmap[type].name) vty_out (vty, " %d: %s with route-map \"%s\"%s%s", nroute[type], @@ -852,8 +864,8 @@ ospf6_routemap_rule_set_metric_type (void *rule, struct prefix *prefix, route_map_object_t type, void *object) { - char *metric_type = rule; - struct ospf6_route *route = object; + char *metric_type = (char *) rule; + struct ospf6_route *route = (struct ospf6_route *) object; if (type != RMAP_OSPF6) return RMAP_OKAY; @@ -893,8 +905,8 @@ ospf6_routemap_rule_set_metric (void *rule, struct prefix *prefix, route_map_object_t type, void *object) { - char *metric = rule; - struct ospf6_route *route = object; + char *metric = (char *) rule; + struct ospf6_route *route = (struct ospf6_route *) object; if (type != RMAP_OSPF6) return RMAP_OKAY; @@ -933,9 +945,10 @@ ospf6_routemap_rule_set_forwarding (void *rule, struct prefix *prefix, route_map_object_t type, void *object) { - char *forwarding = rule; - struct ospf6_route *route = object; - struct ospf6_external_info *info = route->route_option; + char *forwarding = (char *) rule; + struct ospf6_route *route = (struct ospf6_route *) object; + struct ospf6_external_info *info = + (struct ospf6_external_info *) route->route_option; if (type != RMAP_OSPF6) return RMAP_OKAY; @@ -1191,7 +1204,8 @@ void ospf6_asbr_external_route_show (struct vty *vty, struct ospf6_route *route) { - struct ospf6_external_info *info = route->route_option; + struct ospf6_external_info *info = + (struct ospf6_external_info *) route->route_option; char prefix[64], id[16], forwarding[64]; u_int32_t tmp_id; diff -Naur quagga-0.98.5/ospf6d/ospf6d.c quagga-0.98.5-manet/ospf6d/ospf6d.c --- quagga-0.98.5/ospf6d/ospf6d.c 2005-05-31 04:48:20.000000000 -0700 +++ quagga-0.98.5-manet/ospf6d/ospf6d.c 2006-02-20 13:42:12.000000000 -0800 @@ -32,7 +32,9 @@ #include "ospf6_lsdb.h" #include "ospf6_message.h" #include "ospf6_route.h" +#ifndef SIM #include "ospf6_zebra.h" +#endif //SIM #include "ospf6_spf.h" #include "ospf6_top.h" #include "ospf6_area.h" @@ -43,6 +45,20 @@ #include "ospf6_abr.h" #include "ospf6_flood.h" #include "ospf6d.h" +#ifdef SIM +#include "sim.h" +using namespace std; + +/* + * Global Variables SIM + * needed for the quagga C libraries + * They are reassigned to the corresponding instance variable, as needed, + * via the SetGlobals() method + */ +extern struct ospf6 *ospf6; // This is the pointer that we keep rewriting +extern struct thread_master *master; //Also a pointer we keep rewriting +#endif //SIM + #ifdef HAVE_SNMP #include "ospf6_snmp.h" @@ -109,7 +125,9 @@ { config_write_ospf6_debug_message (vty); config_write_ospf6_debug_lsa (vty); +#ifndef SIM config_write_ospf6_debug_zebra (vty); +#endif //SIM config_write_ospf6_debug_interface (vty); config_write_ospf6_debug_neighbor (vty); config_write_ospf6_debug_spf (vty); @@ -1808,8 +1826,9 @@ ospf6_area_init (); ospf6_interface_init (); ospf6_neighbor_init (); +#ifndef SIM ospf6_zebra_init (); - +#endif //SIM ospf6_lsa_init (); ospf6_spf_init (); ospf6_intra_init (); @@ -1826,12 +1845,17 @@ install_element_ospf6_debug_lsa (); install_element_ospf6_debug_interface (); install_element_ospf6_debug_neighbor (); +#ifndef SIM install_element_ospf6_debug_zebra (); +#endif //SIM install_element_ospf6_debug_spf (); install_element_ospf6_debug_route (); install_element_ospf6_debug_asbr (); install_element_ospf6_debug_abr (); install_element_ospf6_debug_flood (); +#ifdef OSPF6_CONFIG + install_element_ospf6_debug_database(); +#endif //OSPF6_CONFIG install_element (VIEW_NODE, &show_version_ospf6_cmd); install_element (ENABLE_NODE, &show_version_ospf6_cmd); @@ -1929,7 +1953,49 @@ /* Make ospf protocol socket. */ ospf6_serv_sock (); +#ifndef SIM thread_add_read (master, ospf6_receive, NULL, ospf6_sock); +#endif //SIM } +#if defined(OSPF6_MANET) || defined(BUGFIX) +char *ip2str(u_int32_t addr) +{ + static char str[16]; + unsigned char *ip; + ip = (unsigned char *) &addr; + sprintf(str,"%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); + return str; +} + +void set_time(struct timeval *t) +{ + struct timeval now; + +#ifdef SIM + gettimeofday_sim (&now, (struct timezone *)NULL); +#else + gettimeofday (&now, (struct timezone *)NULL); +#endif //SIM + t->tv_sec = now.tv_sec; + t->tv_usec = now.tv_usec; + return; +} + +float elapsed_time(struct timeval *t) +{ + struct timeval now; + float T; + +#ifdef SIM + gettimeofday_sim (&now, (struct timezone *)NULL); +#else + gettimeofday (&now, (struct timezone *)NULL); +#endif //SIM + T = (float)(now.tv_sec - t->tv_sec) + + (float)(now.tv_usec - t->tv_usec) / 1000000; + + return T; +} +#endif //OSPF6_MANET diff -Naur quagga-0.98.5/ospf6d/ospf6d.conf.sample quagga-0.98.5-manet/ospf6d/ospf6d.conf.sample --- quagga-0.98.5/ospf6d/ospf6d.conf.sample 2004-05-18 11:57:06.000000000 -0700 +++ quagga-0.98.5-manet/ospf6d/ospf6d.conf.sample 2006-02-03 13:32:53.000000000 -0800 @@ -1,24 +1,49 @@ ! ! Zebra configuration saved from vty -! 2003/11/28 00:49:49 +! 2000/05/11 02:09:37 ! -hostname ospf6d@plant -password zebra +hostname hulk +password hulk +log file /var/log/zebra-ospf6d.log log stdout -service advanced-vty ! -debug ospf6 neighbor state +!debug ospf6 message hello +!debug ospf6 message dbdesc +!debug ospf6 message lsreq +!debug ospf6 message lsupdate +!debug ospf6 message lsack +!debug ospf6 neighbor +!debug ospf6 spf database +!debug ospf6 interface +!debug ospf6 abr +!debug ospf6 lsa router +!debug ospf6 zebra +!debug ospf6 route table +! +interface eth1 + ipv6 ospf6 priority 1 + ipv6 ospf6 transmit-delay 1 + ipv6 ospf6 instance-id 0 + ipv6 ospf6 ifmtu 1500 + ipv6 ospf6 cost 1 + ipv6 ospf6 hello-interval 2 + ipv6 ospf6 dead-interval 6 + ipv6 ospf6 retransmit-interval 5 + ipv6 ospf6 network manet-reliable +! ipv6 ospf6 network flood mpr +! ipv6 ospf6 network point-to-multipoint + ipv6 ospf6 network flood mdr + ipv6 ospf6 ackinterval 500 +! ipv6 ospf6 diffhellos + ipv6 ospf6 pushbackinterval 4000 + ipv6 ospf6 backupwaitinterval 500 + ipv6 ospf6 twohoprefresh 3 + ipv6 ospf6 hellorepeatcount 3 + ipv6 ospf6 adjacencyconnectivity biconnected + ipv6 ospf6 lsafullness minhoplsa + ipv6 ospf6 flood-delay 100 ! -interface fxp0 - ipv6 ospf6 cost 1 - ipv6 ospf6 hello-interval 10 - ipv6 ospf6 dead-interval 40 - ipv6 ospf6 retransmit-interval 5 - ipv6 ospf6 priority 0 - ipv6 ospf6 transmit-delay 1 - ipv6 ospf6 instance-id 0 -! -interface lo0 +interface lo ipv6 ospf6 cost 1 ipv6 ospf6 hello-interval 10 ipv6 ospf6 dead-interval 40 @@ -26,27 +51,18 @@ ipv6 ospf6 priority 1 ipv6 ospf6 transmit-delay 1 ipv6 ospf6 instance-id 0 + ipv6 ospf6 network loopback ! router ospf6 - router-id 255.1.1.1 + router-id 10.0.0.2 redistribute static route-map static-ospf6 - interface fxp0 area 0.0.0.0 -! -access-list access4 permit 127.0.0.1/32 + interface eth1 area 0.0.0.0 + interface lo area 0.0.0.0 ! -ipv6 access-list access6 permit 3ffe:501::/32 -ipv6 access-list access6 permit 2001:200::/48 -ipv6 access-list access6 permit ::1/128 +ipv6 prefix-list hostroute seq 10 permit 3ffe:501:100c:4380::/60 le 128 ge 128 ! -ipv6 prefix-list test-prefix seq 1000 deny any -! -route-map static-ospf6 permit 10 - match ipv6 address prefix-list test-prefix +route-map static-ospf6 permit 50 + match ipv6 address prefix-list hostroute set metric-type type-2 - set metric 2000 -! -line vty - access-class access4 - ipv6 access-class access6 - exec-timeout 0 0 + set metric 30 ! diff -Naur quagga-0.98.5/ospf6d/ospf6d.h quagga-0.98.5-manet/ospf6d/ospf6d.h --- quagga-0.98.5/ospf6d/ospf6d.h 2004-09-13 07:01:13.000000000 -0700 +++ quagga-0.98.5-manet/ospf6d/ospf6d.h 2006-02-20 13:42:12.000000000 -0800 @@ -118,6 +118,18 @@ void ospf6_debug (); void ospf6_init (); +#if defined(BUGFIX) || defined(OSPF6_MANET) +char *ip2str(u_int32_t addr); +void set_time(struct timeval *t); +float elapsed_time(struct timeval *t); +#endif //OSPF6_MANET + +#if defined(BUGFIX) || defined(OSPF6_MANET) +typedef char boolean; +#define false 0 +#define true 1 +#endif //BUGFIX + #endif /* OSPF6D_H */ diff -Naur quagga-0.98.5/ospf6d/ospf6_flood.c quagga-0.98.5-manet/ospf6d/ospf6_flood.c --- quagga-0.98.5/ospf6d/ospf6_flood.c 2004-12-23 22:00:11.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_flood.c 2006-02-20 13:42:12.000000000 -0800 @@ -41,6 +41,19 @@ #include "ospf6_neighbor.h" #include "ospf6_flood.h" +#ifdef SIM +#include "sim.h" +#include "ospf6_sim_printing.h" +#endif //SIM +#if defined(OSPF6_MANET) || defined(BUGFIX) +#include "ospf6d.h" //for settime() +#endif //OSPF6_MANET || BUGFIX +#ifdef OSPF6_MANET_MPR_FLOOD +#include "ospf6_mpr.h" +#endif //OSPF6_MANET_MPR_FLOOD +#ifdef OSPF6_MANET_MDR_FLOOD +#include "ospf6_mdr.h" +#endif //OSPF6_MANET_MDR_FLOOD unsigned char conf_debug_ospf6_flooding; @@ -108,9 +121,30 @@ return; } +#ifdef BUGFIX + set_time(&lsa->originated); +#endif //BUGFIX + +#ifdef SIM //ETRACE + char id[16], adv_router[16]; + inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); + inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,sizeof (adv_router)); + TraceEvent_sim(2,"Orig LSA %s -id %s -advrt %s -age %d -seq %lu -len %d", + ospf6_lstype_name(lsa->header->type), id, adv_router, + ntohs(age_mask(lsa->header)), ntohl(lsa->header->seqnum), + ntohs(lsa->header->length)); +#endif //ETRACE + /* store it in the LSDB for self-originated LSAs */ lsdb_self = ospf6_get_scoped_lsdb_self (lsa); ospf6_lsdb_add (ospf6_lsa_copy (lsa), lsdb_self); +#ifdef OSPF6_CONFIG + if (IS_OSPF6_DEBUG_DATABASE (DATABASE_DETAIL)) + ospf6_debug_lsdb_show(OSPF6_DEBUG_DATABASE_DETAIL, lsdb_self); + else if (IS_OSPF6_DEBUG_DATABASE (DATABASE)) + ospf6_debug_lsdb_show(OSPF6_DEBUG_DATABASE, lsdb_self); +#endif //OSPF6_CONFIG + lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa, LS_REFRESH_TIME); @@ -217,6 +251,21 @@ /* Remove the old instance from all neighbors' Link state retransmission list (RFC2328 13.2 last paragraph) */ +#ifdef OSPF6_MANET_TEMPORARY_LSDB + if (lsa->cache == 1) //XXX what should be done with old + old = ospf6_lsdb_lookup_cache (lsa->header->type, lsa->header->id, + lsa->header->adv_router, lsa->lsdb); + else + { + old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, + lsa->header->adv_router, lsa->lsdb); + if (old) + { + THREAD_OFF (old->expire); + ospf6_flood_clear (old); + } + } +#else old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, lsa->header->adv_router, lsa->lsdb); if (old) @@ -224,8 +273,14 @@ THREAD_OFF (old->expire); ospf6_flood_clear (old); } +#endif //OSPF6_MANET_TEMPORARY_LSDB +#ifdef SIM + gettimeofday_sim (&now, (struct timezone *) NULL); +#else gettimeofday (&now, (struct timezone *) NULL); +#endif //SIM + if (! OSPF6_LSA_IS_MAXAGE (lsa)) lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa, MAXAGE + lsa->birth.tv_sec - now.tv_sec); @@ -236,107 +291,659 @@ lsa->installed = now; ospf6_lsdb_add (lsa, lsa->lsdb); +#ifdef SIM_ETRACE_STAT + if (ntohs(lsa->header->type) == OSPF6_LSTYPE_ROUTER) + { + update_statistics(OSPF6_ROUTER_LSA_INSTALL, 1); + update_statistics(OSPF6_ROUTER_LSA_HOPCOUNT, hopcount_mask(lsa->header)>>4); + } +#endif //SIM_ETRACE_STAT + +#ifdef OSPF6_CONFIG + if (IS_OSPF6_DEBUG_DATABASE (DATABASE_DETAIL)) + ospf6_debug_lsdb_show(OSPF6_DEBUG_DATABASE_DETAIL, lsa->lsdb); + else if (IS_OSPF6_DEBUG_DATABASE (DATABASE)) + ospf6_debug_lsdb_show(OSPF6_DEBUG_DATABASE, lsa->lsdb); +#endif //OSPF6_CONFIG + +#ifdef OSPF6_MANET_TEMPORARY_LSDB + if (lsa->cache == 1) + return; +#endif //OSPF6_MANET_TEMPORARY_LSDB + +#ifdef OSPF6_MANET_MPR_FLOOD +{ +// Chandra03 3.4.2 paragraph 1 +// If you get a new LSA, update your 2hop neighbor list accordingly + + struct ospf6_neighbor *on; + plistnode i; + struct ospf6_interface *oi; + struct interface *ifp; + + if (lsa->header->type == htons(OSPF6_LSTYPE_ROUTER)) + { + for (i = listhead(iflist); i; nextnode(i)) + { + ifp = (struct interface *) getdata (i); + oi = (struct ospf6_interface *) ifp->info; + if (!oi || oi->type != OSPF6_IFTYPE_MANETRELIABLE || + oi->flooding != OSPF6_FLOOD_MPR_SDCDS) + continue; + on = ospf6_neighbor_lookup(lsa->header->adv_router, oi); + if (on) + update_2hop_neighbor_list(on, lsa->header); + } + } +} +#endif //OSPF6_MANET_MPR_FLOOD return; } -/* RFC2740 section 3.5.2. Sending Link State Update packets */ -/* RFC2328 section 13.3 Next step in the flooding procedure */ +#ifdef OSPF6_MANET_MPR_FLOOD +//Chandra03 3.4.8 void -ospf6_flood_interface (struct ospf6_neighbor *from, +ospf6_flood_interface_mpr (struct ospf6_neighbor *from, struct ospf6_lsa *lsa, struct ospf6_interface *oi) { - struct listnode *node; + plistnode node; struct ospf6_neighbor *on; struct ospf6_lsa *req; int retrans_added = 0; int is_debug = 0; + struct ospf6_mack *mack; + boolean flood_lsa = true; + +#ifdef SIM_ETRACE_STAT + boolean suppressed_flood = false; +#endif //SIM_ETRACE_STAT + + /* Determine whether the originator of the LSA ("from") is an MPR selector*/ + //Chandra03 3.4.8 paragraph 2 condition 1 + if (from != NULL && +#ifndef CISCO_INTEROP + from->Fbit && +#endif //CISCO_INTEROP + !from->Relay_Abit && + !ospf6_lookup_relay_selector(oi, from->router_id)) + flood_lsa = false; if (IS_OSPF6_DEBUG_FLOODING || IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) - { - is_debug++; - zlog_debug ("Flooding on %s: %s", oi->interface->name, lsa->name); - } + { + is_debug++; + zlog_debug ("Flooding on %s: %s", oi->interface->name, lsa->name); + } /* (1) For each neighbor */ for (node = listhead (oi->neighbor_list); node; nextnode (node)) + { + on = (struct ospf6_neighbor *) getdata (node); + + if (is_debug) + zlog_debug ("To neighbor %s", on->name); + + /* (a) if neighbor state < Exchange, examine next */ + if (on->state < OSPF6_NEIGHBOR_EXCHANGE) { - on = (struct ospf6_neighbor *) getdata (node); + if (is_debug) + zlog_debug ("Neighbor state less than ExChange, next neighbor"); + continue; + } + /* (b) if neighbor not yet Full, check request-list */ + if (on->state != OSPF6_NEIGHBOR_FULL) + { if (is_debug) - zlog_debug ("To neighbor %s", on->name); + zlog_debug ("Neighbor not yet Full"); - /* (a) if neighbor state < Exchange, examin next */ - if (on->state < OSPF6_NEIGHBOR_EXCHANGE) + req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, + lsa->header->adv_router, on->request_list); + if (req == NULL) { if (is_debug) - zlog_debug ("Neighbor state less than ExChange, next neighbor"); - continue; + zlog_debug ("Not on request-list for this neighbor"); + /* fall through */ + } + else + { + /* If new LSA less recent, examin next neighbor */ + if (ospf6_lsa_compare (lsa, req) > 0) + { + if (is_debug) + zlog_debug ("Requesting is newer, next neighbor"); + continue; + } + + /* If the same instance, delete from request-list and + examin next neighbor */ + if (ospf6_lsa_compare (lsa, req) == 0) + { + if (is_debug) + zlog_debug ("Requesting the same, remove it, next neighbor"); + ospf6_lsdb_remove (req, on->request_list); + continue; + } + + /* If the new LSA is more recent, delete from request-list */ + if (ospf6_lsa_compare (lsa, req) < 0) + { + if (is_debug) + zlog_debug ("Received is newer, remove requesting"); + ospf6_lsdb_remove (req, on->request_list); + /* fall through */ + } } + } - /* (b) if neighbor not yet Full, check request-list */ - if (on->state != OSPF6_NEIGHBOR_FULL) - { - if (is_debug) - zlog_debug ("Neighbor not yet Full"); + /* (c) If the new LSA was received from this neighbor, + examin next neighbor */ + if (from == on) + { + if (is_debug) + zlog_debug ("Received is from the neighbor, next neighbor"); + continue; + } + + /* At this point, we are not positive that the neighbor has + an up-to-date instance of this new LSA */ + /* However, in the MANET case, we need to: + i) check whether neighbor sent a multicast ACK for it already + ii) whether I am an active relay for this originator */ + /* Has LSA been acked previously with multicast ack? */ + mack = ospf6_lookup_mack(on, lsa->header); + //Chandra03 3.4.9 paragraph 1 condition 2 + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE && mack) + { //Don't add LSA to neighbor's retransmission list + continue; // examine next neighbor: neighbor already acked + } + + /* check if this is a flooding node. Must check here due to request + * list deletion above */ + if (!flood_lsa) + { +#ifdef SIM_ETRACE_STAT + suppressed_flood = true; /*Flag that transmission was suppressed*/ +#endif //SIM_ETRACE_STAT + /* Add this neighbor (on) to the list of neighbors for which + LSA is stored on pushback list for possible retransmission */ + ospf6_pushback_lsa_add(lsa, on); + continue; + } + + /* (d) add retrans-list, schedule retransmission */ + if (is_debug) + zlog_debug ("Add retrans-list of this neighbor"); + ospf6_increment_retrans_count (lsa); +#ifdef OSPF6_DELAYED_FLOOD + set_time(&lsa->rxmt_time); + ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); + on->thread_send_lsupdate = + ospf6_send_lsupdate_delayed_msec(master, ospf6_lsupdate_send_neighbor, + on, oi->rxmt_interval*1000, on->thread_send_lsupdate); +#else + //thread_add_timer must be used for delayed events + ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); + if (on->thread_send_lsupdate == NULL) + on->thread_send_lsupdate = + thread_add_timer (master, ospf6_lsupdate_send_neighbor, + on, on->ospf6_if->rxmt_interval); +#endif // OSPF6_DELAYED_FLOOD + retrans_added++; + } + +#ifdef SIM_ETRACE_STAT + /* At this point, I have cycled through all neighbors on this i/f */ + if(suppressed_flood) + { + char id[16], adv_router[16]; + inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); + inet_ntop (AF_INET, &lsa->header->adv_router, adv_router, + sizeof (adv_router)); + TraceEvent_sim(2,"Suppress Flood LSA %s -id %s -advrt %s -age %d -seq %lu -len %d from %s", + ospf6_lstype_name(lsa->header->type), id, adv_router, + ntohs(age_mask(lsa->header)), ntohl(lsa->header->seqnum), + ntohs(lsa->header->length), from->name); +#ifdef SIM + ospf6_print_pushback_list_sim(lsa); +#endif //SIM + update_statistics(OSPF6_LSA_FLOOD_SUPPRESS, 1); + } +#endif //SIM_ETRACE_STAT - req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, + /* (2) examin next interface if not added to retrans-list */ + if (retrans_added == 0) + { + if (is_debug) + zlog_debug ("No retransmission scheduled, next interface"); + return; + } + + /* (3) If the new LSA was received on this interface, + and it was from DR or BDR, examin next interface */ + if (from && from->ospf6_if == oi && + (from->router_id == oi->drouter || from->router_id == oi->bdrouter)) + { + if (is_debug) + zlog_debug ("Received is from the I/F's DR or BDR, next interface"); + return; + } + + /* (4) If the new LSA was received on this interface, + and the interface state is BDR, examin next interface */ + if (from && from->ospf6_if == oi && oi->state == OSPF6_INTERFACE_BDR) + { + if (is_debug) + zlog_debug ("Received is from the I/F, itself BDR, next interface"); + return; + } + + //Chandra03 3.4.9 paragraph 1 condition 3 + if (from && from->ospf6_if == oi) + SET_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK); + + /* (5) flood the LSA out the interface. */ + if (is_debug) + zlog_debug ("Schedule flooding for the interface"); + ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list); + +#ifdef SIM_ETRACE_STAT + char id[16], adv_router[16]; + inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); + inet_ntop (AF_INET,&lsa->header->adv_router,adv_router,sizeof (adv_router)); TraceEvent_sim(2,"Schedule Flood LSA %s -id %s -advrt %s -age %d -seq %lu -len %d from %s", + ospf6_lstype_name(lsa->header->type), id, adv_router, + ntohs(age_mask(lsa->header)), ntohl(lsa->header->seqnum), + ntohs(lsa->header->length), from->name); + update_statistics(OSPF6_LSA_FLOOD_RELAY, 1); +#endif //SIM_ETRACE_STAT + +#ifdef OSPF6_DELAYED_FLOOD + oi->thread_send_lsupdate = + ospf6_send_lsupdate_delayed_msec(master, ospf6_lsupdate_send_interface, + oi, oi->flood_delay, + oi->thread_send_lsupdate); +#else + if (oi->thread_send_lsupdate == NULL) + oi->thread_send_lsupdate = + thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0); +#endif //OSPF6_DELAYED_FLOOD +} +#endif //OSPF6_MANET_MPR_FLOOD + +#ifdef OSPF6_MANET_MDR_FLOOD +void +ospf6_flood_interface_mdr (struct ospf6_neighbor *from, + struct ospf6_lsa *lsa, struct ospf6_interface *oi) +{ + plistnode node; + struct ospf6_neighbor *on; + struct ospf6_lsa *req; + int retrans_added = 0; + int is_debug = 0; + struct ospf6_mack *mack; + pList flood_neighbors = list_new(); + boolean flood_lsa = true; + + if (IS_OSPF6_DEBUG_FLOODING || + IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) + { + is_debug++; + zlog_debug ("Flooding on %s: %s", oi->interface->name, lsa->name); + } + + /* (1) For each neighbor */ + for (node = listhead (oi->neighbor_list); node; nextnode (node)) + { + on = (struct ospf6_neighbor *) getdata (node); + + if (is_debug) + zlog_debug ("To neighbor %s", on->name); + + /* (a) if neighbor state < Exchange, examin next */ + // Consider adjacent and (backup) dependent neighbors. + // RGO. Change for version 05, require all bidirectional neighbors + // to be covered + //if (on->state < OSPF6_NEIGHBOR_EXCHANGE + // && !on->dependent && !on->bdependent) + if (on->state < OSPF6_NEIGHBOR_TWOWAY) + { + if (is_debug) + zlog_debug ("Neighbor state less than TwoWay, next neighbor"); + continue; + } + + /* (b) if neighbor not yet Full, check request-list */ + if (on->state >= OSPF6_NEIGHBOR_EXCHANGE && on->state != OSPF6_NEIGHBOR_FULL) + { + if (is_debug) + zlog_debug ("Neighbor not yet Full"); + + req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, lsa->header->adv_router, on->request_list); - if (req == NULL) - { - if (is_debug) - zlog_debug ("Not on request-list for this neighbor"); - /* fall through */ - } - else - { - /* If new LSA less recent, examin next neighbor */ - if (ospf6_lsa_compare (lsa, req) > 0) - { - if (is_debug) - zlog_debug ("Requesting is newer, next neighbor"); - continue; - } - - /* If the same instance, delete from request-list and - examin next neighbor */ - if (ospf6_lsa_compare (lsa, req) == 0) - { - if (is_debug) - zlog_debug ("Requesting the same, remove it, next neighbor"); - ospf6_lsdb_remove (req, on->request_list); - continue; - } - - /* If the new LSA is more recent, delete from request-list */ - if (ospf6_lsa_compare (lsa, req) < 0) - { - if (is_debug) - zlog_debug ("Received is newer, remove requesting"); - ospf6_lsdb_remove (req, on->request_list); - /* fall through */ - } - } + if (req == NULL) + { + if (is_debug) + zlog_debug ("Not on request-list for this neighbor"); + /* fall through */ + } + else + { + /* If new LSA less recent, examin next neighbor */ + if (ospf6_lsa_compare (lsa, req) > 0) + { + if (is_debug) + zlog_debug ("Requesting is newer, next neighbor"); + continue; + } + + /* If the same instance, delete from request-list and + examin next neighbor */ + if (ospf6_lsa_compare (lsa, req) == 0) + { + if (is_debug) + zlog_debug ("Requesting the same, remove it, next neighbor"); + ospf6_lsdb_remove (req, on->request_list); + continue; + } + + /* If the new LSA is more recent, delete from request-list */ + if (ospf6_lsa_compare (lsa, req) < 0) + { + if (is_debug) + zlog_debug ("Received is newer, remove requesting"); + ospf6_lsdb_remove (req, on->request_list); + /* fall through */ + } } + } /* (c) If the new LSA was received from this neighbor, examin next neighbor */ if (from == on) + { + if (is_debug) + zlog_debug ("Received is from the neighbor, next neighbor"); + continue; + } + + //Ogierv3 Section 6 Par 3 + /* At this point, we are not positive that the neighbor has + an up-to-date instance of this new LSA */ + /* However, in the MANET case, we need to: + i) check whether neighbor sent a multicast ACK for it already + ii) whether I am an active relay for this originator */ + /* Has LSA been acked previously with multicast ack? */ + mack = ospf6_lookup_mack(on, lsa->header); + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE && mack) + { //Don't add LSA to neighbor's retransmission list + continue; // examine next neighbor: neighbor already acked + } + /* Here, checking for coverage of this neighbor on the sender's RNL. + If not present, I add this to the flood_neighbors list. + If LSA was received as a unicast, however, can't assume that + neighbor "on" was covered by the transmission, so still need to + add to flood_neighbors regardless of from->rnl*/ + if (from) + if (!from->Report2Hop || + (!CHECK_FLAG (lsa->flag, OSPF6_LSA_RECVMCAST)) || + !ospf6_mdr_lookup_neighbor(from->rnl, on->router_id)) + listnode_add(flood_neighbors, on); + + // Retransmit only to adjacent neighbors. + if (on->state < OSPF6_NEIGHBOR_EXCHANGE) + continue; + + /* (d) add retrans-list, schedule retransmission */ + if (is_debug) + zlog_debug ("Add retrans-list of this neighbor"); + ospf6_increment_retrans_count (lsa); + +#ifdef OSPF6_DELAYED_FLOOD + set_time(&lsa->rxmt_time); + ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); + on->thread_send_lsupdate = + ospf6_send_lsupdate_delayed_msec(master, ospf6_lsupdate_send_neighbor, + on, oi->rxmt_interval*1000, on->thread_send_lsupdate); +#else + //thread_add_timer must be used for delayed events + ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); + if (on->thread_send_lsupdate == NULL) + on->thread_send_lsupdate = + thread_add_timer (master, ospf6_lsupdate_send_neighbor, + on, oi->rxmt_interval); +#endif // OSPF6_DELAYED_FLOOD + retrans_added++; + + } + + /* (2) examin next interface if not added to retrans-list */ + /* + if (retrans_added == 0) + { + if (is_debug) + zlog_debug ("No retransmission scheduled, next interface"); + list_delete (flood_neighbors); + return; + } + */ + + //Ogierv3 Section 6 - Remove (3) and (4) + + //Ogierv3 Section 6 - Replace (5) + //Ogierv3 Forwarding Procedure bullet(a) + if (from && oi->mdr_level == OSPF6_MDR) + { + if (flood_neighbors->count == 0) + flood_lsa = false; + } + + //Ogierv3 Forwarding Procedure bullet(c) + if (from && oi->mdr_level == OSPF6_BMDR) + { + for (node = listhead(flood_neighbors); node; nextnode (node)) + { + on = (struct ospf6_neighbor *) getdata (node); + ospf6_pushback_lsa_add(lsa, on); + } + flood_lsa = false; + } + + if (from && oi->mdr_level == OSPF6_OTHER) + { + //OTHER routers do not flood + flood_lsa = false; + } + list_delete (flood_neighbors); + + if (!flood_lsa) + { +#ifdef SIM_ETRACE_STAT + char id[16], adv_router[16]; + inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); + inet_ntop (AF_INET, &lsa->header->adv_router, adv_router, + sizeof (adv_router)); + TraceEvent_sim(2,"Suppress Flood LSA %s -id %s -advrt %s -age %d -seq %lu -len %d from %s", + ospf6_lstype_name(lsa->header->type), id, adv_router, + ntohs(age_mask(lsa->header)), ntohl(lsa->header->seqnum), + ntohs(lsa->header->length), from->name); +#ifdef SIM + ospf6_print_pushback_list_sim(lsa); +#endif //SIM + update_statistics(OSPF6_LSA_FLOOD_SUPPRESS, 1); +#endif //SIM_ETRACE_STAT + return; + } + + if (from && from->ospf6_if == oi) + SET_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK); + + /* (5) flood the LSA out the interface. */ + if (is_debug) + zlog_debug ("Schedule flooding for the interface"); + +#ifdef SIM_ETRACE_STAT + char id[16], adv_router[16]; + inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); + inet_ntop (AF_INET,&lsa->header->adv_router,adv_router,sizeof (adv_router)); + TraceEvent_sim(2,"Schedule Flood LSA %s -id %s -advrt %s -age %d -seq %lu -len %d from %s", + ospf6_lstype_name(lsa->header->type), id, adv_router, + ntohs(age_mask(lsa->header)), ntohl(lsa->header->seqnum), + ntohs(lsa->header->length), from->name); + update_statistics(OSPF6_LSA_FLOOD_RELAY, 1); +#endif //SIM_ETRACE_STAT + + ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list); +#ifdef OSPF6_DELAYED_FLOOD + oi->thread_send_lsupdate = + ospf6_send_lsupdate_delayed_msec(master, ospf6_lsupdate_send_interface, + oi, oi->flood_delay, + oi->thread_send_lsupdate); +#else + if (oi->thread_send_lsupdate == NULL) + oi->thread_send_lsupdate = + thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0); +#endif //OSPF6_DELAYED_FLOOD +} +#endif //OSPF6_MANET_MDR_FLOOD + +/* RFC2740 section 3.5.2. Sending Link State Update packets */ +/* RFC2328 section 13.3 Next step in the flooding procedure */ +void +ospf6_flood_interface (struct ospf6_neighbor *from, + struct ospf6_lsa *lsa, struct ospf6_interface *oi) +{ + plistnode node; + struct ospf6_neighbor *on; + struct ospf6_lsa *req; + int retrans_added = 0; + int is_debug = 0; + +#ifdef OSPF6_CONFIG + if (oi->type == OSPF6_IFTYPE_LOOPBACK) + return; +#endif //OSPF6_CONFIG + +#ifdef OSPF6_MANET + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE) + { +#ifdef OSPF6_MANET_MPR_FLOOD + if (oi->flooding == OSPF6_FLOOD_MPR_SDCDS) + { + ospf6_flood_interface_mpr(from, lsa, oi); + return; + } +#endif //OSPF6_MANET_MPR_FLOOD +#ifdef OSPF6_MANET_MDR_FLOOD + if (oi->flooding == OSPF6_FLOOD_MDR_SICDS) + { + ospf6_flood_interface_mdr(from, lsa, oi); + return; + } +#endif //OSPF6_MANET_MDR_FLOOD + } +#endif //OSPF6_MANET + + if (IS_OSPF6_DEBUG_FLOODING || + IS_OSPF6_DEBUG_FLOOD_TYPE (lsa->header->type)) + { + is_debug++; + zlog_debug ("Flooding on %s: %s", oi->interface->name, lsa->name); + } + + /* (1) For each neighbor */ + for (node = listhead (oi->neighbor_list); node; nextnode (node)) + { + on = (struct ospf6_neighbor *) getdata (node); + + if (is_debug) + zlog_debug ("To neighbor %s", on->name); + + /* (a) if neighbor state < Exchange, examin next */ + if (on->state < OSPF6_NEIGHBOR_EXCHANGE) + { + if (is_debug) + zlog_debug ("Neighbor state less than ExChange, next neighbor"); + continue; + } + + /* (b) if neighbor not yet Full, check request-list */ + if (on->state != OSPF6_NEIGHBOR_FULL) + { + if (is_debug) + zlog_debug ("Neighbor not yet Full"); + + req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, + lsa->header->adv_router, on->request_list); + if (req == NULL) { if (is_debug) - zlog_debug ("Received is from the neighbor, next neighbor"); - continue; + zlog_debug ("Not on request-list for this neighbor"); + /* fall through */ + } + else + { + /* If new LSA less recent, examin next neighbor */ + if (ospf6_lsa_compare (lsa, req) > 0) + { + if (is_debug) + zlog_debug ("Requesting is newer, next neighbor"); + continue; + } + + /* If the same instance, delete from request-list and + examin next neighbor */ + if (ospf6_lsa_compare (lsa, req) == 0) + { + if (is_debug) + zlog_debug ("Requesting the same, remove it, next neighbor"); + ospf6_lsdb_remove (req, on->request_list); + continue; + } + + /* If the new LSA is more recent, delete from request-list */ + if (ospf6_lsa_compare (lsa, req) < 0) + { + if (is_debug) + zlog_debug ("Received is newer, remove requesting"); + ospf6_lsdb_remove (req, on->request_list); + /* fall through */ + } } + } + + /* (c) If the new LSA was received from this neighbor, + examin next neighbor */ + if (from == on) + { + if (is_debug) + zlog_debug ("Received is from the neighbor, next neighbor"); + continue; + } /* (d) add retrans-list, schedule retransmission */ if (is_debug) zlog_debug ("Add retrans-list of this neighbor"); ospf6_increment_retrans_count (lsa); +#ifdef OSPF6_DELAYED_FLOOD + set_time(&lsa->rxmt_time); + ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); + on->thread_send_lsupdate = + ospf6_send_lsupdate_delayed_msec(master, ospf6_lsupdate_send_neighbor, + on, oi->rxmt_interval*1000, on->thread_send_lsupdate); +#elif BUGFIX + //thread_add_timer must be used for delayed events ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); if (on->thread_send_lsupdate == NULL) on->thread_send_lsupdate = thread_add_timer (master, ospf6_lsupdate_send_neighbor, on, on->ospf6_if->rxmt_interval); +#else + ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); + if (on->thread_send_lsupdate == NULL) + on->thread_send_lsupdate = + thread_add_event (master, ospf6_lsupdate_send_neighbor, + on, on->ospf6_if->rxmt_interval); +#endif // OSPF6_DELAYED_FLOOD and BUGFIX retrans_added++; } @@ -367,34 +974,71 @@ return; } +#ifdef BUGFIX + if (from && from->ospf6_if == oi) + SET_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK); +#endif //BUGFIX + /* (5) flood the LSA out the interface. */ if (is_debug) zlog_debug ("Schedule flooding for the interface"); + +#ifdef SIM_ETRACE_STAT + char id[16], adv_router[16]; + inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); + inet_ntop (AF_INET,&lsa->header->adv_router,adv_router,sizeof (adv_router)); TraceEvent_sim(2,"Schedule Flood LSA %s -id %s -advrt %s -age %d -seq %lu -len %d from %s", + ospf6_lstype_name(lsa->header->type), id, adv_router, + ntohs(age_mask(lsa->header)), ntohl(lsa->header->seqnum), + ntohs(lsa->header->length), from->name); + update_statistics(OSPF6_LSA_FLOOD_RELAY, 1); +#endif //SIM_ETRACE_STAT + +#ifdef OSPF6_CONFIG + if (oi->type == OSPF6_IFTYPE_BROADCAST || + oi->type == OSPF6_IFTYPE_MANETRELIABLE || + oi->type == OSPF6_IFTYPE_POINTOMULTIPOINT || + oi->type == OSPF6_IFTYPE_NBMA) +#else if (if_is_broadcast (oi->interface)) - { - ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list); - if (oi->thread_send_lsupdate == NULL) - oi->thread_send_lsupdate = - thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0); - } +#endif //OSPF6_CONFIG + { + ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list); +#ifdef OSPF6_DELAYED_FLOOD + oi->thread_send_lsupdate = + ospf6_send_lsupdate_delayed_msec(master, ospf6_lsupdate_send_interface, + oi, oi->flood_delay, + oi->thread_send_lsupdate); +#else + if (oi->thread_send_lsupdate == NULL) + oi->thread_send_lsupdate = + thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0); +#endif //OSPF6_DELAYED_FLOOD + } else + { + /* reschedule retransmissions to all neighbors */ + for (node = listhead (oi->neighbor_list); node; nextnode (node)) { - /* reschedule retransmissions to all neighbors */ - for (node = listhead (oi->neighbor_list); node; nextnode (node)) - { - on = (struct ospf6_neighbor *) getdata (node); - THREAD_OFF (on->thread_send_lsupdate); - on->thread_send_lsupdate = - thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0); - } + on = (struct ospf6_neighbor *) getdata (node); +#ifdef OSPF6_DELAYED_FLOOD + on->thread_send_lsupdate = + ospf6_send_lsupdate_delayed_msec(master, ospf6_lsupdate_send_neighbor, + on, oi->flood_delay, + on->thread_send_lsupdate); +#else + THREAD_OFF (on->thread_send_lsupdate); + on->thread_send_lsupdate = + thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0); +#endif //OSPF6_DELAYED_FLOOD } + } } void ospf6_flood_area (struct ospf6_neighbor *from, struct ospf6_lsa *lsa, struct ospf6_area *oa) { - struct listnode *node; + plistnode node; struct ospf6_interface *oi; for (node = listhead (oa->if_list); node; nextnode (node)) @@ -419,7 +1063,7 @@ ospf6_flood_process (struct ospf6_neighbor *from, struct ospf6_lsa *lsa, struct ospf6 *process) { - struct listnode *node; + plistnode node; struct ospf6_area *oa; for (node = listhead (process->area_list); node; nextnode (node)) @@ -450,9 +1094,12 @@ void ospf6_flood_clear_interface (struct ospf6_lsa *lsa, struct ospf6_interface *oi) { - struct listnode *node; + plistnode node; struct ospf6_neighbor *on; struct ospf6_lsa *rem; +#ifdef OSPF6_DELAYED_FLOOD + struct ospf6_lsa *update; +#endif //OSPF6_DELAYED_FLOOD for (node = listhead (oi->neighbor_list); node; nextnode (node)) { @@ -468,14 +1115,29 @@ ospf6_decrement_retrans_count (rem); ospf6_lsdb_remove (rem, on->retrans_list); } +#ifdef OSPF6_DELAYED_FLOOD + //remove stale LSA from neighbor update list + update = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, + lsa->header->adv_router, on->lsupdate_list); + if (update && ospf6_lsa_compare (update, lsa) == 0) + {//update is a stale lsa + if (IS_OSPF6_DEBUG_FLOODING) + zlog_info ("Remove %s from neighbor lsupdate_list of %s", + update->name, on->name); + ospf6_lsdb_remove (update, on->lsupdate_list); + } +#endif //OSPF6_DELAYED_FLOOD } } void ospf6_flood_clear_area (struct ospf6_lsa *lsa, struct ospf6_area *oa) { - struct listnode *node; + plistnode node; struct ospf6_interface *oi; +#ifdef OSPF6_DELAYED_FLOOD + struct ospf6_lsa *update; +#endif //OSPF6_DELAYED_FLOOD for (node = listhead (oa->if_list); node; nextnode (node)) { @@ -491,14 +1153,25 @@ continue; #endif/*0*/ - ospf6_flood_clear_interface (lsa, oi); + ospf6_flood_clear_interface (lsa, oi); +#ifdef OSPF6_DELAYED_FLOOD + //remove stale LSA from interface update list + update = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, + lsa->header->adv_router, oi->lsupdate_list); + if (update && ospf6_lsa_compare (update, lsa) == 0) + { //update is a stale lsa + if (IS_OSPF6_DEBUG_FLOODING) + zlog_info ("Remove %s from interface lsupdate_list", update->name); + ospf6_lsdb_remove (update, oi->lsupdate_list); + } +#endif //OSPF6_DELAYED_FLOOD } } void ospf6_flood_clear_process (struct ospf6_lsa *lsa, struct ospf6 *process) { - struct listnode *node; + plistnode node; struct ospf6_area *oa; for (node = listhead (process->area_list); node; nextnode (node)) @@ -523,6 +1196,9 @@ void ospf6_flood_clear (struct ospf6_lsa *lsa) { +#ifdef OSPF6_DELAYED_FLOOD + ospf6_pushback_lsa_delete(lsa); +#endif //OSPF6_DELAYED_FLOOD ospf6_flood_clear_process (lsa, ospf6); } @@ -564,8 +1240,22 @@ /* Delayed acknowledgement */ ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); if (oi->thread_send_lsack == NULL) +#ifdef OSPF6_MANET + { + // Remove "3" magic number -- send ACK after ackInterval + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE) + //Chandra03 3.4.9 paragraph 1 condition 1 + oi->thread_send_lsack = + thread_add_timer_msec (master, ospf6_lsack_send_interface, + oi, oi->ackInterval); + else + oi->thread_send_lsack = + thread_add_timer (master, ospf6_lsack_send_interface, oi, 3); + } +#else oi->thread_send_lsack = thread_add_timer (master, ospf6_lsack_send_interface, oi, 3); +#endif //OSPF6_MANET } else { @@ -588,8 +1278,22 @@ /* Delayed acknowledgement */ ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); if (oi->thread_send_lsack == NULL) +#ifdef OSPF6_MANET + { + // Remove "3" magic number -- send ACK after ackInterval + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE) + //Chandra03 3.4.9 paragraph 1 condition 1 + oi->thread_send_lsack = + thread_add_timer_msec (master, ospf6_lsack_send_interface, + oi, oi->ackInterval); + else + oi->thread_send_lsack = + thread_add_timer (master, ospf6_lsack_send_interface, oi, 3); + } +#else oi->thread_send_lsack = thread_add_timer (master, ospf6_lsack_send_interface, oi, 3); +#endif //OSPF6_MANET } else { @@ -606,10 +1310,31 @@ { if (is_debug) zlog_debug ("Direct acknowledgement (BDR & Duplicate)"); +#ifdef OSPF6_MANET + // This is implementing multicast ACK + /// Delay by ackInterval for coalescing ACKs + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE) + { + ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); + if (oi->thread_send_lsack == NULL) + //Chandra03 3.4.9 paragraph 1 condition 1 + oi->thread_send_lsack = + thread_add_timer_msec (master, ospf6_lsack_send_interface, + oi, oi->ackInterval); + } + else + { + ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list); + if (from->thread_send_lsack == NULL) + from->thread_send_lsack = + thread_add_event (master, ospf6_lsack_send_neighbor, from, 0); + } +#else ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list); if (from->thread_send_lsack == NULL) from->thread_send_lsack = thread_add_event (master, ospf6_lsack_send_neighbor, from, 0); +#endif //OSPF6_MANET return; } @@ -621,8 +1346,14 @@ } static void +#ifdef OSPF6_MANET +ospf6_acknowledge_lsa_allother (struct ospf6_lsa *lsa, int ismore_recent, + struct ospf6_neighbor *from, + struct in6_addr *dst) +#else ospf6_acknowledge_lsa_allother (struct ospf6_lsa *lsa, int ismore_recent, struct ospf6_neighbor *from) +#endif //OSPF6_MANET { struct ospf6_interface *oi; int is_debug = 0; @@ -652,8 +1383,22 @@ /* Delayed acknowledgement */ ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); if (oi->thread_send_lsack == NULL) +#ifdef OSPF6_MANET + { + // Remove "3" magic number -- send ACK after ackInterval + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE) + //Chandra03 3.4.9 paragraph 1 condition 1 + oi->thread_send_lsack = + thread_add_timer_msec (master, ospf6_lsack_send_interface, + oi, oi->ackInterval); + else + oi->thread_send_lsack = + thread_add_timer (master, ospf6_lsack_send_interface, oi, 3); + } +#else oi->thread_send_lsack = thread_add_timer (master, ospf6_lsack_send_interface, oi, 3); +#endif //OSPF6_MANET return; } @@ -672,12 +1417,60 @@ if (CHECK_FLAG (lsa->flag, OSPF6_LSA_DUPLICATE) && ! CHECK_FLAG (lsa->flag, OSPF6_LSA_IMPLIEDACK)) { +#ifdef OSPF6_MANET + //Chandra03 3.4.9 paragraph 1 condition 3 + //only acknowledge the first arrival of the lsa + if(oi->type==OSPF6_IFTYPE_MANETRELIABLE && IN6_IS_ADDR_MULTICAST(dst)) + { + return; //NO ACK + } +#endif //OSPF6_MANET + + if (is_debug) zlog_debug ("Direct acknowledgement (AllOther & Duplicate)"); + +#ifdef OSPF6_MANET + // Send multicast ACK after waiting for ackInterval to coalesce ACKs + // Chandra03 3.4.8.3 paragraph 2 condition 3 + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE) + { + ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsack_list); +#ifdef OSPF6_MANET_MDR_FLOOD + // SICDS sends a multicast ACK immediately if router + // is MDR/BMDR, or if full adjacencies are used. + if (oi->flooding == OSPF6_FLOOD_MDR_SICDS && + (oi->AdjConnectivity == OSPF6_ADJ_FULLYCONNECTED || + oi->mdr_level == OSPF6_MDR || oi->mdr_level == OSPF6_BMDR)) + { + if (oi->thread_send_lsack) + THREAD_OFF(oi->thread_send_lsack); + oi->thread_send_lsack = + thread_add_timer_msec (master, ospf6_lsack_send_interface, + oi, 0); + } + else +#endif //OSPF6_MANET_MDR_FLOOD + if (oi->thread_send_lsack == NULL) + //Chandra03 3.4.9 paragraph 1 condition 1 + //Chandra03 3.4.9 paragraph 1 condition 7 + oi->thread_send_lsack = + thread_add_timer_msec (master, ospf6_lsack_send_interface, + oi, oi->ackInterval); + } + else + { + ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list); + if (from->thread_send_lsack == NULL) + from->thread_send_lsack = + thread_add_event (master, ospf6_lsack_send_neighbor, from, 0); + } +#else ospf6_lsdb_add (ospf6_lsa_copy (lsa), from->lsack_list); if (from->thread_send_lsack == NULL) from->thread_send_lsack = thread_add_event (master, ospf6_lsack_send_neighbor, from, 0); +#endif //OSPF6_MANET return; } @@ -689,8 +1482,13 @@ } void +#ifdef OSPF6_MANET +ospf6_acknowledge_lsa (struct ospf6_lsa *lsa, int ismore_recent, + struct ospf6_neighbor *from, struct in6_addr *dst) +#else ospf6_acknowledge_lsa (struct ospf6_lsa *lsa, int ismore_recent, struct ospf6_neighbor *from) +#endif //OSPF6_MANET { struct ospf6_interface *oi; @@ -700,7 +1498,11 @@ if (oi->state == OSPF6_INTERFACE_BDR) ospf6_acknowledge_lsa_bdrouter (lsa, ismore_recent, from); else +#ifdef OSPF6_MANET + ospf6_acknowledge_lsa_allother (lsa, ismore_recent, from, dst); +#else ospf6_acknowledge_lsa_allother (lsa, ismore_recent, from); +#endif //OSPF6_MANET } /* RFC2328 section 13 (4): @@ -714,7 +1516,7 @@ struct ospf6_interface *oi; struct ospf6_area *oa; struct ospf6 *process = NULL; - struct listnode *i, *j, *k; + plistnode i, j, k; int count = 0; if (! OSPF6_LSA_IS_MAXAGE (lsa)) @@ -748,10 +1550,16 @@ /* RFC2328 section 13 The Flooding Procedure */ void +#ifdef OSPF6_MANET +ospf6_receive_lsa (struct ospf6_lsa_header *lsa_header, + struct ospf6_neighbor *from, + struct in6_addr *dst) +#else ospf6_receive_lsa (struct ospf6_neighbor *from, struct ospf6_lsa_header *lsa_header) +#endif //OSPF6_MANET { - struct ospf6_lsa *new = NULL, *old = NULL, *rem = NULL; + struct ospf6_lsa *new_ = NULL, *old = NULL, *rem = NULL; int ismore_recent; unsigned short cksum; int is_debug = 0; @@ -760,34 +1568,33 @@ assert (from); /* make lsa structure for received lsa */ - new = ospf6_lsa_create (lsa_header); + new_ = ospf6_lsa_create (lsa_header); if (IS_OSPF6_DEBUG_FLOODING || - IS_OSPF6_DEBUG_FLOOD_TYPE (new->header->type)) + IS_OSPF6_DEBUG_FLOOD_TYPE (new_->header->type)) { is_debug++; zlog_debug ("LSA Receive from %s", from->name); - ospf6_lsa_header_print (new); + ospf6_lsa_header_print (new_); } /* (1) LSA Checksum */ - cksum = ntohs (new->header->checksum); - if (ntohs (ospf6_lsa_checksum (new->header)) != cksum) + cksum = ntohs (new_->header->checksum); + if (ntohs (ospf6_lsa_checksum (new_->header)) != cksum) { if (is_debug) zlog_debug ("Wrong LSA Checksum, discard"); - ospf6_lsa_delete (new); + ospf6_lsa_delete (new_); return; } /* (2) Examine the LSA's LS type. - RFC2470 3.5.1. Receiving Link State Update packets */ if (IS_AREA_STUB (from->ospf6_if->area) && - OSPF6_LSA_SCOPE (new->header->type) == OSPF6_SCOPE_AS) + OSPF6_LSA_SCOPE (new_->header->type) == OSPF6_SCOPE_AS) { if (is_debug) zlog_debug ("AS-External-LSA (or AS-scope LSA) in stub area, discard"); - ospf6_lsa_delete (new); + ospf6_lsa_delete (new_); return; } @@ -795,58 +1602,93 @@ RFC2470 3.5.1. Receiving Link State Update packets */ /* Flooding scope check. LSAs with unknown scope are discarded here. Set appropriate LSDB for the LSA */ - switch (OSPF6_LSA_SCOPE (new->header->type)) + switch (OSPF6_LSA_SCOPE (new_->header->type)) { case OSPF6_SCOPE_LINKLOCAL: - new->lsdb = from->ospf6_if->lsdb; + new_->lsdb = from->ospf6_if->lsdb; break; case OSPF6_SCOPE_AREA: - new->lsdb = from->ospf6_if->area->lsdb; + new_->lsdb = from->ospf6_if->area->lsdb; break; case OSPF6_SCOPE_AS: - new->lsdb = from->ospf6_if->area->ospf6->lsdb; + new_->lsdb = from->ospf6_if->area->ospf6->lsdb; break; default: if (is_debug) zlog_debug ("LSA has reserved scope, discard"); - ospf6_lsa_delete (new); + ospf6_lsa_delete (new_); return; } +#ifdef OSPF6_MANET + /* If LSA was received as multicast, flag it (for later flooding decisions)*/ + if (IN6_IS_ADDR_MULTICAST(dst)) + SET_FLAG (new_->flag, OSPF6_LSA_RECVMCAST); +#endif + +#ifdef SIM_ETRACE_STAT + ospf6_lsa_increment_hopcount(new_->header); +#endif //SIM_ETRACE_STAT + /* (4) if MaxAge LSA and if we have no instance, and no neighbor is in states Exchange or Loading */ - if (ospf6_is_maxage_lsa_drop (new, from)) + if (ospf6_is_maxage_lsa_drop (new_, from)) { /* log */ if (is_debug) zlog_debug ("Drop MaxAge LSA with direct acknowledgement."); /* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */ - ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list); +#ifdef OSPF6_MANET + if (from->ospf6_if->type == OSPF6_IFTYPE_MANETRELIABLE) + { + ospf6_lsdb_add (ospf6_lsa_copy (new_), from->ospf6_if->lsack_list); + if (from->ospf6_if->thread_send_lsack == NULL) + //Chandra03 3.4.9 paragraph 1 condition 1 + from->ospf6_if->thread_send_lsack = + thread_add_timer_msec (master, + ospf6_lsack_send_interface, + from->ospf6_if, + from->ospf6_if->ackInterval); + } + else + { + ospf6_lsdb_add (ospf6_lsa_copy (new_), from->lsack_list); + if (from->thread_send_lsack == NULL) + from->thread_send_lsack = + thread_add_event (master, ospf6_lsack_send_neighbor, from, 0); + } +#else + ospf6_lsdb_add (ospf6_lsa_copy (new_), from->lsack_list); if (from->thread_send_lsack == NULL) from->thread_send_lsack = thread_add_event (master, ospf6_lsack_send_neighbor, from, 0); +#endif //OSPF6_MANET /* b) Discard */ - ospf6_lsa_delete (new); + ospf6_lsa_delete (new_); return; } /* (5) */ /* lookup the same database copy in lsdb */ - old = ospf6_lsdb_lookup (new->header->type, new->header->id, - new->header->adv_router, new->lsdb); + old = ospf6_lsdb_lookup (new_->header->type, new_->header->id, + new_->header->adv_router, new_->lsdb); if (old) { - ismore_recent = ospf6_lsa_compare (new, old); - if (ntohl (new->header->seqnum) == ntohl (old->header->seqnum)) + ismore_recent = ospf6_lsa_compare (new_, old); + if (ntohl (new_->header->seqnum) == ntohl (old->header->seqnum)) { if (is_debug) zlog_debug ("Received is duplicated LSA"); - SET_FLAG (new->flag, OSPF6_LSA_DUPLICATE); + SET_FLAG (new_->flag, OSPF6_LSA_DUPLICATE); } } +#ifdef OSPF6_MANET + ospf6_store_mack(from, new_->header); +#endif //OSPF6_MANET + /* if no database copy or received is more recent */ if (old == NULL || ismore_recent < 0) { @@ -857,18 +1699,30 @@ if (old) { struct timeval now, res; +#ifdef SIM + gettimeofday_sim (&now, (struct timezone *) NULL); +#else gettimeofday (&now, (struct timezone *) NULL); +#endif //SIM timersub (&now, &old->installed, &res); +#ifdef OSPF6_CONFIG + if (res.tv_sec < from->ospf6_if->area->ospf6->minLSArrival) +#else if (res.tv_sec < MIN_LS_ARRIVAL) +#endif //OSPF6_CONFIG { if (is_debug) zlog_debug ("LSA can't be updated within MinLSArrival, discard"); - ospf6_lsa_delete (new); + ospf6_lsa_delete (new_); return; /* examin next lsa */ } } - gettimeofday (&new->received, (struct timezone *) NULL); +#ifdef SIM + gettimeofday_sim (&new_->received, (struct timezone *) NULL); +#else + gettimeofday (&new_->received, (struct timezone *) NULL); +#endif //SIM if (is_debug) zlog_debug ("Flood, Install, Possibly acknowledge the received LSA"); @@ -877,8 +1731,8 @@ /* Prevent self-originated LSA to be flooded. this is to make reoriginated instance of the LSA not to be rejected by other routers due to MinLSArrival. */ - if (new->header->adv_router != from->ospf6_if->area->ospf6->router_id) - ospf6_flood (from, new); + if (new_->header->adv_router != from->ospf6_if->area->ospf6->router_id) + ospf6_flood (from, new_); /* (c) Remove the current database copy from all neighbors' Link state retransmission lists. */ @@ -886,13 +1740,33 @@ /* (d), installing lsdb, which may cause routing table calculation (replacing database copy) */ - ospf6_install_lsa (new); + ospf6_install_lsa (new_); + +#ifdef OSPF6_MANET_TEMPORARY_LSDB +{ + struct ospf6_lsa *cache_lsa; + cache_lsa = ospf6_lsdb_lookup_cache(new_->header->type, new_->header->id, + new_->header->adv_router, new_->lsdb); + if (cache_lsa) + { + if (ospf6_lsa_compare(new_, cache_lsa) < 1) + { + // new lsa more rececnt or same as cache_lsa + ospf6_lsdb_remove (cache_lsa, cache_lsa->lsdb); + } + } +} +#endif //OSPF6_MANET_TEMPORARY_LSDB /* (e) possibly acknowledge */ - ospf6_acknowledge_lsa (new, ismore_recent, from); +#ifdef OSPF6_MANET + ospf6_acknowledge_lsa (new_, ismore_recent, from, dst); +#else + ospf6_acknowledge_lsa (new_, ismore_recent, from); +#endif //OSPF6_MANET /* (f) Self Originated LSA, section 13.4 */ - if (new->header->adv_router == from->ospf6_if->area->ospf6->router_id) + if (new_->header->adv_router == from->ospf6_if->area->ospf6->router_id) { /* Self-originated LSA (newer than ours) is received from another router. We have to make a new instance of the LSA @@ -902,15 +1776,15 @@ zlog_debug ("Newer instance of the self-originated LSA"); zlog_debug ("Schedule reorigination"); } - new->refresh = thread_add_event (master, ospf6_lsa_refresh, new, 0); + new_->refresh = thread_add_event (master, ospf6_lsa_refresh, new_, 0); } return; } /* (6) if there is instance on sending neighbor's request list */ - if (ospf6_lsdb_lookup (new->header->type, new->header->id, - new->header->adv_router, from->request_list)) + if (ospf6_lsdb_lookup (new_->header->type, new_->header->id, + new_->header->adv_router, from->request_list)) { /* if no database copy, should go above state (5) */ assert (old); @@ -924,7 +1798,7 @@ /* BadLSReq */ thread_add_event (master, bad_lsreq, from, 0); - ospf6_lsa_delete (new); + ospf6_lsa_delete (new_); return; } @@ -934,9 +1808,74 @@ if (is_debug) zlog_debug ("The same instance as database copy (neither recent)"); +#ifdef OSPF6_MANET + if (from->ospf6_if->type == OSPF6_IFTYPE_MANETRELIABLE && + old->pushBackTimer && ospf6_lsa_compare (new_, old) == 0) + { +#ifdef OSPF6_MANET_MPR_FLOOD + if (from->ospf6_if->flooding == OSPF6_FLOOD_MPR_SDCDS) + { + //Chandra03 3.4.8 paragraph 2 condition 2.2 + // possibly remove old LSA source from the pushback neighbor list + ospf6_pushback_lsa_neighbor_delete(old, from); + if (old->pushBackTimer && ospf6_pushback_check_coverage(old, from)) + { + //if neighbors of "from" cover neighbors in pushback neigh list + //reset pushBackTimer and wait for more acks to come in + THREAD_OFF(old->pushBackTimer); + old->pushBackTimer = + thread_add_timer_msec (master, ospf6_pushback_expiration, old, + from->ospf6_if->pushBackInterval+pushback_jitter(from->ospf6_if)); + +#ifdef SIM_ETRACE_STAT + char id[16], adv_router[16]; + inet_ntop (AF_INET, &old->header->id, id, sizeof (id)); + inet_ntop (AF_INET, &old->header->adv_router, adv_router, + sizeof (adv_router)); + TraceEvent_sim(2,"Re-pushback Flood LSA %s -id %s -advrt %s -age %d -seq %lu -len %d from %s", + ospf6_lstype_name(old->header->type), id, adv_router, + ntohs(age_mask(old->header)), ntohl(old->header->seqnum), + ntohs(old->header->length), from->name); +#endif //SIM_ETRACE_STAT + } + } +#endif //OSPF6_MANET_MPR_FLOOD + +#ifdef OSPF6_MANET_MDR_FLOOD + if (from->ospf6_if->flooding == OSPF6_FLOOD_MDR_SICDS) + { + plistnode n; + u_int32_t *id; + struct ospf6_neighbor *neigh; + + //remove sender from pushback list + ospf6_pushback_lsa_neighbor_delete(old,from); + //loop over neighbor neighbors + //RGO-- enforce that LSA was received as multicast-- otherwise, + // cannot assume that sender's neighbors received + if (IN6_IS_ADDR_MULTICAST(dst)) + { + for (n = listhead(from->rnl); n; nextnode(n)) + { + if (!old->pushBackTimer) + break; + id = (u_int32_t *) getdata(n); + if (*id == from->ospf6_if->area->ospf6->router_id) + continue; + neigh = ospf6_neighbor_lookup(*id, from->ospf6_if); + //remove sender's neighbors from pushback list + if (neigh) + ospf6_pushback_lsa_neighbor_delete(old,neigh); + } + } + } +#endif //OSPF6_MANET_MDR_FLOOD + } +#endif //OSPF6_MANET + /* (a) if on retrans-list, Treat this LSA as an Ack: Implied Ack */ - rem = ospf6_lsdb_lookup (new->header->type, new->header->id, - new->header->adv_router, from->retrans_list); + rem = ospf6_lsdb_lookup (new_->header->type, new_->header->id, + new_->header->adv_router, from->retrans_list); if (rem) { if (is_debug) @@ -944,7 +1883,7 @@ zlog_debug ("It is on the neighbor's retrans-list."); zlog_debug ("Treat as an Implied acknowledgement"); } - SET_FLAG (new->flag, OSPF6_LSA_IMPLIEDACK); + SET_FLAG (new_->flag, OSPF6_LSA_IMPLIEDACK); ospf6_decrement_retrans_count (rem); ospf6_lsdb_remove (rem, from->retrans_list); } @@ -953,9 +1892,13 @@ zlog_debug ("Possibly acknowledge and then discard"); /* (b) possibly acknowledge */ - ospf6_acknowledge_lsa (new, ismore_recent, from); +#ifdef OSPF6_MANET + ospf6_acknowledge_lsa (new_, ismore_recent, from, dst); +#else + ospf6_acknowledge_lsa (new_, ismore_recent, from); +#endif //OSPF6_MANET - ospf6_lsa_delete (new); + ospf6_lsa_delete (new_); return; } @@ -973,9 +1916,19 @@ zlog_debug ("The LSA is in Seqnumber Wrapping"); zlog_debug ("MaxAge & MaxSeqNum, discard"); } - ospf6_lsa_delete (new); + ospf6_lsa_delete (new_); + return; + } + +#ifdef OSPF6_MANET_MDR_FLOOD + // SICDS does not send LSA to non-adjacent neighbor here. + if (from->ospf6_if->flooding == OSPF6_FLOOD_MDR_SICDS && + from->state < OSPF6_NEIGHBOR_EXCHANGE) + { + ospf6_lsa_delete (new_); //XXX Insure return; } +#endif //OSPF6_MANET_MDR_FLOOD /* Otherwise, Send database copy of this LSA to this neighbor */ { @@ -987,17 +1940,214 @@ /* XXX, MinLSArrival check !? RFC 2328 13 (8) */ - ospf6_lsdb_add (ospf6_lsa_copy (old), from->lsupdate_list); - if (from->thread_send_lsupdate == NULL) - from->thread_send_lsupdate = - thread_add_event (master, ospf6_lsupdate_send_neighbor, from, 0); - ospf6_lsa_delete (new); - return; - } +#ifdef OSPF6_MANET + // XXX BOEING Draft Change -- suppressing stale LSA responses + // when the LSA will be sent pushBack algorithm + if (old->pushBackTimer) + { + ospf6_lsa_delete (new_); + return; + } +#endif //OSPF6_MANET + +#if defined(SIM_ETRACE_STAT) + struct ospf6_lsa *old_copy = ospf6_lsa_copy(old); + old_copy->unicast_stale = true; + ospf6_lsdb_add (old_copy, from->lsupdate_list); + +#ifdef OSPF6_MANET_MPR_FLOOD + char id[16], adv_router[16], buf[128]; + inet_ntop (AF_INET, &old->header->id, id, sizeof (id)); + inet_ntop (AF_INET, &old->header->adv_router, adv_router, + sizeof (adv_router)); + inet_ntop (AF_INET6, dst, buf, sizeof(char)*128); + TraceEvent_sim(2,"Database LSA %s -id %s -advrt %s -age %d -seq %lu -len %d is more recent than -age %d -seq %lu -len %d from %s to %s", + ospf6_lstype_name(old->header->type), id, adv_router, + ntohs(age_mask(old->header)), ntohl(old->header->seqnum), + ntohs(old->header->length), ntohs(age_mask(new_->header)), + ntohl(new_->header->seqnum), ntohs(new_->header->length), + from->name, buf); +#endif //OSPF6_MANET_MPR_FLOOD +#else + ospf6_lsdb_add (ospf6_lsa_copy (old), from->lsupdate_list); +#endif //SIM_ETRACE_STAT + +#ifdef OSPF6_DELAYED_FLOOD + from->thread_send_lsupdate = + ospf6_send_lsupdate_delayed_msec(master, ospf6_lsupdate_send_neighbor, + from, from->ospf6_if->flood_delay, + from->thread_send_lsupdate); +#else +#ifdef BUGFIX + //should respond to lsa immediately if not a duplicate, but + //this code could respond to lsa before MinLSArrival passes + //RFC 2328 13 (8) + THREAD_OFF(from->thread_send_lsupdate); + from->thread_send_lsupdate = NULL; +#endif //BUGFIX + if (from->thread_send_lsupdate == NULL) + from->thread_send_lsupdate = + thread_add_event (master, ospf6_lsupdate_send_neighbor, from, 0); +#endif //OSPF6_DELAYED_FLOOD + ospf6_lsa_delete (new_); return; } + return; + } } +#ifdef OSPF6_MANET_TEMPORARY_LSDB +void +ospf6_receive_lsa_below_exchange (struct ospf6_lsa_header *lsa_header, + struct ospf6_interface *oi) +{ + struct ospf6_lsa *new_ = NULL, *old = NULL; + unsigned short cksum; + struct ospf6_lsdb *lsdb = NULL; + int ismore_recent = 1; + int is_debug = 0; + + if(oi->type != OSPF6_IFTYPE_MANETRELIABLE) + return; + + /* make lsa structure for received lsa */ + new_ = ospf6_lsa_create (lsa_header); + + if (IS_OSPF6_DEBUG_FLOODING || + IS_OSPF6_DEBUG_FLOOD_TYPE (new_->header->type)) + { + is_debug++; + zlog_debug ("LSA Receive Below Exchange"); + ospf6_lsa_header_print (new_); + } + + /* (1) LSA Checksum */ + cksum = ntohs (new_->header->checksum); + if (ntohs (ospf6_lsa_checksum (new_->header)) != cksum) + { + if (is_debug) + zlog_info ("Wrong LSA Checksum"); + ospf6_lsa_delete (new_); + return; + } + + /* (2) Examine the LSA's LS type. + RFC2470 3.5.1. Receiving Link State Update packets */ + if (IS_AREA_STUB (oi->area) && + OSPF6_LSA_SCOPE (new_->header->type) == OSPF6_SCOPE_AS) + { + if (is_debug) + zlog_debug ("AS-External-LSA (or AS-scope LSA) in stub area, discard"); + ospf6_lsa_delete (new_); + return; + } + + /* (3) LSA which have reserved scope is discarded + RFC2470 3.5.1. Receiving Link State Update packets */ + /* Flooding scope check. LSAs with unknown scope are discarded here. + Set appropriate LSDB for the LSA */ + switch (OSPF6_LSA_SCOPE (new_->header->type)) + { + case OSPF6_SCOPE_LINKLOCAL: + new_->lsdb = oi->lsdb; + break; + case OSPF6_SCOPE_AREA: + new_->lsdb = oi->area->lsdb; + break; + case OSPF6_SCOPE_AS: + new_->lsdb = oi->area->ospf6->lsdb; + break; + default: + if (is_debug) + zlog_debug ("LSA has reserved scope, discard"); + ospf6_lsa_delete (new_); + return; + } + + /* (4) if MaxAge LSA and if we have no instance, and no neighbor + is in states Exchange or Loading */ + if (ospf6_is_maxage_lsa_drop (new_, NULL)) + { + /* log */ + if (is_debug) + zlog_info ("Drop MaxAge LSA"); + ospf6_lsa_delete (new_); + return; + } + + if (new_->header->adv_router == oi->area->ospf6->router_id) + { //self originated: ignore non-neighbor LSAs XXX? + ospf6_lsa_delete (new_); + return; + } + + lsdb = ospf6_get_scoped_lsdb (new_); + old = ospf6_lsdb_lookup (new_->header->type, new_->header->id, + new_->header->adv_router, lsdb); + if (old && ospf6_lsa_compare (old, new_) < 1) + { + ospf6_lsa_delete (new_); + return; + } + + /* (5) */ + /* limit the size of the LSA cache */ + /* lookup the same database copy in lsdb cache*/ + if (lsdb->count_cache > 200) + { + ospf6_lsa_delete (new_); + return; + } + + old = ospf6_lsdb_lookup_cache (new_->header->type, new_->header->id, + new_->header->adv_router, lsdb); + if (old) + ismore_recent = ospf6_lsa_compare (new_, old); + + /* if no database copy or received is more recent */ + if (old == NULL || ismore_recent < 0) + { + /* (a) MinLSArrival check */ + if (old) + { + struct timeval now, res; +#ifdef SIM + gettimeofday_sim (&now, (struct timezone *) NULL); +#else + gettimeofday (&now, (struct timezone *) NULL); +#endif //SIM + timersub (&now, &old->installed, &res); +#ifdef OSPF6_CONFIG + if (res.tv_sec < oi->area->ospf6->minLSArrival) +#else + if (res.tv_sec < MIN_LS_ARRIVAL) +#endif //OSPF6_CONFIG + { + if (is_debug) + zlog_info ("LSA can't be updated within MinLSArrival"); + ospf6_lsa_delete (new_); + return; /* examin next lsa */ + } + } + +#ifdef SIM + gettimeofday_sim (&new_->installed, (struct timezone *) NULL); +#else + gettimeofday (&new_->installed, (struct timezone *) NULL); +#endif //SIM + new_->cache = 1; + ospf6_lsdb_add (new_, lsdb); +#ifdef OSPF6_CONFIG + if (IS_OSPF6_DEBUG_DATABASE (DATABASE_DETAIL)) + ospf6_debug_lsdb_show(OSPF6_DEBUG_DATABASE_DETAIL, lsdb); + else if (IS_OSPF6_DEBUG_DATABASE (DATABASE)) + ospf6_debug_lsdb_show(OSPF6_DEBUG_DATABASE, lsdb); +#endif //OSPF6_CONFIG + } + else + ospf6_lsa_delete (new_); +} +#endif //OSPF6_MANET_TEMPORARY_LSDB DEFUN (debug_ospf6_flooding, debug_ospf6_flooding_cmd, @@ -1040,8 +2190,3 @@ install_element (CONFIG_NODE, &debug_ospf6_flooding_cmd); install_element (CONFIG_NODE, &no_debug_ospf6_flooding_cmd); } - - - - - diff -Naur quagga-0.98.5/ospf6d/ospf6_flood.h quagga-0.98.5-manet/ospf6d/ospf6_flood.h --- quagga-0.98.5/ospf6d/ospf6_flood.h 2004-09-01 14:36:14.000000000 -0700 +++ quagga-0.98.5-manet/ospf6d/ospf6_flood.h 2006-02-20 13:42:12.000000000 -0800 @@ -54,9 +54,20 @@ void ospf6_flood (struct ospf6_neighbor *from, struct ospf6_lsa *lsa); /* receive & install */ +void ospf6_install_lsa (struct ospf6_lsa *lsa); + +#ifdef OSPF6_MANET +void ospf6_receive_lsa (struct ospf6_lsa_header *header, + struct ospf6_neighbor *from, + struct in6_addr *dst); +#else void ospf6_receive_lsa (struct ospf6_neighbor *from, struct ospf6_lsa_header *header); -void ospf6_install_lsa (struct ospf6_lsa *lsa); +#endif //OSPF6_MANET_MPR_FLOOD +#ifdef OSPF6_MANET_TEMPORARY_LSDB +void ospf6_receive_lsa_below_exchange (struct ospf6_lsa_header *lsa_header, + struct ospf6_interface *oi); +#endif //OSPF6_MANET_TEMPORARY_LSDB int config_write_ospf6_debug_flood (struct vty *vty); void install_element_ospf6_debug_flood (); diff -Naur quagga-0.98.5/ospf6d/ospf6_interface.c quagga-0.98.5-manet/ospf6d/ospf6_interface.c --- quagga-0.98.5/ospf6d/ospf6_interface.c 2005-03-27 06:14:48.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_interface.c 2006-02-20 13:42:12.000000000 -0800 @@ -22,7 +22,7 @@ #include #include "memory.h" -#include "if.h" +#include "lib/if.h" #include "log.h" #include "command.h" #include "thread.h" @@ -41,6 +41,27 @@ #include "ospf6_intra.h" #include "ospf6_spf.h" #include "ospf6d.h" +#ifdef OSPF6_MANET +#include "ospf6_proto.h" +#endif //OSPF6_MANET +#ifdef SIM +#include "sim.h" +#endif //SIM + +#if (defined (USER_CHECKSUM) && !defined(__LINKSYS__))//extra incl for getifaddrs +#include +#include +#include +#include +#include + +static struct in6_addr * +ospf6_interface_get_linklocal_address(struct interface *ifp); + +#endif +#ifdef __LINKSYS__ +int get_linksys_linklocal_address( struct interface *ifp, struct in6_addr *); +#endif unsigned char conf_debug_ospf6_interface = 0; @@ -123,7 +144,15 @@ oi->area = (struct ospf6_area *) NULL; oi->neighbor_list = list_new (); oi->neighbor_list->cmp = ospf6_neighbor_cmp; +#if (defined( __LINKSYS__) && defined(USER_CHECKSUM)) + oi->linklocal_addr = (struct in6_addr *) malloc(sizeof(struct in6_addr)); + get_linksys_linklocal_address(ifp,oi->linklocal_addr); +#elif defined(USER_CHECKSUM) + oi->linklocal_addr = ospf6_interface_get_linklocal_address(ifp); +#elif (!defined( __LINKSYS__) && !defined(USER_CHECKSUM)) oi->linklocal_addr = (struct in6_addr *) NULL; +#endif + oi->instance_id = 0; oi->transdelay = 1; oi->priority = 1; @@ -135,6 +164,63 @@ oi->state = OSPF6_INTERFACE_DOWN; oi->flag = 0; +#ifdef OSPF6_MANET + oi->ackInterval = 1800; + oi->ack_cache_timeout = 100; //Sec + oi->diff_hellos = false; + +#ifdef OSPF6_MANET_MPR_FLOOD + oi->pushBackInterval = 2000; //msecs +#ifdef OSPF6_MANET_MPR_SP + oi->smart_peering = false; + oi->unsynch_adj = false; +#endif// OSPF6_MANET_MPR_SP +#endif //OSPF6_MANET_MPR_FLOOD + +#ifdef OSPF6_MANET_MDR_FLOOD + oi->BackupWaitInterval = 2000; //msec (greater than flood_delay + prop delay) + oi->TwoHopRefresh = 3; + oi->HelloRepeatCount = 3; + oi->NonPersistentMDR = false; + oi->AdjConnectivity = OSPF6_ADJ_BICONNECTED; + oi->LSAFullness = OSPF6_LSA_FULLNESS_MIN; + oi->MDRConstraint = 3; // constraint h for MPN, should be 2 or 3. + oi->full_adj_part_lsa = 0; // For full adjacencies with partial LSAs. +#ifdef OSPF6_MANET_DIFF_HELLO +#ifdef OSPF6_MANET_MDR_LQ + oi->link_quality = true; +#endif //OSPF6_MANET_MDR_LQ +#endif //OSPF6_MANET_DIFF_HELLO +#endif //OSPF6_MANET_MDR_FLOOD +#endif //OSPF6_MANET + +#ifdef SIM_ETRACE_STAT + oi->num_2way_neigh = 0; + set_time(&oi->neigh_2way_change_time); + oi->num_full_neigh = 0; + set_time(&oi->neigh_full_change_time); + set_time(&oi->relaysel_change_time); +#endif //SIM_ETRACE_STAT + +#ifdef OSPF6_DELAYED_FLOOD + oi->flood_delay = 100; //msec +#endif //OSPF6_DELAYED_FLOOD + +#ifdef OSPF6_JITTER + oi->jitter = 100; //msec +#endif // OSPF6_JITTER + +#ifdef OSPF6_CONFIG + if (if_is_broadcast (ifp)) + oi->type = OSPF6_IFTYPE_BROADCAST; + else if (if_is_pointopoint (ifp)) + oi->type = OSPF6_IFTYPE_POINTOPOINT; + else if (if_is_loopback (ifp)) + oi->type = OSPF6_IFTYPE_LOOPBACK; + else + oi->type = OSPF6_IFTYPE_NONE; +#endif //OSPF6_CONFIG + /* Try to adjust I/O buffer size with IfMtu */ oi->ifmtu = ifp->mtu6; iobuflen = ospf6_iobuf_size (ifp->mtu6); @@ -175,6 +261,67 @@ } list_delete (oi->neighbor_list); + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE) + { +#ifdef OSPF6_MANET_MPR_FLOOD +#ifdef OSPF6_MANET_DIFF_HELLO + struct drop_neighbor *drop_neigh; +#endif //OSPF6_MANET_DIFF_HELLO + struct ospf6_relay *relay; + struct ospf6_relay_selector *relay_sel; + + /* two_hop_list -- must be after neighbor delete + * two_hop data structures cleared in one hop list delete above + */ + list_delete (oi->two_hop_list); + +#ifdef OSPF6_MANET_DIFF_HELLO + //drop_neighbor_list + for (n = listhead (oi->drop_neighbor_list); n; nextnode(n)) + { + drop_neigh = (struct drop_neighbor *) getdata(n); + free(drop_neigh->expire_time); + free(drop_neigh); + } + list_delete (oi->drop_neighbor_list); +#endif //OSPF6_MANET_DIFF_HELLO + //relay_list + for (n = listhead(oi->relay_list); n; nextnode(n)) + { + relay = (struct ospf6_relay *) getdata(n); + free(relay->drop_expire_time); + free(relay); + } + list_delete (oi->relay_list); + + //relay_sel_list + for (n = listhead(oi->relay_sel_list); n; nextnode(n)) + { + relay_sel = (struct ospf6_relay_selector *) getdata(n); + free(relay_sel->expire_time); + free(relay_sel); + } + list_delete (oi->relay_sel_list); +#endif //OSPF6_MANET_MPR_FLOOD + +#if defined(OSPF6_MANET_MDR_FLOOD) && defined(OSPF6_MANET_DIFF_HELLO) + if (oi->lnl) + { + struct ospf6_lnl_element *lnl_element; + //lnl + for (n = listhead(oi->lnl); n; nextnode(n)) + { + lnl_element = (struct ospf6_lnl_element *) getdata(n); + free(lnl_element); + } + list_delete (oi->lnl); + } +#endif //OSPF6_MANET_DIFF_HELLO && OSPF6_MANET_MDR_FLOOD + + + } + + THREAD_OFF (oi->thread_send_hello); THREAD_OFF (oi->thread_send_lsupdate); THREAD_OFF (oi->thread_send_lsack); @@ -233,8 +380,77 @@ THREAD_OFF (oi->thread_send_lsupdate); THREAD_OFF (oi->thread_send_lsack); } +#if (defined(USER_CHECKSUM) && defined(__LINKSYS__)) + +/* the linksys and other non-libc2.3 machines do not support + IPv6 address retrieval in getifaddrs(). This routine uses + the /proc/net/if_inet6 to search for an IPv6 address for a + given interface. +*/ +int get_linksys_linklocal_address( struct interface *ifp, struct in6_addr *iAddr) +{ + unsigned char a[8][5], f[32],v6addr[64]; + unsigned int b,c,d,e; + int stat=0, found=0; + + FILE *fp = fopen("/proc/net/if_inet6","r"); + + if(!fp) return -1; + while(!feof(fp)) { + + fscanf(fp, "%4s%4s%4s%4s%4s%4s%4s%4s %x %x %x %x\t%s", + a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],&b,&c,&d,&e,&f); + + if(!strcmp(f,ifp->name)) { /* found our interface! */ + sprintf(v6addr,"%s:%s:%s:%s:%s:%s:%s:%s",a[0],a[1],a[2],a[3],a[4],a[5], + a[6],a[7]); + fprintf(stderr,"%s --> %s\n",f,v6addr); + stat = inet_pton(AF_INET6, v6addr, iAddr); + if(stat) /* we found and address and could decode it */ + found = 1; + } + } + + fclose(fp); + return found; +} +#endif + +#if (defined(USER_CHECKSUM) && !defined(__LINKSYS__)) +/* +* in order to compute the checksum, we need to find the +* source address that will be used. Note that the +* getifaddrs() call used below works for IPv4 only +* in glibc < 2.3. +* +*/ static struct in6_addr * +ospf6_interface_get_linklocal_address(struct interface *ifp) +{ + struct in6_addr *l = (struct in6_addr *) NULL; + + struct ifaddrs *ifap0, *ifap; + struct sockaddr_in6 *sin6=NULL; + + if (getifaddrs(&ifap0)) { + return l; + } + + for (ifap = ifap0; ifap; ifap=ifap->ifa_next) { + if (ifap->ifa_addr == NULL) + continue; + if (!strcmp(ifap->ifa_name,ifp->name) && (ifap->ifa_addr->sa_family == AF_INET6)) { + sin6 = (struct sockaddr_in6 *) ifap->ifa_addr; + if(IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) + l = &sin6->sin6_addr; + } + } + return l; + +} +#else +static struct in6_addr * ospf6_interface_get_linklocal_address (struct interface *ifp) { struct listnode *n; @@ -256,6 +472,7 @@ } return l; } +#endif void ospf6_interface_if_add (struct interface *ifp) @@ -339,8 +556,11 @@ return; /* reset linklocal pointer */ +#if defined(__LINKSYS__) && defined(USER_CHECKSUM) + get_linksys_linklocal_address(ifp,oi->linklocal_addr); +#else oi->linklocal_addr = ospf6_interface_get_linklocal_address (ifp); - +#endif /* if area is null, do not make connected-route list */ if (oi->area == NULL) return; @@ -357,7 +577,9 @@ CONTINUE_IF_ADDRESS_LINKLOCAL (IS_OSPF6_DEBUG_INTERFACE, c->address); CONTINUE_IF_ADDRESS_UNSPECIFIED (IS_OSPF6_DEBUG_INTERFACE, c->address); CONTINUE_IF_ADDRESS_LOOPBACK (IS_OSPF6_DEBUG_INTERFACE, c->address); +#ifndef SIM //XXX BOEING why is v4compat not allowed? CONTINUE_IF_ADDRESS_V4COMPAT (IS_OSPF6_DEBUG_INTERFACE, c->address); +#endif //SIM CONTINUE_IF_ADDRESS_V4MAPPED (IS_OSPF6_DEBUG_INTERFACE, c->address); /* apply filter */ @@ -374,7 +596,7 @@ { if (IS_OSPF6_DEBUG_INTERFACE) zlog_debug ("%s on %s filtered by prefix-list %s ", - buf, oi->interface->name, oi->plist_name); + buf, oi->interface->name, oi->plist_name); continue; } } @@ -648,7 +870,13 @@ thread_add_event (master, ospf6_hello_send, oi, 0); /* decide next interface state */ +#ifdef OSPF6_CONFIG + if (oi->type == OSPF6_IFTYPE_POINTOPOINT || + oi->type == OSPF6_IFTYPE_POINTOMULTIPOINT || + oi->type == OSPF6_IFTYPE_MANETRELIABLE) +#else if (if_is_pointopoint (oi->interface)) +#endif // OSPF6_CONFIG ospf6_interface_state_change (OSPF6_INTERFACE_POINTTOPOINT, oi); else if (oi->priority == 0) ospf6_interface_state_change (OSPF6_INTERFACE_DROTHER, oi); @@ -803,6 +1031,81 @@ else oi = (struct ospf6_interface *) ifp->info; +#ifdef OSPF6_CONFIG + if (oi->type == OSPF6_IFTYPE_BROADCAST) + type = "BROADCAST"; + else if (oi->type == OSPF6_IFTYPE_LOOPBACK) + type = "LOOPBACK"; + else if (oi->type == OSPF6_IFTYPE_NBMA) + type = "NBMA"; + else if (oi->type == OSPF6_IFTYPE_POINTOMULTIPOINT) + type = "POINT TO MULTIPOINT"; + else if (oi->type == OSPF6_IFTYPE_MANETRELIABLE) + type = "MANET"; + else if (oi->type == OSPF6_IFTYPE_POINTOPOINT) + type = "POINT TO POINT"; + vty_out (vty, " OSPF6 type %s%s", type, VTY_NEWLINE); + + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE) + { + if (oi->flooding == OSPF6_FLOOD_MDR_SICDS) + type = "MDR"; + else if (oi->flooding == OSPF6_FLOOD_MPR_SDCDS) + type = "MPR"; + else + type = "BROADCAST"; + vty_out (vty, " OSPF6 MANET flooding type %s%s", type, VTY_NEWLINE); + + if (oi->flooding == OSPF6_FLOOD_MPR_SDCDS) + { + plistnode n; + struct ospf6_relay *relay; + struct ospf6_relay_selector *relay_sel; + char router_id[32]; + + vty_out (vty, " Relay list: "); + for (n = listhead(oi->relay_list); n; nextnode(n)) + { + relay = (struct ospf6_relay *) getdata(n); + if (!relay->active) + continue; + inet_ntop (AF_INET, &relay->router_id, router_id, sizeof(router_id)); + vty_out(vty, "%s,", router_id); + } + vty_out (vty, "%s", VTY_NEWLINE); + + vty_out (vty, " Relay Sel list: "); + for (n = listhead(oi->relay_sel_list); n; nextnode(n)) + { + relay_sel = (struct ospf6_relay_selector *) getdata(n); + inet_ntop (AF_INET, &relay_sel->router_id, router_id,sizeof(router_id)); + vty_out(vty, "%s,", router_id); + } + vty_out (vty, "%s", VTY_NEWLINE); + } + else if (oi->flooding == OSPF6_FLOOD_MDR_SICDS) + { + switch (oi->mdr_level) + { + case OSPF6_MDR: + type = "MDR"; + break; + case OSPF6_BMDR: + type = "BMDR"; + break; + case OSPF6_OTHER: + type = "OTHER"; + break; + default: + type = "???"; + break; + } + vty_out (vty, " Router is an %s router%s", type, VTY_NEWLINE); + } + } + +#endif //OSPF6_CONFIG + vty_out (vty, " Internet Address:%s", VNL); for (i = listhead (ifp->connected); i; nextnode (i)) { @@ -854,7 +1157,11 @@ vty_out (vty, " Number of I/F scoped LSAs is %u%s", oi->lsdb->count, VNL); +#ifdef SIM + gettimeofday_sim (&now, (struct timezone *) NULL); +#else gettimeofday (&now, (struct timezone *) NULL); +#endif //SIM timerclear (&res); if (oi->thread_send_lsupdate) @@ -950,7 +1257,7 @@ return CMD_WARNING; } - oi = ifp->info; + oi = (struct ospf6_interface *) ifp->info; if (oi == NULL) { vty_out (vty, "OSPFv3 is not enabled on %s%s", argv[0], VNL); @@ -1233,6 +1540,438 @@ return CMD_SUCCESS; } +#if defined(OSPF6_CONFIG) && defined(OSPF6_DELAYED_FLOOD) +DEFUN (ipv6_ospf6_flooddelay, + ipv6_ospf6_flooddelay_cmd, + "ipv6 ospf6 flood-delay <1-65535>", + IP6_STR + OSPF6_STR + "Time in msec to coalesce LSAs before sending\n" + SECONDS_STR + ) +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + oi->flood_delay = strtol (argv[0], NULL, 10); + return CMD_SUCCESS; +} +#endif // defined(OSPF6_CONFIG) && defined(OSPF6_DELAYED_FLOOD) + +#if defined(OSPF6_CONFIG) && defined(OSPF6_JITTER) +DEFUN (ipv6_ospf6_jitter, + ipv6_ospf6_jitter_cmd, + "ipv6 ospf6 jitter <1-65535>", + IP6_STR + OSPF6_STR + "Time in msec to jitter sending of all ospf6 packets\n" + SECONDS_STR + ) +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + oi->jitter = strtol (argv[0], NULL, 10); + return CMD_SUCCESS; +} +#endif //OSPF6_CONFIG + +#ifdef OSPF6_MANET +DEFUN (ipv6_ospf6_ackinterval, + ipv6_ospf6_ackinterval_cmd, + "ipv6 ospf6 ackinterval <1-65535>", + IP6_STR + OSPF6_STR + "Interval of time to coalesce acks\n" + SECONDS_STR + ) +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + oi->ackInterval = strtol (argv[0], NULL, 10); + return CMD_SUCCESS; +} + +DEFUN (ipv6_ospf6_diffhellos, + ipv6_ospf6_diffhellos_cmd, + "ipv6 ospf6 diffhellos", + IP6_STR + OSPF6_STR) +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + oi->diff_hellos = true; + + return CMD_SUCCESS; +} + +DEFUN (no_ipv6_ospf6_diffhellos, + no_ipv6_ospf6_diffhellos_cmd, + "no ipv6 ospf6 diffhellos", + IP6_STR + OSPF6_STR) +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + oi->diff_hellos = false; + + return CMD_SUCCESS; +} + +#ifdef OSPF6_MANET_MPR_FLOOD + +#ifdef OSPF6_MANET_MPR_SP +DEFUN (ipv6_ospf6_smartpeering, + ipv6_ospf6_smartpeering_cmd, + "ipv6 ospf6 smartpeering", + IP6_STR + OSPF6_STR) +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + oi->smart_peering = true; + + return CMD_SUCCESS; +} + +DEFUN (no_ipv6_ospf6_smartpeering, + no_ipv6_ospf6_smartpeering_cmd, + "no ipv6 ospf6 smartpeering", + IP6_STR + OSPF6_STR) +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + oi->smart_peering = false; + + return CMD_SUCCESS; +} + +DEFUN (ipv6_ospf6_unsynchadj, + ipv6_ospf6_unsynchadj_cmd, + "ipv6 ospf6 unsynchadj", + IP6_STR + OSPF6_STR) +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + oi->unsynch_adj = true; + + return CMD_SUCCESS; +} + +DEFUN (no_ipv6_ospf6_unsynchadj, + no_ipv6_ospf6_unsynchadj_cmd, + "no ipv6 ospf6 unsynchadj", + IP6_STR + OSPF6_STR) +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + oi->unsynch_adj = false; + + return CMD_SUCCESS; +} +#endif //OSPF6_MANET_MPR_SP + +DEFUN (ipv6_ospf6_pushbackinterval, + ipv6_ospf6_pushbackinterval_cmd, + "ipv6 ospf6 pushbackinterval <1-65535>", + IP6_STR + OSPF6_STR + "Interval of time for non-overlapping relays to wait before flooding\n" + SECONDS_STR + ) +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + oi->pushBackInterval = strtol (argv[0], NULL, 10); + return CMD_SUCCESS; +} +#endif //OSPF6_MANET_MPR_FLOOD + +#ifdef OSPF6_MANET_MDR_FLOOD +DEFUN (ipv6_ospf6_backupwaitinterval, + ipv6_ospf6_backupwaitinterval_cmd, + "ipv6 ospf6 backupwaitinterval <1-65535>", + IP6_STR + OSPF6_STR + "Interval of time for MBDRs to wait before flooding\n" + SECONDS_STR + ) +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + oi->BackupWaitInterval = strtol (argv[0], NULL, 10); + return CMD_SUCCESS; +} + +DEFUN (ipv6_ospf6_twohoprefresh, + ipv6_ospf6_twohoprefresh_cmd, + "ipv6 ospf6 twohoprefresh <1-65535>", + IP6_STR + OSPF6_STR + "Full Hellos are sent every TwoHopRefresh Hellos\n" + SECONDS_STR + ) +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + oi->TwoHopRefresh = strtol (argv[0], NULL, 10); + return CMD_SUCCESS; +} + +DEFUN (ipv6_ospf6_hellorepeatcount, + ipv6_ospf6_hellorepeatcount_cmd, + "ipv6 ospf6 hellorepeatcount <1-65535>", + IP6_STR + OSPF6_STR + "Total hellos in succession that cannot be missed using diff hellos\n" + "Number of successive losses\n" + ) +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + oi->HelloRepeatCount = strtol (argv[0], NULL, 10); + return CMD_SUCCESS; +} + +DEFUN (ipv6_ospf6_nonpersistentmdr, + ipv6_ospf6_nonpersistentmdr_cmd, + "ipv6 ospf6 nonpersistent_mdr", + IP6_STR + OSPF6_STR + "Persistent MDR/MBDR election\n") +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + oi->NonPersistentMDR = true; + + return CMD_SUCCESS; +} + +DEFUN (no_ipv6_ospf6_nonpersistentmdr, + no_ipv6_ospf6_nonpersistentmdr_cmd, + "no ipv6 ospf6 nonpersistent_mdr", + IP6_STR + OSPF6_STR + "No Persistent MDR/MBDR election\n") +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + oi->NonPersistentMDR = false; + + return CMD_SUCCESS; +} + +DEFUN (ipv6_ospf6_adjacencyconnectivity, + ipv6_ospf6_adjacencyconnectivity_cmd, + "ipv6 ospf6 adjacencyconnectivity (uniconnected|biconnected|fully)", + IP6_STR + OSPF6_STR + "Level of adjacencies between neighbors\n" + "Specify uniconnected adjacencies between routers\n" + "Specify biconnected adjacencies between routers\n" + "Specify fully connected adjacencies between routers\n") +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (!oi) + oi = ospf6_interface_create (ifp); + assert (oi); + + if (strncmp (argv[0], "uni", 3) == 0) + oi->AdjConnectivity = OSPF6_ADJ_UNICONNECTED; + else if (strncmp (argv[0], "bi", 2) == 0) + oi->AdjConnectivity = OSPF6_ADJ_BICONNECTED; + else if (strncmp (argv[0], "full", 3) == 0) + oi->AdjConnectivity = OSPF6_ADJ_FULLYCONNECTED; + else + oi->AdjConnectivity = OSPF6_ADJ_BICONNECTED; + + return CMD_SUCCESS; + +} + +DEFUN (ipv6_ospf6_lsafullnesss, + ipv6_ospf6_lsafullness_cmd, + "ipv6 ospf6 lsafullness (minlsa|minhoplsa|mdrfulllsa|fulllsa)", + IP6_STR + OSPF6_STR + "Level of LSA fullness\n" + "Specify min size LSAs (only adjacent neighbors)\n" + "Specify partial LSAs for min-hop routing\n" + "Specify full LSAs from MDR/MBDRs\n" + "Specify full LSAs (all routable neighbors)\n") +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (!oi) + oi = ospf6_interface_create (ifp); + assert (oi); + + if (strncmp (argv[0], "minlsa", 6) == 0) + oi->LSAFullness = OSPF6_LSA_FULLNESS_MIN; + else if (strncmp (argv[0], "minhop", 6) == 0) + oi->LSAFullness = OSPF6_LSA_FULLNESS_MINHOP; + else if (strncmp (argv[0], "minhop2paths", 6) == 0) + oi->LSAFullness = OSPF6_LSA_FULLNESS_MINHOP2PATHS; + else if (strncmp (argv[0], "mdrfull", 6) == 0) + oi->LSAFullness = OSPF6_LSA_FULLNESS_MDRFULL; + else if (strncmp (argv[0], "full", 4) == 0) + oi->LSAFullness = OSPF6_LSA_FULLNESS_FULL; + else + oi->LSAFullness = OSPF6_LSA_FULLNESS_MIN; + + return CMD_SUCCESS; + +} +#endif //OSPF6_MANET_MDR_FLOOD +#endif //OSPF6_MANET + /* interface variable set command */ DEFUN (ipv6_ospf6_deadinterval, ipv6_ospf6_deadinterval_cmd, @@ -1461,6 +2200,201 @@ return CMD_SUCCESS; } +#ifdef OSPF6_CONFIG +DEFUN (ipv6_ospf6_network, + ipv6_ospf6_network_cmd, + "ipv6 ospf6 network (broadcast|non-broadcast|point-to-multipoint|point-to-point|manet-reliable|loopback)", + "IPv6 Information\n" + "OSPF6 interface commands\n" + "Network type\n" + "Specify OSPF6 broadcast multi-access network\n" + "Specify OSPF6 NBMA network\n" + "Specify OSPF6 point-to-multipoint network\n" + "Specify OSPF6 manet-reliable network\n" + "Specify OSPF6 point-to-point network\n" + "Specify OSPF6 loopback\n") +{ + + struct ospf6_interface *oi; + struct interface *ifp; + int old_type; + + ifp = (struct interface *) vty->index; + assert (ifp); + oi = (struct ospf6_interface *) ifp->info; + if (!oi) + oi = ospf6_interface_create (ifp); + assert (oi); + old_type = oi->type; + + if (strncmp (argv[0], "b", 1) == 0) + oi->type = OSPF6_IFTYPE_BROADCAST; + else if (strncmp (argv[0], "n", 1) == 0) + oi->type = OSPF6_IFTYPE_NBMA; + else if (strncmp (argv[0], "point-to-m", 10) == 0) + oi->type = OSPF6_IFTYPE_POINTOMULTIPOINT; + else if (strncmp (argv[0], "point-to-p", 10) == 0) + oi->type = OSPF6_IFTYPE_POINTOPOINT; + else if (strncmp (argv[0], "manet-r", 7) == 0) + oi->type = OSPF6_IFTYPE_MANETRELIABLE; + else if (strncmp (argv[0], "l", 1) == 0) + oi->type = OSPF6_IFTYPE_LOOPBACK; + +#ifdef OSPF6_MANET + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE) + { //install extra structures neccesary for manet interface +#ifdef OSPF6_MANET_MPR_FLOOD + oi->two_hop_list = list_new(); + oi->relay_list = list_new(); + oi->relay_sel_list = list_new(); + oi->mpr_change = true; + +#ifdef OSPF6_MANET_DIFF_HELLO + oi->drop_neighbor_list = list_new(); + oi->scs_num = 0; + oi->increment_scs = false; + oi->full_state = false; + oi->initialization = true; +#endif //OSPF6_MANET_DIFF_HELLO +#endif //OSPF6_MANET_MPR_FLOOD + +#if defined(OSPF6_MANET_MDR_FLOOD) && defined(OSPF6_MANET_DIFF_HELLO) + oi->lnl = list_new(); + oi->hsn = 0; + oi->full_hello_count = 0; +#endif //OSPF6_MANET_DIFF_HELLO && OSPF6_MANET_MDR_FLOOD + } +#endif //OSPF6_MANET + + if (oi->type == old_type) + return CMD_SUCCESS; + + /*for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) + { + struct ospf_interface *oi = rn->info; + + if (!oi) + continue; + oi->type = IF_DEF_PARAMS (ifp)->type; + + if (oi->state > ISM_Down) + { + OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown); + OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceUp); + } + } +*/ + return CMD_SUCCESS; +} + +ALIAS (ipv6_ospf6_network, + ospf6_network_cmd, + "ospf6 network (broadcast|non-broadcast|point-to-multipoint|point-to-point|manet-reliable|loopback)", + "OSPF interface commands\n" + "Network type\n" + "Specify OSPF6 broadcast multi-access network\n" + "Specify OSPF6 NBMA network\n" + "Specify OSPF6 point-to-multipoint network\n" + "Specify OSPF6 manet-reliable network\n" + "Specify OSPF6 point-to-point network\n" + "Specify OSPF6 loopback\n") + +DEFUN (no_ipv6_ospf6_network, + no_ipv6_ospf6_network_cmd, + "no ipv6 ospf6 network", + NO_STR + "IP Information\n" + "OSPF6 interface commands\n" + "Network type\n") +{ + struct ospf6_interface *oi; + struct interface *ifp; + int old_type; + + ifp = (struct interface *) vty->index; + assert (ifp); + oi = (struct ospf6_interface *) ifp->info; + if (!oi) + oi = ospf6_interface_create (ifp); + assert (oi); + old_type = oi->type; + + oi->type = OSPF6_IFTYPE_NONE; + + if (oi->type == old_type) + return CMD_SUCCESS; + +/* + struct route_node *rn; + if (IF_DEF_PARAMS (ifp)->type == old_type) + return CMD_SUCCESS; + + for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn)) + { + + if (!oi) + continue; + + oi->type = IF_DEF_PARAMS (ifp)->type; + + if (oi->state > ISM_Down) + { + OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown); + OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceUp); + } + } +*/ + return CMD_SUCCESS; +} + +ALIAS (no_ipv6_ospf6_network, + no_ospf6_network_cmd, + "no ospf6 network", + NO_STR + "OSPF6 interface commands\n" + "Network type\n") + + +DEFUN (ipv6_ospf6_network_flood, + ipv6_ospf6_network_flood_cmd, + "ipv6 ospf6 network flood (broadcast|mpr|mdr)", + "IPv6 Information\n" + "OSPF6 interface commands\n" + "Network type\n" + "manet flooding\n" + "Specify OSPF6 broadcast flooding\n" + "Specify OSPF6 mpr flooding\n" + "Specify OSPF6 essential SI-CDS flooding\n") +{ + + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + oi = (struct ospf6_interface *) ifp->info; + if (!oi) + oi = ospf6_interface_create (ifp); + assert (oi); + + if (strncmp (argv[0], "b", 1) == 0) + oi->flooding = OSPF6_FLOOD_BROADCAST; +#ifdef OSPF6_MANET_MPR_FLOOD + if (strncmp (argv[0], "mpr", 3) == 0) + oi->flooding = OSPF6_FLOOD_MPR_SDCDS; +#endif //OSPF6_MANET_MPR_FLOOD +#ifdef OSPF6_MANET_MDR_FLOOD + else if (strncmp (argv[0], "mdr", 3) == 0) + oi->flooding = OSPF6_FLOOD_MDR_SICDS; +#endif //OSPF6_MANET_MDR_FLOOD + else + oi->flooding = OSPF6_FLOOD_BROADCAST; + + return CMD_SUCCESS; +} +#endif //OSPF6_CONFIG + + DEFUN (no_ipv6_ospf6_advertise_prefix_list, no_ipv6_ospf6_advertise_prefix_list_cmd, "no ipv6 ospf6 advertise prefix-list", @@ -1598,6 +2532,46 @@ install_element (INTERFACE_NODE, &ipv6_ospf6_advertise_prefix_list_cmd); install_element (INTERFACE_NODE, &no_ipv6_ospf6_advertise_prefix_list_cmd); + +#ifdef OSPF6_CONFIG + install_element (INTERFACE_NODE, &ipv6_ospf6_network_cmd); + install_element (INTERFACE_NODE, &no_ipv6_ospf6_network_cmd); + install_element (INTERFACE_NODE, &ipv6_ospf6_network_flood_cmd); +#endif //OSPF6_CONFIG + +#if defined(OSPF6_CONFIG) && defined(OSPF6_DELAYED_FLOOD) + install_element (INTERFACE_NODE, &ipv6_ospf6_flooddelay_cmd); +#endif //OSPF6_CONFIG +#if defined(OSPF6_CONFIG) && defined(OSPF6_JITTER) + install_element (INTERFACE_NODE, &ipv6_ospf6_jitter_cmd); +#endif //defined(OSPF6_CONFIG) && defined(OSPF6_JITTER) + +#ifdef OSPF6_MANET + install_element (INTERFACE_NODE, &ipv6_ospf6_ackinterval_cmd); + install_element (INTERFACE_NODE, &ipv6_ospf6_diffhellos_cmd); + install_element (INTERFACE_NODE, &no_ipv6_ospf6_diffhellos_cmd); + +#ifdef OSPF6_MANET_MPR_FLOOD +#ifdef OSPF6_MANET_MPR_SP + install_element (INTERFACE_NODE, &ipv6_ospf6_smartpeering_cmd); + install_element (INTERFACE_NODE, &no_ipv6_ospf6_smartpeering_cmd); + install_element (INTERFACE_NODE, &ipv6_ospf6_unsynchadj_cmd); + install_element (INTERFACE_NODE, &no_ipv6_ospf6_unsynchadj_cmd); +#endif //OSPF6_MANET_MPR_SP + install_element (INTERFACE_NODE, &ipv6_ospf6_pushbackinterval_cmd); +#endif //OSPF6_MANET_MPR_FLOOD + +#ifdef OSPF6_MANET_MDR_FLOOD + install_element (INTERFACE_NODE, &ipv6_ospf6_backupwaitinterval_cmd); + install_element (INTERFACE_NODE, &ipv6_ospf6_twohoprefresh_cmd); + install_element (INTERFACE_NODE, &ipv6_ospf6_hellorepeatcount_cmd); + install_element (INTERFACE_NODE, &ipv6_ospf6_nonpersistentmdr_cmd); + install_element (INTERFACE_NODE, &no_ipv6_ospf6_nonpersistentmdr_cmd); + install_element (INTERFACE_NODE, &ipv6_ospf6_adjacencyconnectivity_cmd); + install_element (INTERFACE_NODE, &ipv6_ospf6_lsafullness_cmd); +#endif //OSPF6_MANET_MDR_FLOOD +#endif // OSPF6_MANET + } DEFUN (debug_ospf6_interface, @@ -1642,4 +2616,10 @@ install_element (CONFIG_NODE, &no_debug_ospf6_interface_cmd); } - +#ifdef OSPF6_MANET_DIFF_HELLO +u_int16_t ospf6_increment_scs(u_int16_t scs_num) +{ + scs_num++; + return scs_num; +} +#endif //OSPF6_MANET_DIFF_HELLO diff -Naur quagga-0.98.5/ospf6d/ospf6_interface.h quagga-0.98.5-manet/ospf6d/ospf6_interface.h --- quagga-0.98.5/ospf6d/ospf6_interface.h 2004-10-10 05:54:58.000000000 -0700 +++ quagga-0.98.5-manet/ospf6d/ospf6_interface.h 2006-02-20 13:42:12.000000000 -0800 @@ -22,7 +22,16 @@ #ifndef OSPF6_INTERFACE_H #define OSPF6_INTERFACE_H +#ifdef SIM +#include "lib/if.h" +#include "ospf6d.h" //for boolean +#else #include "if.h" +#endif //SIM + +#ifdef OSPF6_MANET +#include "vty.h" +#endif //OSPF6_MANET /* Debug option */ extern unsigned char conf_debug_ospf6_interface; @@ -33,6 +42,24 @@ #define IS_OSPF6_DEBUG_INTERFACE \ (conf_debug_ospf6_interface) +#ifdef OSPF6_MANET_MDR_FLOOD +typedef enum { + OSPF6_ADJ_FULLYCONNECTED = 0, + OSPF6_ADJ_UNICONNECTED, + OSPF6_ADJ_BICONNECTED +}ospf6_AdjConnectivity; + +//How much information to include in LSAs +//These are defined in Ogier's draft, Appendix C +typedef enum { + OSPF6_LSA_FULLNESS_MIN = 0, //minimal LSAs (only adjacent neighbors) + OSPF6_LSA_FULLNESS_MINHOP, //partial LSAs for min-hop routing + OSPF6_LSA_FULLNESS_MINHOP2PATHS, //same as above, with some path redundancy + OSPF6_LSA_FULLNESS_MDRFULL, //full LSAs from MDR/MBDRs + OSPF6_LSA_FULLNESS_FULL //full LSAs (all routable neighbors) +}ospf6_LSAFullness; +#endif //OSPF6_MANET_MDR_FLOOD + /* Interface structure */ struct ospf6_interface { @@ -43,7 +70,7 @@ struct ospf6_area *area; /* list of ospf6 neighbor */ - struct list *neighbor_list; + pList neighbor_list; /* linklocal address of this I/F */ struct in6_addr *linklocal_addr; @@ -102,7 +129,132 @@ /* prefix-list name to filter connected prefix */ char *plist_name; + +#ifdef SIM_ETRACE_STAT + int num_2way_neigh; + struct timeval neigh_2way_change_time; + int num_full_neigh; + struct timeval neigh_full_change_time; + struct timeval relaysel_change_time; +#endif //SIM_ETRACE_STAT + +#ifdef OSPF6_CONFIG + /* OSPF6 Interface Type */ + u_char type; + u_char flooding; +#endif //OSPF6_CONFIG + +#ifdef OSPF6_DELAYED_FLOOD + int flood_delay; //msec +#endif //OSPF6_DELAYED_FLOOD + +#ifdef OSPF6_JITTER + int jitter; //msec +#endif //defined(OSPF6_JITTER) + +#ifdef OSPF6_MANET + long ackInterval; + int ack_cache_timeout; + boolean diff_hellos; +#endif //OSPF6_MANET + +#ifdef OSPF6_MANET_MPR_FLOOD + long pushBackInterval; + pList two_hop_list; + pList relay_list; + pList relay_sel_list; + boolean mpr_change; + +#ifdef OSPF6_MANET_MPR_SP + boolean smart_peering; + boolean unsynch_adj; +#endif //OSPF6_MANET_MPR_SP + +#ifdef OSPF6_MANET_DIFF_HELLO + pList drop_neighbor_list; + u_int16_t scs_num; + boolean increment_scs; + boolean full_state; + boolean initialization; +#ifdef OSPF6_MANET_MDR_LQ + boolean link_quality; +#endif //OSPF6_MANET_MDR_LQ +#endif //OSPF6_MANET_DIFF_HELLO +#endif //OSPF6_MANET_MPR_FLOOD + +#ifdef OSPF6_MANET_MDR_FLOOD + long BackupWaitInterval; + int **cost_matrix; + int **lsa_cost_matrix; + int AdjConnectivity; //1=uniconnected, 2=biconnected, 0=fully connected + int LSAFullness; + int MDRConstraint; // MPN parameter h, should be 2 or 3. + int mdr_level; + int mdr_count; + struct ospf6_neighbor *parent; + struct ospf6_neighbor *bparent; + u_int16_t TwoHopRefresh; + u_int16_t HelloRepeatCount; + boolean NonPersistentMDR; + boolean full_adj_part_lsa; // For full adjacencies with partial LSAs. +#ifdef OSPF6_MANET_DIFF_HELLO + pList lnl; + u_int16_t hsn; + u_int full_hello_count; +#endif //OSPF6_MANET_DIFF_HELLO +#endif //OSPF6_MANET_MDR_FLOOD + +}; + +#ifdef OSPF6_MANET_DIFF_HELLO +struct drop_neighbor +{ + u_int32_t router_id; + struct timeval *expire_time; + boolean first; +}; +#endif //OSPF6_MANET_DIFF_HELLO + +#ifdef OSPF6_MANET_MPR_FLOOD +struct ospf6_relay +{ + u_int32_t router_id; + boolean newly_activated; + boolean active; + + boolean drop; + struct timeval *drop_expire_time; +}; + +struct ospf6_relay_selector +{ + u_int32_t router_id; + struct timeval *expire_time; +#ifdef SIM_ETRACE_STAT + struct timeval install_time; +#endif //SIM_ETRACE_STAT }; +#endif //OSPF6_MANET_MPR_FLOOD + + +#ifdef OSPF6_CONFIG +#define OSPF6_IFTYPE_NONE 0 +#define OSPF6_IFTYPE_POINTOPOINT 1 +#define OSPF6_IFTYPE_BROADCAST 2 +#define OSPF6_IFTYPE_NBMA 3 +#define OSPF6_IFTYPE_POINTOMULTIPOINT 4 +#define OSPF6_IFTYPE_VIRTUALLINK 5 +#define OSPF6_IFTYPE_LOOPBACK 6 +#define OSPF6_IFTYPE_MANETRELIABLE 7 +#define OSPF6_IFTYPE_MAX 8 + +typedef enum { + OSPF6_FLOOD_BROADCAST = 0, + OSPF6_FLOOD_MPR_SDCDS = 1, + OSPF6_FLOOD_MDR_SICDS = 2 +} ospf6_flooding_type; +#endif //OSPF6_CONFIG + /* interface state */ #define OSPF6_INTERFACE_NONE 0 @@ -149,5 +301,9 @@ int config_write_ospf6_debug_interface (struct vty *vty); void install_element_ospf6_debug_interface (); +#ifdef OSPF6_MANET_DIFF_HELLO +u_int16_t ospf6_increment_scs(u_int16_t scs_num); +#endif //OSPF6_MANET_DIFF_HELLO + #endif /* OSPF6_INTERFACE_H */ diff -Naur quagga-0.98.5/ospf6d/ospf6_intra.c quagga-0.98.5-manet/ospf6d/ospf6_intra.c --- quagga-0.98.5/ospf6d/ospf6_intra.c 2004-12-23 22:00:12.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_intra.c 2006-02-20 13:42:12.000000000 -0800 @@ -25,7 +25,7 @@ #include "linklist.h" #include "thread.h" #include "memory.h" -#include "if.h" +#include "lib/if.h" #include "prefix.h" #include "table.h" #include "vty.h" @@ -47,6 +47,14 @@ #include "ospf6_flood.h" #include "ospf6d.h" +#ifdef BUGFIX +#include "ospf6_flood.h" +#ifdef SIM_ETRACE_STAT +#include "sim.h" +#endif //SIM_ETRACE_STAT +#endif //BUGFIX + + /******************************/ /* RFC2740 3.4.3.1 Router-LSA */ /******************************/ @@ -129,12 +137,25 @@ router_lsa = (struct ospf6_router_lsa *) ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header)); +#ifdef OSPF6_MANET + OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_V6,2); + OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_E,2); + OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_MC,2); + OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_N,2); + OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_R,2); + OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_DC,2); + OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_AF,2); + OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_L,1); + OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_I,1); //same as D + OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_D,1); //same as I +#else OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_V6); OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_E); OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_MC); OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_N); OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_R); OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_DC); +#endif //OSPF6_MANET if (ospf6_is_router_abr (ospf6)) SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B); @@ -161,6 +182,13 @@ continue; /* Nor are interfaces without any full adjacencies described */ + +#ifdef OSPF6_MANET_MDR_FLOOD + //MDR may include non-adjacent neighbors in LSA. + if (!(oi->flooding == OSPF6_MANET_MDR_FLOOD && + oi->AdjConnectivity > OSPF6_ADJ_FULLYCONNECTED)) +#endif //OSPF6_MANET_MDR_FLOOD + { count = 0; for (j = listhead (oi->neighbor_list); j; nextnode (j)) { @@ -170,6 +198,7 @@ } if (count == 0) continue; + } /* Multiple Router-LSA instance according to size limit setting */ if ( (oa->router_lsa_size_limit != 0) @@ -213,26 +242,139 @@ } /* Point-to-Point interfaces */ +#ifdef OSPF6_CONFIG + if(oi->type == OSPF6_IFTYPE_POINTOPOINT || + oi->type == OSPF6_IFTYPE_POINTOMULTIPOINT || + oi->type == OSPF6_IFTYPE_MANETRELIABLE) +#else if (if_is_pointopoint (oi->interface)) +#endif //OSPF6_CONFIG { for (j = listhead (oi->neighbor_list); j; nextnode (j)) { on = (struct ospf6_neighbor *) getdata (j); - if (on->state != OSPF6_NEIGHBOR_FULL) - continue; + +#ifdef OSPF6_MANET_MDR_FLOOD + // LSAFullness determines which neighbors to include. + if (oi->flooding == OSPF6_FLOOD_MDR_SICDS && + oi->AdjConnectivity > OSPF6_ADJ_FULLYCONNECTED) + { + if (oi->LSAFullness == OSPF6_LSA_FULLNESS_MIN) + // minimal LSAs (adjacent nbrs) + { + if (on->state != OSPF6_NEIGHBOR_FULL) + { on->adv = false; continue; } // Not advertised. + } + if (oi->LSAFullness == OSPF6_LSA_FULLNESS_MINHOP || + oi->LSAFullness == OSPF6_LSA_FULLNESS_MINHOP2PATHS) + // partial LSAs + { + if (!(on->state >= OSPF6_NEIGHBOR_TWOWAY && on->adv)) + { on->adv = false; continue; } // Not advertised. + } + // Make sure neighbors less than 2-way are not routable. + if (on->state < OSPF6_NEIGHBOR_TWOWAY) + on->routable = false; + if (oi->LSAFullness == OSPF6_LSA_FULLNESS_MDRFULL) + // full LSAs only for MDR/BDMR + { + // Other includes Full MDR/BMDR nbrs that are (b)parent + // or are already advertised (persistence). + if (oi->mdr_level == OSPF6_OTHER && + oi->full_adj_part_lsa && + (on->state != OSPF6_NEIGHBOR_FULL || + on->mdr_level < OSPF6_BMDR || + !(oi->parent == on || oi->bparent == on || on->adv))) + { on->adv = false; continue; } // Not advertised. + // No need to check for parents in partial adj case. + else if (oi->mdr_level == OSPF6_OTHER && + !oi->full_adj_part_lsa && + (on->state != OSPF6_NEIGHBOR_FULL || + on->mdr_level < OSPF6_BMDR)) + { on->adv = false; continue; } // Not advertised. + + // MDR/BMDR includes all full or routable nbrs, + // depending on full_adj_part_lsa. + if (oi->mdr_level >= OSPF6_BMDR && + oi->full_adj_part_lsa && + on->state != OSPF6_NEIGHBOR_FULL) + { on->adv = false; continue; } // Not advertised. + else if (oi->mdr_level >= OSPF6_BMDR && + !oi->full_adj_part_lsa && !on->routable) + { on->adv = false; continue; } // Not advertised. + } + if (oi->LSAFullness > OSPF6_LSA_FULLNESS_MDRFULL) + // full LSAs + { + if (!(on->state >= OSPF6_NEIGHBOR_TWOWAY && on->routable)) + { on->adv = false; continue; } // Not advertised. + } + } + else +#endif //OSPF6_MANET_MDR_FLOOD +#if defined(OSPF6_MANET_MPR_FLOOD) && defined(OSPF6_MANET_MPR_SP) + //Roy-01 4 para 3 and 4.1 para 2 bullet 2 + //allow 2-way neighbors in router-lsa + if (oi->flooding == OSPF6_FLOOD_MPR_SDCDS && oi->unsynch_adj) + { + if (on->state < OSPF6_NEIGHBOR_TWOWAY || !on->routable) + continue; + } + else +#endif //OSPF6_MANET_MPR_FLOOD && OSPF6_MANET_MPR_SP + + { + if (on->state != OSPF6_NEIGHBOR_FULL) + continue; + } lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT; lsdesc->metric = htons (oi->cost); lsdesc->interface_id = htonl (oi->interface->ifindex); lsdesc->neighbor_interface_id = htonl (on->ifindex); lsdesc->neighbor_router_id = on->router_id; - +#ifdef OSPF6_MANET_MDR_FLOOD + if (oi->flooding == OSPF6_FLOOD_MDR_SICDS && + oi->AdjConnectivity > OSPF6_ADJ_FULLYCONNECTED) + { + if (on->state == OSPF6_NEIGHBOR_FULL) + lsdesc->metric = htons (oi->cost+9); //FIXME Why 9,10 + else + lsdesc->metric = htons (oi->cost+10); + } + on->adv = true; // Neighbor is advertised. +#endif //OSPF6_MANET_MDR_FLOOD +#if defined(OSPF6_MANET_MPR_SP) && defined(OSPF6_MANET_MPR_FLOOD) +//Changes by: Stan Ratliff +//Date: November 1st, 2005 +//Reason: Add a flag to router-LSAs to identify unsynchronized adjacencies + if (oi->flooding == OSPF6_FLOOD_MPR_SDCDS && oi->unsynch_adj) + { + if (on->state == OSPF6_NEIGHBOR_FULL) + { + lsdesc->metric = htons(oi->cost+9); + lsdesc->lsdesc_flag = 0x00; + } + else + { + //Roy-01 4.1 para 7 [A] + //tag 2-way links in router-lsa + lsdesc->metric = htons(oi->cost+10); + lsdesc->lsdesc_flag = OSPF6_ROUTER_LSDESC_UNSYNC; + } + } +#endif //OSPF6_MANET_MPR_SP && OSPF6_MANET_MPR_FLOOD lsdesc++; } } /* Broadcast and NBMA interfaces */ +#ifdef OSPF6_CONFIG + if (oi->type == OSPF6_IFTYPE_BROADCAST || + oi->type == OSPF6_IFTYPE_NBMA) +#else if (if_is_broadcast (oi->interface)) +#endif //OSPF6_CONFIG { /* If this router is not DR, and If this router not fully adjacent with DR, @@ -308,6 +450,10 @@ ospf6_lsa_purge (lsa); } +#ifdef SIM_ETRACE_STAT + update_statistics(OSPF6_ORIG_RTR_LSA, 1); +#endif //SIM_ETRACE_STAT + return 0; } @@ -1102,8 +1248,13 @@ route->path.cost = ls_entry->path.cost + ntohs (op->prefix_metric); +#ifdef BUGFIX + for (i = 0; i < OSPF6_MULTI_PATH_LIMIT && + ospf6_nexthop_is_set (&ls_entry->nexthop[i]); i++) +#else for (i = 0; ospf6_nexthop_is_set (&ls_entry->nexthop[i]) && i < OSPF6_MULTI_PATH_LIMIT; i++) +#endif //BUGFIX ospf6_nexthop_copy (&route->nexthop[i], &ls_entry->nexthop[i]); if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX)) @@ -1230,12 +1381,22 @@ } if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE)) +#ifdef SIM_ETRACE_STAT + { + update_statistics(OSPF6_ROUTE_CHANGES, 1); + ospf6_route_remove (route, oa->route_table); + } +#else ospf6_route_remove (route, oa->route_table); +#endif //SIM_ETRACE_STAT else if (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) || CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE)) { if (hook_add) (*hook_add) (route); +#ifdef SIM_ETRACE_STAT + update_statistics(OSPF6_ROUTE_CHANGES, 1); +#endif //SIM_ETRACE_STAT } route->flag = 0; @@ -1373,3 +1534,147 @@ } +#ifdef BUGFIX +//prevent LSAs from being originated before MinLSInterval +void ospf6_lsa_schedule(struct ospf6_area *oa, struct ospf6_interface *oi, + int type, boolean stub) +{ + struct ospf6 *o = NULL; + struct ospf6_lsa *old; + int link_state_id; + long time_msec = -1; + + switch(type) + { + case OSPF6_LSTYPE_ROUTER: + link_state_id = 0; + o = oa->ospf6; + old = ospf6_lsdb_lookup (htons (type), link_state_id, + o->router_id, oa->lsdb); + break; + case OSPF6_LSTYPE_NETWORK: + link_state_id = oi->interface->ifindex; + o = oi->area->ospf6; + old = ospf6_lsdb_lookup (htons (type), htonl(link_state_id), + o->router_id, oi->area->lsdb); + break; + case OSPF6_LSTYPE_LINK: + link_state_id = oi->interface->ifindex; + o = oi->area->ospf6; + old = ospf6_lsdb_lookup (htons (type), htonl(link_state_id), + o->router_id, oi->lsdb); + break; + case OSPF6_LSTYPE_INTRA_PREFIX: + if (stub) + { + link_state_id = 0; + o = oa->ospf6; + old = ospf6_lsdb_lookup (htons (type), link_state_id, + o->router_id, oa->lsdb); + } + else + { + link_state_id = oi->interface->ifindex; + o = oi->area->ospf6; + old = ospf6_lsdb_lookup (htons (type), htonl(link_state_id), + o->router_id, oi->area->lsdb); + } + break; + default: + zlog_warn ("No such LSA type"); + return; + break; + } + if (old) + { +#ifdef OSPF6_CONFIG + time_msec = + (long)(((float)o->minLSInterval- elapsed_time(&old->originated)) * 1000); +#else + time_msec = + (long)(((float)MIN_LS_INTERVAL- elapsed_time(&old->originated)) * 1000); +#endif //OSPF6_CONFIG +#ifdef SIM_ETRACE_STAT + if (time_msec > 0) + TraceEvent_sim(2,"Delay LSA type %x orig by %d msec", type, time_msec); +#endif //SIM_ETRACE_STAT + } + switch(type) + { + case OSPF6_LSTYPE_ROUTER: + if (time_msec > 0) + { + THREAD_OFF(oa->thread_router_lsa); + oa->thread_router_lsa = + thread_add_timer_msec(master, ospf6_router_lsa_originate, oa, time_msec); + //XXX FIXME ospf6_flood_clear(old); + //should we clear our own old cued LSA (rxmt list) ???? + //while we wait to originate a new one + } + else + { + oa->thread_router_lsa = + thread_add_event(master, ospf6_router_lsa_originate, oa, 0); + } + break; + case OSPF6_LSTYPE_NETWORK: + if (time_msec > 0) + { + THREAD_OFF(oi->thread_network_lsa); + oi->thread_network_lsa = + thread_add_timer_msec(master, ospf6_network_lsa_originate,oi, time_msec); + } + else + { + oi->thread_network_lsa = + thread_add_event(master, ospf6_network_lsa_originate, oi, 0); + } + break; + case OSPF6_LSTYPE_LINK: + if (time_msec > 0) + { + THREAD_OFF(oi->thread_link_lsa); + oi->thread_link_lsa = + thread_add_timer_msec(master, ospf6_link_lsa_originate, oi, time_msec); + } + else + { + oi->thread_link_lsa = + thread_add_event(master, ospf6_link_lsa_originate, oi, 0); + } + break; + case OSPF6_LSTYPE_INTRA_PREFIX: + if (stub) + { + if (time_msec > 0) + { + THREAD_OFF(oa->thread_intra_prefix_lsa); + oa->thread_intra_prefix_lsa = + thread_add_timer_msec(master, ospf6_intra_prefix_lsa_originate_stub, + oa, time_msec); + } + else + { + oa->thread_intra_prefix_lsa = + thread_add_event(master, ospf6_intra_prefix_lsa_originate_stub,oa, 0); + } + } + else + { + if (time_msec > 0) + { + THREAD_OFF(oi->thread_intra_prefix_lsa); + oi->thread_intra_prefix_lsa = + thread_add_timer_msec(master,ospf6_intra_prefix_lsa_originate_transit, + oi, time_msec); + } + else + { + oi->thread_intra_prefix_lsa = + thread_add_event(master,ospf6_intra_prefix_lsa_originate_transit,oi,0); + } + } + break; + } +} +#endif //BUGFIX diff -Naur quagga-0.98.5/ospf6d/ospf6_intra.h quagga-0.98.5-manet/ospf6d/ospf6_intra.h --- quagga-0.98.5/ospf6d/ospf6_intra.h 2004-08-14 22:52:07.000000000 -0700 +++ quagga-0.98.5-manet/ospf6d/ospf6_intra.h 2006-02-20 13:42:12.000000000 -0800 @@ -22,6 +22,11 @@ #ifndef OSPF6_INTRA_H #define OSPF6_INTRA_H +#ifdef BUGFIX +#include "ospf6d.h" +#include "ospf6_area.h" +#endif //BUGFIX + /* Router-LSA */ struct ospf6_router_lsa { @@ -34,18 +39,41 @@ struct ospf6_router_lsdesc { u_char type; +#ifdef OSPF6_MANET_MPR_SP +//Changes by: Stan Ratliff +//Date: November 1st, 2005 +//Reason: Add a flag to router-LSAs to identify unsynchronized adjacencies + u_char lsdesc_flag; /* Was reserved, used for SMART_PEERING */ +#else u_char reserved; +#endif //OSPF6_MANET_MPR_SP u_int16_t metric; /* output cost */ u_int32_t interface_id; u_int32_t neighbor_interface_id; u_int32_t neighbor_router_id; }; +#ifdef OSPF6_MANET_MPR_SP +//Changes by: Stan Ratliff +//Date: November 1st, 2005 +//Reason: Add a flag to router-LSAs to identify unsynchronized adjacencies +#define OSPF6_ROUTER_LSDESC_UNSYNC 1 /* SMART_PEERING */ +#endif //OSPF6_MANET_MPR_SP + #define OSPF6_ROUTER_LSDESC_POINTTOPOINT 1 #define OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK 2 #define OSPF6_ROUTER_LSDESC_STUB_NETWORK 3 #define OSPF6_ROUTER_LSDESC_VIRTUAL_LINK 4 +#ifdef OSPF6_MANET_MPR_SP +//Changes by: Stan Ratliff +//Date: November 1st, 2005 +//Reason: Add a flag to router-LSAs to identify unsynchronized adjacencies +#define ROUTER_LSDESC_IS_UNSYNC(x) \ + ((((struct ospf6_router_lsdesc *)(x))->lsdesc_flag & \ + OSPF6_ROUTER_LSDESC_UNSYNC == OSPF6_ROUTER_LSDESC_UNSYNC) ? 1 : 0) +#endif //OSPF6_MANET_MPR_SP + #define ROUTER_LSDESC_IS_TYPE(t,x) \ ((((struct ospf6_router_lsdesc *)(x))->type == \ OSPF6_ROUTER_LSDESC_ ## t) ? 1 : 0) @@ -94,7 +122,36 @@ /* followed by ospf6 prefix(es) */ }; - +#ifdef BUGFIX +struct ospf6_interface; +void ospf6_lsa_schedule(struct ospf6_area *oa, struct ospf6_interface *oi, + int type, boolean stub); +#define OSPF6_ROUTER_LSA_SCHEDULE(oa) \ + do { \ + if (! (oa)->thread_router_lsa) \ + ospf6_lsa_schedule(oa, NULL, OSPF6_LSTYPE_ROUTER, false); \ + } while (0) +#define OSPF6_NETWORK_LSA_SCHEDULE(oi) \ + do { \ + if (! (oi)->thread_network_lsa) \ + ospf6_lsa_schedule(NULL, oi, OSPF6_LSTYPE_NETWORK, false); \ + } while (0) +#define OSPF6_LINK_LSA_SCHEDULE(oi) \ + do { \ + if (! (oi)->thread_link_lsa) \ + ospf6_lsa_schedule(NULL, oi, OSPF6_LSTYPE_LINK, false); \ + } while (0) +#define OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oa) \ + do { \ + if (! (oa)->thread_intra_prefix_lsa) \ + ospf6_lsa_schedule(oa, NULL, OSPF6_LSTYPE_INTRA_PREFIX, true); \ + } while (0) +#define OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi) \ + do { \ + if (! (oi)->thread_intra_prefix_lsa) \ + ospf6_lsa_schedule(NULL, oi, OSPF6_LSTYPE_INTRA_PREFIX, false); \ + } while (0) +#else #define OSPF6_ROUTER_LSA_SCHEDULE(oa) \ do { \ if (! (oa)->thread_router_lsa) \ @@ -127,6 +184,7 @@ thread_add_event (master, ospf6_intra_prefix_lsa_originate_transit, \ oi, 0); \ } while (0) +#endif //BUGFIX #define OSPF6_NETWORK_LSA_EXECUTE(oi) \ do { \ diff -Naur quagga-0.98.5/ospf6d/ospf6_lsa.c quagga-0.98.5-manet/ospf6d/ospf6_lsa.c --- quagga-0.98.5/ospf6d/ospf6_lsa.c 2004-12-23 22:00:12.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_lsa.c 2006-02-20 13:42:12.000000000 -0800 @@ -42,8 +42,11 @@ #include "ospf6_flood.h" #include "ospf6d.h" +#ifdef SIM +#include "sim.h" +#endif //SIM -vector ospf6_lsa_handler_vector; +pVector ospf6_lsa_handler_vector; int ospf6_unknown_lsa_show (struct vty *vty, struct ospf6_lsa *lsa) @@ -95,7 +98,8 @@ if (index >= vector_max (ospf6_lsa_handler_vector)) handler = &unknown_handler; else - handler = vector_slot (ospf6_lsa_handler_vector, index); + handler = (struct ospf6_lsa_handler *) + vector_slot (ospf6_lsa_handler_vector, index); if (handler == NULL) handler = &unknown_handler; @@ -138,12 +142,21 @@ ospf6_lsa_age_current (lsa1); ospf6_lsa_age_current (lsa2); +#ifdef SIM_ETRACE_STAT + if (ntohs (age_mask(lsa1->header)) == MAXAGE && + ntohs (age_mask(lsa2->header)) != MAXAGE) + return 1; + if (ntohs (age_mask(lsa1->header)) != MAXAGE && + ntohs (age_mask(lsa2->header)) == MAXAGE) + return 1; +#else if (ntohs (lsa1->header->age) == MAXAGE && ntohs (lsa2->header->age) != MAXAGE) return 1; if (ntohs (lsa1->header->age) != MAXAGE && ntohs (lsa2->header->age) == MAXAGE) return 1; +#endif //SIM_ETRACE_STAT /* compare body */ if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length)) @@ -180,11 +193,19 @@ assert (lsa && lsa->header); +#ifdef SIM + if (gettimeofday_sim (&now, (struct timezone *)NULL) < 0) +#else if (gettimeofday (&now, (struct timezone *)NULL) < 0) +#endif //SIM zlog_warn ("LSA: gettimeofday failed, may fail LSA AGEs: %s", safe_strerror (errno)); +#ifdef SIM_ETRACE_STAT + lsa->birth.tv_sec = now.tv_sec - ntohs (age_mask(lsa->header)); +#else lsa->birth.tv_sec = now.tv_sec - ntohs (lsa->header->age); +#endif //SIM_ETRACE_STAT lsa->birth.tv_usec = now.tv_usec; return; @@ -203,7 +224,11 @@ assert (lsa->header); /* current time */ +#ifdef SIM + if (gettimeofday_sim (&now, (struct timezone *)NULL) < 0) +#else if (gettimeofday (&now, (struct timezone *)NULL) < 0) +#endif //SIM zlog_warn ("LSA: gettimeofday failed, may fail LSA AGEs: %s", safe_strerror (errno)); @@ -213,7 +238,12 @@ /* if over MAXAGE, set to it */ age = (ulage > MAXAGE ? MAXAGE : ulage); + +#ifdef SIM_ETRACE_STAT + lsa->header->age = htons (age) + hopcount_mask(lsa->header); +#else lsa->header->age = htons (age); +#endif //SIM_ETRACE_STAT return age; } @@ -226,7 +256,13 @@ age = ospf6_lsa_age_current (lsa) + transdelay; if (age > MAXAGE) age = MAXAGE; + +#ifdef SIM_ETRACE_STAT + lsa->header->age = htons (age) + hopcount_mask(lsa->header); +#else lsa->header->age = htons (age); +#endif //SIM_ETRACE_STAT + } void @@ -239,7 +275,13 @@ THREAD_OFF (lsa->expire); THREAD_OFF (lsa->refresh); +#ifdef SIM + //setting birth to 0 would normally make (now - birth > MAXAGE) + memset (&lsa->birth, 0, sizeof (struct timeval)); + lsa->birth.tv_sec = (MAXAGE)*-1; +#else memset (&lsa->birth, 0, sizeof (struct timeval)); +#endif //SIM thread_execute (master, ospf6_lsa_expire, lsa, 0); } @@ -317,9 +359,15 @@ sizeof (adv_router)); zlog_debug (" [%s Id:%s Adv:%s]", ospf6_lstype_name (header->type), id, adv_router); +#ifdef SIM_ETRACE_STAT + zlog_debug (" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d", + ntohs (age_mask(header)), (u_long) ntohl (header->seqnum), + ntohs (header->checksum), ntohs (header->length)); +#else zlog_debug (" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d", ntohs (header->age), (u_long) ntohl (header->seqnum), ntohs (header->checksum), ntohs (header->length)); +#endif //SIM_ETRACE_STAT } void @@ -351,7 +399,11 @@ inet_ntop (AF_INET, &lsa->header->adv_router, adv_router, sizeof (adv_router)); +#ifdef SIM + gettimeofday_sim (&now, NULL); +#else gettimeofday (&now, NULL); +#endif //SIM timersub (&now, &lsa->installed, &res); timerstring (&res, duration, sizeof (duration)); @@ -479,6 +531,13 @@ /* calculate birth of this lsa */ ospf6_lsa_age_set (lsa); +#ifdef OSPF6_MANET + lsa->pushBackTimer = NULL; +#endif //OSPF6_MANET +#ifdef OSPF6_MANET_TEMPORARY_LSDB + lsa->cache = 0; +#endif //OSPF6_MANET_TEMPORARY_LSDB + return lsa; } @@ -522,6 +581,10 @@ THREAD_OFF (lsa->expire); THREAD_OFF (lsa->refresh); +#ifdef OSPF6_MANET + ospf6_pushback_lsa_delete(lsa); +#endif //OSPF6_MANET + /* do free */ XFREE (MTYPE_OSPF6_LSA, lsa->header); XFREE (MTYPE_OSPF6_LSA, lsa); @@ -537,6 +600,11 @@ copy = ospf6_lsa_create_headeronly (lsa->header); else copy = ospf6_lsa_create (lsa->header); + +#ifdef SIM_ETRACE_STAT + copy->header->age += hopcount_mask(lsa->header); +#endif //SIM_ETRACE_STAT + assert (copy->lock == 0); copy->birth = lsa->birth; @@ -545,6 +613,10 @@ copy->installed = lsa->installed; copy->lsdb = lsa->lsdb; +#ifdef OSPF6_DELAYED_FLOOD + copy->rxmt_time = lsa->rxmt_time; +#endif //OSPF6_DELAYED_FLOOD + return copy; } @@ -609,7 +681,7 @@ int ospf6_lsa_refresh (struct thread *thread) { - struct ospf6_lsa *old, *self, *new; + struct ospf6_lsa *old, *self, *new_; struct ospf6_lsdb *lsdb_self; assert (thread); @@ -636,23 +708,39 @@ self->header->adv_router, old->lsdb); ospf6_lsa_checksum (self->header); - new = ospf6_lsa_create (self->header); - new->lsdb = old->lsdb; - new->refresh = thread_add_timer (master, ospf6_lsa_refresh, new, + new_ = ospf6_lsa_create (self->header); + new_->lsdb = old->lsdb; + new_->refresh = thread_add_timer (master, ospf6_lsa_refresh, new_, LS_REFRESH_TIME); /* store it in the LSDB for self-originated LSAs */ - ospf6_lsdb_add (ospf6_lsa_copy (new), lsdb_self); + ospf6_lsdb_add (ospf6_lsa_copy (new_), lsdb_self); +#ifdef OSPF6_CONFIG + if (IS_OSPF6_DEBUG_DATABASE (DATABASE_DETAIL)) + ospf6_debug_lsdb_show(OSPF6_DEBUG_DATABASE_DETAIL, lsdb_self); + else if (IS_OSPF6_DEBUG_DATABASE (DATABASE)) + ospf6_debug_lsdb_show(OSPF6_DEBUG_DATABASE, lsdb_self); +#endif //OSPF6_CONFIG - if (IS_OSPF6_DEBUG_LSA_TYPE (new->header->type)) + if (IS_OSPF6_DEBUG_LSA_TYPE (new_->header->type)) { zlog_debug ("LSA Refresh:"); - ospf6_lsa_header_print (new); + ospf6_lsa_header_print (new_); } +#ifdef SIM_ETRACE_STAT + char id[16], adv_router[16]; + inet_ntop (AF_INET,&new_->header->id, id, sizeof (id)); + inet_ntop (AF_INET,&new_->header->adv_router, adv_router,sizeof (adv_router)); + TraceEvent_sim(2,"Re-orig LSA %s -id %s -advrt %s -age %d -seq %lu -len %d", + ospf6_lstype_name(new_->header->type), id, adv_router, + ntohs(age_mask(new_->header)), ntohl(new_->header->seqnum), + ntohs(new_->header->length)); +#endif //SIM_ETRACE_STAT + ospf6_flood_clear (old); - ospf6_flood (NULL, new); - ospf6_install_lsa (new); + ospf6_flood (NULL, new_); + ospf6_install_lsa (new_); return 0; } @@ -762,7 +850,8 @@ for (i = 0; i < vector_max (ospf6_lsa_handler_vector); i++) { - handler = vector_slot (ospf6_lsa_handler_vector, i); + handler = (struct ospf6_lsa_handler *) + vector_slot (ospf6_lsa_handler_vector, i); if (handler == NULL) continue; if (type && handler->type == type) @@ -830,7 +919,8 @@ for (i = 0; i < vector_max (ospf6_lsa_handler_vector); i++) { - handler = vector_slot (ospf6_lsa_handler_vector, i); + handler = (struct ospf6_lsa_handler *) + vector_slot (ospf6_lsa_handler_vector, i); if (handler == NULL) continue; if (type && handler->type == type) @@ -891,7 +981,8 @@ strncat (strbuf, "debug ospf6 lsa (", STRSIZE - strlen (strbuf)); for (i = 0; i < vector_max (ospf6_lsa_handler_vector); i++) { - handler = vector_slot (ospf6_lsa_handler_vector, i); + handler = (struct ospf6_lsa_handler *) + vector_slot (ospf6_lsa_handler_vector, i); if (handler == NULL) continue; strncat (strbuf, ospf6_lsa_handler_name (handler), @@ -913,7 +1004,8 @@ for (i = 0; i < vector_max (ospf6_lsa_handler_vector); i++) { - handler = vector_slot (ospf6_lsa_handler_vector, i); + handler = (struct ospf6_lsa_handler *) + vector_slot (ospf6_lsa_handler_vector, i); if (handler == NULL) continue; strncat (docbuf, "Debug ", DOCSIZE - strlen (docbuf)); @@ -978,7 +1070,8 @@ for (i = 0; i < vector_max (ospf6_lsa_handler_vector); i++) { - handler = vector_slot (ospf6_lsa_handler_vector, i); + handler = (struct ospf6_lsa_handler *) + vector_slot (ospf6_lsa_handler_vector, i); if (handler == NULL) continue; if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG)) @@ -999,3 +1092,34 @@ } +#ifdef SIM_ETRACE_STAT +void ospf6_lsa_increment_hopcount(struct ospf6_lsa_header *lsa_header) +{ + if ((lsa_header->age & 0x00F0) == 0xF0) + return; //this would overflow the hopcount space of 4 bits; + + //printf(" age %x\n", lsa_header->age); + lsa_header->age += 0x10; //hopcount is bits 5 to 8 when in network order + //printf(" hopcount = %x age = %x\n", (hopcount_mask(lsa_header)), + // ntohs(age_mask(lsa_header))); + //printf(" age %x\n", lsa_header->age); +} + +//This function expects the age to be in network order (not host) +//the lsa_header age is in network order +u_int16_t age_mask(struct ospf6_lsa_header *lsa_header) +{ + u_int16_t age = (lsa_header->age & 0xFF0F); + return age; +} + +//This function expects the age to be in network order (not host) +//the lsa_header age is in network order +u_int16_t hopcount_mask(struct ospf6_lsa_header *lsa_header) +{ + //hopcount is bits 5 to 8 when in network order + u_int16_t hopcount = (lsa_header->age & 0x00F0); + return hopcount; +} +#endif //SIM_ETRACE_STAT + diff -Naur quagga-0.98.5/ospf6d/ospf6_lsa.h quagga-0.98.5-manet/ospf6d/ospf6_lsa.h --- quagga-0.98.5/ospf6d/ospf6_lsa.h 2004-12-08 14:01:48.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_lsa.h 2006-02-20 13:42:12.000000000 -0800 @@ -22,6 +22,13 @@ #ifndef OSPF6_LSA_H #define OSPF6_LSA_H +#if defined(SIM) || defined(GTNETS) +#include "linklist.h" //for pList +#endif //SIM || GTNETS +#ifdef SIM_ETRACE_STAT +#include "ospf6d.h" +#endif //SIM_ETRACE_STAT + /* Debug option */ #define OSPF6_LSA_DEBUG 0x01 #define OSPF6_LSA_DEBUG_ORIGINATE 0x02 @@ -130,15 +137,33 @@ int retrans_count; struct ospf6_lsdb *lsdb; +#ifdef OSPF6_MANET_TEMPORARY_LSDB + u_int16_t cache; +#endif //OSPF6_MANET_TEMPORARY_LSDB /* lsa instance */ struct ospf6_lsa_header *header; + +#ifdef SIM_ETRACE_STAT + boolean unicast_stale; +#endif //SIM_ETRACE_STAT +#ifdef OSPF6_DELAYED_FLOOD + struct timeval rxmt_time; /* start of rxmt interval */ +#endif //OSPF6_DELAYED_FLOOD +#ifdef OSPF6_MANET + struct thread *pushBackTimer; + pList pushback_neighbor_list; +#endif //OSPF6_MANET }; #define OSPF6_LSA_HEADERONLY 0x01 #define OSPF6_LSA_FLOODBACK 0x02 #define OSPF6_LSA_DUPLICATE 0x04 #define OSPF6_LSA_IMPLIEDACK 0x08 +#ifdef OSPF6_MANET +// Mark received LSA as being receive on multicast (for reflooding decisions) +#define OSPF6_LSA_RECVMCAST 0x10 +#endif struct ospf6_lsa_handler { @@ -248,5 +273,10 @@ int config_write_ospf6_debug_lsa (struct vty *vty); void install_element_ospf6_debug_lsa (); -#endif /* OSPF6_LSA_H */ +#ifdef SIM_ETRACE_STAT +void ospf6_lsa_increment_hopcount(struct ospf6_lsa_header *); +u_int16_t age_mask(struct ospf6_lsa_header *); +u_int16_t hopcount_mask(struct ospf6_lsa_header *); +#endif //SIM_ETRACE_STAT +#endif /* OSPF6_LSA_H */ diff -Naur quagga-0.98.5/ospf6d/ospf6_lsdb.c quagga-0.98.5-manet/ospf6d/ospf6_lsdb.c --- quagga-0.98.5/ospf6d/ospf6_lsdb.c 2004-12-23 22:00:12.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_lsdb.c 2006-02-20 13:42:12.000000000 -0800 @@ -33,12 +33,21 @@ #include "ospf6_lsdb.h" #include "ospf6d.h" +#ifdef OSPF6_CONFIG +#include "ospf6_intra.h" +#ifdef SIM +#include "sim.h" +#endif //SIM +unsigned char conf_debug_ospf6_database = 0; +#endif //OSPF6_CONFIG + struct ospf6_lsdb * ospf6_lsdb_create (void *data) { struct ospf6_lsdb *lsdb; - lsdb = XCALLOC (MTYPE_OSPF6_LSDB, sizeof (struct ospf6_lsdb)); + lsdb = (struct ospf6_lsdb *) + XCALLOC (MTYPE_OSPF6_LSDB, sizeof (struct ospf6_lsdb)); if (lsdb == NULL) { zlog_warn ("Can't malloc lsdb"); @@ -78,7 +87,14 @@ unsigned int num = 0; for (debug = ospf6_lsdb_head (lsdb); debug; debug = ospf6_lsdb_next (debug)) +#ifdef OSPF6_MANET_TEMPORARY_LSDB + { + if (debug->cache == 0) + num++; + } +#else num++; +#endif //OSPF6_MANET_TEMPORARY_LSDB if (num == lsdb->count) return; @@ -106,13 +122,17 @@ struct ospf6_lsa *next, *prev, *old = NULL; memset (&key, 0, sizeof (key)); +#ifdef OSPF6_MANET_TEMPORARY_LSDB + ospf6_lsdb_set_key (&key, &lsa->cache, sizeof (lsa->cache)); +#endif //OSPF6_MANET_TEMPORARY_LSDB ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type)); ospf6_lsdb_set_key (&key, &lsa->header->adv_router, sizeof (lsa->header->adv_router)); ospf6_lsdb_set_key (&key, &lsa->header->id, sizeof (lsa->header->id)); - current = route_node_get (lsdb->table, (struct prefix *) &key); - old = current->info; + current = (struct route_node *) + route_node_get (lsdb->table, (struct prefix *) &key); + old = (struct ospf6_lsa *) current->info; current->info = lsa; ospf6_lsa_lock (lsa); @@ -137,7 +157,7 @@ lsa->next = NULL; else { - next = nextnode->info; + next = (struct ospf6_lsa *) nextnode->info; lsa->next = next; next->prev = lsa; route_unlock_node (nextnode); @@ -153,13 +173,20 @@ lsa->prev = NULL; else { - prev = prevnode->info; + prev = (struct ospf6_lsa *) prevnode->info; lsa->prev = prev; prev->next = lsa; route_unlock_node (prevnode); } +#ifdef OSPF6_MANET_TEMPORARY_LSDB + if (lsa->cache == 1) + lsdb->count_cache++; + else + lsdb->count++; +#else lsdb->count++; +#endif //OSPF6_MANET_TEMPORARY_LSDB } if (old) @@ -212,6 +239,9 @@ struct prefix_ipv6 key; memset (&key, 0, sizeof (key)); +#ifdef OSPF6_MANET_TEMPORARY_LSDB + ospf6_lsdb_set_key (&key, &lsa->cache, sizeof (lsa->cache)); +#endif //OSPF6_MANET_TEMPORARY_LSDB ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type)); ospf6_lsdb_set_key (&key, &lsa->header->adv_router, sizeof (lsa->header->adv_router)); @@ -226,7 +256,26 @@ lsa->next->prev = lsa->prev; node->info = NULL; + +#ifdef OSPF6_MANET_TEMPORARY_LSDB + if (lsa->cache == 1) + lsdb->count_cache--; + else + lsdb->count--; +#else lsdb->count--; +#endif //OSPF6_MANET_TEMPORARY_LSDB + +#ifdef BUGFIX + if(lsa->expire) { + THREAD_OFF(lsa->expire); + lsa->expire=0; + } + if(lsa->refresh) { + THREAD_OFF(lsa->refresh); + lsa->refresh=0; + } +#endif //BUGFIX if (lsdb->hook_remove) (*lsdb->hook_remove) (lsa); @@ -248,6 +297,10 @@ return NULL; memset (&key, 0, sizeof (key)); +#ifdef OSPF6_MANET_TEMPORARY_LSDB + u_int16_t cache = 0; + ospf6_lsdb_set_key (&key, &cache, sizeof (cache)); +#endif //OSPF6_MANET_TEMPORARY_LSDB ospf6_lsdb_set_key (&key, &type, sizeof (type)); ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router)); ospf6_lsdb_set_key (&key, &id, sizeof (id)); @@ -258,6 +311,33 @@ return (struct ospf6_lsa *) node->info; } + +#ifdef OSPF6_MANET_TEMPORARY_LSDB +struct ospf6_lsa * +ospf6_lsdb_lookup_cache (u_int16_t type, u_int32_t id, u_int32_t adv_router, + struct ospf6_lsdb *lsdb) +{ + struct route_node *node; + struct prefix_ipv6 key; + + if (lsdb == NULL) + return NULL; + + memset (&key, 0, sizeof (key)); + u_int16_t cache = 1; + ospf6_lsdb_set_key (&key, &cache, sizeof (cache)); + ospf6_lsdb_set_key (&key, &type, sizeof (type)); + ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router)); + ospf6_lsdb_set_key (&key, &id, sizeof (id)); + + node = route_node_lookup (lsdb->table, (struct prefix *) &key); + if (node == NULL || node->info == NULL) + return NULL; + return (struct ospf6_lsa *) node->info; +} +#endif //OSPF6_MANET_TEMPORARY_LSDB + + /* Macro version of check_bit (). */ #define CHECK_BIT(X,P) ((((u_char *)(X))[(P) / 8]) >> (7 - ((P) % 8)) & 1) @@ -274,9 +354,14 @@ return NULL; memset (&key, 0, sizeof (key)); +#ifdef OSPF6_MANET_TEMPORARY_LSDB + u_int16_t cache = 0; + ospf6_lsdb_set_key (&key, &cache, sizeof (cache)); +#endif //OSPF6_MANET_TEMPORARY_LSDB ospf6_lsdb_set_key (&key, &type, sizeof (type)); ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router)); ospf6_lsdb_set_key (&key, &id, sizeof (id)); + p = (struct prefix *) &key; { @@ -317,8 +402,8 @@ while (node && node->info == NULL) node = route_next (node); - lsa_prev = prev->info; - lsa_next = (node ? node->info : NULL); + lsa_prev = (struct ospf6_lsa *) prev->info; + lsa_next = (struct ospf6_lsa *) (node ? node->info : NULL); assert (lsa_prev); assert (lsa_prev->next == lsa_next); if (lsa_next) @@ -376,6 +461,10 @@ struct ospf6_lsa *lsa; memset (&key, 0, sizeof (key)); +#ifdef OSPF6_MANET_TEMPORARY_LSDB + u_int16_t cache = 0; + ospf6_lsdb_set_key (&key, &cache, sizeof (cache)); +#endif //OSPF6_MANET_TEMPORARY_LSDB ospf6_lsdb_set_key (&key, &type, sizeof (type)); ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router)); @@ -399,7 +488,7 @@ if (! prefix_match ((struct prefix *) &key, &node->p)) return NULL; - lsa = node->info; + lsa = (struct ospf6_lsa *) node->info; ospf6_lsa_lock (lsa); return lsa; @@ -432,6 +521,10 @@ struct ospf6_lsa *lsa; memset (&key, 0, sizeof (key)); +#ifdef OSPF6_MANET_TEMPORARY_LSDB + u_int16_t cache = 0; + ospf6_lsdb_set_key (&key, &cache, sizeof (cache)); +#endif //OSPF6_MANET_TEMPORARY_LSDB ospf6_lsdb_set_key (&key, &type, sizeof (type)); /* Walk down tree. */ @@ -453,7 +546,7 @@ if (! prefix_match ((struct prefix *) &key, &node->p)) return NULL; - lsa = node->info; + lsa = (struct ospf6_lsa *) node->info; ospf6_lsa_lock (lsa); return lsa; @@ -579,4 +672,328 @@ return ((u_int32_t) htonl (seqnum)); } +#ifdef OSPF6_CONFIG +DEFUN (debug_ospf6_database, + debug_ospf6_database_cmd, + "debug ospf6 database", + DEBUG_STR + OSPF6_STR + "Dump ospf6 database\n" + ) +{ + unsigned char level = 0; + level = OSPF6_DEBUG_DATABASE; + OSPF6_DEBUG_DATABASE_ON (level); + return CMD_SUCCESS; +} + +DEFUN (no_debug_ospf6_database, + no_debug_ospf6_database_cmd, + "no debug ospf6 database", + NO_STR + DEBUG_STR + OSPF6_STR + "Dump ospf6 database\n" + ) +{ + unsigned char level = 0; + level = OSPF6_DEBUG_DATABASE; + OSPF6_DEBUG_DATABASE_OFF (level); + return CMD_SUCCESS; +} + +DEFUN (debug_ospf6_database_detail, + debug_ospf6_database_detail_cmd, + "debug ospf6 database detail", + DEBUG_STR + OSPF6_STR + "Dump ospf6 database\n" + "High detail\n" + ) +{ + unsigned char level = 0; + level = OSPF6_DEBUG_DATABASE_DETAIL; + OSPF6_DEBUG_DATABASE_ON (level); + return CMD_SUCCESS; +} + +DEFUN (no_debug_ospf6_database_detail, + no_debug_ospf6_database_detail_cmd, + "no debug ospf6 database detail", + NO_STR + DEBUG_STR + OSPF6_STR + "Dump ospf6 database\n" + "High detail\n" + ) +{ + unsigned char level = 0; + level = OSPF6_DEBUG_DATABASE_DETAIL; + OSPF6_DEBUG_DATABASE_OFF (level); + return CMD_SUCCESS; +} + +void +install_element_ospf6_debug_database() +{ + install_element (ENABLE_NODE, &debug_ospf6_database_cmd); + install_element (ENABLE_NODE, &debug_ospf6_database_detail_cmd); + install_element (CONFIG_NODE, &debug_ospf6_database_cmd); + install_element (CONFIG_NODE, &debug_ospf6_database_detail_cmd); + install_element (ENABLE_NODE, &no_debug_ospf6_database_cmd); + install_element (ENABLE_NODE, &no_debug_ospf6_database_detail_cmd); + install_element (CONFIG_NODE, &no_debug_ospf6_database_cmd); + install_element (CONFIG_NODE, &no_debug_ospf6_database_detail_cmd); +} + +void +ospf6_debug_lsdb_show (int level, struct ospf6_lsdb *lsdb) +{ + struct ospf6_lsa *lsa; + char adv_router[16], id[16]; + struct timeval now, res; + char duration[16]; + int count = 0; + + zlog_debug("DUMPING DATABASE %p", lsdb); + lsa = ospf6_lsdb_head (lsdb); + while (lsa) + { + assert(lsa); + assert(lsa->header); + + inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); + inet_ntop (AF_INET, &lsa->header->adv_router, adv_router, + sizeof (adv_router)); +#ifdef SIM + gettimeofday_sim (&now, NULL); +#else + gettimeofday (&now, NULL); +#endif //SIM + timersub (&now, &lsa->installed, &res); + timerstring (&res, duration, sizeof (duration)); + + if (level == OSPF6_DEBUG_DATABASE) + { + zlog_debug ("%-12s %-15s %-15s %4hu %8lx %04hx %4hu %8s", + ospf6_lstype_name (lsa->header->type), + id, adv_router, ospf6_lsa_age_current (lsa), + (u_long) ntohl (lsa->header->seqnum), + ntohs (lsa->header->checksum), ntohs (lsa->header->length), + duration); + } + else if (level == OSPF6_DEBUG_DATABASE_DETAIL) + { + zlog_debug ("LSA %d", ++count); + zlog_debug(" Age: %4hu Type: %s", ospf6_lsa_age_current (lsa), + ospf6_lstype_name (lsa->header->type)); + zlog_debug(" Link State ID: %s", id); + zlog_debug(" Advertising Router: %s", adv_router); + zlog_debug(" LS Sequence Number: %#010lx", + (u_long) ntohl (lsa->header->seqnum)); + zlog_debug(" CheckSum: %#06hx Length: %hu", + ntohs (lsa->header->checksum), ntohs (lsa->header->length)); + switch(ntohs(lsa->header->type)) + { + case OSPF6_LSTYPE_ROUTER: + ospf6_debug_router_lsa_show(lsa); + break; + case OSPF6_LSTYPE_NETWORK: + ospf6_debug_network_lsa_show(lsa); + break; + case OSPF6_LSTYPE_LINK: + ospf6_debug_link_lsa_show(lsa); + break; + case OSPF6_LSTYPE_INTRA_PREFIX: + ospf6_debug_intra_prefix_lsa_show(lsa); + break; + default: + zlog_debug(" logging not implemented for LSA %s", lsa->name); + break; + } + } + else + { + zlog_debug("bad level when displaying database"); + } + lsa = ospf6_lsdb_next (lsa); + } +} + +int +ospf6_debug_router_lsa_show (struct ospf6_lsa *lsa) +{ + char *start, *end, *current; + char buf[32], name[32], bits[16], options[32]; + struct ospf6_router_lsa *router_lsa; + struct ospf6_router_lsdesc *lsdesc; + + router_lsa = (struct ospf6_router_lsa *) + ((char *) lsa->header + sizeof (struct ospf6_lsa_header)); + + ospf6_capability_printbuf (router_lsa->bits, bits, sizeof (bits)); + ospf6_options_printbuf (router_lsa->options, options, sizeof (options)); + zlog_debug (" Bits: %s Options: %s", bits, options); + + start = (char *) router_lsa + sizeof (struct ospf6_router_lsa); + end = (char *) lsa->header + ntohs (lsa->header->length); + for (current = start; current + sizeof (struct ospf6_router_lsdesc) <= end; + current += sizeof (struct ospf6_router_lsdesc)) + { + lsdesc = (struct ospf6_router_lsdesc *) current; + + if (lsdesc->type == OSPF6_ROUTER_LSDESC_POINTTOPOINT) + snprintf (name, sizeof (name), "Point-To-Point"); + else if (lsdesc->type == OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK) + snprintf (name, sizeof (name), "Transit-Network"); + else if (lsdesc->type == OSPF6_ROUTER_LSDESC_STUB_NETWORK) + snprintf (name, sizeof (name), "Stub-Network"); + else if (lsdesc->type == OSPF6_ROUTER_LSDESC_VIRTUAL_LINK) + snprintf (name, sizeof (name), "Virtual-Link"); + else + snprintf (name, sizeof (name), "Unknown (%#x)", lsdesc->type); + + zlog_debug (" Type: %s Metric: %d", + name, ntohs (lsdesc->metric)); + zlog_debug (" Interface ID: %s", + inet_ntop (AF_INET, &lsdesc->interface_id, + buf, sizeof (buf))); + zlog_debug (" Neighbor Interface ID: %s", + inet_ntop (AF_INET, &lsdesc->neighbor_interface_id, + buf, sizeof (buf))); + zlog_debug (" Neighbor Router ID: %s", + inet_ntop (AF_INET, &lsdesc->neighbor_router_id, + buf, sizeof (buf))); + } + return 0; +} + +int ospf6_debug_network_lsa_show (struct ospf6_lsa *lsa) +{ + char *start, *end, *current; + struct ospf6_network_lsa *network_lsa; + struct ospf6_network_lsdesc *lsdesc; + char buf[128], options[32]; + network_lsa = (struct ospf6_network_lsa *) + ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header)); + + ospf6_options_printbuf (network_lsa->options, options, sizeof (options)); + zlog_debug (" Options: %s", options); + + start = (char *) network_lsa + sizeof (struct ospf6_network_lsa); + end = (char *) lsa->header + ntohs (lsa->header->length); + for (current = start; current + sizeof (struct ospf6_network_lsdesc) <= end; + current += sizeof (struct ospf6_network_lsdesc)) + { + lsdesc = (struct ospf6_network_lsdesc *) current; + inet_ntop (AF_INET, &lsdesc->router_id, buf, sizeof (buf)); + zlog_debug (" Attached Router: %s", buf); + } + return 0; +} + +int ospf6_debug_link_lsa_show (struct ospf6_lsa *lsa) +{ + char *start, *end, *current; + struct ospf6_link_lsa *link_lsa; + int prefixnum; + char buf[128], options[32]; + struct ospf6_prefix *prefix; + const char *p, *mc, *la, *nu; + struct in6_addr in6; + + link_lsa = (struct ospf6_link_lsa *) + ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header)); + + ospf6_options_printbuf (link_lsa->options, options, sizeof (options)); + inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf)); + prefixnum = ntohl (link_lsa->prefix_num); + + zlog_debug (" Priority: %d Options: %s", + link_lsa->priority, options); + zlog_debug (" LinkLocal Address: %s", buf); + zlog_debug (" Number of Prefix: %d", prefixnum); + + start = (char *) link_lsa + sizeof (struct ospf6_link_lsa); + end = (char *) lsa->header + ntohs (lsa->header->length); + for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix)) + { + prefix = (struct ospf6_prefix *) current; + if (prefix->prefix_length == 0 || + current + OSPF6_PREFIX_SIZE (prefix) > end) + break; + + p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ? + "P" : "--"); + mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ? + "MC" : "--"); + la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ? + "LA" : "--"); + nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ? + "NU" : "--"); + zlog_debug (" Prefix Options: %s|%s|%s|%s", + p, mc, la, nu); + + memset (&in6, 0, sizeof (in6)); + memcpy (&in6, OSPF6_PREFIX_BODY (prefix), + OSPF6_PREFIX_SPACE (prefix->prefix_length)); + inet_ntop (AF_INET6, &in6, buf, sizeof (buf)); + zlog_debug (" Prefix: %s/%d", + buf, prefix->prefix_length); + } + return 0; +} +int ospf6_debug_intra_prefix_lsa_show (struct ospf6_lsa *lsa) +{ + char *start, *end, *current; + struct ospf6_intra_prefix_lsa *intra_prefix_lsa; + int prefixnum; + char buf[128]; + struct ospf6_prefix *prefix; + char id[16], adv_router[16]; + const char *p, *mc, *la, *nu; + struct in6_addr in6; + + intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *) + ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header)); + + prefixnum = ntohs (intra_prefix_lsa->prefix_num); + + zlog_debug(" Number of Prefix: %d", prefixnum); + + inet_ntop (AF_INET, &intra_prefix_lsa->ref_id, id, sizeof (id)); + inet_ntop (AF_INET, &intra_prefix_lsa->ref_adv_router, + adv_router, sizeof (adv_router)); + zlog_debug(" Reference: %s Id: %s Adv: %s", + ospf6_lstype_name (intra_prefix_lsa->ref_type), id, adv_router); + + start = (char *) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa); + end = (char *) lsa->header + ntohs (lsa->header->length); + for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix)) + { + prefix = (struct ospf6_prefix *) current; + if (prefix->prefix_length == 0 || + current + OSPF6_PREFIX_SIZE (prefix) > end) + break; + + p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ? + "P" : "--"); + mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ? + "MC" : "--"); + la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ? + "LA" : "--"); + nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ? + "NU" : "--"); + zlog_debug (" Prefix Options: %s|%s|%s|%s", + p, mc, la, nu); + + memset (&in6, 0, sizeof (in6)); + memcpy (&in6, OSPF6_PREFIX_BODY (prefix), + OSPF6_PREFIX_SPACE (prefix->prefix_length)); + inet_ntop (AF_INET6, &in6, buf, sizeof (buf)); + zlog_debug(" Prefix: %s/%d", buf, prefix->prefix_length); + } + return 0; +} +#endif //OSPF6_CONFIG diff -Naur quagga-0.98.5/ospf6d/ospf6_lsdb.h quagga-0.98.5-manet/ospf6d/ospf6_lsdb.h --- quagga-0.98.5/ospf6d/ospf6_lsdb.h 2004-12-08 14:01:48.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_lsdb.h 2006-02-20 13:42:12.000000000 -0800 @@ -25,15 +25,26 @@ #include "prefix.h" #include "table.h" +#ifdef BUGFIX +#include "ospf6_lsa.h" +#endif //BUGFIX + struct ospf6_lsdb { void *data; /* data structure that holds this lsdb */ struct route_table *table; u_int32_t count; +#ifdef OSPF6_MANET_TEMPORARY_LSDB + u_int32_t count_cache; +#endif //OSPF6_MANET_TEMPORARY_LSDB void (*hook_add) (struct ospf6_lsa *); void (*hook_remove) (struct ospf6_lsa *); }; +#ifdef BUGFIX +//XXX BUG still present +//RFC 2328 chapter 14 paragraph 2 states the MaxAge LSA +//should be flooded #define OSPF6_LSDB_MAXAGE_REMOVER(lsdb) \ do { \ struct ospf6_lsa *lsa; \ @@ -45,9 +56,26 @@ continue; \ if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type)) \ zlog_debug ("Remove MaxAge %s", lsa->name); \ + /* ospf6_flood(NULL, lsa); */ \ ospf6_lsdb_remove (lsa, lsdb); \ } \ } while (0) +#else +#define OSPF6_LSDB_MAXAGE_REMOVER(lsdb) \ + do { \ + struct ospf6_lsa *lsa; \ + for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa)) \ + { \ + if (! OSPF6_LSA_IS_MAXAGE (lsa)) \ + continue; \ + if (lsa->retrans_count != 0) \ + continue; \ + if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type)) \ + zlog_debug ("Remove MaxAge %s", lsa->name); \ + ospf6_lsdb_remove (lsa, lsdb); \ + } \ + } while (0) +#endif //BUGFIX /* Function Prototypes */ struct ospf6_lsdb *ospf6_lsdb_create (void *data); @@ -56,6 +84,12 @@ struct ospf6_lsa * ospf6_lsdb_lookup (u_int16_t type, u_int32_t id, u_int32_t adv_router, struct ospf6_lsdb *lsdb); +#ifdef OSPF6_MANET_TEMPORARY_LSDB +struct ospf6_lsa * +ospf6_lsdb_lookup_cache (u_int16_t type, u_int32_t id, u_int32_t adv_router, + struct ospf6_lsdb *lsdb); +#endif //OSPF6_MANET_TEMPORARY_LSDB + struct ospf6_lsa * ospf6_lsdb_lookup_next (u_int16_t type, u_int32_t id, u_int32_t adv_router, struct ospf6_lsdb *lsdb); @@ -95,6 +129,29 @@ u_int32_t ospf6_new_ls_seqnum (u_int16_t type, u_int32_t id, u_int32_t adv_router, struct ospf6_lsdb *lsdb); +#ifdef OSPF6_CONFIG +/* Debug option */ +extern unsigned char conf_debug_ospf6_database; +#define OSPF6_DEBUG_DATABASE 0x01 +#define OSPF6_DEBUG_DATABASE_DETAIL 0x02 +#define OSPF6_DEBUG_DATABASE_ON(level) \ + (conf_debug_ospf6_database |= (level)) +#define OSPF6_DEBUG_DATABASE_OFF(level) \ + (conf_debug_ospf6_database &= ~(level)) +#define IS_OSPF6_DEBUG_DATABASE(level) \ + (conf_debug_ospf6_database & OSPF6_DEBUG_ ## level) + +void install_element_ospf6_debug_database(); +void ospf6_debug_lsdb_show (int level, struct ospf6_lsdb *lsdb); + +int ospf6_debug_router_lsa_show (struct ospf6_lsa *lsa); +int ospf6_debug_network_lsa_show (struct ospf6_lsa *lsa); +int ospf6_debug_link_lsa_show (struct ospf6_lsa *lsa); +int ospf6_debug_intra_prefix_lsa_show (struct ospf6_lsa *lsa); + + +#endif //OSPF6_CONFIG + #endif /* OSPF6_LSDB_H */ diff -Naur quagga-0.98.5/ospf6d/ospf6_main.c quagga-0.98.5-manet/ospf6d/ospf6_main.c --- quagga-0.98.5/ospf6d/ospf6_main.c 2004-12-07 07:39:32.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_main.c 2006-02-20 13:42:12.000000000 -0800 @@ -28,12 +28,14 @@ #include "command.h" #include "vty.h" #include "memory.h" -#include "if.h" +#include "lib/if.h" #include "filter.h" #include "prefix.h" #include "plist.h" #include "privs.h" +#ifndef SIM #include "sigevent.h" +#endif //SIM #include "ospf6d.h" @@ -50,6 +52,36 @@ ZCAP_BIND }; +#ifdef SIM +#if defined (QUAGGA_USER) +char *quagga_u = QUAGGA_USER; +#else +char *quagga_u = NULL; +#endif +#if defined (QUAGGA_GROUP) +char *quagga_g = QUAGGA_GROUP; +#else +char *quagga_g = NULL; +#endif +#if defined (VTY_GROUP) +char *vty_g = VTY_GROUP; +#else +char *vty_g = NULL; +#endif + +struct zebra_privs_t ospf6d_privs = +{ + _caps_p, + NULL, + 2, + 0, + quagga_u, + quagga_g, + vty_g, + NULL, + NULL +}; +#else struct zebra_privs_t ospf6d_privs = { #if defined(QUAGGA_USER) @@ -65,6 +97,7 @@ .cap_num_p = 2, .cap_num_i = 0 }; +#endif //SIM /* ospf6d options, we use GNU getopt library. */ struct option longopts[] = @@ -82,7 +115,9 @@ }; /* Configuration file and directory. */ +#ifndef SIM char config_default[] = SYSCONFDIR OSPF6_DEFAULT_CONFIG; +#endif //SIM /* ospf6d program name. */ char *progname; @@ -90,6 +125,7 @@ /* is daemon? */ int daemon_mode = 0; +// Global Variable /* Master of threads. */ struct thread_master *master; @@ -153,6 +189,7 @@ zlog_rotate (NULL); } +#ifndef SIM struct quagga_signal_t ospf6_signals[] = { { @@ -296,5 +333,5 @@ /* Not reached. */ exit (0); } - +#endif //SIM diff -Naur quagga-0.98.5/ospf6d/ospf6_mdr.c quagga-0.98.5-manet/ospf6d/ospf6_mdr.c --- quagga-0.98.5/ospf6d/ospf6_mdr.c 1969-12-31 16:00:00.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_mdr.c 2006-02-20 13:42:12.000000000 -0800 @@ -0,0 +1,840 @@ +/* + * Copyright (C) Boeing Co. + * + * Much of the code in this file was written by Richard Ogier + * or was transcribed from C code written by him. + * This code implements the MDR extension of OSPF as described in + * draft-ogier-manet-ospf-extension-06.txt. + */ + +#ifdef OSPF6_MANET_MDR_FLOOD + +#include "zebra.h" +#include "thread.h" +#include "ospf6_mdr.h" +#include "ospf6_area.h" +#include "ospf6_flood.h" +#include "ospf6_intra.h" +#include "ospf6_lsa.h" +#include "ospf6_top.h" +#ifdef SIM_ETRACE_STAT +#include "sim.h" +#endif //SIM_ETRACE_STAT + +//Determine if node is in CDS +void ospf6_calculate_mdr(struct ospf6_interface *oi) +{ + plistnode j,k,u; + struct ospf6_neighbor *onj, *onk, *onu, *onv; + struct ospf6_neighbor *max_on = NULL, *max_on2 = NULL, *min_on = NULL; + struct ospf6_neighbor *max_nbr = NULL; // RGO + pList q; + pList tree = list_new(); + u_int32_t rid = oi->area->ospf6->router_id; + int maxid = -1, maxid2 = -1; + int max_mdr_level = OSPF6_OTHER, max_mdr_level2 = OSPF6_OTHER; + struct tree_node *child, *child2, *tu, *tv, *root; + int min_hops2, cost2; + boolean dr=false, bdr=false; + + // Do not calculate MDRs within hello_interval of start time. + if (elapsed_time(&ospf6->starttime) < oi->hello_interval) + return; + + //cost_matrix must be freed at the end of this function + ospf6_mdr_create_cost_matrix(oi); + +#ifdef SIM_ETRACE_STAT + char router_id[16]; + inet_ntop (AF_INET, &rid, router_id, sizeof (router_id)); +#endif //SIM_ETRACE_STAT + +// A.1. PHASE 1 - 1.3 + // First find the largest nbr ID + // For persistent version, find largest DR level first. + for (j = listhead(oi->neighbor_list); j; nextnode(j)) + { + onj = (struct ospf6_neighbor *) getdata (j); + + //some intitialization + // Select dependent neighbors. + onj->dependent = false; + onj->hops = INFTY; + onj->hops2 = INFTY; + + if (ospf6_mdr_cost(onj, NULL) != 1) + continue; // nbr must be twoway + + //Find Max and 2nd Max Neighbor + if (ospf6_sidcds_lexicographic(oi, onj->mdr_level, max_mdr_level, 0, 0, + ntohl(onj->router_id), maxid)) + { + // previous max neighbor becomes 2nd max neighbor + maxid2 = maxid; + max_mdr_level2 = max_mdr_level; + max_on2 = max_on; + + maxid = ntohl(onj->router_id); + max_mdr_level = onj->mdr_level; + max_on = onj; + } + else if (ospf6_sidcds_lexicographic(oi, onj->mdr_level, max_mdr_level2, + 0, 0, ntohl(onj->router_id), maxid2)) + { + maxid2 = ntohl(onj->router_id); + max_mdr_level2 = onj->mdr_level; + max_on2 = onj; + } + } + + if (maxid == -1) + { + //no neighbors + oi->mdr_level = OSPF6_OTHER; + oi->parent = NULL; + oi->bparent = NULL; + + //clean up + remove_tree(tree); + ospf6_mdr_free_cost_matrix(oi); + return; + } + +#ifdef SIM_ETRACE_STAT + TraceEvent_sim(2,"nbr: max_mdr_level=%d maxid=%d", max_mdr_level, maxid); + TraceEvent_sim(2,"nbr: max_mdr_level2=%d maxid2=%d", max_mdr_level2, maxid2); +#endif //SIM_ETRACE_STAT + +// A.1. PHASE 1 - 1.1 + if (ospf6_sidcds_lexicographic(oi, oi->mdr_level, max_mdr_level, 0, 0, + ntohl(rid), maxid)) + { + // Generate LSA if Other becomes MDR or BMDR. + if (oi->LSAFullness == OSPF6_LSA_FULLNESS_MDRFULL && + oi->mdr_level == OSPF6_OTHER) + OSPF6_ROUTER_LSA_SCHEDULE (oi->area); + + oi->mdr_level = OSPF6_MDR; //dr = true + + // Make all neighbors dependent + // RGO. Modification for version 07. A dependent neighbor + // must be an MDR (or BMDR if AdjConn = 2). + for (j = listhead(oi->neighbor_list); j; nextnode(j)) + { + onj = (struct ospf6_neighbor *) getdata (j); + // Select dependent neighbors. + if (ospf6_mdr_cost(onj, NULL) == 1) + if (onj->mdr_level == OSPF6_MDR || + (oi->AdjConnectivity == 2 && onj->mdr_level == OSPF6_BMDR)) + onj->dependent = true; + } + + oi->parent = NULL; + oi->bparent = NULL; +#ifdef SIM_ETRACE_STAT + TraceEvent_sim(2,"Phase 1 1.1: I am a DR id = %s mdr_level = %d", + router_id, oi->mdr_level); +#endif //SIM_ETRACE_STAT + //clean up + remove_tree(tree); + ospf6_mdr_free_cost_matrix(oi); + return; //I am a CDS + } + +// A.1. PHASE 1 - 1.2 + //ospf6_mdr_cost() + + // Determine if there is a path from on_max to all other nbrs of this node, + // using only intermediate nodes with larger ID than this node). + // Use BFS, starting with on_max. +// A.1. PHASE 1 - 1.4 + max_on->hops = 0; + add_tree_node(tree, max_on, NULL); + q = list_new(); + q_add(q, max_on); // Add max_on to FIFO. + + +// A.1. PHASE 1 - 1.5 + while ((onk = q_remove(q)) != NULL) + { + // update hops of onk's nbrs + for (u = listhead(oi->neighbor_list); u; nextnode(u)) + { + onu = (struct ospf6_neighbor *) getdata (u); + if (ospf6_mdr_cost(onu, NULL) != 1) + continue; // nbr must be twoway + // Cost is from k to u. + if (ospf6_mdr_cost(onk, onu) != 1) + continue; + if (onk->hops + 1 < onu->hops) + { + onu->hops = onk->hops + 1; + add_tree_node(tree, onu, onk->treenode); + q_add(q, onu); + } + } + } + list_delete(q); + +// A.1. PHASE 1 - 1.6 + // Node is in CDS if any nbr has infinite hops + for (k = listhead(oi->neighbor_list); k; nextnode(k)) + { + onk = (struct ospf6_neighbor *) getdata (k); + if (ospf6_mdr_cost(onk, NULL) != 1) + continue; // nbr must be twoway + //if (onk->hops == INFTY) + if (onk->hops > oi->MDRConstraint) // MPN parameter h. + { +#ifdef SIM_ETRACE_STAT + TraceEvent_sim(2,"Dependent neighbor = %s", ip2str(onk->router_id)); +#endif //SIM_ETRACE_STAT + dr = true; + if (onk->mdr_level == OSPF6_MDR || + (oi->AdjConnectivity == 2 && onk->mdr_level == OSPF6_BMDR)) + onk->dependent = true; + } + } + if (dr) + { +#ifdef SIM_ETRACE_STAT + TraceEvent_sim(2,"Phase 1 1.6: I am a DR id = %s previous mdr_level = %d", + router_id, oi->mdr_level); +#endif //SIM_ETRACE_STAT + // max_on is always dependent (no need to check MDR level). + max_on->dependent = true; + // Parents are updated later. + } + + // ###### Backup DR Calculation ######## +// A.1. PHASE 2 - 2.1 + //use ospf6_mdr_cost2() + +// A.1. PHASE 2 - 2.2 + max_on->hops2 = 0; + +// A.1. PHASE 2 - 2.3 + max_on->treenode->labeled = 1; // root is labeled + // Update hops2 by looking at links between subtrees created + // when root is removed from tree. + for (child=max_on->treenode->first_child; child; child=child->next_sib) + { + for (child2=max_on->treenode->first_child; child2; child2=child2->next_sib) + { + if (child == child2) + continue; + // child is the root of its subtree, so start DFS from child + for (tu = child; tu; tu = dfs_next(tu)) + { + onu = tu->on; + for (tv = child2; tv; tv = dfs_next(tv)) + { + onv = tv->on; + if (ntohl(onu->router_id) == ntohl(onv->router_id)) + printf("Error: u should not equal v \n"); + if (onv->hops2 > max_on->hops2 + ospf6_mdr_cost2(onu,onv)) + onv->hops2 = max_on->hops2 + ospf6_mdr_cost2(onu,onv); + // If we were actually computing disjoint paths, + // we would also update parent nodes here. + } + } + } + } + +// A.1. PHASE 2 - 2.4 + // Next, find the unlabeled node min_on with minimum hops2 and label it. + // This divides the unlabeled subtree containing min_on into smaller + // unlabeled subtrees, one for the parent of min_on if it exists and + // is unlabeled, and one for each unlabeled child of min_on. + // For node-disjoint paths, one of the subtrees must be the parent subtree. + // I.e., we cannot use links between two child subtrees. + // Also, a link from min_on to a node in the parent subtree is allowed. + while (1) + { // will break when no unlabeled node with finite hops2 exists + min_hops2 = INFTY; + for (k = listhead(oi->neighbor_list); k; nextnode(k)) + { + onk = (struct ospf6_neighbor *) getdata (k); + if (ospf6_mdr_cost(onk, NULL) != 1) + continue; // nbr must be twoway + if(!onk->treenode || onk->treenode->labeled) + continue; + if(onk->hops2 < min_hops2) + { + min_hops2 = onk->hops2; + min_on = onk; + } + } + + if (min_hops2 == INFTY) + break; // S-T algorithm done + + min_on->treenode->labeled = 1; + if (!min_on->treenode->parent || min_on->treenode->parent->labeled) + continue; // no parent subtree, so try another kmin + + // Find root of parent subtree + root = min_on->treenode->parent; + while (root->parent && !root->parent->labeled) + root = root->parent; + + // Iterate thru nodes of parent subtree, using DFS + for (tu = root; tu; tu = dfs_next(tu)) + { + onu = tu->on; + if (ntohl(onu->router_id) == ntohl(min_on->router_id)) + printf("Error: onu should not equal min_on\n"); + // First process link from min_on to u + cost2 = ospf6_mdr_cost2(min_on,onu); + if (onu->hops2 > min_on->hops2 + cost2) + onu->hops2 = min_on->hops2 + cost2; + // Now process links between u and each child subtree, in both directions + for (child2=min_on->treenode->first_child;child2;child2=child2->next_sib) + { + if (child2->labeled) + continue; // consider only unlabeled children + for (tv = child2; tv; tv = dfs_next(tv)) + { + onv = tv->on; + if (ntohl(onv->router_id) == ntohl(onu->router_id)) + printf("Error: v should not equal u \n"); + if (ntohl(onv->router_id) == ntohl(min_on->router_id)) + printf("Error: v should not equal kmin \n"); + // Process link from u to v to update onv->hops2 + cost2 = ospf6_mdr_cost2(onu,onv); + if (onv->hops2 > min_on->hops2 + cost2) + onv->hops2 = min_on->hops2 + cost2; + cost2 = ospf6_mdr_cost2(onv,onu); + // Process link from v to u to update onu->hops2 + if (onu->hops2 > min_on->hops2 + cost2) + onu->hops2 = min_on->hops2 + cost2; + } + } + } + } +// A.1. PHASE 2 - 2.5 + // Node is a backup DR if any nbr has infinite hops2 + for (k = listhead(oi->neighbor_list); k; nextnode(k)) + { + onk = (struct ospf6_neighbor *) getdata (k); + if (ospf6_mdr_cost(onk, NULL) != 1) + continue; // nbr must be twoway + if(onk->hops2 == INFTY) + { +// A.1. PHASE 2 - 2.6 + if (!dr) + bdr = true; // Router is a BMDR. + // RGO. Modification for version 07. Backup dependent nbrs + // are selected only if AdjConn = 2, and must be MDR or BMDR. + if (!onk->dependent) + if (oi->AdjConnectivity == 2 && onk->mdr_level >= OSPF6_BMDR) + onk->dependent = true; // onk is a dependent nbr + } + } + if (bdr) + { +#ifdef SIM_ETRACE_STAT + TraceEvent_sim(2,"Phase 2 2.5: I am a BDR id = %s mdr_level = %d", + router_id, oi->mdr_level); +#endif //SIM_ETRACE_STAT + // If Adj_Conn = 2 and max_on is not dependent, then + // it is backup dependent (no need to check MDR level). + if (!max_on->dependent) + if (oi->AdjConnectivity == 2) + max_on->dependent = true; + } + + // PARENT SELECTION. + // RGO. New parent selection rules for version 07. + // For an MDR, parent is always Rmax (max_on). + // For a BMDR and Other, parent is the adjacent MDR neighbor with largest + // RID, if an adjacent MDR neighbor exists, and is otherwise Rmax. + // Backup parent of MDR and BMDR is NULL. + // If AdjConn = 1, backup parent of Other is NULL. + // If AdjConn = 2, backup parent is chosen using the same rules as the + // parent, except that it must be different from the parent (or NULL). + + + if (dr) + { + oi->parent = max_on; + } + else // BMDR or Other + { + // Find an adjacent MDR neighbor with max ID, if one exists. + maxid = -1; + max_mdr_level = 0; + max_nbr = NULL; + for (j = listhead(oi->neighbor_list); j; nextnode(j)) + { + onj = (struct ospf6_neighbor *) getdata (j); + if (onj->state < OSPF6_NEIGHBOR_EXCHANGE) + continue; // consider only adjacent neighbors + if (onj->mdr_level < OSPF6_MDR) + continue; // consider only MDR neighbors + if (ospf6_sidcds_lexicographic(oi, onj->mdr_level, max_mdr_level, 0, 0, + ntohl(onj->router_id), maxid)) + { + maxid = ntohl(onj->router_id); + max_mdr_level = onj->mdr_level; + max_nbr = onj; + } + } + if (maxid != -1) + oi->parent = max_nbr; + else + oi->parent = max_on; + } + + // Select backup parent + // Initialize backup parent to NULL. + // Will remain NULL for MDR/BMDR or if AdjConn = 1. + oi->bparent = NULL; + // If AdjConn = 2, MDR Other selects backup parent, using same + // procedure as for parent, but must not be equal to parent. + if (!dr && !bdr && oi->AdjConnectivity == 2) + { + // Find an adjacent MDR or BMDR neighbor with max ID, excluding parent. + maxid = -1; + max_mdr_level = 0; + max_nbr = NULL; + for (j = listhead(oi->neighbor_list); j; nextnode(j)) + { + onj = (struct ospf6_neighbor *) getdata (j); + if (onj->state < OSPF6_NEIGHBOR_EXCHANGE) + continue; // consider only adjacent neighbors + if (onj == oi->parent) + continue; // backup parent cannot be parent + if (onj->mdr_level < OSPF6_BMDR) + continue; // consider only MDR and BMDR neighbors + if (ospf6_sidcds_lexicographic(oi, onj->mdr_level, max_mdr_level, 0, 0, + ntohl(onj->router_id), maxid)) + { + maxid = ntohl(onj->router_id); + max_mdr_level = onj->mdr_level; + max_nbr = onj; + } + } + if (maxid != -1) + oi->bparent = max_nbr; + else if (oi->parent != max_on) + oi->bparent = max_on; + else + oi->bparent = max_on2; // can be NULL + } + + // Generate LSA if Other becomes MDR or BMDR, + // or if full adjacencies are used and router is Other and the + // parent or bparent is Full but not yet advertised. + if ((oi->LSAFullness == OSPF6_LSA_FULLNESS_MDRFULL && + oi->mdr_level == OSPF6_OTHER && (dr || bdr)) || + (!dr && !bdr && oi->full_adj_part_lsa && + (oi->parent && oi->parent->state == OSPF6_NEIGHBOR_FULL && + !oi->parent->adv || + oi->bparent && oi->bparent->state == OSPF6_NEIGHBOR_FULL && + !oi->bparent->adv))) + OSPF6_ROUTER_LSA_SCHEDULE (oi->area); + + // set correct designated router level + if (dr) + oi->mdr_level = OSPF6_MDR; + else if (bdr) + oi->mdr_level = OSPF6_BMDR; + else + oi->mdr_level = OSPF6_OTHER; + + //clean up + remove_tree(tree); + ospf6_mdr_free_cost_matrix(oi); + +#ifdef SIM_ETRACE_STAT +{ + char p_rid[16]; + char bp_rid[16]; + if (oi->parent) + inet_ntop (AF_INET, &oi->parent->router_id, p_rid, sizeof (p_rid)); + if (oi->bparent) + inet_ntop (AF_INET, &oi->bparent->router_id, bp_rid, sizeof (bp_rid)); + + if (oi->parent && oi->bparent) + TraceEvent_sim(2,"mdr_level = %d parent = %s bparent = %s", + oi->mdr_level, p_rid, bp_rid); + else if (oi->parent) + TraceEvent_sim(2,"mdr_level = %d parent = %s", oi->mdr_level, p_rid); + else + TraceEvent_sim(2,"mdr_level = %d", oi->mdr_level); +} +#endif //SIM_ETRACE_STAT +} + + +void ospf6_mdr_update_adjacencies(struct ospf6_interface *oi) +{ + plistnode j; + struct ospf6_lsa *lsa; + struct ospf6_neighbor *on; + // Check need adjacency for each 2-way neighbor. + for (j = listhead(oi->neighbor_list); j; nextnode(j)) + { + on = (struct ospf6_neighbor *) getdata (j); + if (on && on->state == OSPF6_NEIGHBOR_TWOWAY && need_adjacency(on)) + { + ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on); + SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT); + SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT); + SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT); + THREAD_OFF (on->thread_send_dbdesc); + on->thread_send_dbdesc = + thread_add_event (master, ospf6_dbdesc_send, on, 0); + } + } + // Check keep adjacency for each adjacent neighbor. + for (j = listhead(oi->neighbor_list); j; nextnode(j)) + { + on = (struct ospf6_neighbor *) getdata (j); + if (on && on->state > OSPF6_NEIGHBOR_TWOWAY && !keep_adjacency(on)) + { + ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on); + // Clear retrans_list + ospf6_lsdb_remove_all (on->summary_list); + ospf6_lsdb_remove_all (on->request_list); + for (lsa = ospf6_lsdb_head (on->retrans_list); lsa; + lsa = ospf6_lsdb_next (lsa)) + { + ospf6_decrement_retrans_count (lsa); + ospf6_lsdb_remove (lsa, on->retrans_list); + } + } + if (on && on->state==OSPF6_NEIGHBOR_TWOWAY && on->retrans_list->count > 0) + printf("Error:2-way nbr has nonempty retrans list, count %d dep %d\n", + on->retrans_list->count, on->dependent); + } +} + + +//#####################BFS##################### +void q_add (pList q, struct ospf6_neighbor *on) +{ + listnode_add(q, on); +} + +// Removes head of queue and returns neighbor. +// Returns NULL if queue is empty. +struct ospf6_neighbor *q_remove(pList q) +{ + struct ospf6_neighbor *on; + if (q->head == NULL) + return NULL; + on = (struct ospf6_neighbor *) q->head->data; + list_delete_node(q, q->head); + return on; +} + +//######################TREE########################### +// Tree node must be added only after its parent has been added. +// Parent tree node is found from its ID via a simple array. +// The index of the tree node indexes the array and matrix. +// Tree nodes must be freed after algorithm is done, using the array. +void add_tree_node(pList L, struct ospf6_neighbor *on,struct tree_node *parent) +{ + struct tree_node* u = (struct tree_node *) malloc(sizeof(struct tree_node)); + if (u == NULL) + { + printf("u is NULL \n"); + exit(0); + } + u->on = on; + on->treenode = u; + + u->parent = parent; + u->labeled = 0; // to be set when node is labeled + u->first_child = NULL; + u->last_child = NULL; + u->next_sib = NULL; + if (parent) + { + if (!parent->first_child) + parent->first_child = u; + else + parent->last_child->next_sib = u; + parent->last_child = u; + } + listnode_add(L, u); +} + +void remove_tree(pList L) +{ + plistnode n; + struct tree_node *node; + for (n = listhead(L); n; nextnode(n)) + { + node = (struct tree_node *) getdata (n); + node->on->treenode = NULL; + free(node); + } + list_delete(L); +} + +// Finds next node in DFS of unlabeled subtree. +// Labeled nodes define boundary of subtree. +// Search must start at the root of a subtree. +// Root is defined by parent being NULL or labeled. +// Returns NULL when search is finished. +struct tree_node * dfs_next(struct tree_node* u) +{ + struct tree_node *v, *w; + if (u->labeled) + printf("Error: DFS cannot visit labeled node\n"); + // Return first unlabeled child, if it exists + for (v = u->first_child; v != NULL; v = v->next_sib) + { + if (!v->labeled) return (v); + } + // Find an unlabeled sibling, otherwise go to parent and repeat. + // If parent is NULL or labeled, then root has been reached. + for (v = u; v->parent && !(v->parent->labeled); v = v->parent) + { + for (w = v->next_sib; w; w = w->next_sib) + { + if (!w->labeled) + return (w); + } + } + return (NULL); // DFS is finished. +} + +void ospf6_mdr_free_cost_matrix(struct ospf6_interface *oi) +{ + u_int i; + + //free matrix + for (i = 0; i < oi->neighbor_list->count; i++) + free(oi->cost_matrix[i]); + free(oi->cost_matrix); + oi->cost_matrix = NULL; +} + + + +void ospf6_mdr_create_cost_matrix(struct ospf6_interface *oi) +{ + plistnode j, k, u; + u_int32_t *id; + struct ospf6_neighbor *onj, *onk; + int count = 0; + int num_neigh = oi->neighbor_list->count; + + if (oi->cost_matrix) + { + printf("cost matrix should be NULL\n"); + exit(0); + } + + //intialize matrix to false + oi->cost_matrix = (int **) malloc(sizeof(int*[num_neigh])); + for (j = listhead(oi->neighbor_list); j; nextnode(j)) + { + onj = (struct ospf6_neighbor *) getdata (j); + onj->cost_matrix_index = count; + oi->cost_matrix[count] = (int *) malloc(sizeof(int[num_neigh])); + memset (oi->cost_matrix[count++], 0, sizeof (int[num_neigh])); + } + + //set matrix values + for (j = listhead(oi->neighbor_list); j; nextnode(j)) + { + onj = (struct ospf6_neighbor *) getdata (j); + oi->cost_matrix[onj->cost_matrix_index][onj->cost_matrix_index] = 0; + for (k = listhead(oi->neighbor_list); k; nextnode(k)) + { + onk = (struct ospf6_neighbor *) getdata (k); + if (onj == onk) + continue; //cost = 0 + + if (onj->state < OSPF6_NEIGHBOR_TWOWAY || + onk->state < OSPF6_NEIGHBOR_TWOWAY) + continue; //cost = 0 + + if (!onj->Report2Hop && !onk->Report2Hop) + continue; + + for (u = listhead(onj->rnl); u; nextnode(u)) + { + id = (u_int32_t *) getdata(u); + if (*id == onk->router_id) + { + oi->cost_matrix[onj->cost_matrix_index][onk->cost_matrix_index] = 1; + break; + } + } + } + } + + // The above calculation gives an asymmetric matrix. + // Now make it symmetric depending on Report2Hop. + for (j = listhead(oi->neighbor_list); j; nextnode(j)) + { + onj = (struct ospf6_neighbor *) getdata (j); + for (k = listhead(oi->neighbor_list); k; nextnode(k)) + { + onk = (struct ospf6_neighbor *) getdata (k); + if (onj == onk) + continue; //cost = 0 + if (onj->state < OSPF6_NEIGHBOR_TWOWAY || + onk->state < OSPF6_NEIGHBOR_TWOWAY) + continue; //cost = 0 + if (!onj->Report2Hop && !onk->Report2Hop) + continue; + + if (onj->Report2Hop && onk->Report2Hop) + { + // Assumes cost_matrix value is 1 for neighbors, 0 for not. + oi->cost_matrix[onj->cost_matrix_index][onk->cost_matrix_index] = + oi->cost_matrix[onk->cost_matrix_index][onj->cost_matrix_index] = + oi->cost_matrix[onj->cost_matrix_index][onk->cost_matrix_index] + * oi->cost_matrix[onk->cost_matrix_index][onj->cost_matrix_index]; + } + else if (onj->Report2Hop && !onk->Report2Hop) + { + oi->cost_matrix[onk->cost_matrix_index][onj->cost_matrix_index] = + oi->cost_matrix[onj->cost_matrix_index][onk->cost_matrix_index]; + } + else if (!onj->Report2Hop && onk->Report2Hop) + { + oi->cost_matrix[onj->cost_matrix_index][onk->cost_matrix_index] = + oi->cost_matrix[onk->cost_matrix_index][onj->cost_matrix_index]; + } + } + } +} + +int ospf6_mdr_cost(struct ospf6_neighbor *onj, struct ospf6_neighbor *onk) +{ + struct ospf6_interface *oi = onj->ospf6_if; + + //###### calculation of cost to my neighbor ###### + //###### 2nd entry must be NULL for this calc #### + if (onj->state < OSPF6_NEIGHBOR_TWOWAY) + return 0; //not my neighbor + if (onk == NULL) //indicates link with current node + return 1; + + //must be on same interface + if (oi != onk->ospf6_if) + { + printf("ospf6_mdr_cost called with bad input values\n"); + exit (0); + } + + if (ospf6_sidcds_lexicographic(oi, oi->mdr_level, onj->mdr_level, 0, 0, + ntohl(oi->area->ospf6->router_id), ntohl(onj->router_id))) + return INFTY; + + return oi->cost_matrix[onj->cost_matrix_index][onk->cost_matrix_index]; +} + +int ospf6_mdr_cost2(struct ospf6_neighbor *onj, struct ospf6_neighbor *onk) +{ + int cost; + struct ospf6_interface *oi = onj->ospf6_if; + + if (onj->state < OSPF6_NEIGHBOR_TWOWAY || + onk->state < OSPF6_NEIGHBOR_TWOWAY || + onj == onk || + oi != onk->ospf6_if) + { + printf("ospf6_mdr_cost2 called with bad input values\n"); + exit (0); + } + + cost = ospf6_mdr_cost(onj, onk); + + if (cost != 1) + return INFTY; + + return (1 + onj->hops - onk->hops); +} + +// True if A > B +boolean ospf6_sidcds_lexicographic(struct ospf6_interface *oi, + int DRLevel_A, int DRLevel_B, + int RtrPri_A, int RtrPri_B, + int RID_A, int RID_B) +{ + if (oi->NonPersistentMDR) + { + if (RtrPri_A > RtrPri_B) + return true; + if ((RtrPri_A == RtrPri_B) && (RID_A > RID_B)) + return true; + } + else + { + if (DRLevel_A > DRLevel_B) + return true; + if ((DRLevel_A == DRLevel_B) && (RtrPri_A > RtrPri_B)) + return true; + if ((DRLevel_A == DRLevel_B) && (RtrPri_A == RtrPri_B) && (RID_A > RID_B)) + return true; + } + return false; +} + +// Return true if a change occured. +boolean ospf6_mdr_set_mdr_level(struct ospf6_neighbor *on, + u_int32_t id1, u_int32_t id2) +{ + struct ospf6_interface *oi = on->ospf6_if; + int old_mdr_level, old_child; + boolean remove = false; + boolean changed = false; + + old_mdr_level = on->mdr_level; + old_child = on->child; + on->child = false; + + /*printf("set_mdr_level called, node %d level %d nbr %d level %d dep_sel %d\n", + ntohl(oi->area->ospf6->router_id), oi->mdr_level, + ntohl(on->router_id), on->mdr_level, on->dependent_selector);*/ + if (on->router_id == id1) + on->mdr_level = OSPF6_MDR; + else if (on->router_id == id2) + on->mdr_level = OSPF6_BMDR; + else + on->mdr_level = OSPF6_OTHER; + // Set child even if it is a DR/BDR. + if (oi->area->ospf6->router_id == id1 || + oi->area->ospf6->router_id == id2) + on->child = true; + if (old_mdr_level != on->mdr_level) changed = true; + // child change does not affect CDS calculation. + + if (old_mdr_level >= OSPF6_MDR && on->mdr_level < OSPF6_MDR) + { + oi->mdr_count--; + remove = true; + } + else if (old_mdr_level < OSPF6_MDR && on->mdr_level >= OSPF6_MDR) + { + set_time(&on->mdr_install_time); + oi->mdr_count++; + } + else + return changed; + +#ifdef SIM_ETRACE_STAT + float delta = elapsed_time(&oi->relaysel_change_time); + update_statistics(OSPF6_DURATION_OF_NUM_RELSEL, (double)delta); + update_statistics(OSPF6_NUM_RELSEL_TIMES_DURATION_OF_NUM_RELSEL, + (double)(oi->mdr_count * delta)); + if (remove == true) + { + float lifetime = elapsed_time(&on->mdr_install_time); + update_statistics(OSPF6_RELSEL_LIFETIME, (double)lifetime); + update_statistics(OSPF6_RELSEL_DEATHS, 1); + } + set_time(&oi->relaysel_change_time); +#endif //SIM_ETRACE_STAT + return changed; +} +#endif //OSPF6_MANET_MDR_FLOOD diff -Naur quagga-0.98.5/ospf6d/ospf6_mdr.h quagga-0.98.5-manet/ospf6d/ospf6_mdr.h --- quagga-0.98.5/ospf6d/ospf6_mdr.h 1969-12-31 16:00:00.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_mdr.h 2006-02-20 13:42:12.000000000 -0800 @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2005 Boeing + */ + +#ifndef OSPF6_MDR_H +#define OSPF6_MDR_H + +#ifdef OSPF6_MANET_MDR_FLOOD + +#include "ospf6d.h" //for boolean +#include "ospf6_interface.h" +#include "ospf6_neighbor.h" + +#define INFTY 10000 + +#define OSPF6_OTHER 0 +#define OSPF6_BMDR 1 +#define OSPF6_MDR 2 + +struct tree_node +{ + struct ospf6_neighbor *on; + //int dist1; // hops from source + //int dist2; // differential length of disjoint paths + int labeled; // indicates node is labeled + struct tree_node *parent; // parent in tree + struct tree_node *first_child; // pointer to first child of this node + struct tree_node *last_child; // pointer to last child of this node + struct tree_node *next_sib; // pointer to next child of same parent + // next_sib points to another node at the same hop level as this node + // next_sib is NULL if this is the last child of the parent +}; + + +void q_add (pList, struct ospf6_neighbor *); +struct ospf6_neighbor *q_remove(pList); + +void add_tree_node(pList, struct ospf6_neighbor *, struct tree_node *); +void remove_tree(pList L); +struct tree_node * dfs_next(struct tree_node* u); + +void ospf6_calculate_mdr(struct ospf6_interface *); +void ospf6_mdr_update_adjacencies(struct ospf6_interface *); + +void ospf6_mdr_free_cost_matrix(struct ospf6_interface *oi); +void ospf6_mdr_create_cost_matrix(struct ospf6_interface *oi); +int ospf6_mdr_matrix_element_cost(struct ospf6_neighbor *onj, + struct ospf6_neighbor *onk); +/* the cost2 variant is for backup MDR */ +int ospf6_mdr_cost(struct ospf6_neighbor *onA, struct ospf6_neighbor *onB); +int ospf6_mdr_cost2(struct ospf6_neighbor *onj, struct ospf6_neighbor *onk); + +boolean ospf6_sidcds_lexicographic(struct ospf6_interface *oi, + int DRLevel_A, int DRLevel_B, + int RtrPri_A, int RtrPri_B, + int RID_A, int RID_B); +boolean ospf6_mdr_set_mdr_level(struct ospf6_neighbor *on, + u_int32_t id1, u_int32_t id2); +#endif //OSPF6_MANET_MDR_FLOOD + +#endif /* OSPF6_MDR_H */ + diff -Naur quagga-0.98.5/ospf6d/ospf6_message.c quagga-0.98.5-manet/ospf6d/ospf6_message.c --- quagga-0.98.5/ospf6d/ospf6_message.c 2004-12-23 22:00:12.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_message.c 2006-02-20 13:42:12.000000000 -0800 @@ -42,6 +42,33 @@ #include "ospf6_flood.h" #include "ospf6d.h" +#ifdef SIM +#include "sim.h" +#endif //SIM +#ifdef SIM_ETRACE_STAT +#include "ospf6_sim_printing.h" +#endif //SIM_ETRACE_STAT +#ifdef OSPF6_MANET_MPR_FLOOD +#include "ospf6_mpr.h" +#endif //OSPF6_MANET_MPR_FLOOD +#ifdef OSPF6_MANET_MDR_FLOOD +#include "ospf6_mdr.h" +#endif //OSPF6_MANET_MDR_FLOOD + +#ifdef USER_CHECKSUM +/* IPv6 pseudo header for checksum calculation */ +typedef struct +{ + struct in6_addr src; + struct in6_addr dst; + u_int32_t upper_len; + char zero[3]; + u_int8_t nh; + +} pseudo_header; + +#endif + unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0}; const char *ospf6_message_type_str[] = { "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck" }; @@ -65,7 +92,11 @@ ospf6_hello_print (struct ospf6_header *oh) { struct ospf6_hello *hello; +#ifdef OSPF6_MANET + char options[36]; +#else char options[16]; +#endif //OSPF6_MANET char drouter[16], bdrouter[16], neighbor[16]; char *p; @@ -270,11 +301,436 @@ zlog_warn ("Detect duplicate Router-ID"); return MSG_OK; +} + +#ifdef OSPF6_MANET_MDR_FLOOD +// Ogierv3 10.3 +void +ospf6_mdr_mhello_recv (struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, struct ospf6_header *oh, int len) +{ + struct ospf6_hello *hello; + struct ospf6_neighbor *on; + int neighborchange = 0; + int backupseen = 0; + boolean calc_cds = false; // Set if calculate_cds() must be called. + u_char prev_state; + boolean twoway = false; + boolean rnl_changed = false; + boolean mdr_level_changed; + struct ospf6_LLS_header *lls_ptr = NULL; + + if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK) + return; + + hello = (struct ospf6_hello *) + ((caddr_t) oh + sizeof (struct ospf6_header)); + + /* HelloInterval check */ + if (ntohs (hello->hello_interval) != oi->hello_interval) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("HelloInterval mismatch"); + return; + } + + /* RouterDeadInterval check */ + if (ntohs (hello->dead_interval) != oi->dead_interval) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("RouterDeadInterval mismatch"); + return; + } + + /* E-bit check */ + if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E, 2) != + OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E, 2)) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("E-bit mismatch"); + return; + } + + /* Find neighbor, create if not existent */ + on = ospf6_neighbor_lookup (oh->router_id, oi); + if (on == NULL) + { + on = ospf6_neighbor_create (oh->router_id, oi); + on->prev_drouter = on->drouter = hello->drouter; + on->prev_bdrouter = on->bdrouter = hello->bdrouter; + on->priority = hello->priority; + on->ifindex = ntohl (hello->interface_id); + memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr)); + } + + /* process TLVs */ + /* set LLS pointer */ + prev_state = on->state; + lls_ptr = (struct ospf6_LLS_header *) (hello + 1); + if (ntohs(oh->length) < len && OSPF6_OPT_ISSET(hello->options, OSPF6_OPT_L,1)) + twoway = ospf6_mdr_process_hello_TLVs(on, lls_ptr, + OSPF6_OPT_ISSET(hello->options, OSPF6_OPT_D, 1), &rnl_changed); + if (rnl_changed) + calc_cds = true; + + /* RouterPriority check */ + if (on->priority != hello->priority) + { + on->priority = hello->priority; + calc_cds = true; + neighborchange++; + } + + /* DR check */ + if (on->drouter != hello->drouter) + { + on->prev_drouter = on->drouter; + on->drouter = hello->drouter; + if (on->prev_drouter == on->router_id || on->drouter == on->router_id) + { + neighborchange++; + calc_cds = true; + } + } + + /* BDR check */ + if (on->bdrouter != hello->bdrouter) + { + on->prev_bdrouter = on->bdrouter; + on->bdrouter = hello->bdrouter; + if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id) + { + neighborchange++; + calc_cds = true; + } + } + + /* BackupSeen check */ + if (oi->state == OSPF6_INTERFACE_WAITING) + { + if (hello->bdrouter == on->router_id) + backupseen++; + else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0)) + backupseen++; + } + + mdr_level_changed = ospf6_mdr_set_mdr_level(on, on->drouter, on->bdrouter); + if (mdr_level_changed) calc_cds = true; + + // Receiving Hello changes 2-hop nbr info, and nbr MDR levels, + // and children. But calc_cds must be called before checking + // need adj. Children is the only thing that does not affect + // decision to run calc_cds. Any other change does. + + /* execute neighbor events */ + thread_execute (master, hello_received, on, 0); + if (twoway) + thread_execute (master, twoway_received, on, 0); + else + thread_execute (master, oneway_received, on, 0); + + if (prev_state < OSPF6_NEIGHBOR_TWOWAY && on->state >= OSPF6_NEIGHBOR_TWOWAY) + calc_cds = true; + if (prev_state >= OSPF6_NEIGHBOR_TWOWAY && on->state < OSPF6_NEIGHBOR_TWOWAY) + calc_cds = true; + + // The CDS is calculated only if there is a change to + // 2-hop neighbor information, including the MDR level of neighbors. + + // Things that could require calc cds besides receiving hello: + // dead interval (done). DD packet that changes mdr_level of nbr, + // but we can wait until next hello from the nbr. + + // RGO. MDRs need to be calculated only before sending Hello. + // This sometimes improves performance. + //if (calc_cds) + // ospf6_calculate_mdr(on->ospf6_if); + + // Check to see if any neighbor should be adjacent. + // This can result from calculating CDS and parents, or from + // a change in the MDR level of neighbors, or because there is + // a new neighbor, or because a neighbor (child) selected the + // router as a parent. The last reason is the only time an + // adjacency might be needed without calling calculate_mdr(). + + // Check to see if any adjacent neighbor should be non-adjacent. + // This can result because the router is no longer DR/BDR, or because an + // adjacent neighbor is no longer DR/BDR. (Only two possible reasons.) + + ospf6_mdr_update_adjacencies(on->ospf6_if); + + /* Schedule interface events */ + if (backupseen) + thread_add_event (master, backup_seen, oi, 0); + if (neighborchange) + thread_add_event (master, neighbor_change, oi, 0); +} +#endif //OSPF6_MANET_MDR_FLOOD + +#ifdef OSPF6_MANET_MPR_FLOOD +void +ospf6_mhello_recv (struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, struct ospf6_header *oh, int len) +{ + struct ospf6_hello *hello; + struct ospf6_neighbor *on; + int neighborchange = 0; + int backupseen = 0; + + u_int32_t *router_id_ptr; + int seenrtrnum = 0, router_id_space = 0; + boolean twoway; + struct ospf6_LLS_header *lls_ptr = NULL; + + if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK) + return; + + hello = (struct ospf6_hello *) + ((caddr_t) oh + sizeof (struct ospf6_header)); + + /* HelloInterval check */ + if (ntohs (hello->hello_interval) != oi->hello_interval) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("HelloInterval mismatch"); + return; + } + + /* RouterDeadInterval check */ + if (ntohs (hello->dead_interval) != oi->dead_interval) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("RouterDeadInterval mismatch"); + return; + } + + /* E-bit check */ + if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E, 2) != + OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E, 2)) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("E-bit mismatch"); + return; + } + + /* Find neighbor, create if not existent */ + on = ospf6_neighbor_lookup (oh->router_id, oi); + if (on == NULL) + { + on = ospf6_neighbor_create (oh->router_id, oi); + on->prev_drouter = on->drouter = hello->drouter; + on->prev_bdrouter = on->bdrouter = hello->bdrouter; + on->priority = hello->priority; + on->ifindex = ntohl (hello->interface_id); + memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr)); + } + on->Fbit = OSPF6_OPT_ISSET(hello->options, OSPF6_OPT_F, 1); + + /* set pointer positions */ + router_id_space = ntohs(oh->length) - + sizeof(struct ospf6_header) - sizeof(struct ospf6_hello); + seenrtrnum = router_id_space / sizeof(u_int32_t); + router_id_ptr = (u_int32_t *) (hello + 1); + lls_ptr = (struct ospf6_LLS_header *) (router_id_ptr + seenrtrnum); + + twoway = ospf6_is_rtrid_in_list(oi, router_id_ptr, seenrtrnum); + + /* process TLVs */ + /* set LLS pointer */ + if (ntohs(oh->length) < len && OSPF6_OPT_ISSET(hello->options, OSPF6_OPT_L,1)) + ospf6_mpr_process_TLVs(on, lls_ptr); + + /* RouterPriority check */ + if (on->priority != hello->priority) + { + on->priority = hello->priority; + neighborchange++; + } + + /* DR check */ + if (on->drouter != hello->drouter) + { + on->prev_drouter = on->drouter; + on->drouter = hello->drouter; + if (on->prev_drouter == on->router_id || on->drouter == on->router_id) + neighborchange++; + } + + /* BDR check */ + if (on->bdrouter != hello->bdrouter) + { + on->prev_bdrouter = on->bdrouter; + on->bdrouter = hello->bdrouter; + if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id) + neighborchange++; + } + + /* BackupSeen check */ + if (oi->state == OSPF6_INTERFACE_WAITING) + { + if (hello->bdrouter == on->router_id) + backupseen++; + else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0)) + backupseen++; + } + + /* execute neighbor events */ + thread_execute (master, hello_received, on, 0); + if (twoway) + thread_execute (master, twoway_received, on, 0); + else + thread_execute (master, oneway_received, on, 0); + + /* Schedule interface events */ + if (backupseen) + thread_add_event (master, backup_seen, oi, 0); + if (neighborchange) + thread_add_event (master, neighbor_change, oi, 0); +} + +#ifdef OSPF6_MANET_DIFF_HELLO +void +ospf6_mpr_diff_mhello_recv (struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, struct ospf6_header *oh, int len) +{ + struct ospf6_hello *hello; + struct ospf6_neighbor *on; + int neighborchange = 0; + int backupseen = 0; + + u_int32_t *router_id_ptr; + int seenrtrnum = 0, router_id_space = 0; + boolean twoway, send_mhello = false; + char scs_tlv_option[2] = {0, 0}; + struct ospf6_LLS_header *lls_ptr = NULL; + + if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK) + return; + + hello = (struct ospf6_hello *) + ((caddr_t) oh + sizeof (struct ospf6_header)); + + /* HelloInterval check */ + if (ntohs (hello->hello_interval) != oi->hello_interval) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("HelloInterval mismatch"); + return; + } + + /* RouterDeadInterval check */ + if (ntohs (hello->dead_interval) != oi->dead_interval) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("RouterDeadInterval mismatch"); + return; + } + + /* E-bit check */ + if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E,2) != + OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E,2)) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("E-bit mismatch"); + return; + } + + /* Find neighbor, create if not existent */ + on = ospf6_neighbor_lookup (oh->router_id, oi); + if (on == NULL) + { + //Chandra03 3.3.6.1 paragraph 2 bullet 1 + on = ospf6_neighbor_create (oh->router_id, oi); + on->prev_drouter = on->drouter = hello->drouter; + on->prev_bdrouter = on->bdrouter = hello->bdrouter; + on->priority = hello->priority; + on->ifindex = ntohl (hello->interface_id); + memcpy (&on->linklocal_addr, src, sizeof (struct in6_addr)); + } + on->Fbit = OSPF6_OPT_ISSET(hello->options, OSPF6_OPT_F, 1); + + /* set pointer positions */ + router_id_space = ntohs(oh->length) - + sizeof(struct ospf6_header) - sizeof(struct ospf6_hello); + seenrtrnum = router_id_space / sizeof(u_int32_t); + router_id_ptr = (u_int32_t *) (hello + 1); + lls_ptr = (struct ospf6_LLS_header *) (router_id_ptr + seenrtrnum); + + /* TwoWay check (if false not necessarily oneway with diff hellos) */ + twoway = ospf6_is_rtrid_in_list(oi, router_id_ptr, seenrtrnum); + + /* process TLVs */ + /* set LLS pointer */ + if (ntohs(oh->length) < len && OSPF6_OPT_ISSET(hello->options, OSPF6_OPT_L,1)) + ospf6_mpr_process_diff_TLVs(on, lls_ptr, seenrtrnum, scs_tlv_option, + &twoway, &send_mhello); + + /* RouterPriority check */ + if (on->priority != hello->priority) + { + on->priority = hello->priority; + neighborchange++; + } + + /* DR check */ + if (on->drouter != hello->drouter) + { + on->prev_drouter = on->drouter; + on->drouter = hello->drouter; + if (on->prev_drouter == on->router_id || on->drouter == on->router_id) + neighborchange++; + } + + /* BDR check */ + if (on->bdrouter != hello->bdrouter) + { + on->prev_bdrouter = on->bdrouter; + on->bdrouter = hello->bdrouter; + if (on->prev_bdrouter == on->router_id || on->bdrouter == on->router_id) + neighborchange++; + } + + /* BackupSeen check */ + if (oi->state == OSPF6_INTERFACE_WAITING) + { + if (hello->bdrouter == on->router_id) + backupseen++; + else if (hello->drouter == on->router_id && hello->bdrouter == htonl (0)) + backupseen++; + } + + /* execute neighbor events */ + thread_execute (master, hello_received, on, 0); + if (twoway) + thread_execute (master, twoway_received, on, 0); + else + { + thread_execute (master, oneway_received, on, 0); + if (on->state == OSPF6_NEIGHBOR_INIT) + // Chandra 3.3.7 paragraph 2 + on->request = true; + } + // if (send_mhello && + // elapsed_time(&ospf6->starttime) > oi->dead_interval)//graceful restart + // ospf6_diff_mhello_send(oi, on->linklocal_addr, scs_tlv_option); + + /* Schedule interface events */ + if (backupseen) + thread_add_event (master, backup_seen, oi, 0); + if (neighborchange) + thread_add_event (master, neighbor_change, oi, 0); } +#endif //OSPF6_MANET_DIFF_HELLO +#endif //OSPF6_MANET_MPR_FLOOD void +#ifdef OSPF6_MANET +ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, struct ospf6_header *oh, int len) +#else ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst, struct ospf6_interface *oi, struct ospf6_header *oh) +#endif //OSPF6_MANET { struct ospf6_hello *hello; struct ospf6_neighbor *on; @@ -289,6 +745,33 @@ hello = (struct ospf6_hello *) ((caddr_t) oh + sizeof (struct ospf6_header)); +#ifdef OSPF6_MANET + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE) + { +#ifdef OSPF6_MANET_MPR_FLOOD + if (oi->flooding == OSPF6_FLOOD_MPR_SDCDS) + { + //Chandra03 3.3.9 + if (!OSPF6_OPT_ISSET(hello->options, OSPF6_OPT_I, 1)) + ospf6_mhello_recv (src, dst, oi, oh, len); +#ifdef OSPF6_MANET_DIFF_HELLO + else + //Chandra03 3.3.6.1 paragraph 2 + ospf6_mpr_diff_mhello_recv(src, dst, oi, oh, len); +#endif //OSPF6_MANET_DIFF_HELLO + return; + } +#endif //OSPF6_MANET_MPR_FLOOD +#ifdef OSPF6_MANET_MDR_FLOOD + if (oi->flooding == OSPF6_FLOOD_MDR_SICDS) + { + ospf6_mdr_mhello_recv(src, dst, oi, oh, len); + return; + } +#endif //OSPF6_MANET_MDR_FLOOD + } +#endif //OSPF_MANET + /* HelloInterval check */ if (ntohs (hello->hello_interval) != oi->hello_interval) { @@ -306,8 +789,13 @@ } /* E-bit check */ +#ifdef OSPF6_MANET + if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E,2) != + OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E,2)) +#else if (OSPF6_OPT_ISSET (hello->options, OSPF6_OPT_E) != OSPF6_OPT_ISSET (oi->area->options, OSPF6_OPT_E)) +#endif //OSPF6_MANET { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) zlog_debug ("E-bit mismatch"); @@ -397,6 +885,11 @@ { struct ospf6_dbdesc *dbdesc; char *p; +#ifdef SIM_ETRACE_STAT + int diff_count = 0; + char diff_buf[4000]; + sprintf(diff_buf, "LSAs: "); +#endif //SIM_ETRACE_STAT dbdesc = (struct ospf6_dbdesc *) ((caddr_t) oh + sizeof (struct ospf6_header)); @@ -471,6 +964,10 @@ return; } +#ifdef OSPF6_MANET_MDR_FLOOD + OSPF6_OPT_CLEAR(on->options,OSPF6_OPT_L,1); + OSPF6_OPT_CLEAR(dbdesc->options,OSPF6_OPT_L,1); +#endif //OSPF6_MANET_MDR_FLOOD if (memcmp (on->options, dbdesc->options, sizeof (on->options))) { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) @@ -483,7 +980,7 @@ { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) zlog_debug ("Sequence number mismatch (%#lx expected)", - (u_long) on->dbdesc_seqnum); + (u_long) on->dbdesc_seqnum); thread_add_event (master, seqnumber_mismatch, on, 0); return; } @@ -517,6 +1014,9 @@ { struct ospf6_lsa *his, *mine; struct ospf6_lsdb *lsdb = NULL; +#ifdef OSPF6_MANET_TEMPORARY_LSDB + struct ospf6_lsa *mine_cache = NULL; +#endif //OSPF6_MANET_TEMPORARY_LSDB his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p); @@ -554,6 +1054,65 @@ mine = ospf6_lsdb_lookup (his->header->type, his->header->id, his->header->adv_router, lsdb); +#ifdef OSPF6_MANET + if (mine == NULL || ospf6_lsa_compare (his, mine) < 0) + { //I don't have this LSA or "his" LSA is newer +#ifdef OSPF6_MANET_TEMPORARY_LSDB + mine_cache = ospf6_lsdb_lookup_cache(his->header->type, his->header->id, + his->header->adv_router, lsdb); + if(on->ospf6_if->type == OSPF6_IFTYPE_MANETRELIABLE && + mine_cache && ospf6_lsa_compare (his, mine_cache) == 0) + { + struct ospf6_lsa *mine_lsdb = ospf6_lsa_copy(mine_cache); + /* (b) immediately flood and (c) remove from all retrans-list */ + ospf6_flood (on, mine_lsdb); + + /* (d), installing lsdb, which may cause routing + * table calculation (replacing database copy) */ + ospf6_install_lsa (mine_lsdb); + /* remove lsa from lsdb_cache */ + ospf6_lsdb_remove (mine_cache, lsdb); + } + else + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + { + if (mine == NULL) + zlog_debug ("Add request (No database copy)"); + else + zlog_debug ("Add request (Received MoreRecent)"); + } + ospf6_lsdb_add (his, on->request_list); + } +#else + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + { + if (mine == NULL) + zlog_debug ("Add request (No database copy)"); + else + zlog_debug ("Add request (Received MoreRecent)"); + } + ospf6_lsdb_add (his, on->request_list); +#endif //OSPF6_MANET_TEMPORARY_LSDB +#ifdef SIM_ETRACE_STAT + strcat(diff_buf, his->name); + diff_count++; +#endif //SIM_ETRACE_STAT + } +#ifdef OSPF6_MANET_MDR_FLOOD_DD + { + // If his is newer or same as mine, then remove mine + // from summary_list for neighbor + struct ospf6_lsa *mine_summary; + if (mine != NULL && ospf6_lsa_compare (his, mine) <= 0) + { + mine_summary = ospf6_lsdb_lookup (his->header->type, his->header->id, + his->header->adv_router, on->summary_list); + if (mine_summary) ospf6_lsdb_remove (mine_summary, on->summary_list); + } + } +#endif //OSPF6_MANET_MDR_FLOOD_DD +#else //OSPF6_MANET if (mine == NULL) { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) @@ -566,7 +1125,12 @@ zlog_debug ("Add request (Received MoreRecent)"); ospf6_lsdb_add (his, on->request_list); } +#endif //OSPF6_MANET +#ifdef OSPF6_MANET_MDR_FLOOD_DD + if (!(mine == NULL || ospf6_lsa_compare (his, mine) < 0)) +#else else +#endif //OSPF6_MANET_MDR_FLOOD_DD { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) zlog_debug ("Discard (Existing MoreRecent)"); @@ -574,6 +1138,16 @@ } } +#ifdef SIM_ETRACE_STAT + if (p != (char *)((caddr_t)dbdesc+sizeof(struct ospf6_dbdesc))) + { + TraceEvent_sim(1,"LSA_DATABASE sync diff %d neighbor %s %s", + diff_count, on->name, diff_buf); + update_statistics(OSPF6_DATABASE_EXCHANGES, 1); + update_statistics(OSPF6_NUM_LSA_DIFFS, (double)diff_count); + } +#endif //SIM_ETRACE_STAT + if (p != OSPF6_MESSAGE_END (oh)) { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) @@ -608,6 +1182,11 @@ { struct ospf6_dbdesc *dbdesc; char *p; +#ifdef SIM_ETRACE_STAT + int diff_count = 0; + char diff_buf[4000]; + sprintf(diff_buf, "LSAs: "); +#endif //SIM_ETRACE_STAT dbdesc = (struct ospf6_dbdesc *) ((caddr_t) oh + sizeof (struct ospf6_header)); @@ -692,7 +1271,10 @@ thread_add_event (master, seqnumber_mismatch, on, 0); return; } - +#ifdef OSPF6_MANET_MDR_FLOOD + OSPF6_OPT_CLEAR(on->options,OSPF6_OPT_L,1); + OSPF6_OPT_CLEAR(dbdesc->options,OSPF6_OPT_L,1); +#endif //OSPF6_MANET_MDR_FLOOD if (memcmp (on->options, dbdesc->options, sizeof (on->options))) { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) @@ -705,7 +1287,7 @@ { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) zlog_debug ("Sequence number mismatch (%#lx expected)", - (u_long) on->dbdesc_seqnum + 1); + (u_long) on->dbdesc_seqnum + 1); thread_add_event (master, seqnumber_mismatch, on, 0); return; } @@ -742,6 +1324,9 @@ { struct ospf6_lsa *his, *mine; struct ospf6_lsdb *lsdb = NULL; +#ifdef OSPF6_MANET_TEMPORARY_LSDB + struct ospf6_lsa *mine_cache=NULL; +#endif //OSPF6_MANET_TEMPORARY_LSDB his = ospf6_lsa_create_headeronly ((struct ospf6_lsa_header *) p); @@ -777,15 +1362,68 @@ mine = ospf6_lsdb_lookup (his->header->type, his->header->id, his->header->adv_router, lsdb); if (mine == NULL || ospf6_lsa_compare (his, mine) < 0) + { +#ifdef OSPF6_MANET_TEMPORARY_LSDB + mine_cache = ospf6_lsdb_lookup_cache(his->header->type, his->header->id, + his->header->adv_router, lsdb); + if(on->ospf6_if->type == OSPF6_IFTYPE_MANETRELIABLE && + mine_cache && ospf6_lsa_compare (his, mine_cache) == 0) + { + struct ospf6_lsa *mine_lsdb = ospf6_lsa_copy(mine_cache); + /* (b) immediately flood and (c) remove from all retrans-list */ + ospf6_flood (on, mine_lsdb); + + /* (d), installing lsdb, which may cause routing + * table calculation (replacing database copy) */ + ospf6_install_lsa (mine_lsdb); + /* remove lsa from lsdb_cache */ + ospf6_lsdb_remove (mine_cache, lsdb); + } + else { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) zlog_debug ("Add request-list: %s", his->name); ospf6_lsdb_add (his, on->request_list); } +#else + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_debug ("Add request-list: %s", his->name); + ospf6_lsdb_add (his, on->request_list); +#endif //OSPF6_MANET_TEMPORARY_LSDB +#ifdef SIM_ETRACE_STAT + strcat(diff_buf, his->name); + diff_count++; +#endif //SIM_ETRACE_STAT + } +#ifdef OSPF6_MANET_MDR_FLOOD_DD + { + // If his is newer or same as mine, then remove mine + // from summary_list for neighbor + struct ospf6_lsa *mine_summary; + if (mine != NULL && ospf6_lsa_compare (his, mine) <= 0) + { + mine_summary = ospf6_lsdb_lookup (his->header->type, his->header->id, + his->header->adv_router, on->summary_list); + if (mine_summary) ospf6_lsdb_remove (mine_summary, on->summary_list); + } + } + if (!(mine == NULL || ospf6_lsa_compare (his, mine) < 0)) +#else else +#endif //OSPF6_MANET_MDR_FLOOD_DD ospf6_lsa_delete (his); } +#ifdef SIM_ETRACE_STAT + if (p != (char *)((caddr_t)dbdesc+sizeof(struct ospf6_dbdesc))) + { + TraceEvent_sim(1,"LSA_DATABASE sync diff %d neighbor %s %s", + diff_count, on->name, diff_buf); + update_statistics(OSPF6_DATABASE_EXCHANGES, 1); + update_statistics(OSPF6_NUM_LSA_DIFFS, (double)diff_count); + } +#endif //SIM_ETRACE_STAT + if (p != OSPF6_MESSAGE_END (oh)) { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) @@ -809,8 +1447,13 @@ } void +#ifdef OSPF6_MANET +ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, struct ospf6_header *oh, int len) +#else ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst, struct ospf6_interface *oi, struct ospf6_header *oh) +#endif //OSPF6_MANET { struct ospf6_neighbor *on; struct ospf6_dbdesc *dbdesc; @@ -853,6 +1496,71 @@ dbdesc->reserved2 = 0; } +#ifdef OSPF6_MANET_MDR_FLOOD + if (on->ospf6_if->type == OSPF6_IFTYPE_MANETRELIABLE && + on->ospf6_if->flooding == OSPF6_FLOOD_MDR_SICDS) + { + if (OSPF6_OPT_ISSET(dbdesc->options, OSPF6_OPT_L,1) && + len > ntohs(oh->length)) + { + struct ospf6_LLS_header *lls_ptr = + (struct ospf6_LLS_header *) OSPF6_MESSAGE_END (oh); + ospf6_mdr_process_mdr_TLVs(on, lls_ptr); + } + //this is required due to not moving to EXSTART in twoway_received() + if (on->state == OSPF6_NEIGHBOR_INIT) + ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on); + if (on->state == OSPF6_NEIGHBOR_TWOWAY && need_adjacency(on)) + { + ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on); + SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT); + SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT); + SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT); + + if (ntohl (oh->router_id) < ntohl (ospf6->router_id)) + { + //if neighbor state is TWOWAY and adjacency is needed, + //then send DD packet only if router is master (has larger + //ID than neighbor). If router is slave, then negotiation is + //finished upon reception of the DD packet, and + //this will be handled in ospf6_dbdesc_recv_slave(). + THREAD_OFF (on->thread_send_dbdesc); + on->thread_send_dbdesc = + thread_add_event (master, ospf6_dbdesc_send, on, 0); + } + } + } +#endif //OSPF6_MANET_MDR_FLOOD + +#ifdef OSPF6_MANET_MPR_SP + if (on->ospf6_if->type == OSPF6_IFTYPE_MANETRELIABLE && + on->ospf6_if->flooding == OSPF6_FLOOD_MPR_SDCDS && + on->ospf6_if->smart_peering) + { + //Always form an adjacency if it is inititiated by a neighbor, so + //dd packets aren't retransmitted. + if (on->state == OSPF6_NEIGHBOR_TWOWAY) + { + ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on); + SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT); + SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT); + SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT); + + if (ntohl (oh->router_id) < ntohl (ospf6->router_id)) + { + //if neighbor state is TWOWAY and adjacency is needed, + //then send DD packet only if router is master (has larger + //ID than neighbor). If router is slave, then negotiation is + //finished upon reception of the DD packet, and + //this will be handled in ospf6_dbdesc_recv_slave(). + THREAD_OFF (on->thread_send_dbdesc); + on->thread_send_dbdesc = + thread_add_event (master, ospf6_dbdesc_send, on, 0); + } + } + } +#endif //OSPF6_MANET_MPR_SP + if (ntohl (oh->router_id) < ntohl (ospf6->router_id)) ospf6_dbdesc_recv_master (oh, on); else if (ntohl (ospf6->router_id) < ntohl (oh->router_id)) @@ -953,9 +1661,18 @@ } /* schedule send lsupdate */ + + +#ifdef OSPF6_DELAYED_FLOOD + on->thread_send_lsupdate = + ospf6_send_lsupdate_delayed_msec(master, ospf6_lsupdate_send_neighbor, + on, on->ospf6_if->flood_delay, + on->thread_send_lsupdate); +#else THREAD_OFF (on->thread_send_lsupdate); on->thread_send_lsupdate = thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0); +#endif //OSPF6_DELAYED_FLOOD } void @@ -975,6 +1692,9 @@ { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) zlog_debug ("Neighbor not found, ignore"); +#ifdef OSPF6_MANET_TEMPORARY_LSDB + ospf6_lsupdate_recv_below_exchange (src, dst, oi, oh); +#endif //OSPF6_MANET_TEMPORARY_LSDB return; } @@ -985,12 +1705,43 @@ return; } +#ifdef OSPF6_MANET_MDR_FLOOD + // receive LSAs from neighbors below 2-way Ogierv3 6 par 2 + if (on->ospf6_if->flooding == OSPF6_FLOOD_MDR_SICDS && + on->ospf6_if->type == OSPF6_IFTYPE_MANETRELIABLE) + { + if (on->state < OSPF6_NEIGHBOR_TWOWAY) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_debug ("Neighbor state less than 2-way, ignore"); + return; + } + } + else +#endif //OSPF6_MANET_MDR_FLOOD +#ifdef OSPF6_MANET_MPR_FLOOD //SP_DRAFT_MOD + //receive LSAs from neighbors below 2-way + if (on->ospf6_if->flooding == OSPF6_FLOOD_MPR_SDCDS && + on->ospf6_if->type == OSPF6_IFTYPE_MANETRELIABLE) + { + if (on->state < OSPF6_NEIGHBOR_TWOWAY) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_debug ("Neighbor state less than 2-way, ignore"); + return; + } + } + else +#endif //OSPF6_MANET_MPR_FLOOD if (on->state != OSPF6_NEIGHBOR_EXCHANGE && on->state != OSPF6_NEIGHBOR_LOADING && on->state != OSPF6_NEIGHBOR_FULL) { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) zlog_debug ("Neighbor state less than Exchange, ignore"); +#ifdef OSPF6_MANET_TEMPORARY_LSDB + ospf6_lsupdate_recv_below_exchange (src, dst, oi, oh); +#endif //OSPF6_MANET_TEMPORARY_LSDB return; } @@ -1014,7 +1765,12 @@ break; } + // Pass in dst address in case it is multicast +#ifdef OSPF6_MANET + ospf6_receive_lsa ((struct ospf6_lsa_header *) p, on, dst); +#else ospf6_receive_lsa (on, (struct ospf6_lsa_header *) p); +#endif //OSPF6_MANET num--; } @@ -1039,42 +1795,146 @@ on->state == OSPF6_NEIGHBOR_LOADING)) { THREAD_OFF (on->thread_send_lsreq); - on->thread_send_lsreq = - thread_add_event (master, ospf6_lsreq_send, on, 0); +#ifdef BUGFIX + // this was causing a flood of requests and updates because the + // LSA was not being accepted until after minLSArrival passed + //XXX BOEING Is delaying this send by MinLSArrival acceptable??? +#ifdef SIM_ETRACE_STAT + TraceEvent_sim(2,"Requesting LSAs from %s", on->name); +#endif //SIM_ETRACE_STAT + on->thread_send_lsreq = thread_add_timer (master, ospf6_lsreq_send, on, + oi->area->ospf6->minLSArrival); +#else + on->thread_send_lsreq =thread_add_event (master, ospf6_lsreq_send, on, 0); +#endif //BUGFIX } } +#ifdef OSPF6_MANET_TEMPORARY_LSDB void -ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst, - struct ospf6_interface *oi, struct ospf6_header *oh) +ospf6_lsupdate_recv_below_exchange (struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, struct ospf6_header *oh) { - struct ospf6_neighbor *on; + struct ospf6_lsupdate *lsupdate; + unsigned long num; char *p; - struct ospf6_lsa *his, *mine; - struct ospf6_lsdb *lsdb = NULL; + struct ospf6_area *oa; + plistnode i, j; - assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK); - if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK) - return; + lsupdate = (struct ospf6_lsupdate *) + ((caddr_t) oh + sizeof (struct ospf6_header)); - on = ospf6_neighbor_lookup (oh->router_id, oi); - if (on == NULL) + if(oi->type != OSPF6_IFTYPE_MANETRELIABLE) + return; + + num = ntohl (lsupdate->lsa_number); + + /* Process LSAs */ + for (p = (char *) ((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); + p < OSPF6_MESSAGE_END (oh) && + p + OSPF6_LSA_SIZE (p) <= OSPF6_MESSAGE_END (oh); + p += OSPF6_LSA_SIZE (p)) { - if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Neighbor not found, ignore"); - return; + if (num == 0) + break; + if (OSPF6_LSA_SIZE (p) < sizeof (struct ospf6_lsa_header)) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Malformed LSA length, quit processing"); + break; + } + ospf6_receive_lsa_below_exchange ((struct ospf6_lsa_header *) p, oi); + num--; } - if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr))) + if (num != 0) { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) - zlog_debug ("Seems to be from Secondary I/F of the neighbor, ignore"); - return; + zlog_info ("Malformed LSA number or LSA length"); } - - if (on->state != OSPF6_NEIGHBOR_EXCHANGE && - on->state != OSPF6_NEIGHBOR_LOADING && - on->state != OSPF6_NEIGHBOR_FULL) + if (p != OSPF6_MESSAGE_END (oh)) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_info ("Trailing garbage ignored"); + } + + // XXX BOEING how should database be cleansed FIXME +/* for (i = listhead (oi->area->ospf6->area_list); i; nextnode (i)) + { + oa = (struct ospf6_area *) getdata (i); + for (j = listhead (oa->if_list); j; nextnode (j)) + { + oi = (struct ospf6_interface *) getdata (j); + if(oi->type == OSPF6_IFTYPE_MANETRELIABLE) + ospf6_lsdb_maxage_remover(oi->lsdb_cache); + } + ospf6_lsdb_maxage_remover(oa->lsdb_cache); + } + ospf6_lsdb_maxage_remover(oi->area->ospf6->lsdb_cache); + +} + +void +ospf6_lsdb_maxage_remover(struct ospf6_lsdb *lsdb_cache) +{ + struct ospf6_lsa *lsa; + + for (lsa = ospf6_lsdb_head (lsdb_cache); lsa; lsa = ospf6_lsdb_next (lsa)) + { + if (! OSPF6_LSA_IS_MAXAGE (lsa)) + continue; + else if (lsa->retrans_count != 0) + continue; + if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type)) + zlog_info (" remove maxage %s", lsa->name); + ospf6_lsdb_remove (lsa, lsdb_cache); + } +*/ +} +#endif //OSPF6_MANET_TEMPORARY_LSDB + +void +ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, struct ospf6_header *oh) +{ + struct ospf6_neighbor *on; + char *p; + struct ospf6_lsa *his, *mine; + struct ospf6_lsdb *lsdb = NULL; + + assert (oh->type == OSPF6_MESSAGE_TYPE_LSACK); + if (ospf6_header_examin (src, dst, oi, oh) != MSG_OK) + return; + + on = ospf6_neighbor_lookup (oh->router_id, oi); + if (on == NULL) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_debug ("Neighbor not found, ignore"); + return; + } + + if (memcmp (src, &on->linklocal_addr, sizeof (struct in6_addr))) + { + if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) + zlog_debug ("Seems to be from Secondary I/F of the neighbor, ignore"); + return; + } + +#ifdef OSPF6_MANET_MPR_SH + // SURROGATE_HELLO + //Chandra03 3.4.9 paragraph 1 condition 6 and Chandra03 3.3.6.1 paragraph 1 + //received ack counts as received hello with no state change + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE && + oi->flooding == OSPF6_FLOOD_MPR_SDCDS) +// (oi->flooding == OSPF6_FLOOD_MPR_SDCDS || +// oi->flooding == OSPF6_FLOOD_MDR_SICDS)) // XXX this works with SICDS + thread_execute (master, hello_received, on, 0); +#endif //OSPF6_MANET_MPR_FLOOD + + if (on->state != OSPF6_NEIGHBOR_EXCHANGE && + on->state != OSPF6_NEIGHBOR_LOADING && + on->state != OSPF6_NEIGHBOR_FULL) { if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) zlog_debug ("Neighbor state less than Exchange, ignore"); @@ -1109,6 +1969,10 @@ if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV)) zlog_debug ("%s acknowledged by %s", his->name, on->name); +#ifdef OSPF6_MANET + ospf6_store_mack(on, his->header); +#endif //OSPF6_MANET + /* Find database copy */ mine = ospf6_lsdb_lookup (his->header->type, his->header->id, his->header->adv_router, lsdb); @@ -1120,6 +1984,16 @@ continue; } +#ifdef OSPF6_MANET + // Delete pushback neighbor corresponding to source of LSAck + //Chandra03 3.4.9 paragraph 2 + if (on->ospf6_if->type == OSPF6_IFTYPE_MANETRELIABLE && + mine->pushBackTimer && ospf6_lsa_compare (his, mine) == 0) + { + ospf6_pushback_lsa_neighbor_delete(mine, on); + } +#endif //OSPF6_MANET + /* Check if the LSA is on his retrans-list */ mine = ospf6_lsdb_lookup (his->header->type, his->header->id, his->header->adv_router, on->retrans_list); @@ -1172,8 +2046,8 @@ if (size <= iobuflen) return iobuflen; - recvnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size); - sendnew = XMALLOC (MTYPE_OSPF6_MESSAGE, size); + recvnew = (char *) XMALLOC (MTYPE_OSPF6_MESSAGE, size); + sendnew = (char *) XMALLOC (MTYPE_OSPF6_MESSAGE, size); if (recvnew == NULL || sendnew == NULL) { if (recvnew) @@ -1188,8 +2062,8 @@ XFREE (MTYPE_OSPF6_MESSAGE, recvbuf); if (sendbuf) XFREE (MTYPE_OSPF6_MESSAGE, sendbuf); - recvbuf = recvnew; - sendbuf = sendnew; + recvbuf = (u_char *) recvnew; + sendbuf = (u_char *) sendnew; iobuflen = size; return iobuflen; @@ -1209,7 +2083,9 @@ /* add next read thread */ sockfd = THREAD_FD (thread); +#ifndef SIM thread_add_read (master, ospf6_receive, NULL, sockfd); +#endif //SIM /* initialize */ memset (recvbuf, 0, iobuflen); @@ -1255,7 +2131,14 @@ switch (oh->type) { case OSPF6_MESSAGE_TYPE_HELLO: +#ifdef OSPF6_MANET + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE) + ospf6_mhello_print(oh, len); + else + ospf6_hello_print (oh); +#else ospf6_hello_print (oh); +#endif //OSPF6_MANET break; case OSPF6_MESSAGE_TYPE_DBDESC: ospf6_dbdesc_print (oh); @@ -1286,11 +2169,19 @@ switch (oh->type) { case OSPF6_MESSAGE_TYPE_HELLO: +#ifdef OSPF6_MANET + ospf6_hello_recv (&src, &dst, oi, oh, len); +#else ospf6_hello_recv (&src, &dst, oi, oh); +#endif //OSPF6_MANET break; case OSPF6_MESSAGE_TYPE_DBDESC: +#ifdef OSPF6_MANET + ospf6_dbdesc_recv (&src, &dst, oi, oh, len); +#else ospf6_dbdesc_recv (&src, &dst, oi, oh); +#endif //OSPF6_MANET break; case OSPF6_MESSAGE_TYPE_LSREQ: @@ -1315,8 +2206,14 @@ } void +#ifdef OSPF6_MANET +// Send in length because TLV might be longer than OSPF header length +ospf6_send (struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, struct ospf6_header *oh, int length) +#else ospf6_send (struct in6_addr *src, struct in6_addr *dst, struct ospf6_interface *oi, struct ospf6_header *oh) +#endif //OSPF6_MANET { int len; char srcname[64], dstname[64]; @@ -1324,7 +2221,13 @@ /* initialize */ iovector[0].iov_base = (caddr_t) oh; +#ifdef OSPF6_MANET + iovector[0].iov_len = length; +#else + int length = ntohs(oh->length); iovector[0].iov_len = ntohs (oh->length); +#endif //OSPF6_MANET + iovector[1].iov_base = NULL; iovector[1].iov_len = 0; @@ -1354,7 +2257,14 @@ switch (oh->type) { case OSPF6_MESSAGE_TYPE_HELLO: +#ifdef OSPF6_MANET + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE) + ospf6_mhello_print(oh, length); + else + ospf6_hello_print (oh); +#else ospf6_hello_print (oh); +#endif //OSPF6_MANET break; case OSPF6_MESSAGE_TYPE_DBDESC: ospf6_dbdesc_print (oh); @@ -1374,12 +2284,352 @@ break; } } +#ifdef SIM_ETRACE_STAT + switch (oh->type) + { + case OSPF6_MESSAGE_TYPE_HELLO: + update_statistics(OSPF6_HELLO_SENT, 1); + update_statistics(OSPF6_HELLO_BYTE_SENT, (double)length); + break; + case OSPF6_MESSAGE_TYPE_DBDESC: + update_statistics(OSPF6_DBDESC_SENT, 1); + update_statistics(OSPF6_DBDESC_BYTE_SENT, (double)length); + break; + case OSPF6_MESSAGE_TYPE_LSREQ: + update_statistics(OSPF6_LSREQ_SENT, 1); + update_statistics(OSPF6_LSREQ_BYTE_SENT, (double)length); + break; + case OSPF6_MESSAGE_TYPE_LSUPDATE: + update_statistics(OSPF6_LSUPDATE_SENT, 1); + update_statistics(OSPF6_LSUPDATE_BYTE_SENT, (double)length); + if (IN6_IS_ADDR_MULTICAST(dst)) + { + update_statistics(OSPF6_LSUPDATE_MULTI_SENT, 1); + update_statistics(OSPF6_LSUPDATE_MULTI_BYTE_SENT, (double)length); + } + else + { + update_statistics(OSPF6_LSUPDATE_UNI_SENT, 1); + update_statistics(OSPF6_LSUPDATE_UNI_BYTE_SENT, (double)length); + } + break; + case OSPF6_MESSAGE_TYPE_LSACK: + update_statistics(OSPF6_LSACK_SENT, 1); + update_statistics(OSPF6_LSACK_BYTE_SENT, (double)length); + break; + default: + zlog_info ("Unknown message"); + assert (0); + break; + } +#endif //SIM_ETRACE_STAT /* send message */ +#ifdef USER_CHECKSUM + /* + * prior to sending packet, compute checksum. Done in userspace + * so we can detect extra TLVs on end of packet and not include + * this area of the packet in checksum calc. + */ + oh->checksum = 0; /* initialize checksum */ + oh->checksum = ospf6_do_checksum(src,dst,oh); +#endif len = ospf6_sendmsg (src, dst, &oi->interface->ifindex, iovector); +#ifdef OSPF6_MANET + if (len != length) + zlog_err ("Could not send entire message length %d != %d", length, len); +#else if (len != ntohs (oh->length)) - zlog_err ("Could not send entire message"); + zlog_err ("Could not send entire message length %d != %d", oh->length, len); +#endif //OSPF6_MANET +} + +#ifdef OSPF6_MANET_MDR_FLOOD +// Ogierv3 10.1 +int ospf6_mdr_mhello_send(struct ospf6_interface *oi) +{ + int length=0; + u_int lls_length=0; + struct ospf6_header *oh; + struct ospf6_hello *hello; + u_char *pos, *lls; + u_char hnl[iobuflen], rnl[iobuflen], lnl[iobuflen]; + u_int num_hnl=0, num_rnl=0, num_lnl=0; + u_char dnl[iobuflen]; + u_int num_dnl=0; + boolean diff = false; + +#ifdef SIM_ETRACE_STAT + ospf6_print_neighborhood_sim(oi); +#endif //SIM_ETRACE_STAT + + // Calculate cds and update adj before hello is sent. + ospf6_calculate_mdr(oi); + ospf6_mdr_update_adjacencies(oi); + + memset (sendbuf, 0, iobuflen); + oh = (struct ospf6_header *) sendbuf; + oh->type = OSPF6_MESSAGE_TYPE_HELLO; + + hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header)); + hello->interface_id = htonl (oi->interface->ifindex); + hello->priority = oi->priority; + hello->options[0] = oi->area->options[0]; + hello->options[1] = oi->area->options[1]; + hello->options[2] = oi->area->options[2]; + hello->hello_interval = htons (oi->hello_interval); + hello->dead_interval = htons (oi->dead_interval); + hello->drouter = 0; + hello->bdrouter = 0; + + if (oi->mdr_level == OSPF6_MDR) + { + hello->drouter = oi->area->ospf6->router_id; + if (oi->parent) + hello->bdrouter = oi->parent->router_id; + } + else if (oi->mdr_level == OSPF6_BMDR) + { + hello->bdrouter = oi->area->ospf6->router_id; + if (oi->parent) + hello->drouter = oi->parent->router_id; + } + else + { + if (oi->parent) + hello->drouter = oi->parent->router_id; + if (oi->bparent) + hello->bdrouter = oi->bparent->router_id; + } + + pos = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello)); + oh->length = htons (pos - sendbuf); + +#ifdef OSPF6_MANET_DIFF_HELLO + //Is this a Diff Hello + if (oi->diff_hellos && oi->full_hello_count > 1) + { + oi->full_hello_count--; + diff = true; + OSPF6_OPT_SET(hello->options, OSPF6_OPT_D, 1); + } + else + oi->full_hello_count = oi->TwoHopRefresh; +#endif //OSPF6_MANET_DIFF_HELLO + + // dnl added for Ogierv7 + lls_length = ospf6_mdr_create_neighbor_lists(oi, pos, sendbuf+iobuflen, + &num_hnl, hnl, &num_rnl, rnl, &num_lnl, lnl, + &num_dnl, dnl, diff); + + if (lls_length == 0) + { //No TLVs to append - send empty hello + ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh, ntohs(oh->length)); + oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send, + oi, oi->hello_interval); + return 0; + } + //LLS will be sent + OSPF6_OPT_SET(hello->options, OSPF6_OPT_L, 1); + + /* leave room for LLS header */ + lls = pos; + pos += sizeof(struct ospf6_LLS_header); + +#ifdef OSPF6_MANET_DIFF_HELLO + //Seq TLV + if (oi->diff_hellos) //append seq tlv when diff hellos enabled + pos += ospf6_append_mdr_seq_tlv(oi, pos); + + //LNL TLV + pos += ospf6_append_mdr_neigh_tlv(pos, num_lnl, lnl, OSPF6_TLV_TYPE_LNL); +#endif //OSPF6_MANET_DIFF_HELLO + + //HNL TLV + pos += ospf6_append_mdr_neigh_tlv(pos, num_hnl, hnl, OSPF6_TLV_TYPE_HNL); + + //RNL TLV + pos += ospf6_append_mdr_neigh_tlv(pos, num_rnl, rnl, OSPF6_TLV_TYPE_RNL); + + // DNL added for Ogierv7 + //DNL TLV + pos += ospf6_append_mdr_neigh_tlv(pos, num_dnl, dnl, OSPF6_TLV_TYPE_DNL); + + //LLS header must be added here, so the checksum is computed correctly + ospf6_append_lls_header(oi, lls, lls_length); + + //Send hello + length = pos - sendbuf; + ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh, length); + oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send, + oi, oi->hello_interval); + return 0; +} +#endif //OSPF6_MANET_MDR_FLOOD + +#ifdef OSPF6_MANET_MPR_FLOOD +//Chandra03 3.3.7 +int ospf6_mpr_mhello_send(struct ospf6_interface *oi) +{ + int length; + int relay_length = 0; + struct ospf6_header *oh; + struct ospf6_hello *hello; + u_char *pos, *lls; + + memset (sendbuf, 0, iobuflen); + oh = (struct ospf6_header *) sendbuf; + oh->type = OSPF6_MESSAGE_TYPE_HELLO; + + hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header)); + hello->interface_id = htonl (oi->interface->ifindex); + hello->priority = oi->priority; + hello->options[0] = oi->area->options[0]; + hello->options[1] = oi->area->options[1]; + hello->options[2] = oi->area->options[2]; + hello->hello_interval = htons (oi->hello_interval); + hello->dead_interval = htons (oi->dead_interval); + hello->drouter = oi->drouter; + hello->bdrouter = oi->bdrouter; + + OSPF6_OPT_SET(hello->options, OSPF6_OPT_F, 1); //supports MPR flooding + + ospf6_calculate_relays(oi); + + pos = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello)); + /* new neighbors or all neighbors if A option set*/ + pos += ospf6_create_neighbor_list(oi, sendbuf, pos, true);//full state + oh->length = htons (pos - sendbuf); + + lls = pos; + /* leave room for LLS header */ + pos += sizeof(struct ospf6_LLS_header); + + /* Relay TLV */ + relay_length = ospf6_append_relays(oi, + pos, + sendbuf + iobuflen, + true, + true); + + if (relay_length > 0) //relay(s) to add + { + OSPF6_OPT_SET(hello->options, OSPF6_OPT_L,1); //Relay TLV will be appended + pos += relay_length; + /* place LLS header at the front position of the buffer*/ + length = pos - sendbuf; + ospf6_append_lls_header(oi, lls, (u_int)(pos-lls)); + } + else + length = lls - sendbuf; //no relay(s) to add + + ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh, length); + + oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send, + oi, oi->hello_interval); + return 0; +} + +#ifdef OSPF6_MANET_DIFF_HELLO +//Chandra03 3.3.7 +int ospf6_mpr_diff_mhello_send(struct ospf6_interface *oi, + struct in6_addr dst, + char *scs_tlv_option) +{ + int length; + struct ospf6_header *oh; + struct ospf6_hello *hello; + u_char *pos, *lls; + boolean set_N = false; + + memset (sendbuf, 0, iobuflen); + oh = (struct ospf6_header *) sendbuf; + oh->type = OSPF6_MESSAGE_TYPE_HELLO; + + hello = (struct ospf6_hello *)((caddr_t) oh + sizeof (struct ospf6_header)); + hello->interface_id = htonl (oi->interface->ifindex); + hello->priority = oi->priority; + hello->options[0] = oi->area->options[0]; + hello->options[1] = oi->area->options[1]; + hello->options[2] = oi->area->options[2]; + hello->hello_interval = htons (oi->hello_interval); + hello->dead_interval = htons (oi->dead_interval); + hello->drouter = oi->drouter; + hello->bdrouter = oi->bdrouter; + + OSPF6_OPT_SET(hello->options, OSPF6_OPT_F, 1); //supports MPR flooding + OSPF6_OPT_SET(hello->options, OSPF6_OPT_L, 1); //TLV will be appended + //Chandra03 3.3.6.1 paragraph 1 + OSPF6_OPT_SET(hello->options, OSPF6_OPT_I, 1); //partial hello information + + ospf6_calculate_relays(oi); + + pos = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello)); + /* new neighbors or all neighbors if FS option set*/ + pos += ospf6_create_neighbor_list(oi, sendbuf, pos, + OSPF6_TLV_SCS_OPT_ISSET(scs_tlv_option, OSPF6_TLV_SCS_OPT_FS, 0)); + oh->length = htons (pos - sendbuf); + + lls = pos; + /* leave room for LLS header */ + pos += sizeof(struct ospf6_LLS_header); + + /* SCS TLV */ + if(oi->increment_scs) + oi->scs_num = ospf6_increment_scs(oi->scs_num); + /* append scs below because tlv_option may change -- advance position */ + pos += sizeof(struct ospf6_TLV_header) + sizeof(struct ospf6_scs_TLV); + + /* Drop TLV */ + pos += ospf6_append_drop_neighbors(oi, pos, sendbuf+iobuflen, &set_N); + if(!oi->increment_scs && set_N) + OSPF6_TLV_SCS_OPT_SET(scs_tlv_option, OSPF6_TLV_SCS_OPT_N, 0); + + /* Relay TLV */ + pos += ospf6_append_relays(oi, + pos, + sendbuf + iobuflen, + IN6_IS_ADDR_MULTICAST(&dst), + OSPF6_TLV_SCS_OPT_ISSET(scs_tlv_option, OSPF6_TLV_SCS_OPT_FS, 0)); + + // Request TLV + // Chandra03 3.3.7 paragraph 1 + if (oi->initialization == true) + { + // router interface is initializing + // request full neighbor state from all neighbors + plistnode n; + struct ospf6_neighbor *on; + oi->initialization = false; + OSPF6_TLV_SCS_OPT_SET(scs_tlv_option, OSPF6_TLV_SCS_OPT_R, 0); + for (n = listhead(oi->neighbor_list); n; nextnode(n)) + { //clear all neighbor request + on = (struct ospf6_neighbor *) getdata(n); + on->request = false; + } + } + else + pos += ospf6_append_request(oi, pos, sendbuf+iobuflen, scs_tlv_option); + + /* append SCS TLV */ + ospf6_append_scs(oi, scs_tlv_option, lls+sizeof(struct ospf6_LLS_header)); + + /* place LLS header at the front position of the buffer*/ + length = pos - sendbuf; + ospf6_append_lls_header(oi, lls, (u_int)(pos-lls)); + + ospf6_send (oi->linklocal_addr, &dst, oi, oh, length); + + if (IN6_IS_ADDR_MULTICAST(&dst)) + { /* this is a periodic hello - set next timer thread */ + oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send, + oi, oi->hello_interval); + } + oi->increment_scs = false; + return 0; } +#endif //OSPF6_MANET_DIFF_HELLO +#endif //OSPF6_MANET_MPR_FLOOD int ospf6_hello_send (struct thread *thread) @@ -1402,6 +2652,52 @@ return 0; } +#ifdef OSPF6_CONFIG + if (oi->type == OSPF6_IFTYPE_LOOPBACK) + return 0; + + if(oi->type == OSPF6_IFTYPE_MANETRELIABLE && + oi->flooding == OSPF6_FLOOD_MPR_SDCDS) + { +#ifdef OSPF6_MANET_MPR_FLOOD + if (!oi->diff_hellos) + { + return ospf6_mpr_mhello_send(oi); + } +#ifdef OSPF6_MANET_DIFF_HELLO + //Chandra03 3.3.10 paragraph 2 bullet 1 + else if (elapsed_time(&ospf6->starttime) > oi->dead_interval) + { //graceful restart + struct in6_addr dst; + char scs_tlv_option[2] = {0, 0}; + + //graceful restart + //Chandra03 3.3.10 paragraph 2 bullet 3 + if(elapsed_time(&ospf6->starttime)-oi->dead_intervalhello_interval) + oi->full_state = true; + + if (oi->full_state == true) + { + OSPF6_TLV_SCS_OPT_SET(scs_tlv_option, OSPF6_TLV_SCS_OPT_FS, 0); + oi->full_state = false; + } + + /* initialize destination - may change within send */ + inet_pton (AF_INET6, ALLSPFROUTERS6, &dst); + return ospf6_mpr_diff_mhello_send(oi, dst, scs_tlv_option); + } +#endif //OSPF6_MANET_DIFF_HELLO +#endif //OSPF6_MANET_MPR_FLOOD + } + else if(oi->type == OSPF6_IFTYPE_MANETRELIABLE && + oi->flooding == OSPF6_FLOOD_MDR_SICDS) + { +#ifdef OSPF6_MANET_MDR_FLOOD + return ospf6_mdr_mhello_send(oi); +#endif //OSPF6_MANET_MDR_FLOOD + } +#endif //OSPF6_CONFIG + /* set next thread */ oi->thread_send_hello = thread_add_timer (master, ospf6_hello_send, oi, oi->hello_interval); @@ -1420,7 +2716,7 @@ hello->drouter = oi->drouter; hello->bdrouter = oi->bdrouter; - p = (char *)((caddr_t) hello + sizeof (struct ospf6_hello)); + p = (u_char *)((caddr_t) hello + sizeof (struct ospf6_hello)); for (node = listhead (oi->neighbor_list); node; nextnode (node)) { @@ -1443,7 +2739,11 @@ oh->type = OSPF6_MESSAGE_TYPE_HELLO; oh->length = htons (p - sendbuf); +#ifdef OSPF6_MANET + ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh, ntohs(oh->length)); +#else ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh); +#endif //OSPF6_MANET return 0; } @@ -1455,6 +2755,12 @@ struct ospf6_dbdesc *dbdesc; u_char *p; struct ospf6_lsa *lsa; +#ifdef OSPF6_MANET + int length = 0; +#ifdef OSPF6_MANET_MDR_FLOOD + u_char *lls = NULL; +#endif //OSPF6_MANET_MDR_FLOOD +#endif //OSPF6_MANET on = (struct ospf6_neighbor *) THREAD_ARG (thread); on->thread_send_dbdesc = (struct thread *) NULL; @@ -1482,7 +2788,11 @@ if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT)) { struct timeval tv; +#ifdef SIM + if (gettimeofday_sim (&tv, (struct timezone *) NULL) < 0) +#else if (gettimeofday (&tv, (struct timezone *) NULL) < 0) +#endif //SIM tv.tv_sec = 1; on->dbdesc_seqnum = tv.tv_sec; } @@ -1495,7 +2805,7 @@ dbdesc->seqnum = htonl (on->dbdesc_seqnum); /* if this is not initial one, set LSA headers in dbdesc */ - p = (char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc)); + p = (u_char *)((caddr_t) dbdesc + sizeof (struct ospf6_dbdesc)); if (! CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT)) { for (lsa = ospf6_lsdb_head (on->dbdesc_list); lsa; @@ -1514,12 +2824,49 @@ p += sizeof (struct ospf6_lsa_header); } } +#ifdef OSPF6_MANET +#ifdef OSPF6_MANET_MDR_FLOOD + else if (on->ospf6_if->type == OSPF6_IFTYPE_MANETRELIABLE && + on->ospf6_if->flooding == OSPF6_FLOOD_MDR_SICDS && + on->ospf6_if->AdjConnectivity > OSPF6_ADJ_FULLYCONNECTED) + { + u_int size = sizeof(struct ospf6_LLS_header) + + sizeof(struct ospf6_TLV_header) + + sizeof(struct ospf6_mdr_TLV); + + if (p + size >= sendbuf + iobuflen) + zlog_warn ("Send DD Packet: Buffer shortage on %s", + on->ospf6_if->interface->name); + else + { + lls = p; + + OSPF6_OPT_SET(dbdesc->options, OSPF6_OPT_L, 1); + lls += ospf6_append_lls_header(on->ospf6_if, lls, size); + + /* Router TLV */ + //mdr, mbdr, parent, bparent already up to date ??? XXX + lls += ospf6_append_mdr_tlv(on->ospf6_if, lls); + length = lls - sendbuf; + } + } + if (lls == NULL) + length = p - sendbuf; +#else + length = p - sendbuf; +#endif //OSPF6_MANET_MDR_FLOOD +#endif //OSPF6_MANET - oh->type = OSPF6_MESSAGE_TYPE_DBDESC; oh->length = htons (p - sendbuf); + oh->type = OSPF6_MESSAGE_TYPE_DBDESC; +#ifdef OSPF6_MANET + ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, + on->ospf6_if, oh, length); +#else ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, on->ospf6_if, oh); +#endif //OSPF6_MANET return 0; } @@ -1547,6 +2894,8 @@ ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->dbdesc_list); ospf6_lsdb_remove (lsa, on->summary_list); + //printf("%d %d lsa removed from summary list, count %d \n", + //ospf6->router_id, on->router_id, on->summary_list->count); size += sizeof (struct ospf6_lsa_header); } @@ -1601,7 +2950,7 @@ oh = (struct ospf6_header *) sendbuf; /* set Request entries in lsreq */ - p = (char *)((caddr_t) oh + sizeof (struct ospf6_header)); + p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header)); for (lsa = ospf6_lsdb_head (on->request_list); lsa; lsa = ospf6_lsdb_next (lsa)) { @@ -1622,11 +2971,275 @@ oh->type = OSPF6_MESSAGE_TYPE_LSREQ; oh->length = htons (p - sendbuf); +#ifdef OSPF6_MANET + ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, + on->ospf6_if, oh, ntohs(oh->length)); +#else ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, on->ospf6_if, oh); +#endif //OSPF6_MANET return 0; } +#ifdef OSPF6_DELAYED_FLOOD +int +ospf6_lsupdate_send_neighbor (struct thread *thread) +{ + struct ospf6_neighbor *on; + struct ospf6_header *oh; + struct ospf6_lsupdate *lsupdate; + u_char *p; + int num; + struct ospf6_lsa *lsa; + + double rxmt_time; + double lsa_rxmt_time; + boolean rxmt_now = false; + int rxmt = 0; +#ifdef SIM_ETRACE_STAT + int rxmt_size = 0; + int dbexch_size = 0; + int stale_size = 0; + int dbexch = 0; + int stale = 0; +#endif //SIM_ETRACE_STAT + + on = (struct ospf6_neighbor *) THREAD_ARG (thread); + on->thread_send_lsupdate = (struct thread *) NULL; + + if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) + zlog_debug ("LSUpdate to neighbor %s", on->name); + + if (on->state < OSPF6_NEIGHBOR_EXCHANGE) + { + if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) + zlog_debug ("Quit to send (neighbor state %s)", + ospf6_neighbor_state_str[on->state]); + return 0; + } + + /* if we have nothing to send, return */ + if (on->lsupdate_list->count == 0 && + on->retrans_list->count == 0) + { + if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND)) + zlog_debug ("Quit to send (nothing to send)"); + return 0; + } + + memset (sendbuf, 0, iobuflen); + oh = (struct ospf6_header *) sendbuf; + lsupdate = (struct ospf6_lsupdate *) + ((caddr_t) oh + sizeof (struct ospf6_header)); + p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); + num = 0; + + /* lsupdate_list: lists LSAs which doen't need to be + retransmitted. remove those from the list */ + for (lsa = ospf6_lsdb_head (on->lsupdate_list); lsa; + lsa = ospf6_lsdb_next (lsa)) + { + /* MTU check */ + if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header)) + > on->ospf6_if->ifmtu) + { + ospf6_lsa_unlock (lsa); + break; + } + + ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay); + memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header)); + p += OSPF6_LSA_SIZE (lsa->header); + num++; +#ifdef SIM_ETRACE_STAT + if (lsa->unicast_stale) + { + stale_size += OSPF6_LSA_SIZE (lsa->header); + stale++; + } + else + { + dbexch_size += OSPF6_LSA_SIZE (lsa->header); + dbexch++; + } +#endif //SIM_ETRACE_STAT + assert (lsa->lock == 2); + ospf6_lsdb_remove (lsa, on->lsupdate_list); + } + + //Determine if there is at least one LSA with expired rxmt time + rxmt_time = (double) on->ospf6_if->rxmt_interval; + for (lsa = ospf6_lsdb_head (on->retrans_list); lsa; + lsa = ospf6_lsdb_next (lsa)) + { + lsa_rxmt_time = on->ospf6_if->rxmt_interval-elapsed_time(&lsa->rxmt_time); + if (lsa_rxmt_time < .001)//thread_add_timer only works on 1 msec increment + { + rxmt_now = true; + break; + } + } + + if(rxmt_now) + { + int i; + boolean same; + char *u; + for (lsa = ospf6_lsdb_head (on->retrans_list); lsa; + lsa = ospf6_lsdb_next (lsa)) + { + lsa_rxmt_time = on->ospf6_if->rxmt_interval-elapsed_time(&lsa->rxmt_time); + if (lsa_rxmt_time > ((double) on->ospf6_if->flood_delay)/1000) + { //flood lsa that have expired or will expire within flood_delay msec + //this lsa should not be retransmitted yet + if (lsa_rxmt_time < rxmt_time) + rxmt_time = lsa_rxmt_time; + continue; + } + set_time(&lsa->rxmt_time); //set the time lsa is retransmitted + +/* +#ifdef OSPF6_MANET_MDR_FLOOD + if (on->ospf6_if->flooding == OSPF6_FLOOD_MDR_SICDS && + on->ospf6_if->type == OSPF6_IFTYPE_MANETRELIABLE && + on->ospf6_if->mdr_level == OSPF6_OTHER) + { + //TODO when should this be removed from the list + //TODO will skipping this LSA mess anything up???? + continue; + } +#endif //OSPF6_MANET_MDR_FLOOD +*/ + +#if 1 //SAME XXX BOEING Check if LSA already added from update_list: KEEP ??? + same = false; + u = (char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); + for (i=0; iheader->type == ((struct ospf6_lsa_header *) u)->type && + lsa->header->id == ((struct ospf6_lsa_header *) u)->id && + lsa->header->adv_router == + ((struct ospf6_lsa_header *) u)->adv_router && + lsa->header->seqnum == ((struct ospf6_lsa_header *) u)->seqnum && + lsa->header->length == ((struct ospf6_lsa_header *) u)->length) + { + same = true; + break; + } + u += OSPF6_LSA_SIZE (u); + } + if (same) + continue; +#endif //SAME + + /* MTU check */ + if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header)) + > on->ospf6_if->ifmtu) + { + ospf6_lsa_unlock (lsa); + break; + } + + ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay); + memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header)); + p += OSPF6_LSA_SIZE (lsa->header); + num++; + rxmt++; +#ifdef SIM_ETRACE_STAT + rxmt_size += OSPF6_LSA_SIZE (lsa->header); +#endif //SIM_ETRACE_STAT + } + } + + lsupdate->lsa_number = htonl (num); + + oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE; + oh->length = htons (p - sendbuf); + + if (num != 0) { +#ifdef OSPF6_MANET + ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, + on->ospf6_if, oh, ntohs(oh->length)); +#else + ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, + on->ospf6_if, oh); +#endif //OSPF6_MANET + +#ifdef SIM_ETRACE_STAT + TraceEvent_sim(1,"unicast_LSU %d bytes %d rxmt %d bytes, %d dbexch %d bytes, %d stale %d bytes to %s", + p-sendbuf, rxmt, rxmt_size, dbexch, dbexch_size, stale, + stale_size, ip2str(on->router_id)); + int ospf6head = 20; // add the ospf header length + if (rxmt > 0 && dbexch > 0 || + rxmt > 0 && stale > 0 || + dbexch > 0 && stale > 0) + { + update_statistics(OSPF6_LSUPDATE_UNI_COL_SENT, 1); + update_statistics(OSPF6_LSUPDATE_UNI_COL_BYTE_SENT, + (double) (rxmt_size+dbexch_size+stale_size+ospf6head)); + } + else if (rxmt > 0) + { + update_statistics(OSPF6_LSUPDATE_UNI_RXMT_SENT, 1); + update_statistics(OSPF6_LSUPDATE_UNI_RXMT_BYTE_SENT, + (double)(rxmt_size+ospf6head)); + } + else if (stale > 0) + { + update_statistics(OSPF6_LSUPDATE_UNI_STALE_SENT, 1); + update_statistics(OSPF6_LSUPDATE_UNI_STALE_BYTE_SENT, + (double)(stale_size+ospf6head)); + } + else + { + update_statistics(OSPF6_LSUPDATE_UNI_DBEX_SENT, 1); + update_statistics(OSPF6_LSUPDATE_UNI_DBEX_BYTE_SENT, + (double)(dbexch_size+ospf6head)); + } +#endif //SIM_ETRACE_STAT + } + + if (on->lsupdate_list->count != 0 || on->retrans_list->count != 0) + { + if (on->lsupdate_list->count != 0) + { + on->thread_send_lsupdate = + ospf6_send_lsupdate_delayed_msec(master, ospf6_lsupdate_send_neighbor, + on, on->ospf6_if->flood_delay, + on->thread_send_lsupdate); + } + else + { + on->thread_send_lsupdate = + ospf6_send_lsupdate_delayed_msec(master, ospf6_lsupdate_send_neighbor, + on, (long) (rxmt_time*1000), + on->thread_send_lsupdate); + } + } + return 0; +} + +struct thread *ospf6_send_lsupdate_delayed_msec(struct thread_master *m, + int (*func) (struct thread *), void *arg, long timer_msec, + struct thread *t) +{ + double time_remaining; + if (!t) + { + t = thread_add_timer_msec (m, func, arg, timer_msec); + return t; + } + + time_remaining = elapsed_time(&t->u.sands) * (-1); + if (time_remaining > ((double)timer_msec)/1000) + { + THREAD_OFF (t); + t = thread_add_timer_msec (m, func, arg, timer_msec); + } + return t; +} + +#else //OSPF6_DELAYED_FLOOD int ospf6_lsupdate_send_neighbor (struct thread *thread) { @@ -1665,7 +3278,7 @@ lsupdate = (struct ospf6_lsupdate *) ((caddr_t) oh + sizeof (struct ospf6_header)); - p = (char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); + p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); num = 0; /* lsupdate_list lists those LSA which doesn't need to be @@ -1712,8 +3325,13 @@ oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE; oh->length = htons (p - sendbuf); +#ifdef OSPF6_MANET + ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, + on->ospf6_if, oh, ntohs(oh->length)); +#else ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, on->ospf6_if, oh); +#endif //OSPF6_MANET if (on->lsupdate_list->count != 0 || on->retrans_list->count != 0) @@ -1729,6 +3347,7 @@ return 0; } +#endif //OSPF6_DELAYED_FLOOD int ospf6_lsupdate_send_interface (struct thread *thread) @@ -1760,7 +3379,7 @@ lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh + sizeof (struct ospf6_header)); - p = (char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); + p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate)); num = 0; for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa; @@ -1775,6 +3394,7 @@ } ospf6_lsa_age_update_to_send (lsa, oi->transdelay); + memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header)); p += OSPF6_LSA_SIZE (lsa->header); num++; @@ -1788,18 +3408,55 @@ oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE; oh->length = htons (p - sendbuf); +#ifdef OSPF6_CONFIG + if (oi->type == OSPF6_IFTYPE_BROADCAST || + oi->type == OSPF6_IFTYPE_NBMA) + { + if (oi->state == OSPF6_INTERFACE_DR || + oi->state == OSPF6_INTERFACE_BDR) +#ifdef OSPF6_MANET + ospf6_send (oi->linklocal_addr, &allspfrouters6,oi,oh,ntohs(oh->length)); +#else + ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh); +#endif //OSPF6_MANET + else +#ifdef OSPF6_MANET + ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh, ntohs(oh->length)); +#else + ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh); +#endif //OSPF6_MANET + } + else +#ifdef OSPF6_MANET + if(oi->type == OSPF6_IFTYPE_MANETRELIABLE || + oi->type == OSPF6_IFTYPE_POINTOMULTIPOINT) + ospf6_send (oi->linklocal_addr, &allspfrouters6, oi,oh,ntohs(oh->length)); + else + ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh, ntohs(oh->length)); +#else + ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh); +#endif //OSPF6_MANET + +#else //OSPF6_CONFIG if (oi->state == OSPF6_INTERFACE_DR || oi->state == OSPF6_INTERFACE_BDR) ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh); else ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh); +#endif //OSPF6_CONFIG if (oi->lsupdate_list->count > 0) { +#ifdef OSPF6_DELAYED_FLOOD + oi->thread_send_lsupdate = + ospf6_send_lsupdate_delayed_msec(master, ospf6_lsupdate_send_interface, + oi, oi->flood_delay, + oi->thread_send_lsupdate); +#else oi->thread_send_lsupdate = thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0); +#endif //OSPF6_DELAYED_FLOOD } - return 0; } @@ -1829,7 +3486,7 @@ memset (sendbuf, 0, iobuflen); oh = (struct ospf6_header *) sendbuf; - p = (char *)((caddr_t) oh + sizeof (struct ospf6_header)); + p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header)); for (lsa = ospf6_lsdb_head (on->lsack_list); lsa; lsa = ospf6_lsdb_next (lsa)) @@ -1858,8 +3515,13 @@ oh->type = OSPF6_MESSAGE_TYPE_LSACK; oh->length = htons (p - sendbuf); +#ifdef OSPF6_MANET + ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, + on->ospf6_if, oh, ntohs(oh->length)); +#else ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr, on->ospf6_if, oh); +#endif //OSPF6_MANET return 0; } @@ -1886,10 +3548,60 @@ if (oi->lsack_list->count == 0) return 0; +#if defined(OSPF6_MANET_MPR_SH) && defined(OSPF6_MANET_DIFF_HELLO) + // SURROGATE_HELLO + //Chandra03 3.4.9 paragraph 1 condition 6 and Chandra03 3.3.6.1 paragraph 1 + //sent ack counts as received hello with no state change + // This is the portion in Incremental Hellos that doesn't send a Hello + // that would normally have been sent + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE && + oi->flooding == OSPF6_FLOOD_MPR_SDCDS && + oi->diff_hellos) + { + plistnode n; + boolean request = false; + struct ospf6_neighbor *on; + + ospf6_calculate_relays(oi); + //graceful restart + if(elapsed_time(&ospf6->starttime)-oi->dead_intervalhello_interval) + oi->full_state = true; + + for (n = listhead(oi->neighbor_list); n; nextnode(n)) + { + on = (struct ospf6_neighbor *) getdata(n); + if (on->request == true) + request = true; + } + + if(!oi->increment_scs && !oi->full_state && !oi->initialization && !request) + { + //reset hello interval to (HelloInterval +/- ~U(HelloInterval / 4)) + double jitter; + long interval; +#ifdef SIM + double rand_= (double) rand_sim()/RAND_MAX; +#else + double rand_ = (double) rand()/RAND_MAX; +#endif //SIM + if (rand_ > .5) + jitter = (rand_*oi->hello_interval/4) * 1000; + else + jitter = (-1) * (rand_*oi->hello_interval/4) * 1000; + + interval = (long) oi->hello_interval*1000 + (long) jitter; + + THREAD_OFF(oi->thread_send_hello); + oi->thread_send_hello = + thread_add_timer_msec (master, ospf6_hello_send, oi, interval); + } + } +#endif //defined(OSPF6_MANET_MPR_FLOOD) && defined(OSPF6_MANET_DIFF_HELLO) + memset (sendbuf, 0, iobuflen); oh = (struct ospf6_header *) sendbuf; - p = (char *)((caddr_t) oh + sizeof (struct ospf6_header)); + p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header)); for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa; lsa = ospf6_lsdb_next (lsa)) @@ -1918,11 +3630,40 @@ oh->type = OSPF6_MESSAGE_TYPE_LSACK; oh->length = htons (p - sendbuf); +#ifdef OSPF6_CONFIG + if (oi->type == OSPF6_IFTYPE_BROADCAST || + oi->type == OSPF6_IFTYPE_NBMA) + { + if (oi->state == OSPF6_INTERFACE_DR || + oi->state == OSPF6_INTERFACE_BDR) +#ifdef OSPF6_MANET + ospf6_send (oi->linklocal_addr, &allspfrouters6,oi,oh,ntohs(oh->length)); +#else + ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh); +#endif //OSPF6_MANET + else +#ifdef OSPF6_MANET + ospf6_send (oi->linklocal_addr, &alldrouters6,oi,oh,ntohs(oh->length)); +#else + ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh); +#endif //OSPF6_MANET + } + else + { +#ifdef OSPF6_MANET + ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh, ntohs(oh->length)); +#else + ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh); +#endif //OSPF6_MANET + + } +#else //OSPF6_CONFIG if (oi->state == OSPF6_INTERFACE_DR || oi->state == OSPF6_INTERFACE_BDR) ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh); else ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh); +#endif //OSPF6_CONFIG if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0) { @@ -2154,4 +3895,1457 @@ install_element (CONFIG_NODE, &no_debug_ospf6_message_sendrecv_cmd); } +#ifdef OSPF6_MANET +boolean ospf6_is_rtrid_in_list(struct ospf6_interface *oi, + u_int32_t *router_id, + int num) +{ + int i; + boolean found = false; + for (i = 0; i < num; i++) + { + if (*router_id == oi->area->ospf6->router_id) + { + found = true; + break; + } + router_id++; + } + return found; +} + +int ospf6_append_lls_header(struct ospf6_interface *oi, + u_char *lls, + u_int len) +{ + struct ospf6_LLS_header lls_header; + u_int count; + u_int16_t checksum, *p; /*16-bit*/ + u_int32_t sum = 0; + + /*this checksum algorithm can be found in RFC 1071 section 4.1 */ + count = len; + p = (u_int16_t*) lls; + while (count > 1) { + sum += *p++; + count -= 2; + } + sum += htons(len/4); + + /* add left-over byte, if any */ + if (count > 0) + sum += (char)*p; + + /* Fold 32-bit sum to 16 bits */ + while (sum>>16) + sum = (sum & 0xffff) + (sum >> 16); + + /* take the one's complement of the sum */ + checksum = ~sum; + + lls_header.len = htons((u_int16_t)(len/4)); + lls_header.cksum = checksum; + + memcpy(lls, &lls_header, sizeof(struct ospf6_LLS_header)); + + return(sizeof(struct ospf6_LLS_header)); +} + +void ospf6_tlv_header_assignment(struct ospf6_TLV_header *tlv_header, + u_int16_t type, u_int16_t len) +{ + tlv_header->type = htons(type); + tlv_header->len = htons(len); +} + +#ifdef OSPF6_MANET_MPR_FLOOD +void ospf6_mpr_process_TLVs(struct ospf6_neighbor *on, + struct ospf6_LLS_header *lls_ptr) +{ + struct ospf6_interface *oi = on->ospf6_if; + u_int32_t *relay_id_ptr=NULL; + int length_lls = 0, tlv_val_len, added_relays=0, dropped_relays=0; + struct ospf6_TLV_header *tlv_header = NULL; + struct ospf6_options_TLV *tlv_val_opt = NULL; + struct ospf6_relay_TLV *tlv_val_relay = NULL; + struct ospf6_will_TLV *tlv_val_will = NULL; + + length_lls = ntohs(lls_ptr->len) * 4 - sizeof(struct ospf6_LLS_header); + tlv_header = (struct ospf6_TLV_header *) (lls_ptr + 1); + while (length_lls > 0) + { + tlv_val_len = ntohs(tlv_header->len); + length_lls -= (sizeof(tlv_header) + tlv_val_len); + switch (ntohs(tlv_header->type)) + { + case OSPF6_TLV_TYPE_OPTIONS: + { + assert(!tlv_val_opt); //Malformed packet: 2 option TLVs + tlv_val_opt = (struct ospf6_options_TLV *) (tlv_header + 1); + tlv_header = (struct ospf6_TLV_header *) (tlv_val_opt + 1); + break; + } + case OSPF6_TLV_TYPE_RELAY: + { + assert(!tlv_val_relay); //Malformed packet: 2 RELAY TLVs + tlv_val_relay = (struct ospf6_relay_TLV*) (tlv_header + 1); + added_relays = tlv_val_relay->added; + relay_id_ptr = (u_int32_t *) (tlv_val_relay + 1); + dropped_relays = (ntohs(tlv_header->len)-sizeof(tlv_val_relay)) / + sizeof(u_int32_t) - added_relays; + assert(!dropped_relays);//shouldn't have dropped relays(not diff hellos) + tlv_header = (struct ospf6_TLV_header *) (relay_id_ptr + added_relays); + break; + } + case OSPF6_TLV_TYPE_WILLINGNESS: + { + assert(!tlv_val_will); //Malformed packet: 2 willingness TLVs + tlv_val_will = (struct ospf6_will_TLV*) (tlv_header + 1); + tlv_header = (struct ospf6_TLV_header *) (tlv_val_will + 1); + break; + } + default: + { + /* advance tlv_header pointer */ + tlv_header = (struct ospf6_TLV_header *) + ((char *)tlv_header + (ntohs(tlv_header->len)+sizeof(tlv_header))); + break; + } + } + } + + if (tlv_val_relay) + { + if (OSPF6_TLV_REL_OPT_ISSET(tlv_val_relay->bits,OSPF6_TLV_REL_OPT_A ,0)) + on->Relay_Abit = true; + else + on->Relay_Abit = false; + + if (OSPF6_TLV_REL_OPT_ISSET(tlv_val_relay->bits,OSPF6_TLV_REL_OPT_N ,0)) + on->Relay_Nbit = true; + else + on->Relay_Nbit = false; + + if(relay_id_ptr && ospf6_is_rtrid_in_list(oi, relay_id_ptr, added_relays)) + ospf6_refresh_relay_selector(on); + } +} + +int ospf6_append_relays(struct ospf6_interface *oi, + u_char *pos, + u_char *max_pos, + boolean periodic_hello, + boolean full_neighbor_state) +{ + plistnode n; + int data_size = 0, added_relays = 0, active_size = 0, drop_size = 0; + struct ospf6_relay *relay; + char buffer1[iobuflen], buffer2[iobuflen]; + + n = listhead(oi->relay_list); + while(n) + { + relay = (struct ospf6_relay*) getdata(n); + nextnode(n); + + if (pos + (sizeof(struct ospf6_TLV_header) + + sizeof(struct ospf6_relay_TLV)*(data_size+1)+sizeof(relay)) >= max_pos) + { + zlog_warn ("Send HELLO: Buffer shortage on %s", + oi->interface->name); + break; + } + + if(relay->drop) + { + if (elapsed_time(relay->drop_expire_time) >= oi->dead_interval) + { + ospf6_relay_delete(oi, relay); + continue; + } + if (full_neighbor_state) + continue; //don't list dropped relays when giving full state + memcpy (buffer2+drop_size, &relay->router_id, sizeof(u_int32_t)); + drop_size += sizeof(u_int32_t); + } + else + { + if (!(relay->newly_activated || full_neighbor_state)) + continue; + if (periodic_hello) + relay->newly_activated = false; + memcpy (buffer1+active_size, &relay->router_id, sizeof(u_int32_t)); + active_size += sizeof(u_int32_t); + } + data_size = active_size + drop_size; + } + added_relays = active_size / sizeof(u_int32_t); + + if (data_size > 0) + { + struct ospf6_TLV_header tlv_header; + struct ospf6_relay_TLV relay_tlv; + u_char *tlv; + + relay_tlv.added = added_relays; + OSPF6_TLV_REL_OPT_CLEAR_ALL(relay_tlv.bits); + + ospf6_tlv_header_assignment(&tlv_header, + OSPF6_TLV_TYPE_RELAY, + data_size+sizeof(struct ospf6_relay_TLV)); + data_size += sizeof(sizeof(struct ospf6_TLV_header)); + data_size += sizeof(struct ospf6_relay_TLV); + + tlv = pos; + memcpy(pos, &tlv_header, sizeof(struct ospf6_TLV_header)); + pos += sizeof(struct ospf6_TLV_header); + memcpy(pos, &relay_tlv, sizeof(struct ospf6_relay_TLV)); + pos += sizeof(struct ospf6_relay_TLV); + if (active_size) + { + memcpy(pos, buffer1, active_size); + pos += active_size; + } + if (drop_size) + memcpy(pos, buffer2, drop_size); + } + return data_size; +} + +int ospf6_create_neighbor_list(struct ospf6_interface *oi, + u_char *sendbuf, + u_char *position, + boolean full_neighbor_state) +{ + plistnode n; + int data_size = 0; + struct ospf6_neighbor *on; + + for (n = listhead(oi->neighbor_list); n; nextnode(n)) + { + on = (struct ospf6_neighbor *) getdata(n); + + if (on->state < OSPF6_NEIGHBOR_INIT) + continue; +#ifdef OSPF6_MANET_DIFF_HELLO + if (!(full_neighbor_state || on->below_exchange)) +#else + if (!(full_neighbor_state)) +#endif //OSPF6_MANET_DIFF_HELLO + continue; + + if (position - sendbuf + sizeof (u_int32_t) > oi->ifmtu) + { + if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_HELLO, SEND)) + { + zlog_info ("sending Hello message: exceeds I/F MTU"); + break; + } + } + memcpy (position, &on->router_id, sizeof (u_int32_t)); + position += sizeof (u_int32_t); + data_size += sizeof (u_int32_t); + } + return data_size; +} + +#ifdef OSPF6_MANET_DIFF_HELLO +boolean ospf6_is_scs_wrap_around(u_int16_t old_scs_num, u_int16_t new_scs_num) +{ + if (old_scs_num == MAX_SCS_NUMBER && new_scs_num == 0) + return true; + return false; +} + +int ospf6_append_scs(struct ospf6_interface *oi, + char *opt, + u_char *pos) +{ + struct ospf6_TLV_header tlv_header; + struct ospf6_scs_TLV scs_tlv; + int data_size = 0; + + scs_tlv.number = htons(oi->scs_num); + scs_tlv.bits[0] = opt[0]; + scs_tlv.bits[1] = opt[1]; + data_size += sizeof(struct ospf6_scs_TLV); + + ospf6_tlv_header_assignment(&tlv_header, + OSPF6_TLV_TYPE_SCS, + sizeof(struct ospf6_scs_TLV)); + data_size += sizeof(struct ospf6_TLV_header); + + memcpy(pos, &tlv_header, sizeof(struct ospf6_TLV_header)); + memcpy(pos + sizeof(struct ospf6_TLV_header), + &scs_tlv, sizeof(struct ospf6_scs_TLV)); + + return data_size; +} + +int ospf6_append_drop_neighbors(struct ospf6_interface *oi, + u_char *pos, + u_char *max_pos, + boolean *set_N) +{ + plistnode n; + struct drop_neighbor *drop_neigh; + char drop_tlv[iobuflen]; + int data_size = 0; + + n = listhead(oi->drop_neighbor_list); + while(n) + { + drop_neigh = (struct drop_neighbor *) getdata (n); + nextnode(n); + //Chandra03 3.3.6.2 paragraph 1 bullet 4 + if (elapsed_time(drop_neigh->expire_time) > oi->dead_interval) + { + ospf6_drop_neighbor_delete(oi, drop_neigh); + continue; + } + if (pos + (sizeof(struct ospf6_TLV_header) + + sizeof(u_int32_t) * (data_size+1)) >= max_pos) + { + zlog_warn ("Send HELLO: Buffer shortage on %s", + oi->interface->name); + break; + } + //Chandra03 3.3.6.2 paragraph 1 bullet 4 + if (!drop_neigh->first) + *set_N = true; + drop_neigh->first = false; + memcpy (drop_tlv + data_size, &(drop_neigh->router_id), sizeof(u_int32_t)); + data_size += sizeof(u_int32_t); + } + + if (data_size > 0) + { + struct ospf6_TLV_header tlv_header; + ospf6_tlv_header_assignment(&tlv_header, + OSPF6_TLV_TYPE_NEIGHDROP, + data_size); + memcpy(pos, &tlv_header, sizeof(struct ospf6_TLV_header)); + memcpy(pos + sizeof(struct ospf6_TLV_header), drop_tlv, data_size); + + data_size += sizeof(struct ospf6_TLV_header); + } + return data_size; +} + +int ospf6_append_request(struct ospf6_interface *oi, + u_char *pos, + u_char *max_pos, + char *scs_tlv_option) +{ + int data_size = 0; + plistnode n; + struct ospf6_neighbor *on; + char request_tlv[iobuflen]; + + for (n = listhead(oi->neighbor_list); n; nextnode(n)) + { + on = (struct ospf6_neighbor *) getdata(n); + + if (on->state < OSPF6_NEIGHBOR_INIT) + continue; + + if (on->request == false) + continue; + + if (pos + (sizeof(struct ospf6_TLV_header) + + sizeof(u_int32_t) * (data_size+1)) >= max_pos) + { + zlog_warn ("Send HELLO: Buffer shortage on %s", + oi->interface->name); + break; + } + on->request = false; + memcpy (request_tlv + data_size, &(on->router_id), sizeof(u_int32_t)); + data_size += sizeof(u_int32_t); + } + + if (data_size > 0) + { + struct ospf6_TLV_header tlv_header; + ospf6_tlv_header_assignment(&tlv_header, + OSPF6_TLV_TYPE_REQUEST, + data_size); + memcpy(pos, &tlv_header, sizeof(struct ospf6_TLV_header)); + memcpy(pos + sizeof(struct ospf6_TLV_header), request_tlv, data_size); + + data_size += sizeof(struct ospf6_TLV_header); + OSPF6_TLV_SCS_OPT_SET(scs_tlv_option, OSPF6_TLV_SCS_OPT_R, 0); + } + return data_size; +} + +void ospf6_mpr_process_diff_TLVs(struct ospf6_neighbor *on, + struct ospf6_LLS_header * lls_ptr, + int seenrtrnum, + char *scs_tlv_option, + boolean *twoway, + boolean *send_mhello) +{ + struct ospf6_interface *oi = on->ospf6_if; + u_int16_t old_scs_num, new_scs_num = 0; + u_int32_t *relay_id_ptr=NULL, *drop_relay_id_ptr=NULL; + u_int32_t *tlv_val_req=NULL, *tlv_val_full=NULL, *tlv_val_drop = NULL; + int length_lls=0, tlv_val_len, added_relays=0, dropped_relays=0; + int rtrdropnum=0, reqnum=0, fullnum=0; + struct ospf6_TLV_header *tlv_header = NULL; + struct ospf6_options_TLV *tlv_val_opt = NULL; + struct ospf6_scs_TLV *tlv_val_scs = NULL; + struct ospf6_relay_TLV *tlv_val_relay = NULL; + struct ospf6_will_TLV *tlv_val_will = NULL; + + old_scs_num = on->scs_num; + length_lls = ntohs(lls_ptr->len) * 4 - sizeof(struct ospf6_LLS_header); + tlv_header = (struct ospf6_TLV_header *) (lls_ptr + 1); + while (length_lls > 0) + { + tlv_val_len = ntohs(tlv_header->len); + length_lls -= (sizeof(tlv_header) + tlv_val_len); + switch (ntohs(tlv_header->type)) + { + case OSPF6_TLV_TYPE_OPTIONS: + assert(!tlv_val_opt); //Malformed packet: 2 option TLVs + tlv_val_opt = (struct ospf6_options_TLV *) (tlv_header + 1); + tlv_header = (struct ospf6_TLV_header *) (tlv_val_opt + 1); + break; + case OSPF6_TLV_TYPE_SCS: + assert(!tlv_val_scs); //Malformed packet: 2 SCS TLVs + tlv_val_scs = (struct ospf6_scs_TLV *) (tlv_header + 1); + new_scs_num = ntohs(tlv_val_scs->number); + if (on->set_scs_num) + { + on->set_scs_num = false; + old_scs_num = new_scs_num-2; + on->scs_num = old_scs_num; + } + tlv_header = (struct ospf6_TLV_header *) (tlv_val_scs + 1); + break; + case OSPF6_TLV_TYPE_NEIGHDROP: + { + assert(!tlv_val_drop); //Malformed packet: 2 DROP TLVs + tlv_val_drop = (u_int32_t*) (tlv_header + 1); + rtrdropnum = ntohs(tlv_header->len)/4; + tlv_header = (struct ospf6_TLV_header *) (tlv_val_drop + rtrdropnum); + break; + } + case OSPF6_TLV_TYPE_REQUEST: + assert(!tlv_val_req); //Malformed packet: 2 Request TLVs + tlv_val_req = (u_int32_t*) (tlv_header + 1); + reqnum = ntohs(tlv_header->len)/4; + tlv_header = (struct ospf6_TLV_header *) (tlv_val_req + reqnum); + break; + case OSPF6_TLV_TYPE_FULL: + assert(!tlv_val_full); //Malformed packet: 2 Request TLVs + tlv_val_full = (u_int32_t*) (tlv_header + 1); + fullnum = ntohs(tlv_header->len)/4; + tlv_header = (struct ospf6_TLV_header *) (tlv_val_full + fullnum); + break; + case OSPF6_TLV_TYPE_RELAY: + assert(!tlv_val_relay); //Malformed packet: 2 RELAY TLVs + tlv_val_relay = (struct ospf6_relay_TLV*) (tlv_header + 1); + added_relays = tlv_val_relay->added; + relay_id_ptr = (u_int32_t *) (tlv_val_relay + 1); + dropped_relays = (ntohs(tlv_header->len)-sizeof(tlv_val_relay)) / + sizeof(u_int32_t) - added_relays; + if (dropped_relays) + drop_relay_id_ptr = (u_int32_t *) (tlv_val_relay+(1 + added_relays)); + + tlv_header = (struct ospf6_TLV_header *) + (relay_id_ptr + (added_relays + dropped_relays)); + break; + case OSPF6_TLV_TYPE_WILLINGNESS: + assert(!tlv_val_will); //Malformed packet: 2 willingness TLVs + tlv_val_will = (struct ospf6_will_TLV*) (tlv_header + 1); + tlv_header = (struct ospf6_TLV_header *) (tlv_val_will + 1); + break; + default: + /* advance tlv_header pointer */ + tlv_header = (struct ospf6_TLV_header *) + ((char *)tlv_header + (ntohs(tlv_header->len)+sizeof(tlv_header))); + break; + } + } + + /* SCS processing */ + if (tlv_val_scs) + { + /* Chandra03 3.3.8.2: Receiving Hellos with the R bit set*/ + if (OSPF6_TLV_SCS_OPT_ISSET(tlv_val_scs->bits,OSPF6_TLV_SCS_OPT_R,0)) + { + if (reqnum == 0) //requesting state from all neighbors + on->ospf6_if->full_state = true; + else if (reqnum > 0 && ospf6_is_rtrid_in_list(oi, tlv_val_req, reqnum)) + on->ospf6_if->full_state = true; + } + + /* Chandra03 3.3.8.3 paragraph 1 bullet 1*/ + if (new_scs_num == old_scs_num) + { + if (on->state >= OSPF6_NEIGHBOR_TWOWAY) + *twoway = true; + if (ospf6_lookup_relay_selector(oi, on->router_id)) + ospf6_refresh_relay_selector(on); + } + /* Chandra03 3.3.8.3: Receiving Hello with the FS bit set*/ + else if (OSPF6_TLV_SCS_OPT_ISSET(tlv_val_scs->bits,OSPF6_TLV_SCS_OPT_FS,0)) + { + +/* XXX I don't understand why you would not want full state when + you currently have a different SCS number. + If the SCS number is the same then no processing is done anyway. + if (fullnum > 0 && !ospf6_is_rtrid_in_list(oi, tlv_val_req, reqnum)) + { //full state is not for this neighbor + //twoway will be set in mhello_recv() because full state + if (ospf6_lookup_relay_selector(oi, on->router_id)) + ospf6_refresh_relay_selector(on); + return; + } +*/ + /* Chandra03 3.3.8.3 paragraph 1 bullet 2*/ + on->scs_num = new_scs_num; + if (*twoway) // router_id found in neighbor list + { + struct ospf6_relay_selector *relay_sel; + if (tlv_val_relay && relay_id_ptr && + ospf6_is_rtrid_in_list(oi, relay_id_ptr, added_relays)) + { + ospf6_refresh_relay_selector(on); + } + else if((relay_sel=ospf6_lookup_relay_selector(oi, on->router_id))) + { + ospf6_relay_selector_delete(oi, relay_sel); + } + } + } + else if (on->state >= OSPF6_NEIGHBOR_TWOWAY || *twoway) + { + *twoway = true; + /* Chandra03 3.3.8 paragraph 2 */ + if (new_scs_num < old_scs_num && + !ospf6_is_scs_wrap_around(old_scs_num, new_scs_num)) + { + on->request = true; + } + /* Chandra03 3.3.8 paragraph 3*/ + else if (ospf6_is_scs_wrap_around(old_scs_num, new_scs_num) || + new_scs_num == old_scs_num + 1) + { + boolean increment_scs = false; + + /* Chandra03 3.3.8 paragraph 3 bullet 1*/ + if (seenrtrnum > 0) + increment_scs = true; + + /* Chandra03 3.3.8 paragraph 3 bullet 3*/ + if (rtrdropnum > 0 && tlv_val_drop && + ospf6_is_rtrid_in_list(oi, tlv_val_drop, rtrdropnum)) + { + /*thread_add_event (master, neighbor_change, on->ospf6_if, 0); + listnode_delete (on->ospf6_if->neighbor_list, on); + ospf6_neighbor_delete (on); */ //BOEING Draft Change + *twoway = false; + return; + } + /* Chandra03 3.3.8 paragraph 3 bullet 3*/ + else if (rtrdropnum > 0 && tlv_val_drop) + increment_scs = true; + + /* Chandra03 3.3.8 paragraph 3 bullet 4*/ + if (tlv_val_relay && ((added_relays + dropped_relays) > 0)) + { + increment_scs = true; + if(drop_relay_id_ptr && + ospf6_is_rtrid_in_list(oi, drop_relay_id_ptr, dropped_relays)) + { + struct ospf6_relay_selector *relay_sel; + if((relay_sel=ospf6_lookup_relay_selector(oi, on->router_id))) + ospf6_relay_selector_delete(oi, relay_sel); + } + else if (relay_id_ptr && + ospf6_is_rtrid_in_list(oi, relay_id_ptr, added_relays)) + ospf6_refresh_relay_selector(on); + else if (ospf6_lookup_relay_selector(oi, ospf6->router_id)) + ospf6_refresh_relay_selector(on); + } + + //Chandra03 3.3.8.1 Receiving hellos with the N bit set + if (OSPF6_TLV_SCS_OPT_ISSET(tlv_val_scs->bits,OSPF6_TLV_SCS_OPT_N,0)) + { + on->request = true; + } + else if (increment_scs) + on->scs_num = ospf6_increment_scs(on->scs_num); + else + { /* Chandra03 3.3.8 paragraph 3 bullet 5*/ + on->request = true; + } + } + /* Chandra03 3.3.8 paragraph 4 */ + else if (new_scs_num > old_scs_num + 1) + { + on->request = true; + } + } + } +} +#endif// OSPF6_MANET_DIFF_HELLO +#endif //OSPF6_MANET_MPR_FLOOD + +#ifdef OSPF6_MANET_MDR_FLOOD +// Ogierv3 10.1 +// DNL list added for Ogierv7. +u_int ospf6_mdr_create_neighbor_lists(struct ospf6_interface *oi, + u_char *pos, u_char *max_pos, + u_int *num_hnl, u_char *hnl, + u_int *num_rnl, u_char *rnl, + u_int *num_lnl, u_char *lnl, + u_int *num_dnl, u_char *dnl, + boolean diff) +{ + plistnode n; + struct ospf6_neighbor *on; + u_int lls_length=0, lls_header=0, seq_tlv=0; + u_int hnl_length=0, rnl_length=0, lnl_length=0; + u_int dnl_length=0; + int size_tlv_head = sizeof(struct ospf6_TLV_header); + int size_rid = sizeof(u_int32_t); + + lls_header = sizeof(struct ospf6_LLS_header); +#ifdef OSPF6_MANET_DIFF_HELLO + if (oi->diff_hellos) + seq_tlv = sizeof(struct ospf6_TLV_header) + sizeof(struct ospf6_seq_TLV); +#endif //OSPF6_MANET_DIFF_HELLO + lls_length = lls_header + seq_tlv; + + for (n = listhead(oi->neighbor_list); n; nextnode(n)) + { + on = (struct ospf6_neighbor *) getdata(n); + + if (on->state <= OSPF6_NEIGHBOR_INIT) + { + if (((*num_hnl) && pos+lls_length+size_rid >= max_pos) || + (!(*num_hnl) && pos+lls_length+size_tlv_head+size_rid >= max_pos)) + { + zlog_warn ("Send HELLO: Buffer shortage on %s", oi->interface->name); + break; + } +#ifdef OSPF6_MANET_DIFF_HELLO + if (!diff || (diff && on->changed_hsn + oi->HelloRepeatCount > oi->hsn)) +#endif //OSPF6_MANET_DIFF_HELLO + { + memcpy (hnl, &on->router_id, size_rid); + hnl += size_rid; + (*num_hnl)++; + hnl_length = size_tlv_head + size_rid*(*num_hnl); + } + } + else + { + if (((*num_rnl) && pos+lls_length+size_rid >= max_pos) || + (!(*num_rnl) && pos+lls_length+size_tlv_head+size_rid >= max_pos)) + { + zlog_warn ("Send HELLO: Buffer shortage on %s", oi->interface->name); + break; + } +#ifdef OSPF6_MANET_DIFF_HELLO + // dependent neighbors are included in DNL and therefore + // are not included in the RNL in a full Hello. + if ((!diff && !on->dependent) || + (diff && (on->changed_hsn + oi->HelloRepeatCount > oi->hsn || + !on->reverse_2way))) +#endif //OSPF6_MANET_DIFF_HELLO + { + memcpy (rnl, &on->router_id, size_rid); + rnl += size_rid; + (*num_rnl)++; + rnl_length = size_tlv_head + size_rid*(*num_rnl); + } + } + // Create DNL + if (oi->mdr_level >= OSPF6_BMDR) + { + if (on->dependent && on->state > OSPF6_NEIGHBOR_INIT) + { + memcpy (dnl, &on->router_id, size_rid); + dnl += size_rid; + (*num_dnl)++; + dnl_length = size_tlv_head + size_rid*(*num_dnl); + } + } + lls_length = lls_header + seq_tlv + hnl_length + rnl_length + + dnl_length; + } + +#ifdef OSPF6_MANET_DIFF_HELLO + if (oi->lnl && diff) + { + struct ospf6_lnl_element *lnl_element; + n = listhead(oi->lnl); + while(n) + { + lnl_element = (struct ospf6_lnl_element *) getdata(n); + nextnode(n); + + if (lnl_element->hsn + oi->HelloRepeatCount <= oi->hsn) + { + ospf6_mdr_delete_lnl_element(oi, lnl_element); + continue; + } + + if (((*num_lnl) && pos+lls_length+size_rid >= max_pos) || + (!(*num_lnl) && pos+lls_length+size_tlv_head+size_rid >= max_pos)) + { + zlog_warn ("Send HELLO: Buffer shortage on %s", oi->interface->name); + break; + } + memcpy (lnl, &lnl_element->id, size_rid); + lnl += size_rid; + (*num_lnl)++; + lnl_length = size_tlv_head + size_rid*(*num_lnl); + } + lls_length = lls_header + seq_tlv + hnl_length + rnl_length + lnl_length + + dnl_length; + } +#endif //OSPF6_MANET_DIFF_HELLO + + if (lls_length == sizeof(struct ospf6_LLS_header)) + return 0; + return lls_length; +} + +int ospf6_append_mdr_neigh_tlv(u_char *pos, u_int n, u_char *rid, + u_int16_t type) +{ + struct ospf6_TLV_header tlv_header; + if (n <= 0) + return 0; + ospf6_tlv_header_assignment(&tlv_header, type, sizeof(u_int32_t) * n); + memcpy(pos, &tlv_header, sizeof(struct ospf6_TLV_header)); + memcpy(pos + sizeof(struct ospf6_TLV_header), rid, sizeof(u_int32_t) * n); + + return (sizeof(struct ospf6_TLV_header) + sizeof(u_int32_t) * n); +} + +#ifdef OSPF6_MANET_DIFF_HELLO +int ospf6_append_mdr_seq_tlv(struct ospf6_interface *oi, u_char *pos) +{ + struct ospf6_TLV_header tlv_header; + struct ospf6_seq_TLV seq_tlv; + + seq_tlv.number = htons(oi->hsn++); + OSPF6_TLV_HS_OPT_CLEAR_ALL(seq_tlv.bits); + ospf6_tlv_header_assignment(&tlv_header, OSPF6_TLV_TYPE_HS, 4); + memcpy(pos, &tlv_header, sizeof(struct ospf6_TLV_header)); + + + memcpy(pos + sizeof(struct ospf6_TLV_header), &seq_tlv, sizeof(seq_tlv)); + + return (sizeof(struct ospf6_TLV_header) + sizeof(seq_tlv)); +} +#endif //OSPF6_MANET_DIFF_HELLO + +boolean ospf6_mdr_process_hello_TLVs(struct ospf6_neighbor *on, + struct ospf6_LLS_header *lls_ptr, + boolean diff, boolean *rnl_changed) +{ + struct ospf6_interface *oi = on->ospf6_if; + int length_lls = 0, tlv_val_len; + boolean twoway = false; + u_int i, num_hnl=0, num_rnl=0, num_lnl=0; + u_int num_dnl=0; + struct ospf6_TLV_header *tlv_header = NULL; +#ifdef OSPF6_MANET_DIFF_HELLO + struct ospf6_seq_TLV *seq_tlv = NULL; + boolean insufficienthellosreceived = false; + u_int16_t prev_seq=0; +#endif //OSPF6_MANET_DIFF_HELLO + boolean in_rnl; + plistnode n; + u_int32_t *nid; + u_int32_t *hnl = NULL; + u_int32_t *rnl = NULL; + u_int32_t *lnl = NULL; + u_int32_t *dnl = NULL; // Added for Ogierv7. + *rnl_changed = false; +#ifdef OSPF6_MANET_MDR_LQ + boolean link_quality = false; +#endif //OSPF6_MANET_MDR_LQ + + length_lls = ntohs(lls_ptr->len) * 4 - sizeof(struct ospf6_LLS_header); + tlv_header = (struct ospf6_TLV_header *) (lls_ptr + 1); + while (length_lls > 0) + { + tlv_val_len = ntohs(tlv_header->len); + length_lls -= (sizeof(tlv_header) + tlv_val_len); + switch (ntohs(tlv_header->type)) + { + case OSPF6_TLV_TYPE_HNL: + { + assert(!hnl); //Malformed packet: 2 option TLVs + hnl = (u_int32_t *) (tlv_header + 1); + num_hnl = ntohs(tlv_header->len)/4; + tlv_header = (struct ospf6_TLV_header *) (hnl + num_hnl); + break; + } + case OSPF6_TLV_TYPE_RNL: + { + assert(!rnl); //Malformed packet: 2 option TLVs + rnl = (u_int32_t *) (tlv_header + 1); + num_rnl = ntohs(tlv_header->len)/4; + tlv_header = (struct ospf6_TLV_header *) (rnl + num_rnl); + break; + } + case OSPF6_TLV_TYPE_DNL: // Added for Ogierv7. + { + assert(!dnl); //Malformed packet: 2 option TLVs + dnl = (u_int32_t *) (tlv_header + 1); + num_dnl = ntohs(tlv_header->len)/4; + tlv_header = (struct ospf6_TLV_header *) (dnl + num_dnl); + break; + } + +#ifdef OSPF6_MANET_DIFF_HELLO + case OSPF6_TLV_TYPE_LNL: + { + assert(!lnl); //Malformed packet: 2 option TLVs + lnl = (u_int32_t *) (tlv_header + 1); + num_lnl = ntohs(tlv_header->len)/4; + tlv_header = (struct ospf6_TLV_header *) (lnl + num_lnl); + break; + } + case OSPF6_TLV_TYPE_HS: + { + assert(!seq_tlv); //Malformed packet: 2 option TLVs + seq_tlv = (struct ospf6_seq_TLV *) (tlv_header + 1); + tlv_header = (struct ospf6_TLV_header *) (seq_tlv + 1); + break; + } +#endif //OSPF6_MANET_DIFF_HELLO + default: + { + /* advance tlv_header pointer */ + tlv_header = (struct ospf6_TLV_header *) + ((char *)tlv_header + (ntohs(tlv_header->len)+sizeof(tlv_header))); + break; + } + } + } + + // DNL list is always full whether or not Hello is differential. + // If Hello does not contain DNL, then it has no dependent nbrs. + on->dependent_selector = false; + for (i = 0; i < num_dnl; i++) + if (dnl[i] == oi->area->ospf6->router_id) + on->dependent_selector = true; + +#ifdef OSPF6_MANET_DIFF_HELLO + if (seq_tlv) + { + prev_seq = on->hsn; + on->hsn = ntohs(seq_tlv->number); + } + + //differential hello + if (diff) + { + boolean found = false; + if (!seq_tlv) + { //sequence #s should be found in all hellos when running diff hellos + printf("Error: seq_tlv should exist\n"); + exit(0); + } + + if (on->state > OSPF6_NEIGHBOR_DOWN && + on->hsn > prev_seq + oi->HelloRepeatCount) + insufficienthellosreceived = true; + + //check hello LNL + for (i = 0; i < num_lnl; i++) + { + if (!found && lnl[i] == oi->area->ospf6->router_id) + { + twoway = false; + found = true; + // reverse_2way keeps track of whether neighbor + // considers me to be 2-way. + on->reverse_2way = false; + continue; + } + if (ospf6_mdr_delete_neighbor(on->rnl, lnl[i])) + *rnl_changed = true; + } + //check hello HNL + for (i = 0; i < num_hnl; i++) + { + if (!found && hnl[i] == oi->area->ospf6->router_id) + { + twoway = true; + found = true; + // Neighbor no longer considers me to be 2-way. + // So let him know that I see him. + if (on->reverse_2way) + { + on->reverse_2way = false; //include neighbor in next hello + //on->changed_hsn = oi->hsn; // Include neighbor in next few hellos. + } + continue; + } + if (ospf6_mdr_delete_neighbor(on->rnl, hnl[i])) + *rnl_changed = true; + } + //check hello RNL + for (i = 0; i < num_rnl; i++) + { + if (!found && rnl[i] == oi->area->ospf6->router_id) + { + twoway = true; + found = true; + on->reverse_2way = true; +#ifdef OSPF6_MANET_MDR_LQ + link_quality = true; +#endif //OSPF6_MANET_MDR_LQ + continue; + } + if (!ospf6_mdr_lookup_neighbor(on->rnl, rnl[i])) + { + ospf6_mdr_add_neighbor(on->rnl, rnl[i]); + *rnl_changed = true; + } + } + + //keep same state - not found in any list + // Insufficient hellos implies oneway if router does not find itself. + if (!found && on->state >= OSPF6_NEIGHBOR_TWOWAY && + !insufficienthellosreceived) + { + twoway = true; +#ifdef OSPF6_MANET_MDR_LQ + if(on->reverse_2way) + link_quality = true; +#endif //OSPF6_MANET_MDR_LQ + } + +#ifdef OSPF6_MANET_MDR_LQ + ospf6_mdr_update_link_quality(on, link_quality); +#endif //OSPF6_MANET_MDR_LQ + return twoway; + } +#endif //OSPF6_MANET_DIFF_HELLO + + //not a differential hello + //this code is for the periodic full hello within diff hellos + // RNL need not include any neighbor that is in DNL list, + // so must check both lists. + + in_rnl = ospf6_is_rtrid_in_list(oi, rnl, num_rnl) || + ospf6_is_rtrid_in_list(oi, dnl, num_dnl); + if (ospf6_is_rtrid_in_list(oi, hnl, num_hnl)) + { + twoway = true; + if (on->reverse_2way) + { + on->reverse_2way = false; //include neighbor in next hello + //on->changed_hsn = oi->hsn; // Include neighbor in next few hellos. + } + } + else if (in_rnl) + { + twoway = true; + on->reverse_2way = true; +#ifdef OSPF6_MANET_MDR_LQ + link_quality = true; +#endif //OSPF6_MANET_MDR_LQ + } + else // not in any list of full hello + { + twoway = false; + on->reverse_2way = false; + } + + // Must compare old and new versions of on->rnl to determine + // whether rnl changed. For speed, we require order to be the same. + if (in_rnl && on->rnl->count == 0 && num_rnl == 1) + {} + else if (in_rnl && on->rnl->count != num_rnl-1) + *rnl_changed = true; + else if (!in_rnl && on->rnl->count == 0 && num_rnl == 0) + {} + else if (!in_rnl && on->rnl->count != num_rnl) + *rnl_changed = true; + else + { + for (i = 0; i < num_rnl; i++) + { + //must skip my own ID since it is not in the rnl list + if (rnl[i] == oi->area->ospf6->router_id) + continue; + *rnl_changed = true; + for (n = listhead(on->rnl); n; nextnode(n)) + { + nid = (u_int32_t *) getdata(n); + if (*nid == rnl[i]) + { + *rnl_changed = false; + break; + } + } + if(*rnl_changed) + break; + } + } + + ospf6_mdr_delete_all_neighbors(on->rnl); + if (!on->Report2Hop) + { + on->Report2Hop = true; // full hello received + *rnl_changed = true; // This affects CDS calculation. + } + for (i = 0; i < num_rnl; i++) + { + if (rnl[i] == oi->area->ospf6->router_id) + { + twoway = true; + continue; + } + ospf6_mdr_add_neighbor(on->rnl, rnl[i]); + } + // Repeat for DNL list. + // RNL is actually the union of the 2 lists. + for (i = 0; i < num_dnl; i++) + { + if (dnl[i] == oi->area->ospf6->router_id) + { + twoway = true; + continue; + } + // Add dependent nbr to RNL. + ospf6_mdr_add_neighbor(on->rnl, dnl[i]); + } +#ifdef OSPF6_MANET_MDR_LQ + if(oi->diff_hellos) + ospf6_mdr_update_link_quality(on, link_quality); +#endif //OSPF6_MANET_MDR_LQ + return twoway; +} + +int ospf6_append_mdr_tlv(struct ospf6_interface *oi, u_char *p) +{ + int data_size = 0; + struct ospf6_TLV_header tlv_header; + struct ospf6_mdr_TLV mdr_tlv; + + //find dr, bdr, or parents + if (oi->mdr_level == OSPF6_MDR) + { + mdr_tlv.id1 = oi->area->ospf6->router_id; + if (oi->parent) + mdr_tlv.id2 = oi->parent->router_id; + else + mdr_tlv.id2 = 0; + } + else if (oi->mdr_level == OSPF6_BMDR) + { + mdr_tlv.id2 = oi->area->ospf6->router_id; + if (oi->parent) + mdr_tlv.id1 = oi->parent->router_id; + else + mdr_tlv.id1 = 0; + } + else + { + mdr_tlv.id1 = (oi->parent ? oi->parent->router_id : 0); + mdr_tlv.id2 = (oi->bparent ? oi->bparent->router_id : 0); + } + + ospf6_tlv_header_assignment(&tlv_header, OSPF6_TLV_TYPE_DD, sizeof(mdr_tlv)); + data_size += sizeof(struct ospf6_TLV_header); + memcpy(p, &tlv_header, sizeof(struct ospf6_TLV_header)); + + data_size += sizeof(struct ospf6_mdr_TLV); + memcpy(p + sizeof(struct ospf6_TLV_header), &mdr_tlv, sizeof(mdr_tlv)); + + return data_size; +} + +// Returns true if on->mdr_level changed. +boolean ospf6_mdr_process_mdr_TLVs(struct ospf6_neighbor *on, + struct ospf6_LLS_header *lls_ptr) +{ + int length_lls = 0, tlv_val_len; + struct ospf6_TLV_header *tlv_header = NULL; + struct ospf6_mdr_TLV *dd = NULL; + boolean mdr_level_changed = false; + + length_lls = ntohs(lls_ptr->len) * 4 - sizeof(struct ospf6_LLS_header); + tlv_header = (struct ospf6_TLV_header *) (lls_ptr + 1); + while (length_lls > 0) + { + tlv_val_len = ntohs(tlv_header->len); + length_lls -= (sizeof(tlv_header) + tlv_val_len); + switch (ntohs(tlv_header->type)) + { + case OSPF6_TLV_TYPE_DD: + { + assert(!dd); //Malformed packet: 2 option TLVs + dd = (struct ospf6_mdr_TLV *) (tlv_header + 1); + tlv_header = (struct ospf6_TLV_header *) (dd+1); + break; + } + default: + { + /* advance tlv_header pointer */ + tlv_header = (struct ospf6_TLV_header *) + ((char *)tlv_header + (ntohs(tlv_header->len)+sizeof(tlv_header))); + break; + } + } + } + if (dd) + { + mdr_level_changed = ospf6_mdr_set_mdr_level(on, dd->id1, dd->id2); + if (on->mdr_level == OSPF6_MDR || on->mdr_level == OSPF6_BMDR) + on->dependent_selector = 1; // For need_adjacency(). + } + return mdr_level_changed; +} +#endif // OSPF6_MANET_MDR_FLOOD + + +//################## PRINTING SECTION ######################## +void ospf6_mhello_print (struct ospf6_header *oh, int len) +{ + ospf6_hello_print(oh); + +#if defined(OSPF6_MANET_MPR_FLOOD) || defined (OSPF6_MANET_MDR_FLOOD) +{ + struct ospf6_hello *hello; + struct ospf6_LLS_header * lls_ptr; + struct ospf6_TLV_header *tlv_header; + int seenrtrnum = 0, router_id_space = 0; + u_int32_t *router_id_ptr; + int length_lls = 0, tlv_len=0; + + hello = (struct ospf6_hello *) + ((caddr_t) oh + sizeof (struct ospf6_header)); + + /* set pointer positions */ + router_id_space = ntohs(oh->length) - + sizeof(struct ospf6_header) - sizeof(struct ospf6_hello); + seenrtrnum = router_id_space / sizeof(u_int32_t); + router_id_ptr = (u_int32_t *) (hello + 1); + lls_ptr = (struct ospf6_LLS_header *) (router_id_ptr + seenrtrnum); + + /* process TLVs */ + /* set LLS pointer */ + if (!(OSPF6_OPT_ISSET(hello->options, OSPF6_OPT_L,1) && lls_ptr)) + return; + if (ntohs(oh->length) >= len) + return; //LLS flag lied that data exists beyond OSPF packet + + length_lls = ntohs(lls_ptr->len) * 4 - sizeof(struct ospf6_LLS_header); + tlv_header = (struct ospf6_TLV_header *) (lls_ptr + 1); + + while(length_lls) + { + print_tlv(tlv_header, true); + tlv_len = sizeof(tlv_header) + ntohs(tlv_header->len); + length_lls -= tlv_len; + tlv_header = (struct ospf6_TLV_header *) ((char *) tlv_header + tlv_len); + } +} +#endif //OSPF6_MANET_MPR_FLOOD || OSPF6_MANET_MDR_FLOOD +} + +void print_tlv(struct ospf6_TLV_header *tlv_header, boolean log) +{ + int i; + if (log) + zlog_info(" TLV len:%d type:", ntohs(tlv_header->len)); + else + printf(" TLV len:%d type:", ntohs(tlv_header->len)); + + switch (ntohs(tlv_header->type)) + { + case OSPF6_TLV_TYPE_OPTIONS: + { + struct ospf6_options_TLV *tlv_val_opt; + tlv_val_opt = (struct ospf6_options_TLV *) (tlv_header + 1); + if (log) + zlog_info(" OPTIONS-%x %x %x %x", tlv_val_opt->options[0], + tlv_val_opt->options[1], tlv_val_opt->options[2], + tlv_val_opt->options[3]); + else + printf("OPTIONS-%x %x %x %x\n", tlv_val_opt->options[0], + tlv_val_opt->options[1], tlv_val_opt->options[2], + tlv_val_opt->options[3]); + break; + } +#ifdef OSPF6_MANET_DIFF_HELLO + case OSPF6_TLV_TYPE_SCS: + { + struct ospf6_scs_TLV *tlv_val_scs; + tlv_val_scs = (struct ospf6_scs_TLV *) (tlv_header + 1); + if (log) + zlog_info(" SCS-scs# %x, Bits R:%d, FS:%d, N:%d", + ntohs(tlv_val_scs->number), + (OSPF6_TLV_SCS_OPT_ISSET(tlv_val_scs->bits, OSPF6_TLV_SCS_OPT_R, 0)?1:0), + (OSPF6_TLV_SCS_OPT_ISSET(tlv_val_scs->bits, OSPF6_TLV_SCS_OPT_FS, 0)?1:0), + (OSPF6_TLV_SCS_OPT_ISSET(tlv_val_scs->bits, OSPF6_TLV_SCS_OPT_N, 0)?1:0)); + else + printf("SCS-scs# %x, Bits R:%d, FS:%d, N:%d\n", + ntohs(tlv_val_scs->number), + (OSPF6_TLV_SCS_OPT_ISSET(tlv_val_scs->bits, OSPF6_TLV_SCS_OPT_R, 0)?1:0), + (OSPF6_TLV_SCS_OPT_ISSET(tlv_val_scs->bits, OSPF6_TLV_SCS_OPT_FS, 0)?1:0), + (OSPF6_TLV_SCS_OPT_ISSET(tlv_val_scs->bits, OSPF6_TLV_SCS_OPT_N, 0)?1:0)); + break; + } + case OSPF6_TLV_TYPE_NEIGHDROP: + { + u_int32_t *tlv_val_drop = NULL; + tlv_val_drop = (u_int32_t*) (tlv_header + 1); + if (log) + { + zlog_info(" NEIGHDROP-"); + for (i = 0; i < ntohs(tlv_header->len)/4; i++) + zlog_info(" %s,",ip2str(tlv_val_drop[i])); + } + else + { + printf(" NEIGHDROP-"); + for (i = 0; i < ntohs(tlv_header->len)/4; i++) + printf("%s,",ip2str(tlv_val_drop[i])); + printf("\n"); + } + break; + } + case OSPF6_TLV_TYPE_REQUEST: + { + u_int32_t *tlv_val_req = NULL; + tlv_val_req = (u_int32_t*) (tlv_header + 1); + if (log) + { + zlog_info(" REQUEST-"); + for (i = 0; i < ntohs(tlv_header->len)/4; i++) + zlog_info(" %s,",ip2str(tlv_val_req[i])); + } + else + { + printf(" REQUEST-"); + for (i = 0; i < ntohs(tlv_header->len)/4; i++) + printf("%s,",ip2str(tlv_val_req[i])); + printf("\n"); + } + break; + } + case OSPF6_TLV_TYPE_FULL: + { + u_int32_t *tlv_val_full = NULL; + tlv_val_full = (u_int32_t*) (tlv_header + 1); + if (log) + { + zlog_info(" FULL-"); + for (i = 0; i < ntohs(tlv_header->len)/4; i++) + zlog_info(" %s,",ip2str(tlv_val_full[i])); + } + else + { + printf(" FULL-"); + for (i = 0; i < ntohs(tlv_header->len)/4; i++) + printf("%s,",ip2str(tlv_val_full[i])); + printf("\n"); + } + break; + } +#endif //OSPF6_MANET_DIFF_HELLO +#ifdef OSPF6_MANET_MPR_FLOOD + case OSPF6_TLV_TYPE_RELAY: + { + struct ospf6_relay_TLV *tlv_val_relay; + u_int32_t *relay_id_ptr; + + tlv_val_relay = (struct ospf6_relay_TLV*) (tlv_header + 1); + relay_id_ptr = (u_int32_t *) (tlv_val_relay + 1); + + if (log) + { + zlog_info(" RELAY-added:%d ", tlv_val_relay->added); + for (i = 0; i < ntohs(tlv_header->len)/4-1; i++) + zlog_info(" %s,",ip2str(relay_id_ptr[i])); + } + else + { + printf("RELAY-added:%d ", tlv_val_relay->added); + for (i = 0; i < ntohs(tlv_header->len)/4-1; i++) + printf("%s,",ip2str(relay_id_ptr[i])); + printf("\n"); + } + break; + } + case OSPF6_TLV_TYPE_WILLINGNESS: + { + struct ospf6_will_TLV *tlv_val_will; + tlv_val_will = (struct ospf6_will_TLV*) (tlv_header + 1); + if (log) + zlog_info(" WILLINGNESS-%d", tlv_val_will->will); + else + printf("WILLINGNESS-%d\n", tlv_val_will->will); + break; + } +#endif //OSPF6_MANET_MPR_FLOOD +#ifdef OSPF6_MANET_MDR_FLOOD + case OSPF6_TLV_TYPE_HNL: + { + u_int32_t *tlv_val_hnl = NULL; + tlv_val_hnl = (u_int32_t*) (tlv_header + 1); + if (log) + { + zlog_info(" HNL-"); + for (i = 0; i < ntohs(tlv_header->len)/4; i++) + zlog_info(" %s,",ip2str(tlv_val_hnl[i])); + } + else + { + printf(" HNL-"); + for (i = 0; i < ntohs(tlv_header->len)/4; i++) + printf("%s,",ip2str(tlv_val_hnl[i])); + printf("\n"); + } + break; + } + case OSPF6_TLV_TYPE_RNL: + { + u_int32_t *tlv_val_rnl = NULL; + tlv_val_rnl = (u_int32_t*) (tlv_header + 1); + if (log) + { + zlog_info(" RNL-"); + for (i = 0; i < ntohs(tlv_header->len)/4; i++) + zlog_info(" %s,",ip2str(tlv_val_rnl[i])); + } + else + { + printf(" RNL-"); + for (i = 0; i < ntohs(tlv_header->len)/4; i++) + printf("%s,",ip2str(tlv_val_rnl[i])); + printf("\n"); + } + break; + } + case OSPF6_TLV_TYPE_LNL: + { + u_int32_t *tlv_val_lnl = NULL; + tlv_val_lnl = (u_int32_t*) (tlv_header + 1); + if (log) + { + zlog_info(" LNL-"); + for (i = 0; i < ntohs(tlv_header->len)/4; i++) + zlog_info(" %s,",ip2str(tlv_val_lnl[i])); + } + else + { + printf(" LNL-"); + for (i = 0; i < ntohs(tlv_header->len)/4; i++) + printf("%s,",ip2str(tlv_val_lnl[i])); + printf("\n"); + } + break; + } + case OSPF6_TLV_TYPE_DD: + { + struct ospf6_mdr_TLV *mdr_tlv; + mdr_tlv = (struct ospf6_mdr_TLV *) (tlv_header + 1); + if (log) + { + zlog_info(" DD-ID1 %s", ip2str(mdr_tlv->id1)); + zlog_info(" DD-ID2 %s", ip2str(mdr_tlv->id2)); + } + else + { + printf("DD-ID1 %s ", ip2str(mdr_tlv->id1)); + printf("%s\n", ip2str(mdr_tlv->id2)); + } + break; + } +#ifdef OSPF6_MANET_DIFF_HELLO + case OSPF6_TLV_TYPE_HS: + { + struct ospf6_seq_TLV *seq_tlv; + seq_tlv = (struct ospf6_seq_TLV *) (tlv_header + 1); + if (log) + zlog_info(" SEQ-# %x", ntohs(seq_tlv->number)); + else + printf("SEQ-# %x\n", ntohs(seq_tlv->number)); + break; + } +#endif //OSPF6_MANET_DIFF_HELLO +#endif //OSPF6_MANET_MDR_FLOOD + default: + { + if (log) + zlog_info(" %d", ntohs(tlv_header->type)); + else + printf("%d\n", ntohs(tlv_header->type)); + break; + } + } +} + +//################## END PRINTING SECTION ######################## +#endif //OSPF6_MANET + +#ifdef USER_CHECKSUM + +u_int16_t ospf6_do_checksum(struct in6_addr *saddr, struct in6_addr *daddr,struct ospf6_header *hdr) +{ + pseudo_header ph; + u_int16_t checksum; + unsigned long sum = 0; + int count; + unsigned short *p; /* 16-bit */ + + memset(&ph, 0, sizeof(pseudo_header)); + memcpy(&ph.src, saddr, sizeof(struct in6_addr)); + memcpy(&ph.dst, daddr, sizeof(struct in6_addr)); + ph.upper_len = hdr->length; + ph.nh = IPPROTO_OSPFIGP; + + + + count = sizeof(ph); /* count always even number */ + p = (unsigned short*) &ph; + + /* sum the psuedo-header */ + /* count and p are initialized above per protocol */ + while (count > 1) { + sum += *p++; + count -= 2; + } + + /* one's complement sum 16-bit words of data */ + count = ntohs(hdr->length); + p = (unsigned short*) hdr; + while (count > 1) { + sum += *p++; + count -= 2; + } + /* add left-over byte, if any */ + if (count > 0) + sum += (unsigned char)*p; + + /* Fold 32-bit sum to 16 bits */ + while (sum>>16) + sum = (sum & 0xffff) + (sum >> 16); + /* take the one's complement of the sum */ + checksum = ~sum; + + return(checksum); +} + + +#endif + diff -Naur quagga-0.98.5/ospf6d/ospf6_message.h quagga-0.98.5-manet/ospf6d/ospf6_message.h --- quagga-0.98.5/ospf6d/ospf6_message.h 2004-10-10 05:54:58.000000000 -0700 +++ quagga-0.98.5-manet/ospf6d/ospf6_message.h 2006-02-20 13:42:12.000000000 -0800 @@ -22,6 +22,10 @@ #ifndef OSPF6_MESSAGE_H #define OSPF6_MESSAGE_H +#ifdef OSPF6_MANET +#include "ospf6d.h" //for boolean +#endif //OSPF6_MANET + #define OSPF6_MESSAGE_BUFSIZ 4096 /* Debug option */ @@ -44,6 +48,45 @@ #define OSPF6_MESSAGE_TYPE_LSACK 0x5 /* Flooding acknowledgment */ #define OSPF6_MESSAGE_TYPE_ALL 0x6 /* For debug option */ +#ifdef OSPF6_MANET +/* TLV type */ +#define OSPF6_TLV_TYPE_OPTIONS 0x1 +#define OSPF6_TLV_TYPE_SCS 0x2 +#define OSPF6_TLV_TYPE_NEIGHDROP 0x3 +#define OSPF6_TLV_TYPE_RELAY 0x4 +#define OSPF6_TLV_TYPE_WILLINGNESS 0x5 +#define OSPF6_TLV_TYPE_REQUEST 0x6 //XXX draft error (double assigned type) +#define OSPF6_TLV_TYPE_FULL 0x7 //XXX draft error (double assigned type) + +#define OSPF6_TLV_TYPE_HNL 0x11 +#define OSPF6_TLV_TYPE_RNL 0x12 +#define OSPF6_TLV_TYPE_LNL 0x13 +#define OSPF6_TLV_TYPE_HS 0x14 +#define OSPF6_TLV_TYPE_DD 0x15 +#define OSPF6_TLV_TYPE_DNL 0x16 // Added for Ogierv7. + +//Chandra03 3.3.2 +#define OSPF6_TLV_SCS_OPT_SET(x,opt,i) ((x)[(i)] |= (opt)) +#define OSPF6_TLV_SCS_OPT_ISSET(x,opt,i) ((x)[(i)] & (opt)) +#define OSPF6_TLV_SCS_OPT_CLEAR(x,opt,i) ((x)[(i)] &= ~(opt)) +#define OSPF6_TLV_SCS_OPT_CLEAR_ALL(x) ((x)[0] = (x)[1] = 0) +#define OSPF6_TLV_SCS_OPT_R (1 << 7) /* Request for current state */ +#define OSPF6_TLV_SCS_OPT_FS (1 << 6) /* Answer with current state */ +#define OSPF6_TLV_SCS_OPT_N (1 << 5) /* Incomplete state bit */ + +#define OSPF6_TLV_REL_OPT_SET(x,opt,i) ((x)[(i)] |= (opt)) +#define OSPF6_TLV_REL_OPT_ISSET(x,opt,i) ((x)[(i)] & (opt)) +#define OSPF6_TLV_REL_OPT_CLEAR(x,opt,i) ((x)[(i)] &= ~(opt)) +#define OSPF6_TLV_REL_OPT_CLEAR_ALL(x) ((x)[0] = (x)[1] = (x)[2] = 0) +#define OSPF6_TLV_REL_OPT_A (1 << 7) /* Always flood */ +#define OSPF6_TLV_REL_OPT_N (1 << 6) /* Almost Never flood */ + +#define OSPF6_TLV_HS_OPT_SET(x,opt,i) ((x)[(i)] |= (opt)) +#define OSPF6_TLV_HS_OPT_ISSET(x,opt,i) ((x)[(i)] & (opt)) +#define OSPF6_TLV_HS_OPT_CLEAR(x,opt,i) ((x)[(i)] &= ~(opt)) +#define OSPF6_TLV_HS_OPT_CLEAR_ALL(x) ((x)[0] = (x)[1] = 0) +#endif //OSPF6_MANET + #define OSPF6_MESSAGE_TYPE_CANONICAL(T) \ ((T) > OSPF6_MESSAGE_TYPE_LSACK ? OSPF6_MESSAGE_TYPE_UNKNOWN : (T)) @@ -79,6 +122,94 @@ /* Followed by Router-IDs */ }; +#ifdef OSPF6_MANET +/* OSPFv3 LLS header */ +//Chandra03 3.1.2 +struct ospf6_LLS_header +{ + u_int16_t cksum; + u_int16_t len; //length of entire LLS data block in 32 bit words +}; + +/* OSPFv3 TLV header */ +//Chandra03 3.1.3 +struct ospf6_TLV_header +{ + u_int16_t type; + u_int16_t len; // length of value field in bytes +}; + +/* OSPFv3 options TLV */ +//Chandra03 3.1.4 +struct ospf6_options_TLV +{ + u_char options[4]; +}; +#endif //OSPF6_MANET + +#ifdef OSPF6_MANET_DIFF_HELLO +/* OSPFv3 State Check Sequence TLV */ +//Chandra03 3.3.2 +struct ospf6_scs_TLV +{ + u_int16_t number; + u_char bits[2]; +}; + +/* OSPFv3 Neighbor drop TLV */ +/* No message struct needed here; just includes router-IDs */ + + +/* OSPFv3 Neighbor Request TLV */ +/* No message struct needed here; just includes router-IDs */ +#endif //OSPF6_MANET_DIFF_HELLO + +#ifdef OSPF6_MANET_MPR_FLOOD +/* OSPFv3 Active Overlapping Relays TLV */ +//Chandra03 3.4.6 +struct ospf6_relay_TLV +{ + u_char added; + u_char bits[3]; +}; + +/* OSPFv3 Active Overlapping Relays TLV */ +//Chandra03 3.4.7 +struct ospf6_will_TLV +{ + u_char will; + u_char reserved[3]; +}; +#endif //OSPF6_MANET_MPR_FLOOD + +#ifdef OSPF6_MANET_MDR_FLOOD + +#ifdef OSPF6_MANET_DIFF_HELLO +/* OSPFv3 Hello Sequence TLV */ +struct ospf6_seq_TLV +{ + u_int16_t number; + u_char bits[2]; +}; +#endif //OSPF6_MANET_DIFF_HELLO + +/* OSPFv3 Heard Neighbor List TLV */ +/* No TLV Header needed here */ + +/* OSPFv3 Reported Neighbor List TLV */ +/* No TLV Header needed here */ + +/* OSPFv3 Lost Neighbor List TLV */ +/* No TLV Header needed here */ + +/* OSPFv3 MDR TLV */ +struct ospf6_mdr_TLV +{ + u_int32_t id1; + u_int32_t id2; +}; +#endif //OSPF6_MANET_MDR_FLOOD + /* Database Description */ struct ospf6_dbdesc { @@ -137,5 +268,133 @@ int config_write_ospf6_debug_message (struct vty *); void install_element_ospf6_debug_message (); +#ifdef SIM +#ifdef OSPF6_MANET +void +ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, struct ospf6_header *oh, int len); +void +ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, struct ospf6_header *oh, int len); +#else +void +ospf6_hello_recv (struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, struct ospf6_header *oh); +void +ospf6_dbdesc_recv (struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, struct ospf6_header *oh); +#endif //OSPF6_MANET +void +ospf6_lsreq_recv (struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, struct ospf6_header *oh); +void +ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, struct ospf6_header *oh); +void +ospf6_lsack_recv (struct in6_addr *src, struct in6_addr *dst, + struct ospf6_interface *oi, struct ospf6_header *oh); +#endif //SIM + +#ifdef OSPF6_MANET +struct ospf6_interface; +struct ospf6_relay; +struct ospf6_relay_selector; +struct ospf6_neighbor; +#endif // DEBUG + + +#ifdef OSPF6_DELAYED_FLOOD +struct thread *ospf6_send_lsupdate_delayed_msec(struct thread_master *m, + int (*func) (struct thread *), void *arg, long timer, struct thread *t); +#endif //OSPF6_DELAYED_FLOOD + +#ifdef OSPF6_MANET +boolean ospf6_is_rtrid_in_list(struct ospf6_interface *, u_int32_t *, int); + +int ospf6_append_lls_header(struct ospf6_interface *, u_char *, u_int); +void ospf6_tlv_header_assignment(struct ospf6_TLV_header *,u_int16_t,u_int16_t); + +#ifdef OSPF6_MANET_MPR_FLOOD +int ospf6_mpr_mhello_send (struct ospf6_interface *o6i); + +void ospf6_mpr_process_TLVs(struct ospf6_neighbor *, struct ospf6_LLS_header *); +int ospf6_append_relays(struct ospf6_interface *oi, + u_char *pos, + u_char *max_pos, + boolean periodic_hello, + boolean full_neighbor_state); +int ospf6_create_neighbor_list(struct ospf6_interface *oi, + u_char *sendbuf, + u_char *position, + boolean full_neighbor_state); + +#ifdef OSPF6_MANET_DIFF_HELLO +int ospf6_mpr_diff_mhello_send (struct ospf6_interface *o6i, + struct in6_addr dst, + char *scs_tlv_opt); +boolean ospf6_is_scs_wrap_around(u_int16_t old_scs_num, u_int16_t new_scs_num); +int ospf6_append_scs(struct ospf6_interface *oi, + char *opt, + u_char *pos); +int ospf6_append_drop_neighbors(struct ospf6_interface *oi, + u_char *pos, + u_char *max_pos, + boolean *set_N); +int ospf6_append_request(struct ospf6_interface *oi, + u_char *pos, + u_char *max_pos, + char *scs_tlv_option); +void ospf6_mpr_process_diff_TLVs(struct ospf6_neighbor *on, + struct ospf6_LLS_header * lls_ptr, + int seenrtrnum, + char *scs_tlv_option, + boolean *twoway, + boolean *send_mhello); + +#endif //OSPF6_MANET_DIFF_HELLO +#endif //OSPF6_MANET_MPR_FLOOD + +#ifdef OSPF6_MANET_MDR_FLOOD +int ospf6_mdr_mhello_send(struct ospf6_interface *oi); +// DNL list added for Ogierv7 +u_int ospf6_mdr_create_neighbor_lists(struct ospf6_interface *oi, + u_char *pos, u_char *max_pos, + u_int *num_hnl, u_char *hnl, + u_int *num_rnl, u_char *rnl, + u_int *num_lnl, u_char *lnl, + u_int *num_dnl, u_char *dnl, + boolean diff); +int ospf6_append_mdr_neigh_tlv(u_char *, u_int, u_char *, u_int16_t); +boolean ospf6_mdr_process_hello_TLVs(struct ospf6_neighbor *on, + struct ospf6_LLS_header *lls_ptr, + boolean diff, boolean *rnl_changed); +int ospf6_append_mdr_tlv(struct ospf6_interface *oi, u_char *p); +boolean ospf6_mdr_process_mdr_TLVs(struct ospf6_neighbor *, + struct ospf6_LLS_header *); + +#ifdef OSPF6_MANET_DIFF_HELLO +int ospf6_append_mdr_seq_tlv(struct ospf6_interface *oi, u_char *pos); +#endif //OSPF6_MANET_DIFF_HELLO +#endif //OSPF6_MANET_MDR_FLOOD + +#ifdef OSPF6_MANET_TEMPORARY_LSDB +void ospf6_lsupdate_recv_below_exchange (struct in6_addr *src, + struct in6_addr *dst, + struct ospf6_interface *oi, + struct ospf6_header *oh); +#endif //OSPF6_MANET_TEMPORARY_LSDB + +//################## PRINTING SECTION ######################## +void ospf6_mhello_print (struct ospf6_header *oh, int len); +void print_tlv(struct ospf6_TLV_header *tlv_header, boolean log); + +//################## END PRINTING SECTION ######################## + +#ifdef USER_CHECKSUM +u_int16_t ospf6_do_checksum(struct in6_addr*, struct in6_addr*,struct ospf6_header*); +#endif + +#endif //OSPF6_MANET + #endif /* OSPF6_MESSAGE_H */ diff -Naur quagga-0.98.5/ospf6d/ospf6_mpr.c quagga-0.98.5-manet/ospf6d/ospf6_mpr.c --- quagga-0.98.5/ospf6d/ospf6_mpr.c 1969-12-31 16:00:00.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_mpr.c 2006-02-20 13:42:12.000000000 -0800 @@ -0,0 +1,291 @@ +/* + * Copyright (C) Boeing Co. + */ + +#ifdef OSPF6_MANET_MPR_FLOOD + +#include "zebra.h" +#include "ospf6_mpr.h" +#include "ospf6_area.h" +#ifdef SIM_ETRACE_STAT +#include "sim.h" +#endif //SIM_ETRACE_STAT +#ifdef SIM +#include "ospf6_sim_printing.h" +#endif //SIM + +//Chandra03 3.4.4 +void ospf6_calculate_relays(struct ospf6_interface *oi) +{ + boolean finished = false; + int best_coverage, cover_count; + plistnode n, n2, N2; + struct ospf6_neighbor *on, *best; + struct ospf6_2hop_neighbor *o62n, *o62N; + struct ospf6_relay *relay; + u_int32_t id; + + if (!oi->mpr_change) + return; + + /* initialization */ + for(n = listhead(oi->relay_list); n; nextnode(n)) + { + relay = (struct ospf6_relay *) getdata(n); + relay->active = false; + } + for(n = listhead(oi->neighbor_list); n; nextnode(n)) + { + on = (struct ospf6_neighbor *) getdata(n); + on->covered = false; + } + for(n2 = listhead(oi->two_hop_list); n2; nextnode(n2)) + { + o62n = (struct ospf6_2hop_neighbor *) getdata(n2); + o62n->covered = false; + } + + /* 3. Find 1 hops connected to poorly covered 2 hops */ + for(n2 = listhead(oi->two_hop_list); n2; nextnode(n2)) + { + o62n = (struct ospf6_2hop_neighbor *) getdata(n2); + if (!o62n->covered && o62n->one_hop_neighbor_list->count == 1) + { // this is a poorly covered 2 hop - cover w/ one hop + n = listhead(o62n->one_hop_neighbor_list); + on = (struct ospf6_neighbor *) getdata (n); + if(on->covered) + { + o62n->covered = true; + continue; + } + // not covered yet - now mark this one-hop as covered + on->covered = true; + // mark all two-hops as covered + for(N2 = listhead(on->two_hop_neighbor_list); N2; nextnode(N2)) + { + o62N = (struct ospf6_2hop_neighbor *) getdata(N2); + o62N->covered = true; + } + ospf6_relay_create(oi, on->router_id); + } + } + + finished = false; + /* 4. While uncovered 2 hops exist */ + while(!finished) + { + best = NULL; + best_coverage = 0; + id = 0; + /* 4.1 calculate reachability of this one hop */ + for (n = listhead(oi->neighbor_list); n; nextnode(n)) + { + on = (struct ospf6_neighbor *) getdata(n); + if (on->state < OSPF6_NEIGHBOR_FULL) //XXX OR/SP + continue; + if (on->covered) + continue; + /* count number of two hops that this one hop could cover */ + cover_count = 0; + for (n2 = listhead(on->two_hop_neighbor_list); n2; nextnode(n2)) + { + o62n = (struct ospf6_2hop_neighbor *) getdata(n2); + if (o62n->covered == false) + cover_count++; + } + if (cover_count == 0) + continue; + if ((cover_count > best_coverage) || + (cover_count == best_coverage && on->router_id > id)) + { + id = on->router_id; + best = on; + best_coverage = cover_count; + } + } + /* 4.2 Add the one hop with the best coverage to the MPR list, + * and mark it and its two hops as covered. */ + if (best) + { + best->covered = true; + for (n2 = listhead(best->two_hop_neighbor_list); n2; nextnode(n2)) + { + o62n = (struct ospf6_2hop_neighbor *) getdata (n2); + o62n->covered = true; + } + ospf6_relay_create(oi, best->router_id); + } + else + { + finished = true; + /* No more uncovered two hops */ + } + } // end while(!finished) + + // finalize + oi->mpr_change = false; + n = listhead(oi->relay_list); + while(n) + { + relay = (struct ospf6_relay *) getdata(n); + nextnode(n); + if(!relay->active) + { + if(!relay->drop) + { //this relay was just dropped + relay->drop = true; + relay->newly_activated = false; + set_time(relay->drop_expire_time); +#ifdef OSPF6_MANET_DIFF_HELLO + oi->increment_scs = true; +#endif //OSPF6_MANET_DIFF_HELLO + } + else if (elapsed_time(relay->drop_expire_time) >= oi->dead_interval) + { //relay was flagged dropped in the past, may need to be removed + ospf6_relay_delete(oi, relay); + } + } + } +#ifdef SIM_ETRACE_STAT + ospf6_print_neighborhood_sim(oi); + ospf6_print_relay_list_sim(oi); +#endif //SIM_ETRACE_STAT +} + +void ospf6_relay_create(struct ospf6_interface *oi, u_int32_t id) +{ + plistnode n; + struct ospf6_relay *relay; + + for (n = listhead(oi->relay_list); n; nextnode(n)) + { + relay = (struct ospf6_relay*) getdata(n); + if(relay && relay->router_id == id) + { // relay already in list + if(relay->active) + return; //relay already activated + + if (relay->drop) + {//new relay that was still in drop relay list + relay->newly_activated = true; +#ifdef OSPF6_MANET_DIFF_HELLO + oi->increment_scs = true; +#endif //OSPF6_MANET_DIFF_HELLO + } + relay->drop = false; + relay->active = true; + return; + } + } + /* new relay that was not in the relay list */ + relay = (struct ospf6_relay *) malloc(sizeof(struct ospf6_relay)); + relay->router_id = id; + relay->newly_activated = true; //brand new relay + relay->active = true; + + relay->drop = false; + relay->drop_expire_time = (struct timeval *) malloc(sizeof(struct timeval)); + + listnode_add(oi->relay_list, relay); +#ifdef OSPF6_MANET_DIFF_HELLO + oi->increment_scs = true; +#endif //OSPF6_MANET_DIFF_HELLO + return; +} + +void ospf6_relay_delete(struct ospf6_interface *oi, + struct ospf6_relay *relay) +{ + listnode_delete(oi->relay_list, relay); + free(relay->drop_expire_time); + free(relay); +} + +/* + * Relay Selector Functions + */ +void ospf6_refresh_relay_selector(struct ospf6_neighbor *on) +{ + struct ospf6_relay_selector *relay_sel; + struct ospf6_interface *oi = on->ospf6_if; + + relay_sel = ospf6_lookup_relay_selector(oi, on->router_id); + if (!relay_sel) + { + relay_sel = (struct ospf6_relay_selector *) + malloc(sizeof(struct ospf6_relay_selector)); + relay_sel->expire_time = (struct timeval *) malloc(sizeof(struct timeval)); + relay_sel->router_id = on->router_id; + listnode_add(oi->relay_sel_list, relay_sel); + set_time(relay_sel->expire_time); + +#ifdef SIM_ETRACE_STAT + ospf6_print_relay_selector_list_sim(oi); + float delta = elapsed_time(&oi->relaysel_change_time); + update_statistics(OSPF6_DURATION_OF_NUM_RELSEL, (double)delta); + update_statistics(OSPF6_NUM_RELSEL_TIMES_DURATION_OF_NUM_RELSEL, + (double)((oi->relay_sel_list->count-1) * delta)); + set_time(&relay_sel->install_time); + set_time(&oi->relaysel_change_time); +#endif //SIM_ETRACE_STAT + } + else + { + set_time(relay_sel->expire_time); + } +} + +struct ospf6_relay_selector +*ospf6_lookup_relay_selector(struct ospf6_interface *oi, + u_int32_t id) +{ + plistnode n; + struct ospf6_relay_selector *relay_sel = NULL; + + if (oi->type != OSPF6_IFTYPE_MANETRELIABLE) + return NULL; + + if (oi->flooding != OSPF6_FLOOD_MPR_SDCDS) + return NULL; + + n = listhead(oi->relay_sel_list); + while(n) + { + relay_sel = (struct ospf6_relay_selector *) getdata(n); + nextnode(n); + + if (elapsed_time(relay_sel->expire_time) > oi->dead_interval) + { + ospf6_relay_selector_delete(oi, relay_sel); + } + else if (relay_sel->router_id == id) + break; + relay_sel = NULL; + } + return relay_sel; +} + +void ospf6_relay_selector_delete(struct ospf6_interface *oi, + struct ospf6_relay_selector *relay_sel) +{ +#ifdef SIM_ETRACE_STAT + float delta = elapsed_time(&oi->relaysel_change_time); + float lifetime = elapsed_time(&relay_sel->install_time); //Insure + update_statistics(OSPF6_DURATION_OF_NUM_RELSEL, (double)delta); + update_statistics(OSPF6_NUM_RELSEL_TIMES_DURATION_OF_NUM_RELSEL, + (double)((oi->relay_sel_list->count) * delta)); + update_statistics(OSPF6_RELSEL_LIFETIME, (double)lifetime); + update_statistics(OSPF6_RELSEL_DEATHS, 1); + set_time(&oi->relaysel_change_time); +#endif //SIM_ETRACE_STAT + + listnode_delete(oi->relay_sel_list, relay_sel); + free(relay_sel->expire_time); + free(relay_sel); + +#ifdef SIM_ETRACE_STAT + ospf6_print_relay_selector_list_sim(oi); +#endif //SIM_ETRACE_STAT +} + +#endif //OSPF6_MANET_MPR_FLOOD diff -Naur quagga-0.98.5/ospf6d/ospf6_mpr.h quagga-0.98.5-manet/ospf6d/ospf6_mpr.h --- quagga-0.98.5/ospf6d/ospf6_mpr.h 1969-12-31 16:00:00.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_mpr.h 2006-02-20 13:42:12.000000000 -0800 @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2005 Boeing + */ + +#ifndef OSPF6_MPR_H +#define OSPF6_MPR_H + +#ifdef OSPF6_MANET_MPR_FLOOD +#include "ospf6d.h" //for boolean +#include "ospf6_interface.h" +#include "ospf6_neighbor.h" + +void ospf6_calculate_relays(struct ospf6_interface *); + +void ospf6_relay_create(struct ospf6_interface *, u_int32_t); +void ospf6_relay_delete(struct ospf6_interface *, struct ospf6_relay *); + +void ospf6_refresh_relay_selector(struct ospf6_neighbor *); +struct ospf6_relay_selector * + ospf6_lookup_relay_selector(struct ospf6_interface *, u_int32_t); +void ospf6_relay_selector_delete(struct ospf6_interface *, + struct ospf6_relay_selector *); +#endif //OSPF6_MANET_MPR_FLOOD +#endif /* OSPF6_MPR_H */ + diff -Naur quagga-0.98.5/ospf6d/ospf6_neighbor.c quagga-0.98.5-manet/ospf6d/ospf6_neighbor.c --- quagga-0.98.5/ospf6d/ospf6_neighbor.c 2004-12-23 22:00:12.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_neighbor.c 2006-02-20 13:42:12.000000000 -0800 @@ -38,7 +38,15 @@ #include "ospf6_neighbor.h" #include "ospf6_intra.h" #include "ospf6_flood.h" +#ifdef OSPF6_MANET_MDR_FLOOD +#include "ospf6_route.h" +#include "ospf6_spf.h" +#endif //OSPF6_MANET_MDR_FLOOD #include "ospf6d.h" +#ifdef SIM +#include "sim.h" +#include "ospf6_sim_printing.h" +#endif //SIM unsigned char conf_debug_ospf6_neighbor = 0; @@ -58,7 +66,7 @@ ospf6_neighbor_lookup (u_int32_t router_id, struct ospf6_interface *oi) { - struct listnode *n; + plistnode n; struct ospf6_neighbor *on; for (n = listhead (oi->neighbor_list); n; nextnode (n)) @@ -91,7 +99,11 @@ buf, oi->interface->name); on->ospf6_if = oi; on->state = OSPF6_NEIGHBOR_DOWN; +#ifdef SIM + gettimeofday_sim (&on->last_changed, (struct timezone *) NULL); +#else gettimeofday (&on->last_changed, (struct timezone *) NULL); +#endif //SIM on->router_id = router_id; on->summary_list = ospf6_lsdb_create (on); @@ -103,6 +115,49 @@ on->lsupdate_list = ospf6_lsdb_create (on); on->lsack_list = ospf6_lsdb_create (on); +#ifdef OSPF6_MANET + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE) + { +#ifdef OSPF6_MANET_MPR_FLOOD +#ifdef OSPF6_MANET_DIFF_HELLO + struct drop_neighbor *drop_neigh = NULL; + drop_neigh = ospf6_lookup_drop_neighbor(oi, router_id); + if (drop_neigh) + ospf6_drop_neighbor_delete(oi, drop_neigh); + on->set_scs_num = true; + //Chandra03 3.3.6.1 paragraph 2 bullet 2 + oi->increment_scs = true; + on->below_exchange = true; +#endif //OSPF6_MANET_DIFF_HELLO + on->Fbit = false; + on->Relay_Abit = false; + on->Relay_Nbit = false; + on->two_hop_neighbor_list = NULL; +#endif //OSPF6_MANET_MPR_FLOOD + +#ifdef OSPF6_MANET_MDR_FLOOD +#ifdef OSPF6_MANET_DIFF_HELLO +{ + struct ospf6_lnl_element *lnl_element; + lnl_element = ospf6_mdr_lookup_lnl_element(on); + if (lnl_element) + ospf6_mdr_delete_lnl_element(oi, lnl_element); +} +#endif //OSPF6_MANET_DIFF_HELLO + on->rnl = list_new(); + on->Report2Hop = false; + on->reverse_2way = false; + on->dependent = false; + on->dependent_selector = false; + on->routable = false; + on->adv = false; + on->new_adv = false; +#endif //OSPF6_MANET_MDR_FLOOD + + on->mack_list = list_new(); + } +#endif //OSPF6_MANET + listnode_add_sort (oi->neighbor_list, on); return on; } @@ -135,6 +190,30 @@ ospf6_lsdb_delete (on->lsupdate_list); ospf6_lsdb_delete (on->lsack_list); +#ifdef OSPF6_MANET + if (on->ospf6_if->type == OSPF6_IFTYPE_MANETRELIABLE) + { +#ifdef OSPF6_MANET_MPR_FLOOD +#ifdef OSPF6_MANET_DIFF_HELLO + //Chandra03 3.3.6.2 paragraph 1 bullet 2 + ospf6_drop_neighbor_create(on); + //Chandra03 3.3.6.2 paragraph 1 bullet 3 + on->ospf6_if->increment_scs = true; +#endif //OSPF6_MANET_DIFF_HELLO +#endif //OSPF6_MANET_MPR_FLOOD + +#ifdef OSPF6_MANET_MDR_FLOOD +#ifdef OSPF6_MANET_DIFF_HELLO + ospf6_mdr_add_lnl_element(on); +#endif //OSPF6_MANET_DIFF_HELLO + ospf6_mdr_set_mdr_level(on, 0, 0); //important for statisics gathering + ospf6_mdr_delete_neighbor_list(on->rnl); +#endif //OSPF6_MANET_MDR_FLOOD + + ospf6_mack_list_delete(on); + } +#endif //OSPF6_MANET + THREAD_OFF (on->inactivity_timer); THREAD_OFF (on->thread_send_dbdesc); @@ -145,10 +224,15 @@ XFREE (MTYPE_OSPF6_NEIGHBOR, on); } -static void +//static +void ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on) { u_char prev_state; +#ifdef OSPF6_MANET + u_char type = on->ospf6_if->type; + int change; +#endif //OSPF6_MANET prev_state = on->state; on->state = next_state; @@ -156,16 +240,198 @@ if (prev_state == next_state) return; +#ifdef SIM_ETRACE_STAT + ospf6_neighbor_state_change_stats (prev_state, next_state, on); +#endif //SIM_ETRACE_STAT + +#ifdef SIM + gettimeofday_sim (&on->last_changed, (struct timezone *) NULL); +#else gettimeofday (&on->last_changed, (struct timezone *) NULL); +#endif //SIM /* log */ if (IS_OSPF6_DEBUG_NEIGHBOR (STATE)) { zlog_debug ("Neighbor state change %s: [%s]->[%s]", on->name, - ospf6_neighbor_state_str[prev_state], - ospf6_neighbor_state_str[next_state]); + ospf6_neighbor_state_str[prev_state], + ospf6_neighbor_state_str[next_state]); } +#ifdef OSPF6_MANET + if (type == OSPF6_IFTYPE_MANETRELIABLE) + { +#ifdef OSPF6_MANET_MPR_FLOOD + if (on->ospf6_if->flooding == OSPF6_FLOOD_MPR_SDCDS) + { + if (prev_state == OSPF6_NEIGHBOR_FULL) //XXX OR/SP + { + on->ospf6_if->mpr_change = true; + ospf6_2hop_list_delete(on); + ospf6_update_neighborhood(on->ospf6_if); + } + else if (next_state == OSPF6_NEIGHBOR_FULL) //XXX OR/SP + { + // Building the two-hop neighbor list + // By definition, section 3.4.3 bullet 2 + /* 1-hop neighbor may have been a 2-hop neighbor */ + struct ospf6_2hop_neighbor *o2n = NULL; + o2n = ospf6_2hop_neighbor_lookup(on->router_id, + on->ospf6_if->two_hop_list); + if (o2n) + { + plistnode n; + struct ospf6_neighbor *oN = NULL; + n = listhead (o2n->one_hop_neighbor_list); + while(n) + { + oN = (struct ospf6_neighbor *) getdata (n); + nextnode(n); + listnode_delete(oN->two_hop_neighbor_list, o2n); + } + listnode_delete(on->ospf6_if->two_hop_list, o2n); + list_delete(o2n->one_hop_neighbor_list); + free(o2n); + } + on->two_hop_neighbor_list = list_new(); + on->ospf6_if->mpr_change = true; + ospf6_update_neighborhood(on->ospf6_if); + } +#ifdef OSPF6_MANET_DIFF_HELLO + /* Chandra03 3.3.6.1 paragraph 2 bullet 3*/ + if (on->state >= OSPF6_NEIGHBOR_EXCHANGE) + { + on->below_exchange = false; + } +#endif //OSPF6_MANET_DIFF_HELLO + } +#endif //OSPF6_MANET_MPR_FLOOD + + change = ospf6_manet_update_routable_neighbors(on->ospf6_if); + if (on->ospf6_if->flooding == OSPF6_FLOOD_MDR_SICDS) + { + if (((prev_state < OSPF6_NEIGHBOR_TWOWAY) && + (next_state >= OSPF6_NEIGHBOR_TWOWAY)) || + ((prev_state >= OSPF6_NEIGHBOR_TWOWAY) && + (next_state < OSPF6_NEIGHBOR_TWOWAY)) || + ((prev_state < OSPF6_NEIGHBOR_INIT) && + (next_state >= OSPF6_NEIGHBOR_INIT)) || + ((prev_state >= OSPF6_NEIGHBOR_INIT) && + (next_state < OSPF6_NEIGHBOR_INIT))) + on->changed_hsn = on->ospf6_if->hsn; + // Condition for LSA change depends on LSAFullness. + if (on->ospf6_if->LSAFullness == OSPF6_LSA_FULLNESS_MINHOP || + on->ospf6_if->LSAFullness == OSPF6_LSA_FULLNESS_MINHOP2PATHS) + change = ospf6_mdr_update_adv_neighbors(on->ospf6_if); + } + + //schedule LSAs if change + if (on->ospf6_if->flooding == OSPF6_FLOOD_MDR_SICDS && + on->ospf6_if->AdjConnectivity > OSPF6_ADJ_FULLYCONNECTED && + (on->ospf6_if->LSAFullness == OSPF6_LSA_FULLNESS_FULL || + on->ospf6_if->LSAFullness == OSPF6_LSA_FULLNESS_MINHOP || + on->ospf6_if->LSAFullness == OSPF6_LSA_FULLNESS_MINHOP2PATHS)) + //(on->ospf6_if->LSAFullness == OSPF6_LSA_FULLNESS_MDRFULL && + //!on->ospf6_if->full_adj_part_lsa && + //on->ospf6_if->mdr_level != OSPF6_OTHER))) + { + if (change) + OSPF6_ROUTER_LSA_SCHEDULE (on->ospf6_if->area); + } + // This section handles MDRFULL for all routers, with or without + // full_adj_part_lsa. + else if (on->ospf6_if->flooding == OSPF6_FLOOD_MDR_SICDS && + on->ospf6_if->AdjConnectivity > OSPF6_ADJ_FULLYCONNECTED && + on->ospf6_if->LSAFullness == OSPF6_LSA_FULLNESS_MDRFULL) + { + // Four cases: MDR/BMDR and Other with partial adj, then + // MDR/BMDR and Other with full adj. + if (!on->ospf6_if->full_adj_part_lsa && + on->ospf6_if->mdr_level >= OSPF6_BMDR) + { + if (change) + OSPF6_ROUTER_LSA_SCHEDULE (on->ospf6_if->area); + } + else if (on->ospf6_if->full_adj_part_lsa && + on->ospf6_if->mdr_level >= OSPF6_BMDR) + { + if (prev_state == OSPF6_NEIGHBOR_FULL || + next_state == OSPF6_NEIGHBOR_FULL) + OSPF6_ROUTER_LSA_SCHEDULE (on->ospf6_if->area); + } + // If MDR full LSAs are used and router is Other, schedule an + // LSA if a Full (b)parent is not advertised, or if an advertised + // neighbor becomes less than Full. Similar condition for + // partial-topology adjacencies, but parents need not be checked. + // An LSA is also originated from mdr_calc when a parent + // is selected that is already Full but not yet advertised. + else if (on->ospf6_if->full_adj_part_lsa && + on->ospf6_if->mdr_level == OSPF6_OTHER) + { + if ((on->mdr_level >= OSPF6_BMDR && + (on->ospf6_if->parent == on || on->ospf6_if->bparent == on) && + !on->adv && on->state == OSPF6_NEIGHBOR_FULL) || + on->adv && on->state < OSPF6_NEIGHBOR_FULL) + OSPF6_ROUTER_LSA_SCHEDULE (on->ospf6_if->area); + } + else if (!on->ospf6_if->full_adj_part_lsa && + on->ospf6_if->mdr_level == OSPF6_OTHER) + { + if ((on->mdr_level >= OSPF6_BMDR && + !on->adv && on->state == OSPF6_NEIGHBOR_FULL) || + on->adv && on->state < OSPF6_NEIGHBOR_FULL) + OSPF6_ROUTER_LSA_SCHEDULE (on->ospf6_if->area); + } + } +#ifdef OSPF6_MANET_MPR_SP + else if (on->ospf6_if->flooding == OSPF6_FLOOD_MPR_SDCDS && + on->ospf6_if->smart_peering) + { + struct ospf6_area* oa = on->ospf6_if->area; + boolean new_adjacency = false; + + if (change) //BUGFIX_SP + { + //perform sync SPF, so adjacency check will be working with + //accurate routes + ospf6_spf_calculation(oa->ospf6->router_id,oa->spf_table_sync,oa,true); + ospf6_manet_update_routable_neighbors(on->ospf6_if); + new_adjacency = ospf6_or_update_adjacencies(on->ospf6_if); + } + + //A new router-LSA will be scheduled, but want to delay it because + //an adjacency will come up soon that will cause another router-LSA + //origination + if(new_adjacency && change && on->ospf6_if->unsynch_adj) + { + if (!oa->thread_router_lsa) + oa->thread_router_lsa = + thread_add_timer_msec(master, ospf6_router_lsa_originate, + oa, oa->ospf6->minLSInterval*1000); + + } + //build a router-LSA now + else if(change && on->ospf6_if->unsynch_adj) + OSPF6_ROUTER_LSA_SCHEDULE (on->ospf6_if->area); + else if (prev_state == OSPF6_NEIGHBOR_FULL || + next_state == OSPF6_NEIGHBOR_FULL) + { + OSPF6_ROUTER_LSA_SCHEDULE (on->ospf6_if->area); + } + } +#endif //OSPF6_MANET_MPR_SP + else // full adj or lsa includes only adjacent neighbors + { + if (prev_state == OSPF6_NEIGHBOR_FULL || + next_state == OSPF6_NEIGHBOR_FULL) + { + OSPF6_ROUTER_LSA_SCHEDULE (on->ospf6_if->area); + //OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (on->ospf6_if->area); + } + } + } + else +#endif //OSPF6_MANET if (prev_state == OSPF6_NEIGHBOR_FULL || next_state == OSPF6_NEIGHBOR_FULL) { OSPF6_ROUTER_LSA_SCHEDULE (on->ospf6_if->area); @@ -193,6 +459,95 @@ } +#ifdef SIM_ETRACE_STAT +void ospf6_neighbor_state_change_stats (u_char prev_state, u_char next_state, + struct ospf6_neighbor *on) +{ + TraceEvent_sim(2,"neighbor %s changing state from %s to %s", + ip2str(on->router_id), + ospf6_neighbor_state_str[prev_state], + ospf6_neighbor_state_str[next_state]); + + if (((prev_state < OSPF6_NEIGHBOR_TWOWAY) && + (next_state >= OSPF6_NEIGHBOR_TWOWAY)) || + ((prev_state >= OSPF6_NEIGHBOR_TWOWAY) && + (next_state < OSPF6_NEIGHBOR_TWOWAY))) + { + double *stat = on->ospf6_if->area->ospf6->statistics; + float delta_2way = elapsed_time(&on->ospf6_if->neigh_2way_change_time); + update_statistics(OSPF6_CHANGE_OF_NUM_NEIGHS, 1); + update_statistics(OSPF6_DURATION_OF_NUM_NEIGHS, (double)delta_2way); + update_statistics(OSPF6_NUM_NEIGH_TIMES_DURATION_OF_NUM_NEIGHS, + (double) (on->ospf6_if->num_2way_neigh * delta_2way)); + if (next_state >= OSPF6_NEIGHBOR_TWOWAY) + { + set_time(&on->creation_time); + TraceEvent_sim(1,"num_nbr %d for %f msec newnbr %s for 0 msec", + on->ospf6_if->num_2way_neigh++, delta_2way, ip2str(on->router_id)); + } + else + { + double lifetime = elapsed_time(&on->creation_time); + update_statistics(OSPF6_NEIGH_LIFETIME, lifetime); + update_statistics(OSPF6_NEIGH_DEATHS, 1); + TraceEvent_sim(1,"num_nbr %d for %f msec delnbr %s for %f msec", + on->ospf6_if->num_2way_neigh--, delta_2way, + ip2str(on->router_id),lifetime); + } + set_time(&on->ospf6_if->neigh_2way_change_time); + } + if (next_state==OSPF6_NEIGHBOR_FULL || prev_state==OSPF6_NEIGHBOR_FULL) + { + double *stat = on->ospf6_if->area->ospf6->statistics; + float delta_full = elapsed_time(&on->ospf6_if->neigh_full_change_time); + update_statistics(OSPF6_CHANGE_OF_NUM_ADJ, 1); + update_statistics(OSPF6_DURATION_OF_NUM_ADJ, (double)delta_full); + update_statistics(OSPF6_NUM_ADJ_TIMES_DURATION_OF_NUM_ADJ, + (double) (on->ospf6_if->num_full_neigh * delta_full)); + if (next_state == OSPF6_NEIGHBOR_FULL) + update_statistics(OSPF6_ADJ_ACCUM, 1); + else + update_statistics(OSPF6_ADJ_ACCUM, -1); + + if (next_state == OSPF6_NEIGHBOR_FULL) + on->ospf6_if->num_full_neigh++; + else + { + double lifetime = elapsed_time(&on->creation_time); + on->ospf6_if->num_full_neigh--; + } + set_time(&on->ospf6_if->neigh_full_change_time); + } +} +#endif //SIM_ETRACE_STAT + + +#ifdef OSPF6_MANET_MDR_FLOOD +/* + *keep_adjacency() is used to decide whether an existing adjacency + * should be kept vs. torn down. The condition is less strict than + * need_adjacency(), for hysteresis and adjacency stability. + * (The condition is equivalent to the need_adjacency() condition for an + * OSPF broadcast network, i.e., at least one endpoint must be DR/BDR.) + */ +int +keep_adjacency (struct ospf6_neighbor *on) +{ + struct ospf6_interface *oi = on->ospf6_if; + + return 1; //XXX Never tear down adjacencies, for fair comparison. + + if (oi->AdjConnectivity == OSPF6_ADJ_FULLYCONNECTED) + return 1; + + if (oi->mdr_level == OSPF6_MDR || oi->mdr_level == OSPF6_BMDR || + on->mdr_level == OSPF6_MDR || on->mdr_level == OSPF6_BMDR) + return 1; + else + return 0; +} +#endif //OSPF6_MANET_MDR_FLOOD + /* RFC2328 section 10.4 */ int need_adjacency (struct ospf6_neighbor *on) @@ -200,8 +555,79 @@ if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT || on->ospf6_if->state == OSPF6_INTERFACE_DR || on->ospf6_if->state == OSPF6_INTERFACE_BDR) +#ifdef OSPF6_MANET + { +#ifdef OSPF6_MANET_MDR_FLOOD + if (on->ospf6_if->flooding == OSPF6_FLOOD_MDR_SICDS && + on->ospf6_if->AdjConnectivity > OSPF6_ADJ_FULLYCONNECTED) + { + //Ogierv3 5 + struct ospf6_interface *oi = on->ospf6_if; + u_int32_t bp_rid = 0, p_rid = 0; + if (oi->flooding == OSPF6_FLOOD_MDR_SICDS && + oi->type == OSPF6_IFTYPE_MANETRELIABLE) + { + // Simplified rules for Ogierv7 + // Decision no longer depends on AdjConnectivity. + if (oi->mdr_level >= OSPF6_BMDR && on->mdr_level >= OSPF6_BMDR && + (on->dependent || on->dependent_selector)) + return 1; + + // Form adjacency between child and parent. + // The condition must be symmetric: child and parent must agree. + if (oi->mdr_level >= OSPF6_BMDR && on->child == true) + return 1; + // Return 1 if full adjacencies are used. + if (oi->full_adj_part_lsa) + return 1; + if (on->mdr_level >= OSPF6_BMDR) + { + if (oi->parent) + p_rid = oi->parent->router_id; + if (oi->bparent) + bp_rid = oi->bparent->router_id; + if (on->router_id == p_rid) + return 1; + if (on->router_id == bp_rid) + return 1; // backup parent is adjacent for biconnected + } + return 0; + } + return 1; + } +#endif //OSPF6_MANET_MDR_FLOOD +#if defined(OSPF6_MANET_MPR_FLOOD) && defined(OSPF6_MANET_MPR_SP) +//Changes by: Stan Ratliff +//Date: November 1st, 2005 +//Reason: Remove flag from struct ospf6_neighbor, on_need_adjacency +// Now the route availability is directly checked in spf_table_synch +// Copyright (C) 2005 + + //Roy-01 3.1 para 2 + else if (on->ospf6_if->flooding == OSPF6_FLOOD_MPR_SDCDS) + { + if (on->ospf6_if->smart_peering) + { + struct ospf6_route *route; + struct prefix prefix; + ospf6_linkstate_prefix (on->router_id, htonl (0), &prefix); + route = + ospf6_route_lookup(&prefix, on->ospf6_if->area->spf_table_sync); +// if (route && route->path.cost > 11) +// printf("1. SP-Route cost %d hops %d\n", +// route->path.cost, route->path.cost_e2); + if (route == NULL) + return 1; + else + return 0; + } + } +#endif //defined(OSPF6_MANET_MPR_FLOOD) && defined(OSPF6_MANET_MPR_SP) return 1; - + } +#else + return 1; +#endif //OSPF6_MANET if (on->ospf6_if->drouter == on->router_id || on->ospf6_if->bdrouter == on->router_id) return 1; @@ -247,6 +673,25 @@ thread_add_event (master, neighbor_change, on->ospf6_if, 0); +#ifdef OSPF6_MANET + if (on->ospf6_if->type == OSPF6_IFTYPE_MANETRELIABLE) + { +#ifdef OSPF6_MANET_MDR_FLOOD + if (on->ospf6_if->flooding == OSPF6_FLOOD_MDR_SICDS) + { + // must be run before calculate CDS, so neighbors are in correct state + // RGO. Require state to be INIT before changing to TWOWAY. + // This is necessary if multiple consecutive Hellos are required + // for changing state from DOWN to INIT in hello_received(). + // ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on); + if (on->state == OSPF6_NEIGHBOR_INIT) // For consecutive_hellos + ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on); + return 0; + } +#endif //OSPF6_MANET_MDR_FLOOD + } +#endif //OSPF6_MANET + if (! need_adjacency (on)) { ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on); @@ -294,8 +739,15 @@ for (lsa = ospf6_lsdb_head (on->ospf6_if->lsdb); lsa; lsa = ospf6_lsdb_next (lsa)) { +#ifdef OSPF6_MANET_TEMPORARY_LSDB + if (lsa->cache == 1) + continue; //lsa received in state below exchange +#endif //OSPF6_MANET_TEMPORARY_LSDB if (OSPF6_LSA_IS_MAXAGE (lsa)) { +#ifdef OSPF6_DELAYED_FLOOD + set_time(&lsa->rxmt_time); +#endif //OSPF6_DELAYED_FLOOD ospf6_increment_retrans_count (lsa); ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); } @@ -307,8 +759,15 @@ for (lsa = ospf6_lsdb_head (on->ospf6_if->area->lsdb); lsa; lsa = ospf6_lsdb_next (lsa)) { +#ifdef OSPF6_MANET_TEMPORARY_LSDB + if (lsa->cache == 1) + continue; //lsa received in state below exchange +#endif //OSPF6_MANET_TEMPORARY_LSDB if (OSPF6_LSA_IS_MAXAGE (lsa)) { +#ifdef OSPF6_DELAYED_FLOOD + set_time(&lsa->rxmt_time); +#endif //OSPF6_DELAYED_FLOOD ospf6_increment_retrans_count (lsa); ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); } @@ -320,8 +779,15 @@ for (lsa = ospf6_lsdb_head (on->ospf6_if->area->ospf6->lsdb); lsa; lsa = ospf6_lsdb_next (lsa)) { +#ifdef OSPF6_MANET_TEMPORARY_LSDB + if (lsa->cache == 1) + continue; //lsa received in state below exchange +#endif //OSPF6_MANET_TEMPORARY_LSDB if (OSPF6_LSA_IS_MAXAGE (lsa)) { +#ifdef OSPF6_DELAYED_FLOOD + set_time(&lsa->rxmt_time); +#endif //OSPF6_DELAYED_FLOOD ospf6_increment_retrans_count (lsa); ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); } @@ -511,6 +977,7 @@ if (on->state < OSPF6_NEIGHBOR_TWOWAY) return 0; + if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) zlog_debug ("Neighbor Event %s: *1Way-Received*", on->name); @@ -531,6 +998,20 @@ THREAD_OFF (on->thread_send_lsupdate); THREAD_OFF (on->thread_send_lsack); +#ifdef OSPF6_MANET + if (on->ospf6_if->type == OSPF6_IFTYPE_MANETRELIABLE) + { +#ifdef OSPF6_MANET_MPR_FLOOD + if (on->ospf6_if->flooding == OSPF6_FLOOD_MPR_SDCDS) + { +#ifdef OSPF6_MANET_DIFF_HELLO + on->ospf6_if->increment_scs = true; + on->below_exchange = true; +#endif //OSPF6_MANET_DIFF_HELLO + } +#endif //OSPF6_MANET_MPR_FLOOD + } +#endif //OSPF6_MANET return 0; } @@ -545,6 +1026,10 @@ if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) zlog_debug ("Neighbor Event %s: *InactivityTimer*", on->name); +#ifdef SIM_ETRACE_STAT + TraceEvent_sim(2,"Neighbor Event %s: *InactivityTimer*", on->name); +#endif //SIM_ETRACE_STAT + on->inactivity_timer = NULL; on->drouter = on->prev_drouter = 0; on->bdrouter = on->prev_bdrouter = 0; @@ -553,12 +1038,25 @@ thread_add_event (master, neighbor_change, on->ospf6_if, 0); listnode_delete (on->ospf6_if->neighbor_list, on); +#ifdef OSPF6_MANET + if (on->ospf6_if->type == OSPF6_IFTYPE_MANETRELIABLE) + { +#ifdef OSPF6_MANET_MDR_FLOOD + if (on->ospf6_if->flooding == OSPF6_FLOOD_MDR_SICDS) + { + // The following two functions are called when Hello + // is received, but no hello is received in this case. + ospf6_calculate_mdr(on->ospf6_if); + ospf6_mdr_update_adjacencies(on->ospf6_if); + } +#endif //OSPF6_MANET_MDR_FLOOD + } +#endif //OSPF6_MANET ospf6_neighbor_delete (on); return 0; } - /* vty functions */ /* show neighbor structure */ @@ -579,7 +1077,11 @@ } #endif /*HAVE_GETNAMEINFO*/ +#ifdef SIM + gettimeofday_sim (&now, NULL); +#else gettimeofday (&now, NULL); +#endif //SIM /* Dead time */ h = m = s = 0; @@ -594,7 +1096,13 @@ snprintf (deadtime, sizeof (deadtime), "%02ld:%02ld:%02ld", h, m, s); /* Neighbor State */ +#ifdef OSPF6_CONFIG + if(on->ospf6_if->type == OSPF6_IFTYPE_POINTOMULTIPOINT || + on->ospf6_if->type == OSPF6_IFTYPE_POINTOPOINT || + on->ospf6_if->type == OSPF6_IFTYPE_MANETRELIABLE) +#else if (if_is_pointopoint (on->ospf6_if->interface)) +#endif //OSPF6_CONFIG snprintf (nstate, sizeof (nstate), "PointToPoint"); else { @@ -641,7 +1149,11 @@ inet_ntop (AF_INET, &on->drouter, drouter, sizeof (drouter)); inet_ntop (AF_INET, &on->bdrouter, bdrouter, sizeof (bdrouter)); +#ifdef SIM + gettimeofday_sim (&now, NULL); +#else gettimeofday (&now, NULL); +#endif //SIM timersub (&now, &on->last_changed, &res); timerstring (&res, duration, sizeof (duration)); @@ -665,7 +1177,11 @@ inet_ntop (AF_INET, &on->drouter, drouter, sizeof (drouter)); inet_ntop (AF_INET, &on->bdrouter, bdrouter, sizeof (bdrouter)); +#ifdef SIM + gettimeofday_sim (&now, NULL); +#else gettimeofday (&now, NULL); +#endif //SIM timersub (&now, &on->last_changed, &res); timerstring (&res, duration, sizeof (duration)); @@ -772,7 +1288,7 @@ struct ospf6_neighbor *on; struct ospf6_interface *oi; struct ospf6_area *oa; - struct listnode *i, *j, *k; + plistnode i, j, k; void (*showfunc) (struct vty *, struct ospf6_neighbor *); OSPF6_CMD_CHECK_RUNNING (); @@ -835,7 +1351,7 @@ struct ospf6_neighbor *on; struct ospf6_interface *oi; struct ospf6_area *oa; - struct listnode *i, *j, *k; + plistnode i, j, k; void (*showfunc) (struct vty *, struct ospf6_neighbor *); u_int32_t router_id; @@ -970,4 +1486,769 @@ } +#ifdef OSPF6_MANET + +#ifdef OSPF6_MANET_MPR_FLOOD +void update_2hop_neighbor_list(struct ospf6_neighbor *o6n, + struct ospf6_lsa_header *lsa_header) +{ + plistnode n = NULL; + u_int32_t router_id; + struct ospf6_neighbor *on = NULL; + struct ospf6_2hop_neighbor *o62n = NULL; + struct ospf6_interface *o6i = o6n->ospf6_if; + char *start, *end, *current; + struct ospf6_router_lsa *router_lsa; + struct ospf6_router_lsdesc *router_lsd; + + if (o6n->state == OSPF6_NEIGHBOR_FULL) //XXX OR/SP + { + router_lsa = (struct ospf6_router_lsa *) + ((char *) lsa_header + sizeof (struct ospf6_lsa_header)); + start = (char *) router_lsa + sizeof (struct ospf6_router_lsa); + end = (char *) lsa_header + ntohs (lsa_header->length); + for (current = start; current + sizeof (struct ospf6_router_lsdesc) <= end; + current += sizeof (struct ospf6_router_lsdesc)) + { + router_lsd = (struct ospf6_router_lsdesc *) current; + router_id = router_lsd->neighbor_router_id; + if (ntohl(router_lsd->interface_id) != o6n->ifindex) + continue; //link must be on MANET subnet +#ifdef OSPF6_MANET_MPR_SP + if (ROUTER_LSDESC_IS_UNSYNC(router_lsd)) //BUGFIX_SP + continue; +#endif //OSPF6_MANET_MPR_SP + on = ospf6_neighbor_lookup(router_id, o6i); + if ((!on || on->state < OSPF6_NEIGHBOR_FULL) && //XXX OR/SP + router_id != ospf6->router_id) + { //can't be a one hop and a two hop neighbor + //and can't be the router itself + o62n = ospf6_2hop_neighbor_lookup(router_id,o6n->two_hop_neighbor_list); + if(!o62n) + o62n = ospf6_add_2hop_neighbor(router_id, o6n); + o62n->updated = true; + } + } + } + + /* clean up any neighbors that no longer exist in router LSA */ + if (o6n->two_hop_neighbor_list) + n = listhead (o6n->two_hop_neighbor_list); + while (n) + { + o62n = (struct ospf6_2hop_neighbor *) getdata (n); + nextnode (n); + if (!o62n->updated) + ospf6_2hop_neighbor_delete(o6n, o62n); + else + o62n->updated = false; + } + return; +} + +struct ospf6_2hop_neighbor * +ospf6_2hop_neighbor_lookup (u_int32_t router_id, + pList two_hop_neighbor_list) +{ + plistnode n; + struct ospf6_2hop_neighbor *o62n; + + if (!two_hop_neighbor_list) + return NULL; + + for (n = listhead(two_hop_neighbor_list); n; nextnode(n)) + { + o62n = (struct ospf6_2hop_neighbor *) getdata (n); + if (o62n->router_id == router_id) + return o62n; + } + return NULL; +} + +struct ospf6_2hop_neighbor * +ospf6_add_2hop_neighbor(u_int32_t router_id, struct ospf6_neighbor *o6n) +{ + plistnode n; + struct ospf6_2hop_neighbor *o62n = NULL; + struct ospf6_interface *o6i = o6n->ospf6_if; + + /* is 2hop already in neighbor's neighbor list */ + o62n = ospf6_2hop_neighbor_lookup(router_id,o6n->two_hop_neighbor_list); + if(o62n) + return o62n; + + /* is 2hop neighbor another neighbor's 2hop neighbor */ + for (n = listhead(o6i->two_hop_list); n; nextnode(n)) + { + o62n = (struct ospf6_2hop_neighbor *) getdata(n); + if (o62n->router_id == router_id) + break; + o62n = NULL; + } + + if(!o62n) + { + o62n = (struct ospf6_2hop_neighbor *) + malloc(sizeof(struct ospf6_2hop_neighbor)); + o62n->one_hop_neighbor_list = list_new(); + o62n->router_id = router_id; + listnode_add(o6i->two_hop_list, o62n); + } + listnode_add(o6n->two_hop_neighbor_list, o62n); + listnode_add(o62n->one_hop_neighbor_list, o6n); //didn't check if existing + o6n->ospf6_if->mpr_change = true; + + return o62n; +} + +void ospf6_2hop_list_delete(struct ospf6_neighbor *o6n) +{ + plistnode n; + struct ospf6_2hop_neighbor *o62n = NULL; + + n = listhead(o6n->two_hop_neighbor_list); + while(n) + { + o62n = (struct ospf6_2hop_neighbor *) getdata(n); + nextnode(n); + ospf6_2hop_neighbor_delete(o6n, o62n); + } + list_delete(o6n->two_hop_neighbor_list); + o6n->two_hop_neighbor_list = NULL; +} + +void ospf6_2hop_neighbor_delete(struct ospf6_neighbor *o6n, + struct ospf6_2hop_neighbor *o62n) +{ + listnode_delete(o6n->two_hop_neighbor_list, o62n); + listnode_delete(o62n->one_hop_neighbor_list, o6n); + o6n->ospf6_if->mpr_change = true; + + if (o62n->one_hop_neighbor_list->count == 0) + { + /* Delete 2hop neighbor from interface list + * It is no longer a 2hop neighbor of any neighbor + */ + listnode_delete(o6n->ospf6_if->two_hop_list, o62n); + list_delete(o62n->one_hop_neighbor_list); + free(o62n); + } +} + +void ospf6_update_neighborhood(struct ospf6_interface *o6i) +{ + plistnode n; + struct ospf6_area *area = o6i->area; + struct ospf6_neighbor *o6n; + struct ospf6_lsa *lsa; + for (n = listhead(o6i->neighbor_list); n; nextnode(n)) + { + o6n = (struct ospf6_neighbor *) getdata(n); + lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_ROUTER), htonl(0), + o6n->router_id, area->lsdb); + if (lsa) + update_2hop_neighbor_list(o6n, lsa->header); + } +} + +#ifdef OSPF6_MANET_MPR_SP +//Changes by: Stan Ratliff +//Date: November 1st, 2005 +//Reason: Check if adjacencies need to be added +// Copyright (C) 2005 + +boolean ospf6_or_update_adjacencies(struct ospf6_interface *oi) +{ + plistnode n; + struct ospf6_neighbor *on; + boolean new_adjacency = false; + + if (!oi->smart_peering) + return new_adjacency; + + for (n = listhead(oi->neighbor_list); n; nextnode(n)) + { + on = (struct ospf6_neighbor *) getdata(n); + if (on->state != OSPF6_NEIGHBOR_TWOWAY) + continue; + if (need_adjacency (on)) + { + ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on); + SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT); + SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT); + SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT); + + THREAD_OFF (on->thread_send_dbdesc); + on->thread_send_dbdesc = + thread_add_event (master, ospf6_dbdesc_send, on, 0); + new_adjacency = true; + } + } + return new_adjacency; +} +#endif //OSPF6_MANET_MPR_SP + +#ifdef OSPF6_MANET_DIFF_HELLO +/* + * drop neighbor functions + */ +void ospf6_drop_neighbor_create(struct ospf6_neighbor *o6n) +{ + struct drop_neighbor *drop_neigh = NULL; + + drop_neigh = ospf6_lookup_drop_neighbor(o6n->ospf6_if, o6n->router_id); + + if (!drop_neigh) + { // new drop neighbor + drop_neigh = (struct drop_neighbor *) malloc(sizeof(struct drop_neighbor)); + drop_neigh->expire_time = (struct timeval *) malloc(sizeof(struct timeval)); + drop_neigh->router_id = o6n->router_id; + drop_neigh->first = true; + listnode_add(o6n->ospf6_if->drop_neighbor_list, drop_neigh); + } + set_time(drop_neigh->expire_time); +} + +void ospf6_drop_neighbor_delete(struct ospf6_interface *o6i, + struct drop_neighbor *dneigh) +{ + listnode_delete(o6i->drop_neighbor_list, dneigh); + free(dneigh->expire_time); + free(dneigh); +} + +struct drop_neighbor *ospf6_lookup_drop_neighbor(struct ospf6_interface *oi, + u_int32_t id) +{ + plistnode n; + struct drop_neighbor *drop_neigh = NULL; + + n = listhead(oi->drop_neighbor_list); + while(n) + { + drop_neigh = (struct drop_neighbor *) getdata (n); + nextnode(n); + + if (elapsed_time(drop_neigh->expire_time) > oi->dead_interval) + { + ospf6_drop_neighbor_delete(oi, drop_neigh); + } + else if (id == drop_neigh->router_id) + break; + drop_neigh = NULL; + } + return drop_neigh; +} +#endif //OSPF6_MANET_DIFF_HELLO +#endif //OSPF6_MANET_MPR_FLOOD + +// Section 3.4.3 bullet 2 +void ospf6_store_mack(struct ospf6_neighbor *on, + struct ospf6_lsa_header *lsa_header) +{ + struct ospf6_mack *mack = NULL; + + if (on->ospf6_if->type != OSPF6_IFTYPE_MANETRELIABLE) + return; + + mack = ospf6_lookup_mack(on, lsa_header); + + if (!mack) + { //mack does not exist, allocate mack and add to mack list + mack = (struct ospf6_mack *) malloc(sizeof(struct ospf6_mack)); + mack->expire_time = (struct timeval *) malloc(sizeof(struct timeval)); + mack->type = lsa_header->type; + mack->id = lsa_header->id; + mack->adv_router = lsa_header->adv_router; + listnode_add(on->mack_list, mack); + } + mack->seqnum = lsa_header->seqnum; + set_time(mack->expire_time); + return; +} + +struct ospf6_mack *ospf6_lookup_mack(struct ospf6_neighbor *on, + struct ospf6_lsa_header *lsa_header) +{ + plistnode n; + struct ospf6_mack *mack = NULL; + + if (on->ospf6_if->type != OSPF6_IFTYPE_MANETRELIABLE) + return NULL; + + n = listhead(on->mack_list); + while(n) + { + mack = (struct ospf6_mack *) getdata(n); + nextnode(n); + + if (elapsed_time(mack->expire_time) > on->ospf6_if->ack_cache_timeout) + { //delete expired mack + listnode_delete(on->mack_list, mack); + free(mack->expire_time); + free(mack); + continue; + } + if (mack->type == lsa_header->type && + mack->id == lsa_header->id && + mack->adv_router == lsa_header->adv_router && + ntohl(mack->seqnum) >= ntohl(lsa_header->seqnum)) + { + return mack; // this is the ack being searched for -> return ptr + } + } + return NULL; // mack not found +} + +void ospf6_mack_list_delete(struct ospf6_neighbor *on) +{ //delete all entries in mack list then delete mack list + plistnode n; + struct ospf6_mack *mack = NULL; + + n = listhead(on->mack_list); + while(n) + { + mack = (struct ospf6_mack *) getdata(n); + nextnode(n); + free(mack->expire_time); + free(mack); + } + list_delete(on->mack_list); + on->mack_list = NULL; +} + + +#ifdef OSPF6_MANET +int ospf6_manet_update_routable_neighbors(struct ospf6_interface *oi) +// Updates the set of routable neighbors, by checking if a route +// exists to each neighbor. Returns 1 if there is a change. +{ + plistnode j; + struct ospf6_neighbor *on; + struct ospf6_route *route; + struct prefix prefix; + int change = 0; + + for (j = listhead(oi->neighbor_list); j; nextnode(j)) + { + on = (struct ospf6_neighbor *) getdata (j); + if (!on) continue; + ospf6_linkstate_prefix (on->router_id, htonl (0), &prefix); + + if (oi->flooding == OSPF6_FLOOD_MDR_SICDS) + { + route = ospf6_route_lookup(&prefix, on->ospf6_if->area->spf_table); + if (!on->routable) + { +#ifdef OSPF6_MANET_MDR_LQ + int link_quality = 0, i; + for (i=0; i < 3; i++) + link_quality += on->link_quality[i]; + + if (on->state == OSPF6_NEIGHBOR_FULL || + (route && on->state >= OSPF6_NEIGHBOR_TWOWAY && + (!oi->link_quality || (oi->link_quality && link_quality>2)))) +#else + if (on->state == OSPF6_NEIGHBOR_FULL || + (route && on->state >= OSPF6_NEIGHBOR_TWOWAY && + on->reverse_2way)) // RGO. Always require reverse_2way. +#endif //OSPF6_MANET_MDR_LQ + { + on->routable = 1; + change = 1; + } + } + if (on->routable && on->state < OSPF6_NEIGHBOR_TWOWAY) + { + on->routable = 0; + change = 1; + } + } +#ifdef OSPF6_MANET_MPR_SP + if (oi->flooding == OSPF6_FLOOD_MPR_SDCDS) + { +// route = ospf6_route_lookup(&prefix,on->ospf6_if->area->spf_table); + route = ospf6_route_lookup(&prefix,on->ospf6_if->area->spf_table_sync);//BUGFIX_SP + //if (route && on->state != OSPF6_NEIGHBOR_FULL) + // printf("2. SP-Route cost %d\n", route->path.cost); + if (!on->routable && (on->state == OSPF6_NEIGHBOR_FULL || + (route && on->state >= OSPF6_NEIGHBOR_TWOWAY))) + { + on->routable = 1; + change = 1; + } + if (on->routable && on->state < OSPF6_NEIGHBOR_TWOWAY) + { + on->routable = 0; + change = 1; + } + } +#endif //OSPF6_MANET_MPR_SP + } + return change; +} + + + +#endif //OSPF6_MANET + +#ifdef OSPF6_MANET_MDR_FLOOD +// ospf6_mdr_update_adv_neighbors() was written by Richard Ogier +// and implements min-cost LSAs as described in +// draft-ogier-manet-ospf-extension-06.txt +int ospf6_mdr_update_adv_neighbors(struct ospf6_interface *oi) +{ + plistnode j, k, u; + struct ospf6_neighbor *onj, *onk, *onu, *min_onu; + int change = 0, j_index, k_index, u_index; + int count = 0; + int costj, costk, min_cost; + u_int32_t router_id = oi->area->ospf6->router_id; + + // cost_matrix determines which nbrs are nbrs of each other. + ospf6_mdr_create_cost_matrix(oi); + // lsa_cost_matrix gets inter-nbr costs from nbr LSAs + ospf6_mdr_create_lsa_cost_matrix(oi); + + // Initialize new set of advertised neighbors, so that only + // FULL neighbors are advertised. + for (j = listhead(oi->neighbor_list); j; nextnode(j)) + { + onj = (struct ospf6_neighbor *) getdata (j); + if (onj->state == OSPF6_NEIGHBOR_FULL) onj->new_adv = true; + else onj->new_adv = false; + } + + // For each pair of routable nbrs j, k that are not nbrs of each other, + // find the best intermediate node u to connect j and k. + + for (j = listhead(oi->neighbor_list); j; nextnode(j)) + { + onj = (struct ospf6_neighbor *) getdata (j); + if (!onj) continue; + if (onj->state < OSPF6_NEIGHBOR_TWOWAY) continue; + if (!onj->routable) continue; + j_index = onj->cost_matrix_index; + for (k = listhead(oi->neighbor_list); k; nextnode(k)) + { + onk = (struct ospf6_neighbor *) getdata (k); + if (!onk) continue; + if (onk->state < OSPF6_NEIGHBOR_TWOWAY) continue; + if (!onk->routable) continue; + k_index = onk->cost_matrix_index; + if (oi->cost_matrix[j_index][k_index] == 1) + continue; // j and k must not be neighbors of each other + + min_cost = LS_INFINITY; // find min cost 2-hop path between j and k + min_onu = NULL; // find best intermediate node + // The difference between LSAFullness MINHOP and MINHOP2PATHS applied + // here. For MINHOP, the LSA need not contain links to both j and k, + // but only to j. This will determine whether the router should add + // j to its LSA. min_cost will be the cost of the link to j. + // MINHOP2PATHS contains the old MINHOP (requiring links to both j and k) + for (u = listhead(oi->neighbor_list); u; nextnode(u)) + { + onu = (struct ospf6_neighbor *) getdata (u); + if (!onu) continue; + if (onu->state < OSPF6_NEIGHBOR_TWOWAY) continue; + u_index = onu->cost_matrix_index; + if (oi->LSAFullness == OSPF6_LSA_FULLNESS_MINHOP) { + if (min_cost > oi->lsa_cost_matrix[u_index][j_index] || + (min_cost == oi->lsa_cost_matrix[u_index][j_index] && min_onu && + ospf6_sidcds_lexicographic(oi,onu->mdr_level, min_onu->mdr_level, + 0, 0, ntohl(onu->router_id), ntohl(min_onu->router_id)))) + { + min_onu = onu; + min_cost = oi->lsa_cost_matrix[u_index][j_index]; + } + } else if (oi->LSAFullness == OSPF6_LSA_FULLNESS_MINHOP2PATHS) { + if (min_cost > oi->lsa_cost_matrix[u_index][k_index] + + oi->lsa_cost_matrix[u_index][j_index] || + (min_cost == oi->lsa_cost_matrix[u_index][k_index] + + oi->lsa_cost_matrix[u_index][j_index] && min_onu && + ospf6_sidcds_lexicographic(oi, onu->mdr_level, min_onu->mdr_level, + 0, 0, ntohl(onu->router_id), ntohl(min_onu->router_id)))) + { + min_onu = onu; + min_cost = oi->lsa_cost_matrix[u_index][k_index] + + oi->lsa_cost_matrix[u_index][j_index]; + } + } else { + printf("Wrong LSAFullness in this function\n"); + exit(1); + } + } + // Determine costs to j and k (as would be advertised in LSA) + if (onj->state == OSPF6_NEIGHBOR_FULL) costj = 10; + else costj = 11; + if (onk->state == OSPF6_NEIGHBOR_FULL) costk = 10; + else costk = 11; + + if (oi->LSAFullness == OSPF6_LSA_FULLNESS_MINHOP) { + // If j is advertised, then keep j as adv if min_onu + // gives a larger cost or the same cost and smaller (mdr_level, rid). + if (onj->adv) + { + if (min_cost > costj || (min_cost == costj && + ospf6_sidcds_lexicographic(oi, oi->mdr_level, min_onu->mdr_level, + 0, 0, ntohl(router_id), ntohl(min_onu->router_id)))) + { + onj->new_adv = true; + } + } + // If j is not advertised, then adv j only if min_onu + // gives a larger cost. + if (!onj->adv) + { + if (min_cost > costj) + { + onj->new_adv = true; + } + } + } else { // LSAFullness == OSPF6_LSA_FULLNESS_MINHOP2PATHS + // If j and k are both advertised, then keep both as adv if min_onu + // gives a larger cost or the same cost and smaller (mdr_level, rid). + if (onj->adv && onk->adv) + { + if (min_cost > costj + costk || (min_cost == costj + costk && + ospf6_sidcds_lexicographic(oi, oi->mdr_level, min_onu->mdr_level, + 0, 0, ntohl(router_id), ntohl(min_onu->router_id)))) + { + onj->new_adv = onk->new_adv = true; + } + } + // If j and k are not both advertised, then adv both only if min_onu + // gives a larger cost. + if (!onj->adv || !onk->adv) + { + if (min_cost > costj + costk) + { + onj->new_adv = onk->new_adv = true; + } + } + } + } + } + // Update set of advertised neighbors. + for (j = listhead(oi->neighbor_list); j; nextnode(j)) + { + onj = (struct ospf6_neighbor *) getdata (j); + if (onj->new_adv) count++; + if (!onj->adv && onj->new_adv) + { + onj->adv = true; + //printf("at %d %d nbr %d changed to %d \n", + //router_id, oi->interface->ifindex, onj->router_id, onj->adv); + change = 1; + } + if (onj->adv && !onj->new_adv) + { + onj->adv = false; + // Do not indicate a change if nbr changed from adv to not adv + // but is still 2-way. + if (onj->state < OSPF6_NEIGHBOR_TWOWAY) + change = 1; + } + } + //printf("number of adv nbrs %d number of nbrs %d \n", + //count, oi->neighbor_list->count); + ospf6_mdr_free_cost_matrix(oi); + ospf6_mdr_free_lsa_cost_matrix(oi); + return change; +} + +void ospf6_mdr_create_lsa_cost_matrix(struct ospf6_interface *oi) +{ + plistnode j; + u_int32_t id; + struct ospf6_neighbor *onj, *onk; + int count = 0; + int num_neigh = oi->neighbor_list->count; + int index2, size; //, metric; + struct ospf6_lsa *lsa; + caddr_t lsdesc; + + if (oi->lsa_cost_matrix) + { + printf("lsa cost matrix should be NULL\n"); + exit(0); + } + + //intialize matrix to LS_INFINITY + oi->lsa_cost_matrix = (int **) malloc(sizeof(int*[num_neigh])); + for (j = listhead(oi->neighbor_list); j; nextnode(j)) + { + onj = (struct ospf6_neighbor *) getdata (j); + //if (!onj) continue; + //if (onj->state < OSPF6_NEIGHBOR_TWOWAY) continue; + //onj->cost_matrix_index = count; // Done in create_cost_matrix(). + oi->lsa_cost_matrix[count] = (int *) malloc(sizeof(int[num_neigh])); + //memset (oi->cost_matrix[count++], 0, sizeof (int[num_neigh])); + for (index2 = 0; index2 < num_neigh; index2++) + oi->lsa_cost_matrix[count][index2] = LS_INFINITY; + count++; + } + + //set matrix values by looking at each neighbor's LSA + for (j = listhead(oi->neighbor_list); j; nextnode(j)) + { + onj = (struct ospf6_neighbor *) getdata (j); + //if (!onj) continue; + if (onj->state < OSPF6_NEIGHBOR_TWOWAY) continue; + lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_ROUTER), htonl (0), + onj->router_id, oi->area->lsdb); + if (lsa == NULL) continue; + // For each LS description in the neighbor's LSA + size = sizeof (struct ospf6_router_lsdesc); + for (lsdesc = OSPF6_LSA_HEADER_END (lsa->header) + 4; + lsdesc + size <= OSPF6_LSA_END (lsa->header); lsdesc += size) + { + id = ROUTER_LSDESC_GET_NBR_ROUTERID (lsdesc); + onk = ospf6_neighbor_lookup (id, oi); + if (!onk) continue; + oi->lsa_cost_matrix[onj->cost_matrix_index][onk->cost_matrix_index] + = ROUTER_LSDESC_GET_METRIC (lsdesc); + //metric = ROUTER_LSDESC_GET_METRIC (lsdesc); + //printf("at %d, cost from %d to %d is %d \n", + //ospf6->router_id, onj->cost_matrix_index, onk->cost_matrix_index, metric); + } + } +} + +void ospf6_mdr_free_lsa_cost_matrix(struct ospf6_interface *oi) +{ + u_int i; + + //free matrix + for (i = 0; i < oi->neighbor_list->count; i++) + free(oi->lsa_cost_matrix[i]); + free(oi->lsa_cost_matrix); + oi->lsa_cost_matrix = NULL; +} + +void ospf6_mdr_delete_all_neighbors(pList n_list) +{ + plistnode n; + u_int32_t *neigh; + for (n = listhead (n_list); n; nextnode(n)) + { + neigh = (u_int32_t *) getdata(n); + free(neigh); + } + list_delete_all_node(n_list); +} + +void ospf6_mdr_add_neighbor(pList n_list, u_int32_t id) +{ + u_int32_t *neigh = (u_int32_t *) malloc(sizeof(u_int32_t)); + *neigh = id; + listnode_add(n_list, neigh); +} + +// ZZZ +boolean ospf6_mdr_lookup_neighbor(pList n_list, u_int32_t id) +{ + plistnode n; + u_int32_t *neigh_id; + for (n = listhead(n_list); n; nextnode(n)) + { + neigh_id = (u_int32_t *) getdata(n); + if (id == *neigh_id) + return true; + } + return false; +} + +// Return true if list is changed. +boolean ospf6_mdr_delete_neighbor(pList n_list, u_int32_t id) +{ + plistnode n; + u_int32_t *neigh_id; + boolean changed = false; + + n = listhead(n_list); + while (n) + { + neigh_id = (u_int32_t *) getdata(n); + nextnode(n); + + if (id == *neigh_id) + { + free(neigh_id); + listnode_delete(n_list, neigh_id); + changed = true; + } + } + return changed; +} + +void ospf6_mdr_delete_neighbor_list(pList n_list) +{ + plistnode n; + u_int32_t *id; + for (n = listhead(n_list); n; nextnode(n)) + { + id = (u_int32_t *) getdata(n); + free(id); + } + list_delete (n_list); +} +#ifdef OSPF6_MANET_DIFF_HELLO +//HNL Functions +void ospf6_mdr_add_lnl_element(struct ospf6_neighbor *on) +{ + struct ospf6_interface *oi = on->ospf6_if; + struct ospf6_lnl_element *lnl_element; + + lnl_element = ospf6_mdr_lookup_lnl_element(on); + + if (lnl_element) + { + lnl_element->hsn = oi->hsn; + return; + } + + lnl_element = + (struct ospf6_lnl_element *) malloc(sizeof(struct ospf6_lnl_element)); + lnl_element->id = on->router_id; + lnl_element->hsn = oi->hsn; + listnode_add(oi->lnl, lnl_element); +} + +struct ospf6_lnl_element * +ospf6_mdr_lookup_lnl_element(struct ospf6_neighbor *on) +{ + plistnode n; + struct ospf6_interface *oi = on->ospf6_if; + struct ospf6_lnl_element *lnl_element = NULL; + + for (n = listhead(oi->lnl); n; nextnode(n)) + { + lnl_element = (struct ospf6_lnl_element *) getdata(n); + if (on->router_id == lnl_element->id) + return lnl_element; + } + return lnl_element; +} + +void ospf6_mdr_delete_lnl_element(struct ospf6_interface *oi, + struct ospf6_lnl_element *lnl_element) +{ + listnode_delete(oi->lnl, lnl_element); + free(lnl_element); +} + +#ifdef OSPF6_MANET_MDR_LQ +void ospf6_mdr_update_link_quality(struct ospf6_neighbor*on, boolean quality) +{ + on->link_quality[0] = on->link_quality[1]; + on->link_quality[1] = on->link_quality[2]; + on->link_quality[2] = quality; +} +#endif //OSPF6_MANET_MDR_LQ + +#endif //OSPF6_MANET_DIFF_HELLO + +#endif //OSPF6_MANET_MDR_FLOOD +#endif //OSPF6_MANET diff -Naur quagga-0.98.5/ospf6d/ospf6_neighbor.h quagga-0.98.5-manet/ospf6d/ospf6_neighbor.h --- quagga-0.98.5/ospf6d/ospf6_neighbor.h 2004-10-10 05:54:58.000000000 -0700 +++ quagga-0.98.5-manet/ospf6d/ospf6_neighbor.h 2006-02-20 13:42:12.000000000 -0800 @@ -22,6 +22,19 @@ #ifndef OSPF6_NEIGHBOR_H #define OSPF6_NEIGHBOR_H +#if defined(SIM) || defined(OSPF6_MANET) +#include "ospf6_message.h" +#endif //SIM + +#ifdef OSPF6_MANET +#include "ospf6_lsa.h" +#endif //OSPF6_MANET + +#ifdef OSPF6_MANET_MDR_FLOOD +#include "ospf6_lsdb.h" +#include "ospf6_mdr.h" +#endif //OSPF6_MANET_MDR_FLOOD + /* Debug option */ extern unsigned char conf_debug_ospf6_neighbor; #define OSPF6_DEBUG_NEIGHBOR_STATE 0x01 @@ -93,7 +106,91 @@ struct thread *thread_send_lsreq; struct thread *thread_send_lsupdate; struct thread *thread_send_lsack; + +#ifdef OSPF6_MANET + pList mack_list; + boolean routable; +#endif //OSPF6_MANET + +#ifdef OSPF6_MANET_MPR_FLOOD + pList two_hop_neighbor_list; + boolean covered; + boolean Fbit; + boolean Relay_Abit; + boolean Relay_Nbit; +#endif //OSPF6_MANET_MPR_FLOOD + +#ifdef OSPF6_MANET_DIFF_HELLO + boolean below_exchange; // Chandra03 3.3.6.1 bullet 3 + u_int16_t scs_num; //Chandra03 3.3.8 paragraph 1 + boolean set_scs_num; + boolean request; +#endif //OSPF6_MANET_DIFF_HELLO + +#ifdef OSPF6_MANET_MDR_FLOOD + //New neighbor variables. + boolean dependent; + boolean dependent_selector; + boolean adv; // advertised neighbor + boolean new_adv; + pList rnl; // List of router IDs. + pList lnl; + struct ospf6_neighbor *parent; + int hops; + int hops2; + struct tree_node *treenode; + boolean child; + boolean Report2Hop; + boolean reverse_2way; + int mdr_level; + struct timeval mdr_install_time; + int cost_matrix_index; +#ifdef OSPF6_MANET_MDR_LQ + boolean link_quality[3]; +#endif //OSPF6_MANET_MDR_LQ +#ifdef OSPF6_MANET_DIFF_HELLO + u_int16_t hsn; + u_int16_t changed_hsn; +#endif //OSPF6_MANET_DIFF_HELLO +#endif //OSPF6_MANET_MDR_FLOOD + +#ifdef SIM //ETRACE + struct timeval creation_time; +#endif //SIM + +}; + +#ifdef OSPF6_MANET +struct ospf6_mack +{ + u_int16_t age; /* LS age */ + u_int16_t type; /* LS type */ + u_int32_t id; /* Link State ID */ + u_int32_t adv_router; /* Advertising Router */ + u_int32_t seqnum; /* LS sequence number */ + struct timeval *expire_time; +}; + +#ifdef OSPF6_MANET_MPR_FLOOD +struct ospf6_2hop_neighbor +{ + u_int32_t router_id; + boolean covered; + boolean updated; + pList one_hop_neighbor_list; }; +#endif //OSPF6_MANET_MPR_FLOOD + +#if defined(OSPF6_MANET_MDR_FLOOD) && defined(OSPF6_MANET_DIFF_HELLO) +struct ospf6_lnl_element +{ + u_int32_t id; + u_int16_t hsn; +}; +#endif //OSPF6_MANET_DIFF_HELLO && OSPF6_MANET_MDR_FLOOD + +#endif //OSPF6_MANET + /* Neighbor state */ #define OSPF6_NEIGHBOR_DOWN 1 @@ -134,5 +231,72 @@ int config_write_ospf6_debug_neighbor (struct vty *vty); void install_element_ospf6_debug_neighbor (); -#endif /* OSPF6_NEIGHBOR_H */ +#ifdef OSPF6_MANET +void ospf6_store_mack(struct ospf6_neighbor *on, + struct ospf6_lsa_header *lsa_header); +struct ospf6_mack *ospf6_lookup_mack(struct ospf6_neighbor *on, + struct ospf6_lsa_header *lsa_header); +void ospf6_mack_list_delete(struct ospf6_neighbor *on); +int ospf6_manet_update_routable_neighbors(struct ospf6_interface *oi); + +#ifdef OSPF6_MANET_MPR_FLOOD +void update_2hop_neighbor_list(struct ospf6_neighbor *o6n, + struct ospf6_lsa_header *lsa_header); +struct ospf6_2hop_neighbor *ospf6_2hop_neighbor_lookup (u_int32_t router_id, + pList two_hop_neighbor_list); +struct ospf6_2hop_neighbor *ospf6_add_2hop_neighbor(u_int32_t router_id, + struct ospf6_neighbor *o6n); +void ospf6_2hop_list_delete(struct ospf6_neighbor *o6n); +void ospf6_2hop_neighbor_delete(struct ospf6_neighbor *o6n, + struct ospf6_2hop_neighbor *o62n); +void ospf6_update_neighborhood(struct ospf6_interface *o6i); + +#ifdef OSPF6_MANET_MPR_SP +boolean ospf6_or_update_adjacencies(struct ospf6_interface *oi); +#endif //OSPF6_MANET_MPR_SP + +#ifdef OSPF6_MANET_DIFF_HELLO +struct drop_neighbor; +struct drop_neighbor *ospf6_lookup_drop_neighbor(struct ospf6_interface *oi, + u_int32_t id); +void ospf6_drop_neighbor_delete(struct ospf6_interface *o6i, + struct drop_neighbor *element); +void ospf6_drop_neighbor_create(struct ospf6_neighbor *o6n); +#endif //OSPF6_MANET_DIFF_HELLO +#endif //OSPF6_MANET_MPR_FLOOD + +#ifdef OSPF6_MANET_MDR_FLOOD +int need_adjacency (struct ospf6_neighbor *on); +int keep_adjacency (struct ospf6_neighbor *on); +void ospf6_mdr_delete_all_neighbors(pList n_list); +void ospf6_mdr_add_neighbor(pList n_list, u_int32_t id); +boolean ospf6_mdr_delete_neighbor(pList n_list, u_int32_t id); +boolean ospf6_mdr_lookup_neighbor(pList n_list, u_int32_t id); +void ospf6_mdr_delete_neighbor_list(pList n_list); +void ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on); +#ifdef OSPF6_MANET_DIFF_HELLO +int ospf6_insufficienthellosreceived (struct ospf6_neighbor *on); +void ospf6_mdr_add_lnl_element(struct ospf6_neighbor *on); +struct ospf6_lnl_element * + ospf6_mdr_lookup_lnl_element(struct ospf6_neighbor *on); +void ospf6_mdr_delete_lnl_element(struct ospf6_interface *oi, + struct ospf6_lnl_element *lnl_element); +void ospf6_mdr_create_lsa_cost_matrix(struct ospf6_interface *oi); +int ospf6_mdr_update_adv_neighbors(struct ospf6_interface *oi); +void ospf6_mdr_free_lsa_cost_matrix(struct ospf6_interface *oi); +#ifdef OSPF6_MANET_MDR_LQ +void ospf6_mdr_update_link_quality(struct ospf6_neighbor*on, boolean quality); +#endif //OSPF6_MANET_MDR_LQ +#endif //OSPF6_MANET_DIFF_HELLO +#endif //OSPF6_MANET_MDR_FLOOD + +#endif //OSPF6_MANET + + +#ifdef SIM_ETRACE_STAT +void ospf6_neighbor_state_change_stats (u_char prev_state, u_char next_state, + struct ospf6_neighbor *on); +#endif //SIM_ETRACE_STAT + +#endif /* OSPF6_NEIGHBOR_H */ diff -Naur quagga-0.98.5/ospf6d/ospf6_network.c quagga-0.98.5-manet/ospf6d/ospf6_network.c --- quagga-0.98.5/ospf6d/ospf6_network.c 2004-12-23 22:00:12.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_network.c 2006-02-20 13:42:12.000000000 -0800 @@ -24,12 +24,19 @@ #include "log.h" #include "memory.h" #include "sockunion.h" +#ifndef SIM #include "sockopt.h" +#endif //SIM #include "privs.h" #include "ospf6_proto.h" #include "ospf6_network.h" +#ifdef SIM +#include "sim.h" +#include "ospf6_interface.h" +#endif //SIM + extern struct zebra_privs_t ospf6d_privs; int ospf6_sock; @@ -41,9 +48,14 @@ ospf6_set_reuseaddr () { u_int on = 0; +#ifdef SIM + if (setsockopt_sim (ospf6_sock, SOL_SOCKET, SO_REUSEADDR, &on, + sizeof (u_int)) < 0) +#else if (setsockopt (ospf6_sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (u_int)) < 0) - zlog_warn ("Network: set SO_REUSEADDR failed: %s", safe_strerror (errno)); +#endif //SIM + zlog_warn ("Network: set SO_REUSEADDR failed: %s", strerror (errno)); } /* setsockopt MulticastLoop to off */ @@ -51,16 +63,25 @@ ospf6_reset_mcastloop () { u_int off = 0; +#ifdef SIM + if (setsockopt_sim (ospf6_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, + &off, sizeof (u_int)) < 0) +#else if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, sizeof (u_int)) < 0) +#endif //SIM zlog_warn ("Network: reset IPV6_MULTICAST_LOOP failed: %s", - safe_strerror (errno)); + strerror (errno)); } void ospf6_set_pktinfo () { +#ifdef SIM + setsockopt_ipv6_pktinfo_sim (ospf6_sock, 1); +#else setsockopt_ipv6_pktinfo (ospf6_sock, 1); +#endif //SIM } void @@ -68,9 +89,14 @@ { int offset = 12; #ifndef DISABLE_IPV6_CHECKSUM +#ifdef SIM + if (setsockopt_sim (ospf6_sock, IPPROTO_IPV6, IPV6_CHECKSUM, + &offset, sizeof (offset)) < 0) +#else if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_CHECKSUM, &offset, sizeof (offset)) < 0) - zlog_warn ("Network: set IPV6_CHECKSUM failed: %s", safe_strerror (errno)); +#endif //SIM + zlog_warn ("Network: set IPV6_CHECKSUM failed: %s", strerror (errno)); #else zlog_warn ("Network: Don't set IPV6_CHECKSUM"); #endif /* DISABLE_IPV6_CHECKSUM */ @@ -80,6 +106,7 @@ int ospf6_serv_sock () { +#ifndef SIM if (ospf6d_privs.change (ZPRIVS_RAISE)) zlog_err ("ospf6_serv_sock: could not raise privs"); @@ -102,7 +129,10 @@ #endif /*1*/ ospf6_reset_mcastloop (); ospf6_set_pktinfo (); +#ifndef USER_CHECKSUM ospf6_set_checksum (); +#endif +#endif //SIM /* setup global in6_addr, allspf6 and alldr6 for later use */ inet_pton (AF_INET6, ALLSPFROUTERS6, &allspfrouters6); @@ -122,8 +152,13 @@ memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6, sizeof (struct in6_addr)); +#ifdef SIM + retval = setsockopt_sim (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, + &mreq6, sizeof (mreq6)); +#else retval = setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6, sizeof (mreq6)); +#endif //SIM if (retval < 0) zlog_err ("Network: Join AllSPFRouters on ifindex %d failed: %s", @@ -144,8 +179,13 @@ memcpy (&mreq6.ipv6mr_multiaddr, &allspfrouters6, sizeof (struct in6_addr)); +#ifdef SIM + if (setsockopt_sim (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, + &mreq6, sizeof (mreq6)) < 0) +#else if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq6, sizeof (mreq6)) < 0) +#endif //SIM zlog_warn ("Network: Leave AllSPFRouters on ifindex %d Failed: %s", ifindex, safe_strerror (errno)); #if 0 @@ -164,8 +204,13 @@ memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6, sizeof (struct in6_addr)); +#ifdef SIM + if (setsockopt_sim (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, + &mreq6, sizeof (mreq6)) < 0) +#else if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6, sizeof (mreq6)) < 0) +#endif //SIM zlog_warn ("Network: Join AllDRouters on ifindex %d Failed: %s", ifindex, safe_strerror (errno)); #if 0 @@ -184,8 +229,13 @@ memcpy (&mreq6.ipv6mr_multiaddr, &alldrouters6, sizeof (struct in6_addr)); +#ifdef SIM + if (setsockopt_sim (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, + &mreq6, sizeof (mreq6)) < 0) +#else if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq6, sizeof (mreq6)) < 0) +#endif //SIM zlog_warn ("Network: Leave AllDRouters on ifindex %d Failed", ifindex); #if 0 else @@ -261,7 +311,17 @@ smsghdr.msg_control = (caddr_t) cmsgbuf; smsghdr.msg_controllen = sizeof (cmsgbuf); +#ifdef SIM +#ifdef OSPF6_JITTER + struct ospf6_interface * oi = + ospf6_interface_lookup_by_ifindex(*ifindex); + retval = sendmsg_sim (ospf6_sock, &smsghdr, 0, oi->jitter); +#else + retval = sendmsg_sim (ospf6_sock, &smsghdr, 0); +#endif //OSPF6_JITTER +#else retval = sendmsg (ospf6_sock, &smsghdr, 0); +#endif //SIM if (retval != iov_totallen (message)) zlog_warn ("sendmsg failed: ifindex: %d: %s (%d)", *ifindex, safe_strerror (errno), errno); diff -Naur quagga-0.98.5/ospf6d/ospf6_proto.c quagga-0.98.5-manet/ospf6d/ospf6_proto.c --- quagga-0.98.5/ospf6d/ospf6_proto.c 2004-10-10 05:54:58.000000000 -0700 +++ quagga-0.98.5-manet/ospf6d/ospf6_proto.c 2006-02-20 13:42:12.000000000 -0800 @@ -72,7 +72,26 @@ void ospf6_options_printbuf (u_char *options, char *buf, int size) { +#ifdef OSPF6_MANET + const char *dc, *r, *n, *mc, *e, *v6, *AF, *L, *I, *F; +#else const char *dc, *r, *n, *mc, *e, *v6; +#endif //OSPF6_MANET + +#ifdef OSPF6_MANET + F = (OSPF6_OPT_ISSET (options, OSPF6_OPT_F, 1) ? "F" : "--"); + I = (OSPF6_OPT_ISSET (options, OSPF6_OPT_I, 1) ? "I" : "--"); //same as D + L = (OSPF6_OPT_ISSET (options, OSPF6_OPT_L, 1) ? "L" : "--"); + AF = (OSPF6_OPT_ISSET (options, OSPF6_OPT_AF, 1) ? "AF" : "--"); + dc = (OSPF6_OPT_ISSET (options, OSPF6_OPT_DC,2) ? "DC" : "--"); + r = (OSPF6_OPT_ISSET (options, OSPF6_OPT_R,2) ? "R" : "--" ); + n = (OSPF6_OPT_ISSET (options, OSPF6_OPT_N,2) ? "N" : "--" ); + mc = (OSPF6_OPT_ISSET (options, OSPF6_OPT_MC,2) ? "MC" : "--"); + e = (OSPF6_OPT_ISSET (options, OSPF6_OPT_E,2) ? "E" : "--" ); + v6 = (OSPF6_OPT_ISSET (options, OSPF6_OPT_V6,2) ? "V6" : "--"); + snprintf (buf, size, "%s|%s|%s|%s|--|--|%s|%s|%s|%s|%s|%s", + F, I, L, AF, dc, r, n, mc, e, v6); +#else dc = (OSPF6_OPT_ISSET (options, OSPF6_OPT_DC) ? "DC" : "--"); r = (OSPF6_OPT_ISSET (options, OSPF6_OPT_R) ? "R" : "-" ); n = (OSPF6_OPT_ISSET (options, OSPF6_OPT_N) ? "N" : "-" ); @@ -80,6 +99,7 @@ e = (OSPF6_OPT_ISSET (options, OSPF6_OPT_E) ? "E" : "-" ); v6 = (OSPF6_OPT_ISSET (options, OSPF6_OPT_V6) ? "V6" : "--"); snprintf (buf, size, "%s|%s|%s|%s|%s|%s", dc, r, n, mc, e, v6); +#endif //OSPF6_MANET } diff -Naur quagga-0.98.5/ospf6d/ospf6_proto.h quagga-0.98.5-manet/ospf6d/ospf6_proto.h --- quagga-0.98.5/ospf6d/ospf6_proto.h 2004-09-28 17:26:19.000000000 -0700 +++ quagga-0.98.5-manet/ospf6d/ospf6_proto.h 2006-02-20 13:42:12.000000000 -0800 @@ -45,6 +45,10 @@ #define INITIAL_SEQUENCE_NUMBER 0x80000001 /* signed 32-bit integer */ #define MAX_SEQUENCE_NUMBER 0x7fffffff /* signed 32-bit integer */ +#ifdef OSPF6_MANET_DIFF_HELLO +#define MAX_SCS_NUMBER 0xffff /* unsigned 16-bit integer */ +#endif //OSPF6_MANET_DIFF_HELLO + #define ALLSPFROUTERS6 "ff02::5" #define ALLDROUTERS6 "ff02::6" @@ -60,11 +64,27 @@ /* OSPF options */ /* present in HELLO, DD, LSA */ +#ifdef OSPF6_MANET +#define OSPF6_OPT_SET(x,opt,i) ((x)[(i)] |= (opt)) +#define OSPF6_OPT_ISSET(x,opt,i) ((x)[(i)] & (opt)) +#define OSPF6_OPT_CLEAR(x,opt,i) ((x)[(i)] &= ~(opt)) +#else #define OSPF6_OPT_SET(x,opt) ((x)[2] |= (opt)) #define OSPF6_OPT_ISSET(x,opt) ((x)[2] & (opt)) #define OSPF6_OPT_CLEAR(x,opt) ((x)[2] &= ~(opt)) +#endif //OSPF6_MANET #define OSPF6_OPT_CLEAR_ALL(x) ((x)[0] = (x)[1] = (x)[2] = 0) + +#ifdef OSPF6_MANET +//Chandra03 3.5 +#define OSPF6_OPT_F (1 << 3) /* Indicates Optimized Flooding */ +#define OSPF6_OPT_I (1 << 2) /* Indicates Incremental Hellos */ +#define OSPF6_OPT_D (1 << 2) /* Indicates Differential Hellos */ +#define OSPF6_OPT_L (1 << 1) /* Indicates an LLS Data Block */ +#define OSPF6_OPT_AF (1 << 0) /* Indicates usage of address families */ +#endif //OSPF6_MANET + #define OSPF6_OPT_DC (1 << 5) /* Demand Circuit handling Capability */ #define OSPF6_OPT_R (1 << 4) /* Forwarding Capability (Any Protocol) */ #define OSPF6_OPT_N (1 << 3) /* Handling Type-7 LSA Capability */ diff -Naur quagga-0.98.5/ospf6d/ospf6_route.c quagga-0.98.5-manet/ospf6d/ospf6_route.c --- quagga-0.98.5/ospf6d/ospf6_route.c 2004-12-23 22:00:12.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_route.c 2006-02-20 13:42:12.000000000 -0800 @@ -33,6 +33,12 @@ #include "ospf6_lsdb.h" #include "ospf6_route.h" #include "ospf6d.h" +#ifdef SIM +#include "sim.h" +#endif //SIM +#ifdef OSPF6_MANET_MPR_FLOOD +#include "linklist.h" //Needed in gtnets +#endif //OSPF6_MANET_MPR_FLOOD unsigned char conf_debug_ospf6_route = 0; @@ -80,7 +86,8 @@ ospf6_route_create () { struct ospf6_route *route; - route = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route)); + route = (struct ospf6_route *) + XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route)); return route; } @@ -93,15 +100,15 @@ struct ospf6_route * ospf6_route_copy (struct ospf6_route *route) { - struct ospf6_route *new; + struct ospf6_route *new_; - new = ospf6_route_create (); - memcpy (new, route, sizeof (struct ospf6_route)); - new->rnode = NULL; - new->prev = NULL; - new->next = NULL; - new->lock = 0; - return new; + new_ = ospf6_route_create (); + memcpy (new_, route, sizeof (struct ospf6_route)); + new_->rnode = NULL; + new_->prev = NULL; + new_->next = NULL; + new_->lock = 0; + return new_; } void @@ -254,13 +261,18 @@ if (IS_OSPF6_DEBUG_ROUTE (TABLE)) zlog_debug ("route add %s", buf); +#ifdef SIM + gettimeofday_sim (&now, NULL); +#else gettimeofday (&now, NULL); +#endif //SIM node = route_node_get (table->table, &route->prefix); route->rnode = node; /* find place to insert */ - for (current = node->info; current; current = current->next) + for (current = (struct ospf6_route *) node->info; + current; current = current->next) { if (! ospf6_route_is_same (current, route)) next = current; @@ -289,6 +301,7 @@ SET_FLAG (old->flag, OSPF6_ROUTE_ADD); ospf6_route_count_assert (table); +//XXX Tracing return old; } @@ -312,6 +325,11 @@ route->installed = old->installed; route->changed = now; +#if defined(BUGFIX) && !defined(SIM) + if (table->hook_remove) + (*table->hook_remove) (old); +#endif //BUGFIX && SIM + ospf6_route_unlock (old); /* will be deleted later */ ospf6_route_lock (route); @@ -389,7 +407,7 @@ { route_unlock_node (nextnode); - next = nextnode->info; + next = (struct ospf6_route *) nextnode->info; route->next = next; next->prev = route; } @@ -408,7 +426,7 @@ { route_unlock_node (prevnode); - prev = prevnode->info; + prev = (struct ospf6_route *) prevnode->info; while (prev->next && ospf6_route_is_same (prev, prev->next)) prev = prev->next; route->prev = prev; @@ -446,7 +464,7 @@ /* find the route to remove, making sure that the route pointer is from the route table. */ - current = node->info; + current = (struct ospf6_route *) node->info; while (current && ospf6_route_is_same (current, route)) { if (current == route) @@ -569,7 +587,7 @@ if (! prefix_match (prefix, &node->p)) return NULL; - route = node->info; + route = (struct ospf6_route *) node->info; ospf6_route_lock (route); return route; } @@ -602,10 +620,11 @@ struct ospf6_route_table * ospf6_route_table_create () { - struct ospf6_route_table *new; - new = XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table)); - new->table = route_table_init (); - return new; + struct ospf6_route_table *new_; + new_ = (struct ospf6_route_table *) + XCALLOC (MTYPE_OSPF6_ROUTE, sizeof (struct ospf6_route_table)); + new_->table = route_table_init (); + return new_; } void @@ -627,7 +646,11 @@ char duration[16], ifname[IFNAMSIZ]; struct timeval now, res; +#ifdef SIM + gettimeofday_sim (&now, (struct timezone *) NULL); +#else gettimeofday (&now, (struct timezone *) NULL); +#endif //SIM timersub (&now, &route->changed, &res); timerstring (&res, duration, sizeof (duration)); @@ -676,7 +699,11 @@ char duration[16]; int i; +#ifdef SIM + gettimeofday_sim (&now, (struct timezone *) NULL); +#else gettimeofday (&now, (struct timezone *) NULL); +#endif //SIM /* destination */ if (route->type == OSPF6_DEST_TYPE_LINKSTATE) diff -Naur quagga-0.98.5/ospf6d/ospf6_sim_printing.c quagga-0.98.5-manet/ospf6d/ospf6_sim_printing.c --- quagga-0.98.5/ospf6d/ospf6_sim_printing.c 1969-12-31 16:00:00.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_sim_printing.c 2006-02-20 13:42:12.000000000 -0800 @@ -0,0 +1,135 @@ +#ifdef SIM + +#include "ospf6_sim_printing.h" +#include "netinet/in.h" +//#include "if.h" +#include "ospf6_neighbor.h" +#include "ospf6_top.h" //for pushback + +void append_sim(char *buf, int buf_len, const char *fmt,...) +{ + char temp_buf[ETRACE_MAXSTR]=""; + va_list al; + int length1, length2; + + va_start(al,fmt); + vsnprintf(temp_buf, ETRACE_MAXSTR, fmt, al); + length1 = strlen(buf); + length2 = strlen(temp_buf); + + if (length1 + length2 >= buf_len) + { + //printf("Error sim.cc: Out of space in buf - increase size of buf_len\n"); + return; + } + va_end(al); + strcat(buf, temp_buf); +} + + +#ifdef OSPF6_MANET_MPR_FLOOD +void ospf6_print_relay_selector_list_sim(struct ospf6_interface *oi) +{ + plistnode n; + struct ospf6_relay_selector *relay_sel; + char buf[ETRACE_MAXSTR]=""; + + append_sim(buf, ETRACE_MAXSTR, "Relay Sel List: "); + for (n = listhead(oi->relay_sel_list); n; nextnode(n)) + { + relay_sel = (struct ospf6_relay_selector *) getdata(n); + append_sim(buf, ETRACE_MAXSTR, "%s:%f, ", ip2str(relay_sel->router_id), + elapsed_time(relay_sel->expire_time)); + } + TraceEvent_sim(2, buf); +} + +void ospf6_print_relay_list_sim(struct ospf6_interface *oi) +{ + plistnode n; + struct ospf6_relay *relay; + char buf[ETRACE_MAXSTR]=""; + + append_sim(buf, ETRACE_MAXSTR, "Relay List: "); + for (n = listhead(oi->relay_list); n; nextnode(n)) + { + relay = (struct ospf6_relay *) getdata(n); + if (!relay->active) + continue; + append_sim(buf, ETRACE_MAXSTR, "%s,", ip2str(relay->router_id)); + } + TraceEvent_sim(2, buf); +} +#endif // OSPF6_MANET_MPR_FLOOD + +#ifdef OSPF6_MANET +void ospf6_print_pushback_list_sim(struct ospf6_lsa *lsa) +{ + plistnode n; + struct ospf6_pushback_neighbor *opbn; + char buf[ETRACE_MAXSTR] = ""; + + if (!lsa->pushback_neighbor_list || lsa->pushback_neighbor_list->count < 1) + return; + + append_sim(buf, ETRACE_MAXSTR, "Pushback list lsa %s: ", lsa->name); + for (n = listhead(lsa->pushback_neighbor_list); n; nextnode(n)) + { + opbn = (struct ospf6_pushback_neighbor *) getdata(n); + append_sim(buf, ETRACE_MAXSTR, "%s, ", ip2str(opbn->router_id)); + } + TraceEvent_sim(2, buf); +} +#endif //OSPF6_MANET + +void ospf6_print_neighborhood_sim(struct ospf6_interface *oi) +{ + plistnode n, n2; + struct ospf6_neighbor *on; + struct ospf6_2hop_neighbor *o62n; + char buf[ETRACE_MAXSTR] = ""; + u_int32_t *id; + + append_sim(buf, ETRACE_MAXSTR, "Neighborhood: "); + for (n = listhead (oi->neighbor_list); n; nextnode (n)) + { + on = (struct ospf6_neighbor *) getdata (n); + +#ifdef OSPF6_MANET_MPR_FLOOD + if (on->two_hop_neighbor_list && oi->flooding == OSPF6_FLOOD_MPR_SDCDS) + { + if (on->state < OSPF6_NEIGHBOR_FULL) + continue; + append_sim(buf, ETRACE_MAXSTR, "neighbor:%s ", ip2str(on->router_id)); + append_sim(buf, ETRACE_MAXSTR, "{"); + for (n2 = listhead (on->two_hop_neighbor_list); n2; nextnode (n2)) + { + o62n = (struct ospf6_2hop_neighbor *) getdata (n2); + append_sim(buf, ETRACE_MAXSTR, "%s,", ip2str(o62n->router_id)); + } + append_sim(buf, ETRACE_MAXSTR, "} "); + } +#endif //OSPF6_MANET_MPR_FLOOD +#ifdef OSPF6_MANET_MDR_FLOOD + if (on->rnl && oi->flooding == OSPF6_FLOOD_MDR_SICDS) + { + if (on->state <= OSPF6_NEIGHBOR_INIT) + continue; + append_sim(buf, ETRACE_MAXSTR, "neighbor:%s ", ip2str(on->router_id)); + append_sim(buf, ETRACE_MAXSTR, "rnl{"); + if (on->rnl) + { + for (n2 = listhead(on->rnl); n2; nextnode(n2)) + { + id = (u_int32_t *) getdata(n2); + append_sim(buf, ETRACE_MAXSTR, "%s,", ip2str(*id)); + } + } + append_sim(buf, ETRACE_MAXSTR, "} "); + } +#endif //OSPF6_MANET_MDR_FLOOD + } + TraceEvent_sim(2, buf); +} + +#endif //SIM diff -Naur quagga-0.98.5/ospf6d/ospf6_sim_printing.h quagga-0.98.5-manet/ospf6d/ospf6_sim_printing.h --- quagga-0.98.5/ospf6d/ospf6_sim_printing.h 1969-12-31 16:00:00.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_sim_printing.h 2006-02-20 13:42:12.000000000 -0800 @@ -0,0 +1,23 @@ +#ifdef SIM + +#ifndef OSPF6_SIM_PRINTING_H +#define OSPF6_SIM_PRINTING_H + +#include "sim.h" + +#include "ospf6d.h" +#include "ospf6_interface.h" +#include "ospf6_lsa.h" //for ospf6_lsa + +#ifdef OSPF6_MANET_MPR_FLOOD +void ospf6_print_relay_selector_list_sim(struct ospf6_interface *oi); +void ospf6_print_relay_list_sim(struct ospf6_interface *oi); +#endif // OSPF6_MANET_MPR_FLOOD +void ospf6_print_neighborhood_sim(struct ospf6_interface *oi); +#ifdef OSPF6_MANET +void ospf6_print_pushback_list_sim(struct ospf6_lsa *lsa); +#endif //OSPF6_MANET + +#endif //OSPF6_SIM_PRINTING_H + +#endif //SIM diff -Naur quagga-0.98.5/ospf6d/ospf6_snmp.c quagga-0.98.5-manet/ospf6d/ospf6_snmp.c --- quagga-0.98.5/ospf6d/ospf6_snmp.c 2004-12-23 22:00:12.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_snmp.c 2006-02-20 13:42:12.000000000 -0800 @@ -1,3 +1,4 @@ +#ifndef SIM /* OSPFv3 SNMP support * Copyright (C) 2004 Yasuhiro Ohara * @@ -531,3 +532,4 @@ #endif /* HAVE_SNMP */ +#endif //SIM diff -Naur quagga-0.98.5/ospf6d/ospf6_snmp.h quagga-0.98.5-manet/ospf6d/ospf6_snmp.h --- quagga-0.98.5/ospf6d/ospf6_snmp.h 2004-10-10 05:54:58.000000000 -0700 +++ quagga-0.98.5-manet/ospf6d/ospf6_snmp.h 2006-02-20 13:42:12.000000000 -0800 @@ -1,3 +1,4 @@ +#ifndef SIM /* OSPFv3 SNMP support * Copyright (C) 2004 Yasuhiro Ohara * @@ -26,4 +27,4 @@ #endif /*OSPF6_SNMP_H*/ - +#endif //SIM diff -Naur quagga-0.98.5/ospf6d/ospf6_spf.c quagga-0.98.5-manet/ospf6d/ospf6_spf.c --- quagga-0.98.5/ospf6d/ospf6_spf.c 2004-12-23 22:00:12.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_spf.c 2006-02-20 13:42:12.000000000 -0800 @@ -32,6 +32,10 @@ #include "linklist.h" #include "thread.h" +#ifdef OSPF6_MANET_MDR_FLOOD +#include "ospf6_neighbor.h" +#endif //OSPF6_MANET_MDR_FLOOD + #include "ospf6_lsa.h" #include "ospf6_lsdb.h" #include "ospf6_route.h" @@ -40,6 +44,9 @@ #include "ospf6_intra.h" #include "ospf6_interface.h" #include "ospf6d.h" +#ifdef SIM +#include "sim.h" +#endif //SIM unsigned char conf_debug_ospf6_spf = 0; @@ -321,6 +328,21 @@ prev = (struct ospf6_vertex *) route->route_option; if (prev->hops > v->hops) +#ifdef BUGFIX //FIXME + { + LIST_LOOP (prev->child_list, w, node) + { + assert (w->parent == prev); + w->parent = v; + listnode_add_sort (v->child_list, w); + } + listnode_delete (prev->parent->child_list, prev); + listnode_add_sort (v->parent->child_list, v); + + //ospf6_vertex_delete (prev); //HACK + route->route_option = v; + } +#else { LIST_LOOP (prev->child_list, w, node) { @@ -334,6 +356,7 @@ ospf6_vertex_delete (prev); route->route_option = v; } +#endif //BUGFIX else ospf6_vertex_delete (v); @@ -393,9 +416,23 @@ /* RFC2328 16.1. Calculating the shortest-path tree for an area */ /* RFC2740 3.8.1. Calculating the shortest path tree for an area */ void +#ifdef OSPF6_MANET_MPR_SP +//Changes by: Stan Ratliff +//Date: November 1st, 2005 +//Reason: Add a flag to enable or disable the use of unsynchronized links +// in the SPF calculation. +// Copyright (C) 2005 + +//Roy-01 4.1 para 6 +ospf6_spf_calculation (u_int32_t router_id, + struct ospf6_route_table *result_table, + struct ospf6_area *oa, + boolean ignore_unsync) +#else ospf6_spf_calculation (u_int32_t router_id, struct ospf6_route_table *result_table, struct ospf6_area *oa) +#endif //OSPF6_MANET_MPR_SP { struct pqueue *candidate_list; struct ospf6_vertex *root, *v, *w; @@ -403,6 +440,11 @@ int size; caddr_t lsdesc; struct ospf6_lsa *lsa; +#if defined(OSPF6_MANET_MDR_FLOOD) || defined(OSPF6_MANET_MPR_FLOOD) + plistnode i2, j; + struct ospf6_interface *oi; + struct ospf6_neighbor *on; +#endif // defined(OSPF6_MANET_MDR_FLOOD) || defined(OSPF6_MANET_MPR_FLOOD) /* initialize */ candidate_list = pqueue_create (); @@ -415,7 +457,15 @@ lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_ROUTER), htonl (0), router_id, oa->lsdb); if (lsa == NULL) +#ifdef BUGFIX + { + //canidate list was not being deleted when returning on NULL + pqueue_delete (candidate_list); return; + } +#else + return; +#endif //BUGFIX root = ospf6_vertex_create (lsa); root->area = oa; root->cost = 0; @@ -423,14 +473,81 @@ root->nexthop[0].ifindex = 0; /* loopbak I/F is better ... */ inet_pton (AF_INET6, "::1", &root->nexthop[0].address); +#if defined(OSPF6_MANET_MDR_FLOOD) || defined(OSPF6_MANET_MPR_FLOOD) + pqueue_enqueue (root, candidate_list); // add root to candidate list + + // For each manet interface, add all 2-way neighbors for which + // LSA exists to candidate list. + + for (i2 = listhead (oa->if_list); i2; nextnode (i2)) + { + oi = (struct ospf6_interface *) getdata (i2); + if (oi->state == OSPF6_INTERFACE_DOWN) continue; + if (oi->type != OSPF6_IFTYPE_MANETRELIABLE) continue; + + if (oi->flooding == OSPF6_FLOOD_MDR_SICDS) + { + if (oi->AdjConnectivity == OSPF6_ADJ_FULLYCONNECTED) + continue; + } +#ifdef OSPF6_MANET_MPR_SP + else if (oi->flooding == OSPF6_FLOOD_MPR_SDCDS) + { + //if (!oi->smart_peering || !oi->unsynch_adj) + if (!oi->smart_peering || !oi->unsynch_adj || ignore_unsync) //BUGFIX_SP + continue; + } +#endif //OSPF6_MANET_MPR_SP + else + continue; + + for (j = listhead(oi->neighbor_list); j; nextnode(j)) + { + on = (struct ospf6_neighbor *) getdata (j); + + // If full adjacencies are used, routable neighbors are the + // same as Full neighbors. + if (oi->flooding == OSPF6_FLOOD_MDR_SICDS && oi->full_adj_part_lsa) + { + if (on->state == OSPF6_NEIGHBOR_FULL) + on->routable = true; + else + on->routable = false; + } + + // Require neighbor to be routable. + if (on->state >= OSPF6_NEIGHBOR_TWOWAY && on->routable || + oi->full_adj_part_lsa && on->state == OSPF6_NEIGHBOR_FULL) + { + lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_ROUTER), htonl (0), + on->router_id, oa->lsdb); + if (lsa == NULL) continue; + v = ospf6_vertex_create (lsa); + v->area = oa; + v->parent = root; + // Full neighbors are given lower cost. + if (on->state == OSPF6_NEIGHBOR_FULL) + v->cost = oi->cost+9; + else + v->cost = oi->cost+10; + //v->cost = oi->cost; + v->hops = 1; + v->nexthop[0].ifindex = oi->interface->ifindex; + v->nexthop[0].address = on->linklocal_addr; + pqueue_enqueue (v, candidate_list); + } + } + } +#else //defined(OSPF6_MANET_MDR_FLOOD) || defined(OSPF6_MANET_MPR_FLOOD) /* Actually insert root to the candidate-list as the only candidate */ pqueue_enqueue (root, candidate_list); +#endif //defined(OSPF6_MANET_MDR_FLOOD) || defined(OSPF6_MANET_MPR_FLOOD) /* Iterate until candidate-list becomes empty */ while (candidate_list->size) { /* get closest candidate from priority queue */ - v = pqueue_dequeue (candidate_list); + v = (struct ospf6_vertex *) pqueue_dequeue (candidate_list); /* installing may result in merging or rejecting of the vertex */ if (ospf6_spf_install (v, result_table) < 0) @@ -443,6 +560,32 @@ for (lsdesc = OSPF6_LSA_HEADER_END (v->lsa->header) + 4; lsdesc + size <= OSPF6_LSA_END (v->lsa->header); lsdesc += size) { +#ifdef OSPF6_MANET_MPR_SP +//Changes by: Stan Ratliff +//Date: November 1st, 2005 +//Reason: Check for unsynchronized links in the SPF calculation. +// Copyright (C) 2005 + + //Roy-01 4.1 para 6 + if (ROUTER_LSDESC_IS_UNSYNC(lsdesc) && ignore_unsync) + continue; +#endif //OSPF6_MANET_MPR_SP +#ifdef OSPF6_MANET_MPR_SP //BUGFIX_SP + //Is this the router's own router-LSA and are we doing synch adj + //If yes, prune links in router-LSA with neighbor state below FULL + if (VERTEX_IS_TYPE (ROUTER, v) && ignore_unsync && v == root) + { + struct ospf6_router_lsdesc* orl = + (struct ospf6_router_lsdesc *)lsdesc; + on = NULL; + oi = ospf6_interface_lookup_by_ifindex (ntohl(orl->interface_id)); + if (oi) + on = ospf6_neighbor_lookup (orl->neighbor_router_id, oi); + //Is the link in the router-LSA below neighbor state FULL + if (!on || on->state < OSPF6_NEIGHBOR_FULL) + continue; + } +#endif //OSPF6_MANET_MPR_SP lsa = ospf6_lsdesc_lsa (lsdesc, v); if (lsa == NULL) continue; @@ -479,7 +622,7 @@ /* add new candidate to the candidate_list */ if (IS_OSPF6_DEBUG_SPF (PROCESS)) zlog_debug (" New candidate: %s hops %d cost %d", - w->name, w->hops, w->cost); + w->name, w->hops, w->cost); pqueue_enqueue (w, candidate_list); } } @@ -513,11 +656,54 @@ zlog_debug ("%s", buffer); } +#ifdef OSPF6_MANET_MPR_SP +//Changes by: Stan Ratliff +//Date: November 1st, 2005 +//Reason: Make sure all neighbors are synchronized +// Copyright (C) 2005 + +//Roy-01 4.2 +void +ospf6_spf_check_smart_peers (struct ospf6_area *oa) +{ + plistnode i2, j; + struct ospf6_interface *oi; + struct ospf6_neighbor *on; + struct ospf6_route *route; + struct prefix prefix; + + for (i2 = listhead (oa->if_list); i2; nextnode (i2)) + { + oi = (struct ospf6_interface *) getdata (i2); + if (oi->state == OSPF6_INTERFACE_DOWN) continue; + if (oi->type != OSPF6_IFTYPE_MANETRELIABLE) continue; + if (oi->flooding != OSPF6_FLOOD_MPR_SDCDS) continue; + if (!oi->smart_peering) continue; + if (!oi->unsynch_adj) continue; + for (j = listhead(oi->neighbor_list); j; nextnode(j)) + { + on = (struct ospf6_neighbor *) getdata (j); + ospf6_linkstate_prefix (on->router_id, htonl (0), &prefix); + route = ospf6_route_lookup(&prefix, on->ospf6_if->area->spf_table_sync); + if (route == NULL){ + thread_execute(master, twoway_received, on, 0); + } + } + } +} +#endif //OSPF6_MANET_MPR_SP + int ospf6_spf_calculation_thread (struct thread *t) { struct ospf6_area *oa; struct timeval start, end, runtime; +#ifdef OSPF6_MANET_MPR_SP + plistnode i; + struct ospf6_interface *oi; + boolean or_sp = false; + struct interface *ifp; +#endif //OSPF6_MANET_MPR_SP oa = (struct ospf6_area *) THREAD_ARG (t); oa->thread_spf_calculation = NULL; @@ -528,9 +714,51 @@ ospf6_spf_log_database (oa); /* execute SPF calculation */ +#ifdef SIM + gettimeofday_sim (&start, (struct timezone *) NULL); +#else gettimeofday (&start, (struct timezone *) NULL); +#endif //SIM + +#ifdef OSPF6_MANET_MPR_SP + //check to see if this is an area with a OR/SP interface + //this is needed, so the double calculation does not take place with other + //interface types + for (i = listhead (oa->if_list); i; nextnode (i)) + { + oi = (struct ospf6_interface *) getdata (i); + if (oi->state == OSPF6_INTERFACE_DOWN) continue; + if (oi->type != OSPF6_IFTYPE_MANETRELIABLE) continue; + if (oi->flooding != OSPF6_FLOOD_MPR_SDCDS) continue; + if (!oi->smart_peering) continue; + if (!oi->unsynch_adj) continue; + or_sp = true; + } + + if (or_sp) + { +//Changes by: Stan Ratliff +//Date: November 1st, 2005 +//Reason: Perform 2 SPF calculations -- one using the +// unsychronized links (above), and the other ignoring those links (below). +// Copyright (C) 2005 + //Roy-01 4.1 para 6 + ospf6_spf_calculation (oa->ospf6->router_id, oa->spf_table, oa, false); + ospf6_spf_calculation (oa->ospf6->router_id, oa->spf_table_sync, oa,true); + ospf6_spf_check_smart_peers(oa); + } + else + ospf6_spf_calculation (oa->ospf6->router_id, oa->spf_table, oa, false); +#else ospf6_spf_calculation (oa->ospf6->router_id, oa->spf_table, oa); - gettimeofday (&end, (struct timezone *) NULL); +#endif //OSPF6_MANET_MPR_SP + + +#ifdef SIM + gettimeofday_sim (&end, (struct timezone *) NULL); +#else + gettimeofday (&end, (struct timezone *) NULL); +#endif //SIM timersub (&end, &start, &runtime); if (IS_OSPF6_DEBUG_SPF (PROCESS) || IS_OSPF6_DEBUG_SPF (TIME)) @@ -540,6 +768,22 @@ ospf6_intra_route_calculation (oa); ospf6_intra_brouter_calculation (oa); + +#ifdef OSPF6_MANET_MPR_SP //BUGFIX_SP -- moved from ospf6_install_lsa +//Roy-01 4.2 +//see if any of our neighbors need to initiate database exchange + for (i = listhead(iflist); i; nextnode(i)) + { + ifp = (struct interface *) getdata (i); + oi = (struct ospf6_interface *) ifp->info; + if (!oi || oi->type != OSPF6_IFTYPE_MANETRELIABLE || + oi->flooding != OSPF6_FLOOD_MPR_SDCDS) + continue; + + ospf6_manet_update_routable_neighbors(oi); + ospf6_or_update_adjacencies(oi); + } +#endif //OSPF6_MANET_MPR_SP return 0; } diff -Naur quagga-0.98.5/ospf6d/ospf6_spf.h quagga-0.98.5-manet/ospf6d/ospf6_spf.h --- quagga-0.98.5/ospf6d/ospf6_spf.h 2004-11-25 12:54:47.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_spf.h 2006-02-20 13:42:12.000000000 -0800 @@ -22,6 +22,10 @@ #ifndef OSPF6_SPF_H #define OSPF6_SPF_H +#ifdef OSPF6_MANET_MPR_SP +#include "ospf6d.h" //for boolean +#endif //OSPF6_MANET_MPR_SP + /* Debug option */ extern unsigned char conf_debug_ospf6_spf; #define OSPF6_DEBUG_SPF_PROCESS 0x01 @@ -69,7 +73,7 @@ /* For tree display */ struct ospf6_vertex *parent; - struct list *child_list; + pList child_list; }; #define OSPF6_VERTEX_TYPE_ROUTER 0x01 @@ -78,9 +82,22 @@ ((v)->type == OSPF6_VERTEX_TYPE_ ## t ? 1 : 0) void ospf6_spf_table_finish (struct ospf6_route_table *result_table); +#ifdef OSPF6_MANET_MPR_SP +//Changes by: Stan Ratliff +//Date: November 1st, 2005 +//Reason: Add a flag to enable or disable the use of unsynchronized links +// in the SPF calculation. +// Copyright (C) 2005 +void ospf6_spf_calculation (u_int32_t router_id, + struct ospf6_route_table *result_table, + struct ospf6_area *oa, + boolean b); +#else void ospf6_spf_calculation (u_int32_t router_id, struct ospf6_route_table *result_table, struct ospf6_area *oa); +#endif //OSPF6_MANET_MPR_SP + void ospf6_spf_schedule (struct ospf6_area *oa); void ospf6_spf_display_subtree (struct vty *vty, const char *prefix, diff -Naur quagga-0.98.5/ospf6d/ospf6_top.c quagga-0.98.5-manet/ospf6d/ospf6_top.c --- quagga-0.98.5/ospf6d/ospf6_top.c 2004-10-11 10:02:40.000000000 -0700 +++ quagga-0.98.5-manet/ospf6d/ospf6_top.c 2006-02-20 13:42:12.000000000 -0800 @@ -35,7 +35,9 @@ #include "ospf6_lsa.h" #include "ospf6_lsdb.h" #include "ospf6_route.h" +#ifndef SIM #include "ospf6_zebra.h" +#endif //SIM #include "ospf6_top.h" #include "ospf6_area.h" @@ -47,9 +49,20 @@ #include "ospf6_abr.h" #include "ospf6_intra.h" #include "ospf6d.h" +#ifdef SIM +#include "sim.h" +#include "ospf6_sim_printing.h" +#endif //SIM +#ifdef OSPF6_MANET_MPR_FLOOD +#include "ospf6_mpr.h" +#endif //OSPF6_MANET_MPR_FLOOD /* global ospf6d variable */ +#ifdef SIM //Global SIM +struct ospf6 *ospf6 = NULL; +#else struct ospf6 *ospf6; +#endif //SIM void ospf6_top_lsdb_hook_add (struct ospf6_lsa *lsa) @@ -83,14 +96,18 @@ ospf6_top_route_hook_add (struct ospf6_route *route) { ospf6_abr_originate_summary (route); +#ifndef SIM ospf6_zebra_route_update_add (route); +#endif //SIM } void ospf6_top_route_hook_remove (struct ospf6_route *route) { ospf6_abr_originate_summary (route); +#ifndef SIM ospf6_zebra_route_update_remove (route); +#endif //SIM } void @@ -114,11 +131,15 @@ { struct ospf6 *o; - o = XMALLOC (MTYPE_OSPF6_TOP, sizeof (struct ospf6)); + o = (struct ospf6 *) XMALLOC (MTYPE_OSPF6_TOP, sizeof (struct ospf6)); memset (o, 0, sizeof (struct ospf6)); /* initialize */ +#ifdef SIM + gettimeofday_sim (&o->starttime, (struct timezone *) NULL); +#else gettimeofday (&o->starttime, (struct timezone *) NULL); +#endif //SIM o->area_list = list_new (); o->area_list->cmp = ospf6_area_cmp; o->lsdb = ospf6_lsdb_create (o); @@ -126,9 +147,16 @@ o->lsdb->hook_add = ospf6_top_lsdb_hook_add; o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove; +#ifdef OSPF6_CONFIG + o->minLSInterval = MIN_LS_INTERVAL; + o->minLSArrival = MIN_LS_ARRIVAL; +#endif //OSPF6_CONFIG + o->route_table = ospf6_route_table_create (); +#ifndef SIM o->route_table->hook_add = ospf6_top_route_hook_add; o->route_table->hook_remove = ospf6_top_route_hook_remove; +#endif //SIM o->brouter_table = ospf6_route_table_create (); o->brouter_table->hook_add = ospf6_top_brouter_hook_add; @@ -146,11 +174,84 @@ struct listnode *i; struct ospf6_area *oa; +#ifdef SIM + if (!o) + return; + plistnode j, k; + struct ospf6_interface *oi; + struct ospf6_neighbor *on; + double lifetime, delta_2way, delta_full; + for (i = listhead (o->area_list); i; nextnode (i)) + { + oa = (struct ospf6_area *) getdata (i); + for (j = listhead (oa->if_list); j; nextnode (j)) + { + oi = (struct ospf6_interface *) getdata (j); +#ifdef OSPF6_MANET_MPR_FLOOD + if (oi->type == OSPF6_IFTYPE_MANETRELIABLE) + { + struct ospf6_relay_selector *relay_sel; + k = listhead(oi->relay_sel_list); + while(k) + { + relay_sel = (struct ospf6_relay_selector *) getdata(k); + nextnode(k); + ospf6_relay_selector_delete(oi, relay_sel); + relay_sel = NULL; + } + } +#endif //OSPF6_MANET_MPR_FLOOD +#ifdef SIM_ETRACE_STAT + delta_2way = elapsed_time(&oi->neigh_2way_change_time); + delta_full = elapsed_time(&oi->neigh_full_change_time); + for (k = listhead (oi->neighbor_list); k; nextnode (k)) + { + on = (struct ospf6_neighbor *) getdata (k); + if (on->state < OSPF6_NEIGHBOR_TWOWAY) + continue; + lifetime = elapsed_time(&on->creation_time); + + update_statistics(OSPF6_CHANGE_OF_NUM_NEIGHS, 1); + update_statistics(OSPF6_DURATION_OF_NUM_NEIGHS, (double)delta_2way); + update_statistics(OSPF6_NUM_NEIGH_TIMES_DURATION_OF_NUM_NEIGHS, + (double) (oi->num_2way_neigh * delta_2way)); + update_statistics(OSPF6_NEIGH_LIFETIME,lifetime); + update_statistics(OSPF6_NEIGH_DEATHS,1); + + if (on->state == OSPF6_NEIGHBOR_FULL) + { + update_statistics(OSPF6_CHANGE_OF_NUM_ADJ,1); + update_statistics(OSPF6_DURATION_OF_NUM_ADJ,(double)delta_full); + update_statistics(OSPF6_NUM_ADJ_TIMES_DURATION_OF_NUM_ADJ, + (double) (oi->num_full_neigh-- * delta_full)); + delta_full = 0; + } + TraceEvent_sim(1,"num_nbr %d for %f msec delnbr %s for %f msec", + oi->num_2way_neigh--, delta_2way, ip2str(on->router_id),lifetime); + delta_2way = 0; + } +#endif //SIM_ETRACE_STAT + } + } +#endif //SIM_ETRAC + + +#ifdef BUGFIX + //deleting oa was causing the loop through list to point to NULL + i = listhead(o->area_list); + while(i) + { + oa = (struct ospf6_area *) getdata (i); + nextnode(i); + ospf6_area_delete (oa); + } +#else for (i = listhead (o->area_list); i; nextnode (i)) { oa = (struct ospf6_area *) getdata (i); ospf6_area_delete (oa); } +#endif //BUGFIX ospf6_lsdb_delete (o->lsdb); ospf6_lsdb_delete (o->lsdb_self); @@ -253,6 +354,58 @@ o->maxage_remover = thread_add_event (master, ospf6_maxage_remover, o, 0); } +#ifdef OSPF6_CONFIG +DEFUN (ospf6_router_minlsinterval, + ospf6_router_minlsinterval_cmd, + "router minls-interval <0-65535>", + ROUTER_STR + "minimum time to originate an LSA\n" + SECONDS_STR) +{ + struct ospf6 *o; + + o = (struct ospf6 *) vty->index; + o->minLSInterval = strtol (argv[0], NULL, 10); + + return CMD_SUCCESS; +} +DEFUN (ospf6_router_minlsarrival, + ospf6_router_minlsarrival_cmd, + "router minls-arrival <0-65535>", + ROUTER_STR + "minimum time to receive an LSA\n" + SECONDS_STR) +{ + struct ospf6 *o; + + o = (struct ospf6 *) vty->index; + + o->minLSArrival = strtol (argv[0], NULL, 10); + + return CMD_SUCCESS; +} +#endif //OSPF6_CONFIG + +#ifdef SIM_ETRACE_STAT +/* change Router_ID commands. */ +DEFUN (ospf6_router_stat, + ospf6_router_stat_cmd, + "router statistics start-time <0-4294967296>", + ROUTER_STR + "statistics\n" + "time to start collecting statistics\n" + SECONDS_STR) +{ + struct ospf6 *o; + + o = (struct ospf6 *) vty->index; + + o->start_stat_time = strtol (argv[0], NULL, 10); + + return CMD_SUCCESS; +} +#endif //SIM_ETRACE_STAT + /* start ospf6 */ DEFUN (router_ospf6, router_ospf6_cmd, @@ -451,7 +604,11 @@ router_id, VNL); /* running time */ +#ifdef SIM + gettimeofday_sim (&now, (struct timezone *)NULL); +#else gettimeofday (&now, (struct timezone *)NULL); +#endif //SIM timersub (&now, &o->starttime, &running); timerstring (&running, duration, sizeof (duration)); vty_out (vty, " Running %s%s", duration, VNL); @@ -680,6 +837,372 @@ install_element (OSPF6_NODE, &ospf6_interface_area_cmd); install_element (OSPF6_NODE, &no_ospf6_interface_area_cmd); install_element (OSPF6_NODE, &no_router_ospf6_cmd); +#ifdef SIM_ETRACE_STAT + install_element (OSPF6_NODE, &ospf6_router_stat_cmd); +#endif //SIM_ETRACE_STAT +#ifdef OSPF6_CONFIG + install_element (OSPF6_NODE, &ospf6_router_minlsinterval_cmd); + install_element (OSPF6_NODE, &ospf6_router_minlsarrival_cmd); +#endif //OSPF6_CONFIG +} + +#ifdef OSPF6_MANET +void ospf6_pushback_lsa_add(struct ospf6_lsa *lsa, + struct ospf6_neighbor *on) +{ + plistnode n; + struct ospf6_pushback_neighbor *opbn = NULL; + + if (on->ospf6_if->type != OSPF6_IFTYPE_MANETRELIABLE) + return; + + ospf6_refresh_lsa_pushback_list(lsa); + + //create the pushback list and schedule expiration + if (lsa->pushBackTimer == NULL) + { +#ifdef OSPF6_MANET_MPR_FLOOD + if (on->ospf6_if->flooding == OSPF6_FLOOD_MPR_SDCDS) + { + lsa->pushBackTimer = + thread_add_timer_msec (master, ospf6_pushback_expiration, lsa, + on->ospf6_if->pushBackInterval + pushback_jitter(on->ospf6_if)); + } +#endif //OSPF6_MANET_MPR_FLOOD + +#ifdef OSPF6_MANET_MDR_FLOOD + if (on->ospf6_if->flooding == OSPF6_FLOOD_MDR_SICDS) + { + lsa->pushBackTimer = + thread_add_timer_msec (master, ospf6_pushback_expiration, lsa, + on->ospf6_if->BackupWaitInterval + pushback_jitter(on->ospf6_if)); + } +#endif //OSPF6_MANET_MDR_FLOOD + if (!on->ospf6_if->flooding == OSPF6_FLOOD_MDR_SICDS || + !on->ospf6_if->flooding == OSPF6_FLOOD_MPR_SDCDS) + { + printf("Interface flooding %d should not call ospf6_pushback_lsa_add()\n", + on->ospf6_if->flooding); + exit(0); + } + lsa->pushback_neighbor_list = list_new(); + } + + //Is this neighbor already on the push back list? + for (n = listhead(lsa->pushback_neighbor_list); n; nextnode(n)) + { + opbn = (struct ospf6_pushback_neighbor *) getdata(n); + if (on->router_id == opbn->router_id && + on->ospf6_if->interface->ifindex == opbn->ifindex) + return; //already in the list + } + + //put the pushback neighbor on the pushback list + opbn = (struct ospf6_pushback_neighbor *) + malloc(sizeof(struct ospf6_pushback_neighbor)); + opbn->router_id = on->router_id; + opbn->ifindex = on->ospf6_if->interface->ifindex; + listnode_add(lsa->pushback_neighbor_list, opbn); +} + +void ospf6_pushback_lsa_neighbor_delete(struct ospf6_lsa *lsa, + struct ospf6_neighbor *on) +{ + plistnode n; + struct ospf6_pushback_neighbor *opbn; + + //Find pushback neighbor, if found remove + for (n = listhead(lsa->pushback_neighbor_list); n; nextnode(n)) + { + opbn = (struct ospf6_pushback_neighbor *) getdata(n); + if (on->router_id == opbn->router_id && + on->ospf6_if->interface->ifindex == opbn->ifindex) + { + listnode_delete(lsa->pushback_neighbor_list, opbn); + free(opbn); + break; + } + } + //clean out old neighbors and cancel pushback thread if pushback + //no more pushback neighbors + ospf6_refresh_lsa_pushback_list(lsa); +} + +void ospf6_pushback_lsa_delete(struct ospf6_lsa *lsa) +{ + plistnode n; + struct ospf6_pushback_neighbor *opbn; + + //cancel pushback thread + THREAD_OFF(lsa->pushBackTimer); + lsa->pushBackTimer = NULL; + + //clean up pushback neighbor list + if (lsa->pushback_neighbor_list) + { + n = listhead(lsa->pushback_neighbor_list); + while(n) + { + opbn = (struct ospf6_pushback_neighbor *) getdata(n); + nextnode(n); + free(opbn); + } + list_delete(lsa->pushback_neighbor_list); + lsa->pushback_neighbor_list = NULL; + } +} + +// Section 3.4.8-2.2 + //Does "from" neighbor's neighbors cover all the pushback neighbors +boolean ospf6_pushback_check_coverage(struct ospf6_lsa *lsa, + struct ospf6_neighbor *from) +{ + plistnode n; + boolean cover = true; + struct ospf6_pushback_neighbor *opbn; + struct ospf6_lsa *r_lsa; + char *start, *end, *current; + struct ospf6_router_lsa *router_lsa; + struct ospf6_router_lsdesc *router_lsd; + + ospf6_refresh_lsa_pushback_list(lsa); +#ifdef SIM + ospf6_print_pushback_list_sim(lsa); +#endif //SIM + + if (!lsa->pushback_neighbor_list) + return cover; //from neighbor covers because no pushback neighbors exist + + //find router lsa for "from" neighbor + r_lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_ROUTER), htonl(0), + from->router_id, from->ospf6_if->area->lsdb); + if (!r_lsa) + return cover; + router_lsa = (struct ospf6_router_lsa *) + ((char *) r_lsa->header + sizeof (struct ospf6_lsa_header)); + start = (char *) router_lsa + sizeof (struct ospf6_router_lsa); + end = (char *) r_lsa->header + ntohs (r_lsa->header->length); + + //loop over pushback neighbor list + n = listhead(lsa->pushback_neighbor_list); + while(n) + { + opbn = (struct ospf6_pushback_neighbor *) getdata(n); + nextnode(n); + cover = false; + //loop over neighbors in router lsa + for (current=start; current + sizeof (struct ospf6_router_lsdesc) <= end; + current += sizeof (struct ospf6_router_lsdesc)) + { + router_lsd = (struct ospf6_router_lsdesc *) current; + if (ntohl(router_lsd->interface_id) != from->ifindex) + continue; //link must be on MANET subnet + if (router_lsd->neighbor_router_id == opbn->router_id) + { //from's neighbor covers this pushback neighbor + cover = true; + break; + } + } + if (!cover) + return cover; + } + return cover; } +int ospf6_pushback_expiration (struct thread *thread) +{ + struct ospf6_lsa *lsa = (struct ospf6_lsa *) THREAD_ARG (thread); + plistnode n, i; + pList eligible_interfaces; + struct ospf6_pushback_neighbor *opbn; + struct ospf6_neighbor *on; + struct ospf6_interface *oi; + + lsa->pushBackTimer = NULL; + ospf6_refresh_lsa_pushback_list(lsa); + if (!lsa->pushback_neighbor_list) + return 0; + + eligible_interfaces = list_new (); + n = listhead(lsa->pushback_neighbor_list); + while(n) + { + opbn = (struct ospf6_pushback_neighbor *) getdata(n); + nextnode(n); + + //neighbor should exist because pushback list was just refreshed + oi = ospf6_interface_lookup_by_ifindex(opbn->ifindex); + on = ospf6_neighbor_lookup (opbn->router_id, oi); + assert(on); + + if (!listnode_lookup(eligible_interfaces, oi)) + listnode_add (eligible_interfaces, oi); + ospf6_pushback_lsa_neighbor_delete(lsa,on); + +#ifdef OSPF6_MANET_MDR_FLOOD + if (oi->flooding == OSPF6_FLOOD_MDR_SICDS) + { + //if LSA is on ack list, this will count as an implict ack + //remove LSA from ack list (MANET always on interface ack list) + struct ospf6_lsa *ack_lsa; + struct ospf6_lsa *rxmt_lsa; + + // Reset rxmt time if LSA is in retrans list. + rxmt_lsa = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, + lsa->header->adv_router, on->retrans_list); + if (rxmt_lsa) + set_time(&rxmt_lsa->rxmt_time); + + //if LSA is on ack list, this will count as an implict ack + //remove LSA from ack list (MANET always on interface ack list) + ack_lsa = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, + lsa->header->adv_router, oi->lsack_list); + + if (ack_lsa) + ospf6_lsdb_remove (ack_lsa, oi->lsack_list); + + continue; + } +#endif //OSPF6_MANET_MDR_FLOOD + + if (IS_OSPF6_DEBUG_FLOODING) + zlog_info (" Add copy of %s to retrans-list of %s", + lsa->name, on->name); + ospf6_increment_retrans_count (lsa); + set_time(&lsa->rxmt_time); + ospf6_lsdb_add (ospf6_lsa_copy (lsa), on->retrans_list); +#ifdef OSPF6_DELAYED_FLOOD + on->thread_send_lsupdate = + ospf6_send_lsupdate_delayed_msec(master, ospf6_lsupdate_send_neighbor, + on, on->ospf6_if->rxmt_interval*1000, + on->thread_send_lsupdate); +#else + if (on->thread_send_lsupdate == NULL) + on->thread_send_lsupdate = + thread_add_timer (master, ospf6_lsupdate_send_neighbor, + on, on->ospf6_if->rxmt_interval); +#endif //OSPF6_DELAYED_FLOOD + } + + for (i = listhead(eligible_interfaces); i; nextnode(i)) + { + oi = (struct ospf6_interface *) getdata(i); + if (IS_OSPF6_DEBUG_FLOODING) + zlog_info (" Add copy of %s to lsupdate_list of %s", + lsa->name, oi->interface->name); +#ifdef SIM_ETRACE_STAT + char id[16], adv_router[16]; + inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id)); + inet_ntop (AF_INET, &lsa->header->adv_router, adv_router, + sizeof (adv_router)); + TraceEvent_sim(2,"Schedule Pushback Flood LSA %s -id %s -advrt %s -age %d -seq %lu -len %d", + ospf6_lstype_name(lsa->header->type), id, adv_router, + ntohs(age_mask(lsa->header)), ntohl(lsa->header->seqnum), + ntohs(lsa->header->length)); + update_statistics(OSPF6_LSA_FLOOD_NONRELAY,1); +#endif //SIM_ETRACE_STAT + + ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list); +#ifdef OSPF6_DELAYED_FLOOD + //XXX BOEING LSAs after this are gone from the perspective of pushback + //with delay equal to 1msec no coalescing takes place + //with a higher delay pushBackInterval is effectively increased + oi->thread_send_lsupdate = + ospf6_send_lsupdate_delayed_msec(master, ospf6_lsupdate_send_interface, + oi, 1, oi->thread_send_lsupdate); +#else + if (oi->thread_send_lsupdate == NULL) + oi->thread_send_lsupdate = + thread_add_event (master, ospf6_lsupdate_send_interface, oi, 0); +#endif //OSPF6_DELAYED_FLOOD + } + list_delete (eligible_interfaces); + return 0; +} + +void +ospf6_refresh_lsa_pushback_list(struct ospf6_lsa *lsa) +{ + plistnode n; + struct ospf6_neighbor *on; + struct ospf6_interface *oi; + struct ospf6_pushback_neighbor *opbn; + + //The neighbor state of pushback neighbors could have changed + //remove those pushback neighbors in a state below EXCHANGE + + if (!lsa->pushback_neighbor_list) + return; + + n = listhead(lsa->pushback_neighbor_list); + while(n) + { + opbn = (struct ospf6_pushback_neighbor *) getdata(n); + nextnode(n); + oi = ospf6_interface_lookup_by_ifindex(opbn->ifindex); + on = ospf6_neighbor_lookup(opbn->router_id, oi); + + //For SICDS, delete neighbors that are below TWOWAY. + if (oi->flooding == OSPF6_FLOOD_MDR_SICDS) + { + if (!on || on->state < OSPF6_NEIGHBOR_TWOWAY) + { //pushback neighbor fell below state TWOWAY + listnode_delete(lsa->pushback_neighbor_list, opbn); + free(opbn); + } + } + else if (!on || on->state < OSPF6_NEIGHBOR_EXCHANGE) + { //pushback neighbor fell below state EXCHANGE + listnode_delete(lsa->pushback_neighbor_list, opbn); + free(opbn); + } + } + //there are no pushback neigbors left, cancel the pushback timer + if (lsa->pushback_neighbor_list->count == 0) + { + ospf6_pushback_lsa_delete(lsa); + } +} + +//return pushback jitter in msec +long pushback_jitter(struct ospf6_interface *oi) +{ + long jitter = 0; + int rand_; + +#ifdef SIM + rand_= rand_sim(); +#else + rand_ = rand(); +#endif //SIM + +#ifdef OSPF6_MANET_MPR_FLOOD + if (oi->flooding == OSPF6_FLOOD_MPR_SDCDS) + jitter = (long) ((double)rand_/RAND_MAX*oi->pushBackInterval); +#endif //OSPF6_MANET_MPR_FLOOD + +#ifdef OSPF6_MANET_MDR_FLOOD + if (oi->flooding == OSPF6_FLOOD_MDR_SICDS) + jitter = (long) ((double)rand_/RAND_MAX*oi->BackupWaitInterval); +#endif //OSPF6_MANET_MDR_FLOOD + + if (!oi->flooding == OSPF6_FLOOD_MDR_SICDS || + !oi->flooding == OSPF6_FLOOD_MPR_SDCDS) + { + printf("Interface flooding %d should not call pushback_jitter()\n", + oi->flooding); + exit(0); + } + return jitter; +} +#endif //OSPF6_MANET + +#ifdef SIM_ETRACE_STAT +void update_statistics(int element, double add) +{ + if (!collect_stats_sim(ospf6)) + return; + ospf6->statistics[element] += add; +} +#endif //SIM_ETRACE_STAT diff -Naur quagga-0.98.5/ospf6d/ospf6_top.h quagga-0.98.5-manet/ospf6d/ospf6_top.h --- quagga-0.98.5/ospf6d/ospf6_top.h 2004-10-11 10:02:40.000000000 -0700 +++ quagga-0.98.5-manet/ospf6d/ospf6_top.h 2006-02-20 13:42:12.000000000 -0800 @@ -23,6 +23,66 @@ #define OSPF6_TOP_H #include "routemap.h" +#ifdef SIM +#include "lib/zebra.h" //for ZEBRA_ROUTE_MAX +#endif //SIM +#ifdef OSPF6_MANET +#include "ospf6d.h" //for boolean +#endif //OSPF6_MANET + +#ifdef SIM_ETRACE_STAT +typedef enum { + OSPF6_HELLO_SENT = 0, + OSPF6_HELLO_BYTE_SENT, + OSPF6_DBDESC_SENT, + OSPF6_DBDESC_BYTE_SENT, + OSPF6_LSREQ_SENT, + OSPF6_LSREQ_BYTE_SENT, + OSPF6_LSACK_SENT, + OSPF6_LSACK_BYTE_SENT, + OSPF6_LSUPDATE_SENT, + OSPF6_LSUPDATE_BYTE_SENT, + OSPF6_LSUPDATE_MULTI_SENT, + OSPF6_LSUPDATE_MULTI_BYTE_SENT, + OSPF6_LSUPDATE_UNI_SENT, + OSPF6_LSUPDATE_UNI_BYTE_SENT, + OSPF6_LSUPDATE_UNI_COL_SENT, + OSPF6_LSUPDATE_UNI_COL_BYTE_SENT, + OSPF6_LSUPDATE_UNI_DBEX_SENT, + OSPF6_LSUPDATE_UNI_DBEX_BYTE_SENT, + OSPF6_LSUPDATE_UNI_STALE_SENT, + OSPF6_LSUPDATE_UNI_STALE_BYTE_SENT, + OSPF6_LSUPDATE_UNI_RXMT_SENT, + OSPF6_LSUPDATE_UNI_RXMT_BYTE_SENT, + + OSPF6_CHANGE_OF_NUM_NEIGHS, + OSPF6_DURATION_OF_NUM_NEIGHS, + OSPF6_NUM_NEIGH_TIMES_DURATION_OF_NUM_NEIGHS, + OSPF6_CHANGE_OF_NUM_ADJ, + OSPF6_DURATION_OF_NUM_ADJ, + OSPF6_NUM_ADJ_TIMES_DURATION_OF_NUM_ADJ, + OSPF6_NEIGH_LIFETIME, + OSPF6_NEIGH_DEATHS, + OSPF6_DATABASE_EXCHANGES, + OSPF6_NUM_LSA_DIFFS, + + OSPF6_DURATION_OF_NUM_RELSEL, + OSPF6_NUM_RELSEL_TIMES_DURATION_OF_NUM_RELSEL, + OSPF6_RELSEL_LIFETIME, + OSPF6_RELSEL_DEATHS, + OSPF6_LSA_FLOOD_RELAY, + OSPF6_LSA_FLOOD_SUPPRESS, + OSPF6_LSA_FLOOD_NONRELAY, + OSPF6_ROUTER_LSA_INSTALL, + OSPF6_ROUTER_LSA_HOPCOUNT, + + OSPF6_ORIG_RTR_LSA, + OSPF6_ROUTE_CHANGES, + OSPF6_ADJ_ACCUM, + + OSPF6_STAT_LENGTH +}ospf6_stats; +#endif //SIM_ETRACE_STAT /* OSPFv3 top level data structure */ struct ospf6 @@ -37,7 +97,7 @@ struct timeval starttime; /* list of areas */ - struct list *area_list; + pList area_list; /* AS scope link state database */ struct ospf6_lsdb *lsdb; @@ -60,6 +120,14 @@ u_char flag; struct thread *maxage_remover; +#ifdef SIM_ETRACE_STAT + double statistics[OSPF6_STAT_LENGTH]; + long start_stat_time; +#endif //SIM_ETRACE_STAT +#ifdef OSPF6_CONFIG + int minLSInterval; + int minLSArrival; +#endif //OSPF6_CONFIG }; #define OSPF6_DISABLED 0x01 @@ -72,6 +140,37 @@ void ospf6_maxage_remove (struct ospf6 *o); -#endif /* OSPF6_TOP_H */ +#ifdef SIM +void ospf6_delete (struct ospf6 *o); +void ospf6_disable (struct ospf6 *o); +void ospf6_enable (struct ospf6 *o); +#endif //SIM +#ifdef OSPF6_MANET +struct ospf6_pushback_neighbor +{ + /* Neighbor Router ID */ + u_int32_t router_id; + /* Neighbor Interface ID */ + u_int32_t ifindex; +}; +struct ospf6_neighbor; +struct ospf6_lsa; +struct ospf6_interface; +void ospf6_pushback_lsa_add(struct ospf6_lsa *lsa, + struct ospf6_neighbor *on); +void ospf6_pushback_lsa_neighbor_delete(struct ospf6_lsa *lsa, + struct ospf6_neighbor *on); +void ospf6_pushback_lsa_delete(struct ospf6_lsa *lsa); +boolean ospf6_pushback_check_coverage(struct ospf6_lsa *lsa, + struct ospf6_neighbor *on); +int ospf6_pushback_expiration (struct thread *thread); +void ospf6_refresh_lsa_pushback_list(struct ospf6_lsa *lsa); +long pushback_jitter(struct ospf6_interface *oi); +#endif //OSPF6_MANET +#ifdef SIM_ETRACE_STAT +void update_statistics(int, double); +#endif //SIM_ETRACE_STAT + +#endif /* OSPF6_TOP_H */ diff -Naur quagga-0.98.5/ospf6d/ospf6_zebra.c quagga-0.98.5-manet/ospf6d/ospf6_zebra.c --- quagga-0.98.5/ospf6d/ospf6_zebra.c 2005-03-05 11:16:48.000000000 -0800 +++ quagga-0.98.5-manet/ospf6d/ospf6_zebra.c 2006-02-20 13:42:12.000000000 -0800 @@ -1,3 +1,4 @@ +#ifndef SIM /* * Copyright (C) 2003 Yasuhiro Ohara * @@ -689,4 +690,4 @@ install_element (CONFIG_NODE, &no_debug_ospf6_zebra_sendrecv_cmd); } - +#endif //SIM diff -Naur quagga-0.98.5/ospf6d/ospf6_zebra.h quagga-0.98.5-manet/ospf6d/ospf6_zebra.h --- quagga-0.98.5/ospf6d/ospf6_zebra.h 2004-05-18 11:57:06.000000000 -0700 +++ quagga-0.98.5-manet/ospf6d/ospf6_zebra.h 2006-02-20 13:42:12.000000000 -0800 @@ -1,3 +1,4 @@ +#ifndef SIM /* * Copyright (C) 2003 Yasuhiro Ohara * @@ -51,3 +52,4 @@ #endif /*OSPF6_ZEBRA_H*/ +#endif //SIM diff -Naur quagga-0.98.5/redhat/quagga.spec quagga-0.98.5-manet/redhat/quagga.spec --- quagga-0.98.5/redhat/quagga.spec 2005-08-28 08:39:49.000000000 -0700 +++ quagga-0.98.5-manet/redhat/quagga.spec 1969-12-31 16:00:00.000000000 -0800 @@ -1,536 +0,0 @@ -# configure options -%define with_snmp 1 -%define with_vtysh 1 -%define with_ospf_te 1 -%define with_nssa 1 -%define with_opaque_lsa 1 -%define with_tcp_zebra 0 -%define with_vtysh 1 -%define with_pam 1 -%define with_ipv6 1 -%define with_ospfclient 1 -%define with_ospfapi 1 -%define with_irdp 1 -%define with_isisd 0 -%define with_shared 1 -%define with_multipath 64 -%define quagga_user quagga -%define vty_group quaggavty - -# path defines -%define _sysconfdir /etc/quagga -%define zeb_src %{_builddir}/%{name}-%{version} -%define zeb_rh_src %{zeb_src}/redhat -%define zeb_docs %{zeb_src}/doc - -# defines for configure -%define _libexecdir %{_exec_prefix}/libexec/quagga -%define _libdir %{_exec_prefix}/%{_lib}/quagga -%define _includedir %{_prefix}/include -%define _localstatedir /var/run/quagga - -# misc internal defines -%define quagga_uid 92 -%define quagga_gid 92 -%define daemon_list zebra ripd ospfd bgpd - -%if %{with_ipv6} -%define daemonv6_list ripngd ospf6d -%else -%define daemonv6_list "" -%endif - -%if %{with_isisd} -%define daemon_other isisd -%else -%define daemon_other "" -%endif - -%define all_daemons %{daemon_list} %{daemonv6_list} %{daemon_other} watchquagga - -# allow build dir to be kept -%define keep_build 0 - -Summary: Routing daemon -Name: quagga -Version: 0.98.5 -Release: 2005082801 -License: GPL -Group: System Environment/Daemons -Source0: http://www.quagga.net/snapshots/cvs/%{name}-%{version}.tar.gz -URL: http://www.quagga.net -%if %{with_snmp} -BuildRequires: net-snmp-devel -Prereq: net-snmp -%endif -%if %{with_vtysh} -BuildRequires: readline readline-devel ncurses ncurses-devel -Prereq: readline ncurses -%endif -BuildRequires: texinfo tetex autoconf pam-devel patch libcap-devel -# Initscripts > 5.60 is required for IPv6 support -Prereq: initscripts >= 5.60 -Prereq: ncurses readline pam -Prereq: /sbin/install-info -Provides: routingdaemon -BuildRoot: %{_tmppath}/%{name}-%{version}-root -Obsoletes: bird gated mrt zebra - -%description -Quagga is a free software that manages TCP/IP based routing -protocol. It takes multi-server and multi-thread approach to resolve -the current complexity of the Internet. - -Quagga supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1, RIPv2, and RIPng. - -Quagga is intended to be used as a Route Server and a Route Reflector. It is -not a toolkit, it provides full routing power under a new architecture. -Quagga by design has a process for each protocol. - -Quagga is a fork of GNU Zebra. - -%package contrib -Summary: contrib tools for quagga -Group: System Environment/Daemons - -%description contrib -Contributed/3rd party tools which may be of use with quagga. - -%package devel -Summary: Header and object files for quagga development -Group: System Environment/Daemons - -%description devel -The quagga-devel package contains the header and object files neccessary for -developing OSPF-API and quagga applications. - -%prep -%setup -q - -%build - -# For standard gcc verbosity, uncomment these lines: -#CFLAGS="%{optflags} -Wall -Wsign-compare -Wpointer-arith" -#CFLAGS="${CFLAGS} -Wbad-function-cast -Wwrite-strings" - -# For ultra gcc verbosity, uncomment these lines also: -#CFLAGS="${CFLAGS} -W -Wcast-qual -Wstrict-prototypes" -#CFLAGS="${CFLAGS} -Wmissing-declarations -Wmissing-noreturn" -#CFLAGS="${CFLAGS} -Wmissing-format-attribute -Wunreachable-code" -#CFLAGS="${CFLAGS} -Wpacked -Wpadded" - -%configure \ -%if !%{with_shared} - --disable-shared \ -%endif -%if %{with_ipv6} - --enable-ipv6 \ -%endif -%if %{with_snmp} - --enable-snmp \ -%endif -%if %{with_multipath} - --enable-multipath=%{with_multipath} \ -%endif -%if %{with_tcp_zebra} - --enable-tcp-zebra \ -%endif -%if %{with_nssa} - --enable-nssa \ -%endif -%if %{with_opaque_lsa} - --enable-opaque-lsa \ -%endif -%if %{with_ospf_te} - --enable-ospf-te \ -%endif -%if %{with_vtysh} - --enable-vtysh \ -%endif -%if %{with_ospfclient} - --enable-ospfclient=yes \ -%else - --enable-ospfclient=no\ -%endif -%if %{with_ospfapi} - --enable-ospfapi=yes \ -%else - --enable-ospfapi=no \ -%endif -%if %{with_irdp} - --enable-irdp=yes \ -%else - --enable-irdp=no \ -%endif -%if %{with_isisd} - --enable-isisd \ -%else - --disable-isisd \ -%endif -%if %{with_pam} - --with-libpam \ -%endif -%if %quagga_user - --enable-user=%quagga_user \ - --enable-group=%quagga_user \ -%endif -%if %vty_group - --enable-vty-group=%vty_group \ -%endif ---enable-netlink --enable-gcc-rdynamic - -make %{?_smp_mflags} MAKEINFO="makeinfo --no-split" - -pushd doc -makeinfo --no-split --html -o quagga.html quagga.texi -popd - -%install -rm -rf $RPM_BUILD_ROOT - -install -d $RPM_BUILD_ROOT/etc/{rc.d/init.d,sysconfig,logrotate.d,pam.d} \ - $RPM_BUILD_ROOT/var/log/quagga $RPM_BUILD_ROOT%{_infodir} - -make install \ - DESTDIR=$RPM_BUILD_ROOT - -# Remove this file, as it is uninstalled and causes errors when building on RH9 -rm -rf $RPM_BUILD_ROOT/usr/share/info/dir - -# install etc sources -for daemon in %{all_daemons} ; do - if [ x"${daemon}" != x"" ] ; then - install %{zeb_rh_src}/${daemon}.init \ - $RPM_BUILD_ROOT/etc/rc.d/init.d/${daemon} - fi -done -install -m644 %{zeb_rh_src}/quagga.pam \ - $RPM_BUILD_ROOT/etc/pam.d/quagga -install -m644 %{zeb_rh_src}/quagga.logrotate \ - $RPM_BUILD_ROOT/etc/logrotate.d/quagga -install -m644 %{zeb_rh_src}/quagga.sysconfig \ - $RPM_BUILD_ROOT/etc/sysconfig/quagga -install -d -m750 $RPM_BUILD_ROOT/var/run/quagga - -%pre -# add vty_group -%if %vty_group -groupadd -r %vty_group 2> /dev/null || : -%endif -# add quagga user and group -%if %quagga_user -/usr/sbin/groupadd -g %quagga_gid quagga 2> /dev/null || : -/usr/sbin/useradd -u %quagga_uid -g %quagga_gid \ - -M -r -s /sbin/nologin -c "Quagga routing suite" \ - -d %_localstatedir %quagga_user 2> /dev/null || : -%endif - -%post -# zebra_spec_add_service -# e.g. zebra_spec_add_service zebrasrv 2600/tcp "zebra service" - -zebra_spec_add_service () -{ - # Add port /etc/services entry if it isn't already there - if [ -f /etc/services ] && \ - ! %__sed -e 's/#.*$//' /etc/services | %__grep -wq $1 ; then - echo "$1 $2 # $3" >> /etc/services - fi -} - -zebra_spec_add_service zebrasrv 2600/tcp "zebra service" -zebra_spec_add_service zebra 2601/tcp "zebra vty" -zebra_spec_add_service ripd 2602/tcp "RIPd vty" -%if %{with_ipv6} -zebra_spec_add_service ripngd 2603/tcp "RIPngd vty" -%endif -zebra_spec_add_service ospfd 2604/tcp "OSPFd vty" -zebra_spec_add_service bgpd 2605/tcp "BGPd vty" -%if %{with_ipv6} -zebra_spec_add_service ospf6d 2606/tcp "OSPF6d vty" -%endif -%if %{with_ospfapi} -zebra_spec_add_service ospfapi 2607/tcp "OSPF-API" -%endif -%if %{with_isisd} -zebra_spec_add_service isisd 2608/tcp "ISISd vty" -%endif - -for daemon in %daemon_list ; do - /sbin/chkconfig --add ${daemon} -done - -/sbin/install-info %{_infodir}/quagga.info.gz %{_infodir}/dir - -# Create dummy files if they don't exist so basic functions can be used. -if [ ! -e %{_sysconfdir}/zebra.conf ]; then - echo "hostname `hostname`" > %{_sysconfdir}/zebra.conf - chmod 640 %{_sysconfdir}/zebra.conf -fi -if [ ! -e %{_sysconfdir}/vtysh.conf ]; then - touch %{_sysconfdir}/vtysh.conf - chmod 640 %{_sysconfdir}/vtysh.conf -fi - -%postun -if [ "$1" -ge 1 ]; then - # Find out which daemons need to be restarted. - for daemon in %all_daemons ; do - if [ -f /var/lock/subsys/$daemon ]; then - eval restart_$daemon=yes - else - eval restart_$daemon=no - fi - done - # Rename restart flags for daemons handled specially. - running_zebra="$restart_zebra" - restart_zebra=no - running_watchquagga="$restart_watchquagga" - restart_watchquagga=no - # Stop watchquagga first. - [ "$running_watchquagga" = yes ] && \ - /etc/rc.d/init.d/watchquagga stop >/dev/null 2>&1 - # Stop all daemons other than zebra and watchquagga. - for daemon in %all_daemons ; do - eval restart=\$restart_${daemon} - [ "$restart" = yes ] && \ - /etc/rc.d/init.d/$daemon stop >/dev/null 2>&1 - done - # Restart zebra. - [ "$running_zebra" = yes ] && \ - /etc/rc.d/init.d/zebra restart >/dev/null 2>&1 - # Start all daemons other than zebra and watchquagga. - for daemon in %all_daemons ; do - eval restart=\$restart_${daemon} - [ "$restart" = yes ] && \ - /etc/rc.d/init.d/$daemon start >/dev/null 2>&1 - done - # Start watchquagga last. - # Avoid postun scriptlet error if watchquagga is not running. - [ "$running_watchquagga" = yes ] && \ - /etc/rc.d/init.d/watchquagga start >/dev/null 2>&1 || : -fi - -%preun -if [ "$1" = "0" ]; then - for daemon in %all_daemons ; do - /etc/rc.d/init.d/${daemon} stop >/dev/null 2>&1 - /sbin/chkconfig --del ${daemon} - done - /sbin/install-info --delete %{_infodir}/quagga.info.gz %{_infodir}/dir -fi - -%clean -%if !%{keep_build} -rm -rf $RPM_BUILD_ROOT -%endif - -%files -%defattr(-,root,root) -%doc */*.sample* AUTHORS COPYING -%doc doc/quagga.html -%doc doc/mpls -%doc ChangeLog INSTALL NEWS README REPORTING-BUGS SERVICES TODO -%if %{quagga_user} -%dir %attr(751,%quagga_user,%quagga_user) %{_sysconfdir} -%dir %attr(750,%quagga_user,%quagga_user) /var/log/quagga -%dir %attr(751,%quagga_user,%quagga_user) /var/run/quagga -%else -%dir %attr(750,root,root) %{_sysconfdir} -%dir %attr(750,root,root) /var/log/quagga -%dir %attr(755,root,root) /usr/share/info -%dir %attr(750,root,root) /var/run/quagga -%endif -%if %{vty_group} -%attr(750,%quagga_user,%vty_group) %{_sysconfdir}/vtysh.conf.sample -%endif -%{_infodir}/*info* -%{_mandir}/man*/* -%{_sbindir}/zebra -%{_sbindir}/ospfd -%{_sbindir}/ripd -%{_sbindir}/bgpd -%{_sbindir}/watchquagga -%if %{with_ipv6} -%{_sbindir}/ripngd -%{_sbindir}/ospf6d -%endif -%if %{with_isisd} -%{_sbindir}/isisd -%endif -%dir %attr(755,root,root) %{_libdir} -%if %{with_shared} -%{_libdir}/lib*.so -%{_libdir}/lib*.so.* -%endif -%if %{with_vtysh} -%{_bindir}/* -%endif -%config /etc/quagga/[!v]* -%config /etc/rc.d/init.d/* -%config(noreplace) /etc/sysconfig/quagga -%config(noreplace) /etc/pam.d/quagga -%config(noreplace) %attr(640,root,root) /etc/logrotate.d/* - -%files contrib -%defattr(-,root,root) -%doc tools - -%files devel -%defattr(-,root,root) -%if %{with_ospfclient} -%{_sbindir}/ospfclient -%endif -%{_libdir}/*.a -%{_libdir}/*.la -%dir %attr(755,root,root) %{_includedir}/%{name} -%{_includedir}/%name/*.h -%dir %attr(755,root,root) %{_includedir}/%{name}/ospfd -%{_includedir}/%name/ospfd/*.h -%if %{with_ospfapi} -%dir %attr(755,root,root) %{_includedir}/%{name}/ospfapi -%{_includedir}/%name/ospfapi/*.h -%endif - -%changelog -%changelog -* Wed Jan 12 2005 Andrew J. Schorr -- on package upgrade, implement careful, phased restart logic -- use gcc -rdynamic flag when linking for better backtraces - -* Wed Dec 22 2004 Andrew J. Schorr -- daemonv6_list should contain only IPv6 daemons - -* Wed Dec 22 2004 Andrew J. Schorr -- watchquagga added -- on upgrade, all daemons should be condrestart'ed -- on removal, all daemons should be stopped - -* Mon Nov 08 2004 Paul Jakma -- Use makeinfo --html to generate quagga.html - -* Sun Nov 07 2004 Paul Jakma -- Fix with_ipv6 set to 0 build - -* Sat Oct 23 2004 Paul Jakma -- Update to 0.97.2 - -* Sat Oct 23 2004 Andrew J. Schorr -- Make directories be owned by the packages concerned -- Update logrotate scripts to use correct path to killall and use pid files - -* Fri Oct 08 2004 Paul Jakma -- Update to 0.97.0 - -* Wed Sep 15 2004 Paul Jakma -- build snmp support by default -- build irdp support -- build with shared libs -- devel subpackage for archives and headers - -* Thu Jan 08 2004 Paul Jakma -- updated sysconfig files to specify local dir -- added ospf_dump.c crash quick fix patch -- added ospfd persistent interface configuration patch - -* Tue Dec 30 2003 Paul Jakma -- sync to CVS -- integrate RH sysconfig patch to specify daemon options (RH) -- default to have vty listen only to 127.1 (RH) -- add user with fixed UID/GID (RH) -- create user with shell /sbin/nologin rather than /bin/false (RH) -- stop daemons on uninstall (RH) -- delete info file on %preun, not %postun to avoid deletion on upgrade. (RH) -- isisd added -- cleanup tasks carried out for every daemon - -* Sun Nov 2 2003 Paul Jakma -- Fix -devel package to include all files -- Sync to 0.96.4 - -* Tue Aug 12 2003 Paul Jakma -- Renamed to Quagga -- Sync to Quagga release 0.96 - -* Tue Mar 20 2003 Paul Jakma -- zebra privileges support - -* Mon Mar 18 2003 Paul Jakma -- Fix mem leak in 'show thread cpu' -- Ralph Keller's OSPF-API -- Amir: Fix configure.ac for net-snmp - -* Sat Mar 1 2003 Paul Jakma -- ospfd IOS prefix to interface matching for 'network' statement -- temporary fix for PtP and IPv6 -- sync to zebra.org CVS - -* Mon Jan 20 2003 Paul Jakma -- update to latest cvs -- Yon's "show thread cpu" patch - 17217 -- walk up tree - 17218 -- ospfd NSSA fixes - 16681 -- ospfd nsm fixes - 16824 -- ospfd OLSA fixes and new feature - 16823 -- KAME and ifindex fixes - 16525 -- spec file changes to allow redhat files to be in tree - -* Sat Dec 28 2002 Alexander Hoogerhuis -- Added conditionals for building with(out) IPv6, vtysh, RIP, BGP -- Fixed up some build requirements (patch) -- Added conditional build requirements for vtysh / snmp -- Added conditional to %files for %_bindir depending on vtysh - -* Mon Nov 11 2002 Paul Jakma -- update to latest CVS -- add Greg Troxel's md5 buffer copy/dup fix -- add RIPv1 fix -- add Frank's multicast flag fix - -* Wed Oct 09 2002 Paul Jakma -- update to latest CVS -- timestamped crypt_seqnum patch -- oi->on_write_q fix - -* Mon Sep 30 2002 Paul Jakma -- update to latest CVS -- add vtysh 'write-config (integrated|daemon)' patch -- always 'make rebuild' in vtysh/ to catch new commands - -* Fri Sep 13 2002 Paul Jakma -- update to 0.93b - -* Wed Sep 11 2002 Paul Jakma -- update to latest CVS -- add "/sbin/ip route flush proto zebra" to zebra RH init on startup - -* Sat Aug 24 2002 Paul Jakma -- update to current CVS -- add OSPF point to multipoint patch -- add OSPF bugfixes -- add BGP hash optimisation patch - -* Fri Jun 14 2002 Paul Jakma -- update to 0.93-pre1 / CVS -- add link state detection support -- add generic PtP and RFC3021 support -- various bug fixes - -* Thu Aug 09 2001 Elliot Lee 0.91a-6 -- Fix bug #51336 - -* Wed Aug 1 2001 Trond Eivind Glomsrød 0.91a-5 -- Use generic initscript strings instead of initscript specific - ( "Starting foo: " -> "Starting $prog:" ) - -* Fri Jul 27 2001 Elliot Lee 0.91a-4 -- Bump the release when rebuilding into the dist. - -* Tue Feb 6 2001 Tim Powers -- built for Powertools - -* Sun Feb 4 2001 Pekka Savola -- Hacked up from PLD Linux 0.90-1, Mandrake 0.90-1mdk and one from zebra.org. -- Update to 0.91a -- Very heavy modifications to init.d/*, .spec, pam, i18n, logrotate, etc. -- Should be quite Red Hat'isque now. diff -Naur quagga-0.98.5/vtysh/extract.pl quagga-0.98.5-manet/vtysh/extract.pl --- quagga-0.98.5/vtysh/extract.pl 2005-08-28 08:39:50.000000000 -0700 +++ quagga-0.98.5-manet/vtysh/extract.pl 1969-12-31 16:00:00.000000000 -0800 @@ -1,200 +0,0 @@ -#! /usr/bin/perl -## -## vtysh/extract.pl. Generated from extract.pl.in by configure. -## -## Virtual terminal interface shell command extractor. -## Copyright (C) 2000 Kunihiro Ishiguro -## -## This file is part of GNU Zebra. -## -## GNU Zebra is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by the -## Free Software Foundation; either version 2, or (at your option) any -## later version. -## -## GNU Zebra is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with GNU Zebra; see the file COPYING. If not, write to the Free -## Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -## 02111-1307, USA. -## - -print < -#include "command.h" -#include "vtysh.h" - -EOF - -$ignore{'"interface IFNAME"'} = "ignore"; -$ignore{'"ip vrf NAME"'} = "ignore"; -$ignore{'"router rip"'} = "ignore"; -$ignore{'"router ripng"'} = "ignore"; -$ignore{'"router ospf"'} = "ignore"; -$ignore{'"router ospf <0-65535>"'} = "ignore"; -$ignore{'"router ospf6"'} = "ignore"; -$ignore{'"router bgp <1-65535>"'} = "ignore"; -$ignore{'"router bgp <1-65535> view WORD"'} = "ignore"; -$ignore{'"router isis WORD"'} = "ignore"; -$ignore{'"address-family ipv4"'} = "ignore"; -$ignore{'"address-family ipv4 (unicast|multicast)"'} = "ignore"; -$ignore{'"address-family ipv6"'} = "ignore"; -$ignore{'"address-family ipv6 unicast"'} = "ignore"; -$ignore{'"address-family vpnv4"'} = "ignore"; -$ignore{'"address-family vpnv4 unicast"'} = "ignore"; -$ignore{'"address-family ipv4 vrf NAME"'} = "ignore"; -$ignore{'"exit-address-family"'} = "ignore"; -$ignore{'"key chain WORD"'} = "ignore"; -$ignore{'"key <0-2147483647>"'} = "ignore"; -$ignore{'"route-map WORD (deny|permit) <1-65535>"'} = "ignore"; -$ignore{'"show route-map"'} = "ignore"; -$ignore{'"line vty"'} = "ignore"; -$ignore{'"who"'} = "ignore"; -$ignore{'"terminal monitor"'} = "ignore"; -$ignore{'"terminal no monitor"'} = "ignore"; -$ignore{'"show history"'} = "ignore"; - -foreach (@ARGV) { - $file = $_; - - open (FH, "cpp -DHAVE_CONFIG_H -DVTYSH_EXTRACT_PL -DHAVE_IPV6 -I../ -I./ -I./.. -I../lib $file |"); - local $/; undef $/; - $line = ; - close (FH); - - @defun = ($line =~ /(?:DEFUN|ALIAS)\s*\((.+?)\);?\s?\s?\n/sg); - @install = ($line =~ /install_element \(\s*[0-9A-Z_]+,\s*&[^;]*;\s*\n/sg); - - # DEFUN process - foreach (@defun) { - my (@defun_array); - @defun_array = split (/,/); - $defun_array[0] = ''; - - - # Actual input command string. - $str = "$defun_array[2]"; - $str =~ s/^\s+//g; - $str =~ s/\s+$//g; - - # Get VTY command structure. This is needed for searching - # install_element() command. - $cmd = "$defun_array[1]"; - $cmd =~ s/^\s+//g; - $cmd =~ s/\s+$//g; - - # $protocol is VTYSH_PROTO format for redirection of user input - if ($file =~ /lib/) { - if ($file =~ /keychain.c/) { - $protocol = "VTYSH_RIPD"; - } - if ($file =~ /routemap.c/) { - $protocol = "VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD"; - } - if ($file =~ /filter.c/) { - $protocol = "VTYSH_ALL"; - } - if ($file =~ /plist.c/) { - if ($defun_array[1] =~ m/ipv6/) { - $protocol = "VTYSH_RIPNGD|VTYSH_OSPF6D|VTYSH_BGPD"; - } else { - $protocol = "VTYSH_RIPD|VTYSH_OSPFD|VTYSH_BGPD"; - } - } - if ($file =~ /distribute.c/) { - if ($defun_array[1] =~ m/ipv6/) { - $protocol = "VTYSH_RIPNGD"; - } else { - $protocol = "VTYSH_RIPD"; - } - } - if ($file =~ /if_rmap.c/) { - if ($defun_array[1] =~ m/ipv6/) { - $protocol = "VTYSH_RIPNGD"; - } else { - $protocol = "VTYSH_RIPD"; - } - } - if ($file =~ /vty.c/) { - $protocol = "VTYSH_ALL"; - } - } else { - ($protocol) = ($file =~ /^.*\/([a-z0-9]+)\/[a-zA-Z0-9_\-]+\.c$/); - $protocol = "VTYSH_" . uc $protocol; - } - - # Append _vtysh to structure then build DEFUN again - $defun_array[1] = $cmd . "_vtysh"; - $defun_body = join (", ", @defun_array); - - # $cmd -> $str hash for lookup - $cmd2str{$cmd} = $str; - $cmd2defun{$cmd} = $defun_body; - $cmd2proto{$cmd} = $protocol; - } - - # install_element() process - foreach (@install) { - my (@element_array); - @element_array = split (/,/); - - # Install node - $enode = $element_array[0]; - $enode =~ s/^\s+//g; - $enode =~ s/\s+$//g; - ($enode) = ($enode =~ /([0-9A-Z_]+)$/); - - # VTY command structure. - ($ecmd) = ($element_array[1] =~ /&([^\)]+)/); - $ecmd =~ s/^\s+//g; - $ecmd =~ s/\s+$//g; - - # Register $ecmd - if (defined ($cmd2str{$ecmd}) - && ! defined ($ignore{$cmd2str{$ecmd}})) { - my ($key); - $key = $enode . "," . $cmd2str{$ecmd}; - $ocmd{$key} = $ecmd; - $odefun{$key} = $cmd2defun{$ecmd}; - push (@{$oproto{$key}}, $cmd2proto{$ecmd}); - } - } -} - -# Check finaly alive $cmd; -foreach (keys %odefun) { - my ($node, $str) = (split (/,/)); - my ($cmd) = $ocmd{$_}; - $live{$cmd} = $_; -} - -# Output DEFSH -foreach (keys %live) { - my ($proto); - my ($key); - $key = $live{$_}; - $proto = join ("|", @{$oproto{$key}}); - printf "DEFSH ($proto$odefun{$key})\n\n"; -} - -# Output install_element -print <