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-03 13:29:45.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-03 13:29:45.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-03 13:29:45.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-03 13:29:45.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-03 13:29:45.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-03 13:29:45.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-03 13:29:45.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(lsa->header->age), 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); @@ -235,108 +290,688 @@ /* actually install */ lsa->installed = now; ospf6_lsdb_add (lsa, lsa->lsdb); +#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 + double *stat; + boolean suppressed_flood = false; + if (collect_stats_sim(oi->area->ospf6)) { + if (oi->area->ospf6->statistics) { + stat = oi->area->ospf6->statistics; + } else { + fprintf(stderr, "No statistics object\n"); + exit(1); + } + } +#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 +#ifdef DEBUG_MANET_R_MACK + printf("don't add retransmit list neighbor: %s", ip2str(on->router_id)); + printf(" LSA type:%d, id:%x, advrtr:%s, seq:%x, exptime:%f\n", + mack->type, mack->id, ip2str(mack->adv_router), + mack->seqnum, elapsed_time(mack->expire_time)); +#endif //DEBUG_MANET_R_MACK + 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(lsa->header->age), ntohl(lsa->header->seqnum), + ntohs(lsa->header->length), from->name); +#ifdef SIM + ospf6_print_pushback_list_sim(lsa); +#endif //SIM + if (collect_stats_sim(oi->area->ospf6)) + stat[OSPF6_LSA_FLOOD_SUPPRESS]++; + } +#endif //SIM_ETRACE_STAT + + /* (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; + } - req = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id, + /* (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(lsa->header->age), ntohl(lsa->header->seqnum), + ntohs(lsa->header->length), from->name); + if (collect_stats_sim(oi->area->ospf6)) + { + double *stat = oi->area->ospf6->statistics; + stat[OSPF6_LSA_FLOOD_RELAY]++; + } +#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; + +#ifdef SIM_ETRACE_STAT + double *stat; + if (collect_stats_sim(oi->area->ospf6)) { + if (oi->area->ospf6->statistics) { + stat = oi->area->ospf6->statistics; + } else { + fprintf(stderr, "No statistics object\n"); + exit(1); + } + } +#endif //SIM_ETRACE_STAT + + 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(lsa->header->age), ntohl(lsa->header->seqnum), + ntohs(lsa->header->length), from->name); +#ifdef SIM + ospf6_print_pushback_list_sim(lsa); +#endif //SIM + if (collect_stats_sim(oi->area->ospf6)) + stat[OSPF6_LSA_FLOOD_SUPPRESS]++; +#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(lsa->header->age), ntohl(lsa->header->seqnum), + ntohs(lsa->header->length), from->name); + if (collect_stats_sim(oi->area->ospf6)) + { + double *stat = oi->area->ospf6->statistics; + stat[OSPF6_LSA_FLOOD_RELAY]++; + } +#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 +1002,75 @@ 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(lsa->header->age), ntohl(lsa->header->seqnum), + ntohs(lsa->header->length), from->name); + if (collect_stats_sim(oi->area->ospf6)) + { + double *stat = oi->area->ospf6->statistics; + stat[OSPF6_LSA_FLOOD_RELAY]++; + } +#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 +1095,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 +1126,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 +1147,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 +1185,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 +1228,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 +1272,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 +1310,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 +1342,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 +1378,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 +1415,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 +1449,65 @@ 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)) + { +#ifdef DEBUG_MANET_R_MACK + printf("don't ack-type:%x, id:%x, advrtr:%s, seq:%x\n", + ntohs(lsa->header->type), ntohl(lsa->header->id), + ip2str(lsa->header->adv_router), ntohl(lsa->header->seqnum)); +#endif //DEBUG_MANET_R_MACK + 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 +1519,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 +1535,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 +1553,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 +1587,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 +1605,34 @@ 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 +1640,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 /* (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 +#ifdef DEBUG_MANET_R_MACK + printf("dbex_receive_lsa-type:%x, id:%x, advrtr:%s, seq:%x\n", + ntohs(new_->header->type), ntohl(new_->header->id), + ip2str(new_->header->adv_router), ntohl(new_->header->seqnum)); +#endif //DEBUG_MANET_R_MACK + 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 +1737,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 +1769,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 +1778,48 @@ /* (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 +#ifdef DEBUG_MANET_R_LSA + printf("Remove LSA from lsdb_cache count %d\n",new_->lsdb->count_cache-1); + printf(" type:%x, id:%x, advrtr:%s, seq:%x, age:%d lock:%d\n", + ntohs(cache_lsa->header->type), ntohl(cache_lsa->header->id), + ip2str(cache_lsa->header->adv_router), + ntohl(cache_lsa->header->seqnum), + cache_lsa->header->age, cache_lsa->lock); +#endif //DEBUG_MANET_R_LSA + ospf6_lsdb_remove (cache_lsa, cache_lsa->lsdb); + } + } +#ifdef DEBUG_MANET_R_LSA_ + printf("Install LSA in lsdb from lsupdate lsdb count %d\n", lsdb->count); + printf(" type:%x, id:%x, advrtr:%s, seq:%x, age:%d\n", + ntohs(new_->header->type), ntohl(new_->header->id), + ip2str(new_->header->adv_router), ntohl(new_->header->seqnum), + new_->header->age); +#endif //DEBUG_MANET_R_LSA +} +#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 +1829,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 +1851,7 @@ /* BadLSReq */ thread_add_event (master, bad_lsreq, from, 0); - ospf6_lsa_delete (new); + ospf6_lsa_delete (new_); return; } @@ -934,9 +1861,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(old->header->age), 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 +1936,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 +1945,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,10 +1969,20 @@ 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 */ { if (is_debug) @@ -987,17 +1993,222 @@ /* 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(old->header->age), ntohl(old->header->seqnum), + ntohs(old->header->length), ntohs(new_->header->age), + 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 +#ifdef DEBUG_MANET_R_LSA + printf("Installed LSA in lsdb for neighbor below 2way\n"); + printf(" type:%x, id:%x, advrtr:%s, seq:%x, age:%d\n", + ntohs(new_->header->type), ntohl(new_->header->id), + ip2str(new_->header->adv_router), ntohl(new_->header->seqnum), + new_->header->age); + printf(" current lsdb cache count%d\n", lsdb->count_cache); +#endif //DEBUG_MANET_R_LSA + } + else + ospf6_lsa_delete (new_); +} +#endif //OSPF6_MANET_TEMPORARY_LSDB DEFUN (debug_ospf6_flooding, 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-03 13:29:45.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-03 13:29:45.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,62 @@ 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. +#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 +260,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 +379,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 +471,7 @@ } return l; } +#endif void ospf6_interface_if_add (struct interface *ifp) @@ -339,8 +555,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 +576,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 +595,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 +869,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 +1030,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 +1156,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 +1256,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 +1539,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 +2199,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 +2531,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 +2615,13 @@ 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) +{ +#ifdef DEBUG_MANET_R_HELLO + printf(" increment scs %x to %x\n", scs_num, scs_num+1); +#endif //DEBUG_MANET_R_HELLO + 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-03 13:29:45.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,131 @@ /* 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; +#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 +300,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-03 13:29:45.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,114 @@ } /* 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) + continue; + } + if (oi->LSAFullness == OSPF6_LSA_FULLNESS_MINHOP || + oi->LSAFullness == OSPF6_LSA_FULLNESS_MINHOP2PATHS) + // partial LSAs + { + if (!(on->state >= OSPF6_NEIGHBOR_TWOWAY && on->adv)) + continue; + } + if (oi->LSAFullness == OSPF6_LSA_FULLNESS_MDRFULL) + // full LSAs only for MDR/BDMR + { + if (oi->mdr_level == OSPF6_OTHER && + on->state != OSPF6_NEIGHBOR_FULL) + continue; + } + if (oi->LSAFullness >= OSPF6_LSA_FULLNESS_MDRFULL) + // full LSAs + { + if (!(on->state >= OSPF6_NEIGHBOR_TWOWAY && on->routable)) + continue; + } + } + 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); + } +#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_NEIGHBO