mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-13 19:02:58 +00:00
Merge volatile/cumulus_ospf6d
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
commit
e708ed69aa
@ -28,6 +28,44 @@ Bind interface to specified area, and start sending OSPF packets. @var{area} ca
|
||||
be specified as 0.
|
||||
@end deffn
|
||||
|
||||
@deffn {OSPF6 Command} {timers throttle spf @var{delay} @var{initial-holdtime} @var{max-holdtime}} {}
|
||||
@deffnx {OSPF6 Command} {no timers throttle spf} {}
|
||||
This command sets the initial @var{delay}, the @var{initial-holdtime}
|
||||
and the @var{maximum-holdtime} between when SPF is calculated and the
|
||||
event which triggered the calculation. The times are specified in
|
||||
milliseconds and must be in the range of 0 to 600000 milliseconds.
|
||||
|
||||
The @var{delay} specifies the minimum amount of time to delay SPF
|
||||
calculation (hence it affects how long SPF calculation is delayed after
|
||||
an event which occurs outside of the holdtime of any previous SPF
|
||||
calculation, and also serves as a minimum holdtime).
|
||||
|
||||
Consecutive SPF calculations will always be seperated by at least
|
||||
'hold-time' milliseconds. The hold-time is adaptive and initially is
|
||||
set to the @var{initial-holdtime} configured with the above command.
|
||||
Events which occur within the holdtime of the previous SPF calculation
|
||||
will cause the holdtime to be increased by @var{initial-holdtime}, bounded
|
||||
by the @var{maximum-holdtime} configured with this command. If the adaptive
|
||||
hold-time elapses without any SPF-triggering event occuring then
|
||||
the current holdtime is reset to the @var{initial-holdtime}.
|
||||
|
||||
@example
|
||||
@group
|
||||
router ospf6
|
||||
timers throttle spf 200 400 10000
|
||||
@end group
|
||||
@end example
|
||||
|
||||
In this example, the @var{delay} is set to 200ms, the @var{initial
|
||||
holdtime} is set to 400ms and the @var{maximum holdtime} to 10s. Hence
|
||||
there will always be at least 200ms between an event which requires SPF
|
||||
calculation and the actual SPF calculation. Further consecutive SPF
|
||||
calculations will always be seperated by between 400ms to 10s, the
|
||||
hold-time increasing by 400ms each time an SPF-triggering event occurs
|
||||
within the hold-time of the previous SPF calculation.
|
||||
|
||||
@end deffn
|
||||
|
||||
@node OSPF6 area
|
||||
@section OSPF6 area
|
||||
|
||||
@ -60,6 +98,10 @@ Sets interface's Router Priority. Default value is 1.
|
||||
Sets interface's Inf-Trans-Delay. Default value is 1.
|
||||
@end deffn
|
||||
|
||||
@deffn {Interface Command} {ipv6 ospf6 network (broadcast|point-to-point)} {}
|
||||
Set explicitly network type for specifed interface.
|
||||
@end deffn
|
||||
|
||||
@node Redistribute routes to OSPF6
|
||||
@section Redistribute routes to OSPF6
|
||||
|
||||
|
@ -27,7 +27,7 @@ pkginclude_HEADERS = \
|
||||
str.h stream.h table.h thread.h vector.h version.h vty.h zebra.h \
|
||||
plist.h zclient.h sockopt.h smux.h md5.h if_rmap.h keychain.h \
|
||||
privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \
|
||||
workqueue.h route_types.h
|
||||
workqueue.h route_types.h libospf.h
|
||||
|
||||
EXTRA_DIST = \
|
||||
regex.c regex-gnu.h \
|
||||
|
24
lib/if.c
24
lib/if.c
@ -304,6 +304,30 @@ if_lookup_address (struct in_addr src)
|
||||
return match;
|
||||
}
|
||||
|
||||
/* Lookup interface by prefix */
|
||||
struct interface *
|
||||
if_lookup_prefix (struct prefix *prefix)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct prefix addr;
|
||||
int bestlen = 0;
|
||||
struct listnode *cnode;
|
||||
struct interface *ifp;
|
||||
struct connected *c;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
|
||||
{
|
||||
for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
|
||||
{
|
||||
if (prefix_cmp(c->address, prefix) == 0)
|
||||
{
|
||||
return ifp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get interface by name if given name interface doesn't exist create
|
||||
one. */
|
||||
struct interface *
|
||||
|
1
lib/if.h
1
lib/if.h
@ -245,6 +245,7 @@ extern struct interface *if_create (const char *name, int namelen);
|
||||
extern struct interface *if_lookup_by_index (unsigned int);
|
||||
extern struct interface *if_lookup_exact_address (struct in_addr);
|
||||
extern struct interface *if_lookup_address (struct in_addr);
|
||||
extern struct interface *if_lookup_prefix (struct prefix *prefix);
|
||||
|
||||
/* These 2 functions are to be used when the ifname argument is terminated
|
||||
by a '\0' character: */
|
||||
|
92
lib/libospf.h
Normal file
92
lib/libospf.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Defines and structures common to OSPFv2 and OSPFv3
|
||||
* Copyright (C) 1998, 99, 2000 Kunihiro Ishiguro, Toshiaki Takada
|
||||
*
|
||||
* 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 _LIBOSPFD_H
|
||||
#define _LIBOSPFD_H
|
||||
|
||||
/* IP precedence. */
|
||||
#ifndef IPTOS_PREC_INTERNETCONTROL
|
||||
#define IPTOS_PREC_INTERNETCONTROL 0xC0
|
||||
#endif /* IPTOS_PREC_INTERNETCONTROL */
|
||||
|
||||
/* Default protocol, port number. */
|
||||
#ifndef IPPROTO_OSPFIGP
|
||||
#define IPPROTO_OSPFIGP 89
|
||||
#endif /* IPPROTO_OSPFIGP */
|
||||
|
||||
/* Architectual Constants */
|
||||
#ifdef DEBUG
|
||||
#define OSPF_LS_REFRESH_TIME 60
|
||||
#else
|
||||
#define OSPF_LS_REFRESH_TIME 1800
|
||||
#endif
|
||||
#define OSPF_MIN_LS_INTERVAL 5
|
||||
#define OSPF_MIN_LS_ARRIVAL 1
|
||||
#define OSPF_LSA_INITIAL_AGE 0 /* useful for debug */
|
||||
#define OSPF_LSA_MAXAGE 3600
|
||||
#define OSPF_CHECK_AGE 300
|
||||
#define OSPF_LSA_MAXAGE_DIFF 900
|
||||
#define OSPF_LS_INFINITY 0xffffff
|
||||
#define OSPF_DEFAULT_DESTINATION 0x00000000 /* 0.0.0.0 */
|
||||
#define OSPF_INITIAL_SEQUENCE_NUMBER 0x80000001
|
||||
#define OSPF_MAX_SEQUENCE_NUMBER 0x7fffffff
|
||||
|
||||
/* OSPF Interface Types */
|
||||
#define OSPF_IFTYPE_NONE 0
|
||||
#define OSPF_IFTYPE_POINTOPOINT 1
|
||||
#define OSPF_IFTYPE_BROADCAST 2
|
||||
#define OSPF_IFTYPE_NBMA 3
|
||||
#define OSPF_IFTYPE_POINTOMULTIPOINT 4
|
||||
#define OSPF_IFTYPE_VIRTUALLINK 5
|
||||
#define OSPF_IFTYPE_LOOPBACK 6
|
||||
#define OSPF_IFTYPE_MAX 7
|
||||
|
||||
/* OSPF interface default values. */
|
||||
#define OSPF_OUTPUT_COST_DEFAULT 10
|
||||
#define OSPF_OUTPUT_COST_INFINITE UINT16_MAX
|
||||
#define OSPF_ROUTER_DEAD_INTERVAL_DEFAULT 40
|
||||
#define OSPF_ROUTER_DEAD_INTERVAL_MINIMAL 1
|
||||
#define OSPF_HELLO_INTERVAL_DEFAULT 10
|
||||
#define OSPF_ROUTER_PRIORITY_DEFAULT 1
|
||||
#define OSPF_RETRANSMIT_INTERVAL_DEFAULT 5
|
||||
#define OSPF_TRANSMIT_DELAY_DEFAULT 1
|
||||
#define OSPF_DEFAULT_BANDWIDTH 10000 /* Kbps */
|
||||
|
||||
#define OSPF_DEFAULT_REF_BANDWIDTH 100000 /* Kbps */
|
||||
|
||||
#define OSPF_POLL_INTERVAL_DEFAULT 60
|
||||
#define OSPF_NEIGHBOR_PRIORITY_DEFAULT 0
|
||||
|
||||
#define OSPF_MTU_IGNORE_DEFAULT 0
|
||||
#define OSPF_FAST_HELLO_DEFAULT 0
|
||||
|
||||
#define OSPF_AREA_BACKBONE 0x00000000 /* 0.0.0.0 */
|
||||
|
||||
/* SPF Throttling timer values. */
|
||||
#define OSPF_SPF_DELAY_DEFAULT 200
|
||||
#define OSPF_SPF_HOLDTIME_DEFAULT 1000
|
||||
#define OSPF_SPF_MAX_HOLDTIME_DEFAULT 10000
|
||||
|
||||
#define OSPF_LSA_MAXAGE_CHECK_INTERVAL 30
|
||||
#define OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT 60
|
||||
|
||||
#endif /* _LIBOSPFD_H */
|
@ -253,7 +253,7 @@ ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
|
||||
}
|
||||
|
||||
/* do not generate if the route cost is greater or equal to LSInfinity */
|
||||
if (route->path.cost >= LS_INFINITY)
|
||||
if (route->path.cost >= OSPF_LS_INFINITY)
|
||||
{
|
||||
if (is_debug)
|
||||
zlog_debug ("The cost exceeds LSInfinity, withdraw");
|
||||
@ -296,7 +296,7 @@ ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
|
||||
/* ranges are ignored when originate backbone routes to transit area.
|
||||
Otherwise, if ranges are configured, the route is suppressed. */
|
||||
if (range && ! CHECK_FLAG (range->flag, OSPF6_ROUTE_REMOVE) &&
|
||||
(route->path.area_id != BACKBONE_AREA_ID ||
|
||||
(route->path.area_id != OSPF_AREA_BACKBONE ||
|
||||
! IS_AREA_TRANSIT (area)))
|
||||
{
|
||||
if (is_debug)
|
||||
@ -537,13 +537,13 @@ ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
|
||||
int i;
|
||||
char buf[64];
|
||||
int is_debug = 0;
|
||||
struct ospf6_inter_prefix_lsa *prefix_lsa = NULL;
|
||||
struct ospf6_inter_router_lsa *router_lsa = NULL;
|
||||
|
||||
memset (&prefix, 0, sizeof (prefix));
|
||||
|
||||
if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
|
||||
{
|
||||
struct ospf6_inter_prefix_lsa *prefix_lsa;
|
||||
|
||||
if (IS_OSPF6_DEBUG_EXAMIN (INTER_PREFIX))
|
||||
{
|
||||
is_debug++;
|
||||
@ -564,8 +564,6 @@ ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
|
||||
}
|
||||
else if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
|
||||
{
|
||||
struct ospf6_inter_router_lsa *router_lsa;
|
||||
|
||||
if (IS_OSPF6_DEBUG_EXAMIN (INTER_ROUTER))
|
||||
{
|
||||
is_debug++;
|
||||
@ -604,7 +602,7 @@ ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
|
||||
}
|
||||
|
||||
/* (1) if cost == LSInfinity or if the LSA is MaxAge */
|
||||
if (cost == LS_INFINITY)
|
||||
if (cost == OSPF_LS_INFINITY)
|
||||
{
|
||||
if (is_debug)
|
||||
zlog_debug ("cost is LS_INFINITY, ignore");
|
||||
@ -632,6 +630,7 @@ ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
|
||||
}
|
||||
|
||||
/* (3) if the prefix is equal to an active configured address range */
|
||||
/* or if the NU bit is set in the prefix */
|
||||
if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
|
||||
{
|
||||
range = ospf6_route_lookup (&prefix, oa->range_table);
|
||||
@ -643,6 +642,32 @@ ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
|
||||
ospf6_route_remove (old, table);
|
||||
return;
|
||||
}
|
||||
|
||||
if (CHECK_FLAG (prefix_lsa->prefix.prefix_options,
|
||||
OSPF6_PREFIX_OPTION_NU) ||
|
||||
CHECK_FLAG (prefix_lsa->prefix.prefix_options,
|
||||
OSPF6_PREFIX_OPTION_LA))
|
||||
{
|
||||
if (is_debug)
|
||||
zlog_debug ("Prefix has NU/LA bit set, ignore");
|
||||
if (old)
|
||||
ospf6_route_remove (old, table);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
|
||||
{
|
||||
/* To pass test suites */
|
||||
if (! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_R) ||
|
||||
! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_V6))
|
||||
{
|
||||
if (is_debug)
|
||||
zlog_debug ("Prefix has NU/LA bit set, ignore");
|
||||
if (old)
|
||||
ospf6_route_remove (old, table);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* (4) if the routing table entry for the ABR does not exist */
|
||||
@ -764,12 +789,34 @@ ospf6_abr_reimport (struct ospf6_area *oa)
|
||||
|
||||
|
||||
/* Display functions */
|
||||
static char *
|
||||
ospf6_inter_area_prefix_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
|
||||
int buflen, int pos)
|
||||
{
|
||||
struct ospf6_inter_prefix_lsa *prefix_lsa;
|
||||
struct in6_addr in6;
|
||||
|
||||
if (lsa != NULL)
|
||||
{
|
||||
prefix_lsa = (struct ospf6_inter_prefix_lsa *)
|
||||
OSPF6_LSA_HEADER_END (lsa->header);
|
||||
|
||||
ospf6_prefix_in6_addr (&in6, &prefix_lsa->prefix);
|
||||
if (buf)
|
||||
{
|
||||
inet_ntop (AF_INET6, &in6, buf, buflen);
|
||||
sprintf (&buf[strlen(buf)], "/%d", prefix_lsa->prefix.prefix_length);
|
||||
}
|
||||
}
|
||||
|
||||
return (buf);
|
||||
}
|
||||
|
||||
static int
|
||||
ospf6_inter_area_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
|
||||
{
|
||||
struct ospf6_inter_prefix_lsa *prefix_lsa;
|
||||
struct in6_addr in6;
|
||||
char buf[64];
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
|
||||
prefix_lsa = (struct ospf6_inter_prefix_lsa *)
|
||||
OSPF6_LSA_HEADER_END (lsa->header);
|
||||
@ -781,14 +828,32 @@ ospf6_inter_area_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
|
||||
buf, sizeof (buf));
|
||||
vty_out (vty, " Prefix Options: %s%s", buf, VNL);
|
||||
|
||||
ospf6_prefix_in6_addr (&in6, &prefix_lsa->prefix);
|
||||
inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
|
||||
vty_out (vty, " Prefix: %s/%d%s", buf,
|
||||
prefix_lsa->prefix.prefix_length, VNL);
|
||||
vty_out (vty, " Prefix: %s%s",
|
||||
ospf6_inter_area_prefix_lsa_get_prefix_str (lsa, buf, sizeof(buf),
|
||||
0), VNL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
ospf6_inter_area_router_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
|
||||
int buflen, int pos)
|
||||
{
|
||||
struct ospf6_inter_router_lsa *router_lsa;
|
||||
|
||||
if (lsa != NULL)
|
||||
{
|
||||
router_lsa = (struct ospf6_inter_router_lsa *)
|
||||
OSPF6_LSA_HEADER_END (lsa->header);
|
||||
|
||||
|
||||
if (buf)
|
||||
inet_ntop (AF_INET, &router_lsa->router_id, buf, buflen);
|
||||
}
|
||||
|
||||
return (buf);
|
||||
}
|
||||
|
||||
static int
|
||||
ospf6_inter_area_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
|
||||
{
|
||||
@ -802,6 +867,7 @@ ospf6_inter_area_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
|
||||
vty_out (vty, " Options: %s%s", buf, VNL);
|
||||
vty_out (vty, " Metric: %lu%s",
|
||||
(u_long) OSPF6_ABR_SUMMARY_METRIC (router_lsa), VNL);
|
||||
|
||||
inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf));
|
||||
vty_out (vty, " Destination Router ID: %s%s", buf, VNL);
|
||||
|
||||
@ -855,14 +921,18 @@ struct ospf6_lsa_handler inter_prefix_handler =
|
||||
{
|
||||
OSPF6_LSTYPE_INTER_PREFIX,
|
||||
"Inter-Prefix",
|
||||
ospf6_inter_area_prefix_lsa_show
|
||||
"IAP",
|
||||
ospf6_inter_area_prefix_lsa_show,
|
||||
ospf6_inter_area_prefix_lsa_get_prefix_str,
|
||||
};
|
||||
|
||||
struct ospf6_lsa_handler inter_router_handler =
|
||||
{
|
||||
OSPF6_LSTYPE_INTER_ROUTER,
|
||||
"Inter-Router",
|
||||
ospf6_inter_area_router_lsa_show
|
||||
"IAR",
|
||||
ospf6_inter_area_router_lsa_show,
|
||||
ospf6_inter_area_router_lsa_get_prefix_str,
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -67,7 +67,8 @@ ospf6_area_lsdb_hook_add (struct ospf6_lsa *lsa)
|
||||
zlog_debug ("Schedule SPF Calculation for %s",
|
||||
OSPF6_AREA (lsa->lsdb->data)->name);
|
||||
}
|
||||
ospf6_spf_schedule (OSPF6_AREA (lsa->lsdb->data));
|
||||
ospf6_spf_schedule (OSPF6_PROCESS(OSPF6_AREA (lsa->lsdb->data)->ospf6),
|
||||
ospf6_lsadd_to_spf_reason(lsa));
|
||||
break;
|
||||
|
||||
case OSPF6_LSTYPE_INTRA_PREFIX:
|
||||
@ -97,7 +98,8 @@ ospf6_area_lsdb_hook_remove (struct ospf6_lsa *lsa)
|
||||
zlog_debug ("Schedule SPF Calculation for %s",
|
||||
OSPF6_AREA (lsa->lsdb->data)->name);
|
||||
}
|
||||
ospf6_spf_schedule (OSPF6_AREA (lsa->lsdb->data));
|
||||
ospf6_spf_schedule (OSPF6_PROCESS(OSPF6_AREA (lsa->lsdb->data)->ospf6),
|
||||
ospf6_lsremove_to_spf_reason(lsa));
|
||||
break;
|
||||
|
||||
case OSPF6_LSTYPE_INTRA_PREFIX:
|
||||
@ -164,9 +166,18 @@ ospf6_area_create (u_int32_t area_id, struct ospf6 *o)
|
||||
oa->summary_router->scope = oa;
|
||||
|
||||
/* set default options */
|
||||
OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
|
||||
if (CHECK_FLAG (o->flag, OSPF6_STUB_ROUTER))
|
||||
{
|
||||
OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_V6);
|
||||
OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_R);
|
||||
}
|
||||
else
|
||||
{
|
||||
OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
|
||||
OSPF6_OPT_SET (oa->options, OSPF6_OPT_R);
|
||||
}
|
||||
|
||||
OSPF6_OPT_SET (oa->options, OSPF6_OPT_E);
|
||||
OSPF6_OPT_SET (oa->options, OSPF6_OPT_R);
|
||||
|
||||
oa->ospf6 = o;
|
||||
listnode_add_sort (o->area_list, oa);
|
||||
@ -182,18 +193,21 @@ ospf6_area_create (u_int32_t area_id, struct ospf6 *o)
|
||||
void
|
||||
ospf6_area_delete (struct ospf6_area *oa)
|
||||
{
|
||||
struct listnode *n, *nnode;
|
||||
struct listnode *n;
|
||||
struct ospf6_interface *oi;
|
||||
|
||||
ospf6_route_table_delete (oa->range_table);
|
||||
ospf6_route_table_delete (oa->summary_prefix);
|
||||
ospf6_route_table_delete (oa->summary_router);
|
||||
|
||||
/* ospf6 interface list */
|
||||
for (ALL_LIST_ELEMENTS (oa->if_list, n, nnode, oi))
|
||||
{
|
||||
ospf6_interface_delete (oi);
|
||||
}
|
||||
/* The ospf6_interface structs store configuration
|
||||
* information which should not be lost/reset when
|
||||
* deleting an area.
|
||||
* So just detach the interface from the area and
|
||||
* keep it around. */
|
||||
for (ALL_LIST_ELEMENTS_RO (oa->if_list, n, oi))
|
||||
oi->area = NULL;
|
||||
|
||||
list_delete (oa->if_list);
|
||||
|
||||
ospf6_lsdb_delete (oa->lsdb);
|
||||
@ -246,6 +260,7 @@ ospf6_area_enable (struct ospf6_area *oa)
|
||||
|
||||
for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
|
||||
ospf6_interface_enable (oi);
|
||||
ospf6_abr_enable_area (oa);
|
||||
}
|
||||
|
||||
void
|
||||
@ -258,6 +273,19 @@ ospf6_area_disable (struct ospf6_area *oa)
|
||||
|
||||
for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
|
||||
ospf6_interface_disable (oi);
|
||||
|
||||
ospf6_abr_disable_area (oa);
|
||||
ospf6_lsdb_remove_all (oa->lsdb);
|
||||
ospf6_lsdb_remove_all (oa->lsdb_self);
|
||||
|
||||
ospf6_spf_table_finish(oa->spf_table);
|
||||
ospf6_route_remove_all(oa->route_table);
|
||||
|
||||
THREAD_OFF (oa->thread_spf_calculation);
|
||||
THREAD_OFF (oa->thread_route_calculation);
|
||||
|
||||
THREAD_OFF (oa->thread_router_lsa);
|
||||
THREAD_OFF (oa->thread_intra_prefix_lsa);
|
||||
}
|
||||
|
||||
|
||||
@ -401,6 +429,7 @@ DEFUN (no_area_range,
|
||||
}
|
||||
|
||||
ospf6_route_remove (range, oa->range_table);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -105,8 +105,6 @@ struct ospf6_area
|
||||
#define OSPF6_AREA_TRANSIT 0x04 /* TransitCapability */
|
||||
#define OSPF6_AREA_STUB 0x08
|
||||
|
||||
#define BACKBONE_AREA_ID (htonl (0))
|
||||
#define IS_AREA_BACKBONE(oa) ((oa)->area_id == BACKBONE_AREA_ID)
|
||||
#define IS_AREA_ENABLED(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_ENABLE))
|
||||
#define IS_AREA_ACTIVE(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_ACTIVE))
|
||||
#define IS_AREA_TRANSIT(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_TRANSIT))
|
||||
|
@ -174,13 +174,20 @@ ospf6_asbr_lsa_add (struct ospf6_lsa *lsa)
|
||||
return;
|
||||
}
|
||||
|
||||
if (OSPF6_ASBR_METRIC (external) == LS_INFINITY)
|
||||
if (OSPF6_ASBR_METRIC (external) == OSPF_LS_INFINITY)
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
|
||||
zlog_debug ("Ignore LSA with LSInfinity Metric");
|
||||
return;
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(external->prefix.prefix_options, OSPF6_PREFIX_OPTION_NU))
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
|
||||
zlog_debug ("Ignore LSA with NU bit set Metric");
|
||||
return;
|
||||
}
|
||||
|
||||
ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &asbr_id);
|
||||
asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table);
|
||||
if (asbr_entry == NULL ||
|
||||
@ -402,6 +409,8 @@ ospf6_asbr_redistribute_unset (int type)
|
||||
ospf6_asbr_redistribute_remove (info->type, route->nexthop[0].ifindex,
|
||||
&route->prefix);
|
||||
}
|
||||
|
||||
ospf6_asbr_routemap_unset (type);
|
||||
}
|
||||
|
||||
void
|
||||
@ -629,7 +638,6 @@ DEFUN (ospf6_redistribute,
|
||||
return CMD_WARNING;
|
||||
|
||||
ospf6_asbr_redistribute_unset (type);
|
||||
ospf6_asbr_routemap_unset (type);
|
||||
ospf6_asbr_redistribute_set (type);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@ -670,7 +678,6 @@ DEFUN (no_ospf6_redistribute,
|
||||
return CMD_WARNING;
|
||||
|
||||
ospf6_asbr_redistribute_unset (type);
|
||||
ospf6_asbr_routemap_unset (type);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@ -890,7 +897,7 @@ ospf6_routemap_rule_set_metric_compile (const char *arg)
|
||||
u_int32_t metric;
|
||||
char *endp;
|
||||
metric = strtoul (arg, &endp, 0);
|
||||
if (metric > LS_INFINITY || *endp != '\0')
|
||||
if (metric > OSPF_LS_INFINITY || *endp != '\0')
|
||||
return NULL;
|
||||
return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
|
||||
}
|
||||
@ -1161,12 +1168,44 @@ ospf6_routemap_init (void)
|
||||
|
||||
|
||||
/* Display functions */
|
||||
static char *
|
||||
ospf6_as_external_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
|
||||
int buflen, int pos)
|
||||
{
|
||||
struct ospf6_as_external_lsa *external;
|
||||
struct in6_addr in6;
|
||||
int prefix_length = 0;
|
||||
|
||||
if (lsa)
|
||||
{
|
||||
external = (struct ospf6_as_external_lsa *)
|
||||
OSPF6_LSA_HEADER_END (lsa->header);
|
||||
|
||||
if (pos == 0)
|
||||
{
|
||||
ospf6_prefix_in6_addr (&in6, &external->prefix);
|
||||
prefix_length = external->prefix.prefix_length;
|
||||
}
|
||||
else {
|
||||
in6 = *((struct in6_addr *)
|
||||
((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
|
||||
OSPF6_PREFIX_SPACE (external->prefix.prefix_length)));
|
||||
}
|
||||
if (buf)
|
||||
{
|
||||
inet_ntop (AF_INET6, &in6, buf, buflen);
|
||||
if (prefix_length)
|
||||
sprintf (&buf[strlen(buf)], "/%d", prefix_length);
|
||||
}
|
||||
}
|
||||
return (buf);
|
||||
}
|
||||
|
||||
static int
|
||||
ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
|
||||
{
|
||||
struct ospf6_as_external_lsa *external;
|
||||
char buf[64];
|
||||
struct in6_addr in6, *forwarding;
|
||||
|
||||
assert (lsa->header);
|
||||
external = (struct ospf6_as_external_lsa *)
|
||||
@ -1191,19 +1230,15 @@ ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
|
||||
ntohs (external->prefix.prefix_refer_lstype),
|
||||
VNL);
|
||||
|
||||
ospf6_prefix_in6_addr (&in6, &external->prefix);
|
||||
inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
|
||||
vty_out (vty, " Prefix: %s/%d%s", buf,
|
||||
external->prefix.prefix_length, VNL);
|
||||
vty_out (vty, " Prefix: %s%s",
|
||||
ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 0), VNL);
|
||||
|
||||
/* Forwarding-Address */
|
||||
if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
|
||||
{
|
||||
forwarding = (struct in6_addr *)
|
||||
((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
|
||||
OSPF6_PREFIX_SPACE (external->prefix.prefix_length));
|
||||
inet_ntop (AF_INET6, forwarding, buf, sizeof (buf));
|
||||
vty_out (vty, " Forwarding-Address: %s%s", buf, VNL);
|
||||
vty_out (vty, " Forwarding-Address: %s%s",
|
||||
ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 1),
|
||||
VNL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1257,7 +1292,9 @@ struct ospf6_lsa_handler as_external_handler =
|
||||
{
|
||||
OSPF6_LSTYPE_AS_EXTERNAL,
|
||||
"AS-External",
|
||||
ospf6_as_external_lsa_show
|
||||
"ASE",
|
||||
ospf6_as_external_lsa_show,
|
||||
ospf6_as_external_lsa_get_prefix_str
|
||||
};
|
||||
|
||||
void
|
||||
@ -1275,6 +1312,20 @@ ospf6_asbr_init (void)
|
||||
install_element (OSPF6_NODE, &no_ospf6_redistribute_cmd);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_asbr_redistribute_reset (void)
|
||||
{
|
||||
int type;
|
||||
|
||||
for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
|
||||
{
|
||||
if (type == ZEBRA_ROUTE_OSPF6)
|
||||
continue;
|
||||
if (ospf6_zebra_is_redistribute (type))
|
||||
ospf6_asbr_redistribute_unset(type);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_asbr_terminate (void)
|
||||
{
|
||||
|
@ -89,6 +89,7 @@ extern void ospf6_asbr_redistribute_remove (int type, int ifindex,
|
||||
extern int ospf6_redistribute_config_write (struct vty *vty);
|
||||
|
||||
extern void ospf6_asbr_init (void);
|
||||
extern void ospf6_asbr_redistribute_reset (void);
|
||||
extern void ospf6_asbr_terminate (void);
|
||||
|
||||
extern int config_write_ospf6_debug_asbr (struct vty *vty);
|
||||
|
@ -113,7 +113,7 @@ ospf6_lsa_originate (struct ospf6_lsa *lsa)
|
||||
ospf6_lsdb_add (ospf6_lsa_copy (lsa), lsdb_self);
|
||||
|
||||
lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
|
||||
LS_REFRESH_TIME);
|
||||
OSPF_LS_REFRESH_TIME);
|
||||
|
||||
if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) ||
|
||||
IS_OSPF6_DEBUG_ORIGINATE_TYPE (lsa->header->type))
|
||||
@ -122,10 +122,8 @@ ospf6_lsa_originate (struct ospf6_lsa *lsa)
|
||||
ospf6_lsa_header_print (lsa);
|
||||
}
|
||||
|
||||
if (old)
|
||||
ospf6_flood_clear (old);
|
||||
ospf6_flood (NULL, lsa);
|
||||
ospf6_install_lsa (lsa);
|
||||
ospf6_flood (NULL, lsa);
|
||||
}
|
||||
|
||||
void
|
||||
@ -208,8 +206,8 @@ ospf6_decrement_retrans_count (struct ospf6_lsa *lsa)
|
||||
void
|
||||
ospf6_install_lsa (struct ospf6_lsa *lsa)
|
||||
{
|
||||
struct ospf6_lsa *old;
|
||||
struct timeval now;
|
||||
struct ospf6_lsa *old;
|
||||
|
||||
if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) ||
|
||||
IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
|
||||
@ -222,16 +220,36 @@ ospf6_install_lsa (struct ospf6_lsa *lsa)
|
||||
if (old)
|
||||
{
|
||||
THREAD_OFF (old->expire);
|
||||
THREAD_OFF (old->refresh);
|
||||
ospf6_flood_clear (old);
|
||||
}
|
||||
|
||||
quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
|
||||
if (! OSPF6_LSA_IS_MAXAGE (lsa))
|
||||
lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa,
|
||||
MAXAGE + lsa->birth.tv_sec - now.tv_sec);
|
||||
OSPF_LSA_MAXAGE + lsa->birth.tv_sec - now.tv_sec);
|
||||
else
|
||||
lsa->expire = NULL;
|
||||
|
||||
if (OSPF6_LSA_IS_SEQWRAP(lsa) &&
|
||||
! (CHECK_FLAG(lsa->flag,OSPF6_LSA_SEQWRAPPED) &&
|
||||
lsa->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER)))
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
|
||||
zlog_debug("lsa install wrapping: sequence 0x%x",
|
||||
ntohl(lsa->header->seqnum));
|
||||
SET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED);
|
||||
/* in lieu of premature_aging, since we do not want to recreate this lsa
|
||||
* and/or mess with timers etc, we just want to wrap the sequence number
|
||||
* and reflood the lsa before continuing.
|
||||
* NOTE: Flood needs to be called right after this function call, by the
|
||||
* caller
|
||||
*/
|
||||
lsa->header->seqnum = htonl (OSPF_MAX_SEQUENCE_NUMBER);
|
||||
lsa->header->age = htons (OSPF_LSA_MAXAGE);
|
||||
ospf6_lsa_checksum (lsa->header);
|
||||
}
|
||||
|
||||
/* actually install */
|
||||
lsa->installed = now;
|
||||
ospf6_lsdb_add (lsa, lsa->lsdb);
|
||||
@ -292,7 +310,7 @@ ospf6_flood_interface (struct ospf6_neighbor *from,
|
||||
if (ospf6_lsa_compare (lsa, req) > 0)
|
||||
{
|
||||
if (is_debug)
|
||||
zlog_debug ("Requesting is newer, next neighbor");
|
||||
zlog_debug ("Requesting is older, next neighbor");
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -300,18 +318,30 @@ ospf6_flood_interface (struct ospf6_neighbor *from,
|
||||
examin next neighbor */
|
||||
if (ospf6_lsa_compare (lsa, req) == 0)
|
||||
{
|
||||
if (is_debug)
|
||||
zlog_debug ("Requesting the same, remove it, next neighbor");
|
||||
if (is_debug)
|
||||
zlog_debug ("Requesting the same, remove it, next neighbor");
|
||||
if (req == on->last_ls_req)
|
||||
{
|
||||
ospf6_lsa_unlock (req);
|
||||
on->last_ls_req = NULL;
|
||||
}
|
||||
ospf6_lsdb_remove (req, on->request_list);
|
||||
ospf6_check_nbr_loading (on);
|
||||
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");
|
||||
if (is_debug)
|
||||
zlog_debug ("Received is newer, remove requesting");
|
||||
if (req == on->last_ls_req)
|
||||
{
|
||||
ospf6_lsa_unlock (req);
|
||||
on->last_ls_req = NULL;
|
||||
}
|
||||
ospf6_lsdb_remove (req, on->request_list);
|
||||
ospf6_check_nbr_loading (on);
|
||||
/* fall through */
|
||||
}
|
||||
}
|
||||
@ -358,17 +388,22 @@ ospf6_flood_interface (struct ospf6_neighbor *from,
|
||||
|
||||
/* (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 (from && from->ospf6_if == oi)
|
||||
{
|
||||
if (is_debug)
|
||||
zlog_debug ("Received is from the I/F, itself BDR, next interface");
|
||||
return;
|
||||
if (oi->state == OSPF6_INTERFACE_BDR)
|
||||
{
|
||||
if (is_debug)
|
||||
zlog_debug ("Received is from the I/F, itself BDR, next interface");
|
||||
return;
|
||||
}
|
||||
SET_FLAG(lsa->flag, OSPF6_LSA_FLOODBACK);
|
||||
}
|
||||
|
||||
/* (5) flood the LSA out the interface. */
|
||||
if (is_debug)
|
||||
zlog_debug ("Schedule flooding for the interface");
|
||||
if (if_is_broadcast (oi->interface))
|
||||
if ((oi->type == OSPF_IFTYPE_BROADCAST) ||
|
||||
(oi->type == OSPF_IFTYPE_POINTOPOINT))
|
||||
{
|
||||
ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list);
|
||||
if (oi->thread_send_lsupdate == NULL)
|
||||
@ -530,15 +565,6 @@ ospf6_acknowledge_lsa_bdrouter (struct ospf6_lsa *lsa, int ismore_recent,
|
||||
assert (from && from->ospf6_if);
|
||||
oi = from->ospf6_if;
|
||||
|
||||
/* LSA has been flood back out receiving interface.
|
||||
No acknowledgement sent. */
|
||||
if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
|
||||
{
|
||||
if (is_debug)
|
||||
zlog_debug ("No acknowledgement (BDR & FloodBack)");
|
||||
return;
|
||||
}
|
||||
|
||||
/* LSA is more recent than database copy, but was not flooded
|
||||
back out receiving interface. Delayed acknowledgement sent
|
||||
if advertisement received from Designated Router,
|
||||
@ -797,7 +823,7 @@ ospf6_receive_lsa (struct ospf6_neighbor *from,
|
||||
{
|
||||
/* log */
|
||||
if (is_debug)
|
||||
zlog_debug ("Drop MaxAge LSA with direct acknowledgement.");
|
||||
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);
|
||||
@ -837,7 +863,7 @@ ospf6_receive_lsa (struct ospf6_neighbor *from,
|
||||
struct timeval now, res;
|
||||
quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
|
||||
timersub (&now, &old->installed, &res);
|
||||
if (res.tv_sec < MIN_LS_ARRIVAL)
|
||||
if (res.tv_sec < OSPF_MIN_LS_ARRIVAL)
|
||||
{
|
||||
if (is_debug)
|
||||
zlog_debug ("LSA can't be updated within MinLSArrival, discard");
|
||||
@ -849,7 +875,11 @@ ospf6_receive_lsa (struct ospf6_neighbor *from,
|
||||
quagga_gettime (QUAGGA_CLK_MONOTONIC, &new->received);
|
||||
|
||||
if (is_debug)
|
||||
zlog_debug ("Flood, Install, Possibly acknowledge the received LSA");
|
||||
zlog_debug ("Install, Flood, Possibly acknowledge the received LSA");
|
||||
|
||||
/* Remove older copies of this LSA from retx lists */
|
||||
if (old)
|
||||
ospf6_flood_clear (old);
|
||||
|
||||
/* (b) immediately flood and (c) remove from all retrans-list */
|
||||
/* Prevent self-originated LSA to be flooded. this is to make
|
||||
@ -858,10 +888,6 @@ ospf6_receive_lsa (struct ospf6_neighbor *from,
|
||||
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. */
|
||||
/* XXX, flood_clear ? */
|
||||
|
||||
/* (d), installing lsdb, which may cause routing
|
||||
table calculation (replacing database copy) */
|
||||
ospf6_install_lsa (new);
|
||||
@ -944,15 +970,15 @@ ospf6_receive_lsa (struct ospf6_neighbor *from,
|
||||
/* If database copy is in 'Seqnumber Wrapping',
|
||||
simply discard the received LSA */
|
||||
if (OSPF6_LSA_IS_MAXAGE (old) &&
|
||||
old->header->seqnum == htonl (MAX_SEQUENCE_NUMBER))
|
||||
old->header->seqnum == htonl (OSPF_MAX_SEQUENCE_NUMBER))
|
||||
{
|
||||
if (is_debug)
|
||||
{
|
||||
zlog_debug ("The LSA is in Seqnumber Wrapping");
|
||||
zlog_debug ("MaxAge & MaxSeqNum, discard");
|
||||
}
|
||||
ospf6_lsa_delete (new);
|
||||
return;
|
||||
ospf6_lsa_delete (new);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise, Send database copy of this LSA to this neighbor */
|
||||
@ -969,8 +995,8 @@ ospf6_receive_lsa (struct ospf6_neighbor *from,
|
||||
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;
|
||||
ospf6_lsa_delete (new);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -73,14 +73,20 @@ ospf6_interface_lookup_by_ifindex (int ifindex)
|
||||
|
||||
/* schedule routing table recalculation */
|
||||
static void
|
||||
ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa)
|
||||
ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa, unsigned int reason)
|
||||
{
|
||||
struct ospf6_interface *oi;
|
||||
|
||||
if (lsa == NULL)
|
||||
return;
|
||||
|
||||
oi = lsa->lsdb->data;
|
||||
switch (ntohs (lsa->header->type))
|
||||
{
|
||||
case OSPF6_LSTYPE_LINK:
|
||||
if (OSPF6_INTERFACE (lsa->lsdb->data)->state == OSPF6_INTERFACE_DR)
|
||||
OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (OSPF6_INTERFACE (lsa->lsdb->data));
|
||||
ospf6_spf_schedule (OSPF6_INTERFACE (lsa->lsdb->data)->area);
|
||||
if (oi->state == OSPF6_INTERFACE_DR)
|
||||
OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
|
||||
ospf6_spf_schedule (oi->area->ospf6, reason);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -88,6 +94,29 @@ ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ospf6_interface_lsdb_hook_add (struct ospf6_lsa *lsa)
|
||||
{
|
||||
ospf6_interface_lsdb_hook(lsa, ospf6_lsadd_to_spf_reason(lsa));
|
||||
}
|
||||
|
||||
static void
|
||||
ospf6_interface_lsdb_hook_remove (struct ospf6_lsa *lsa)
|
||||
{
|
||||
ospf6_interface_lsdb_hook(lsa, ospf6_lsremove_to_spf_reason(lsa));
|
||||
}
|
||||
|
||||
static u_char
|
||||
ospf6_default_iftype(struct interface *ifp)
|
||||
{
|
||||
if (if_is_pointopoint (ifp))
|
||||
return OSPF_IFTYPE_POINTOPOINT;
|
||||
else if (if_is_loopback (ifp))
|
||||
return OSPF_IFTYPE_LOOPBACK;
|
||||
else
|
||||
return OSPF_IFTYPE_BROADCAST;
|
||||
}
|
||||
|
||||
/* Create new ospf6 interface structure */
|
||||
struct ospf6_interface *
|
||||
ospf6_interface_create (struct interface *ifp)
|
||||
@ -112,10 +141,11 @@ ospf6_interface_create (struct interface *ifp)
|
||||
oi->transdelay = OSPF6_INTERFACE_TRANSDELAY;
|
||||
oi->priority = OSPF6_INTERFACE_PRIORITY;
|
||||
|
||||
oi->hello_interval = OSPF6_INTERFACE_HELLO_INTERVAL;
|
||||
oi->dead_interval = OSPF6_INTERFACE_DEAD_INTERVAL;
|
||||
oi->rxmt_interval = OSPF6_INTERFACE_RXMT_INTERVAL;
|
||||
oi->hello_interval = OSPF_HELLO_INTERVAL_DEFAULT;
|
||||
oi->dead_interval = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT;
|
||||
oi->rxmt_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT;
|
||||
oi->cost = OSPF6_INTERFACE_COST;
|
||||
oi->type = ospf6_default_iftype (ifp);
|
||||
oi->state = OSPF6_INTERFACE_DOWN;
|
||||
oi->flag = 0;
|
||||
oi->mtu_ignore = 0;
|
||||
@ -134,8 +164,8 @@ ospf6_interface_create (struct interface *ifp)
|
||||
oi->lsupdate_list = ospf6_lsdb_create (oi);
|
||||
oi->lsack_list = ospf6_lsdb_create (oi);
|
||||
oi->lsdb = ospf6_lsdb_create (oi);
|
||||
oi->lsdb->hook_add = ospf6_interface_lsdb_hook;
|
||||
oi->lsdb->hook_remove = ospf6_interface_lsdb_hook;
|
||||
oi->lsdb->hook_add = ospf6_interface_lsdb_hook_add;
|
||||
oi->lsdb->hook_remove = ospf6_interface_lsdb_hook_remove;
|
||||
oi->lsdb_self = ospf6_lsdb_create (oi);
|
||||
|
||||
oi->route_connected = OSPF6_ROUTE_TABLE_CREATE (INTERFACE, CONNECTED_ROUTES);
|
||||
@ -189,31 +219,28 @@ void
|
||||
ospf6_interface_enable (struct ospf6_interface *oi)
|
||||
{
|
||||
UNSET_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE);
|
||||
|
||||
oi->thread_send_hello =
|
||||
thread_add_event (master, ospf6_hello_send, oi, 0);
|
||||
ospf6_interface_state_update (oi->interface);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_interface_disable (struct ospf6_interface *oi)
|
||||
{
|
||||
struct listnode *node, *nnode;
|
||||
struct ospf6_neighbor *on;
|
||||
|
||||
SET_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE);
|
||||
|
||||
for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
|
||||
ospf6_neighbor_delete (on);
|
||||
|
||||
list_delete_all_node (oi->neighbor_list);
|
||||
thread_execute (master, interface_down, oi, 0);
|
||||
|
||||
ospf6_lsdb_remove_all (oi->lsdb);
|
||||
ospf6_lsdb_remove_all (oi->lsdb_self);
|
||||
ospf6_lsdb_remove_all (oi->lsupdate_list);
|
||||
ospf6_lsdb_remove_all (oi->lsack_list);
|
||||
|
||||
THREAD_OFF (oi->thread_send_hello);
|
||||
THREAD_OFF (oi->thread_send_lsupdate);
|
||||
THREAD_OFF (oi->thread_send_lsack);
|
||||
|
||||
THREAD_OFF (oi->thread_network_lsa);
|
||||
THREAD_OFF (oi->thread_link_lsa);
|
||||
THREAD_OFF (oi->thread_intra_prefix_lsa);
|
||||
}
|
||||
|
||||
static struct in6_addr *
|
||||
@ -260,8 +287,7 @@ ospf6_interface_if_add (struct interface *ifp)
|
||||
}
|
||||
|
||||
/* interface start */
|
||||
if (oi->area)
|
||||
thread_add_event (master, interface_up, oi, 0);
|
||||
ospf6_interface_state_update(oi->interface);
|
||||
}
|
||||
|
||||
void
|
||||
@ -297,8 +323,12 @@ ospf6_interface_state_update (struct interface *ifp)
|
||||
return;
|
||||
if (oi->area == NULL)
|
||||
return;
|
||||
if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
|
||||
return;
|
||||
|
||||
if (if_is_up (ifp))
|
||||
if (if_is_operative (ifp)
|
||||
&& (ospf6_interface_get_linklocal_address(oi->interface)
|
||||
|| if_is_loopback(oi->interface)))
|
||||
thread_add_event (master, interface_up, oi, 0);
|
||||
else
|
||||
thread_add_event (master, interface_down, oi, 0);
|
||||
@ -325,6 +355,9 @@ ospf6_interface_connected_route_update (struct interface *ifp)
|
||||
if (oi->area == NULL)
|
||||
return;
|
||||
|
||||
if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
|
||||
return;
|
||||
|
||||
/* update "route to advertise" interface route table */
|
||||
ospf6_route_remove_all (oi->route_connected);
|
||||
|
||||
@ -401,6 +434,7 @@ ospf6_interface_state_change (u_char next_state, struct ospf6_interface *oi)
|
||||
(next_state != OSPF6_INTERFACE_DR &&
|
||||
next_state != OSPF6_INTERFACE_BDR))
|
||||
ospf6_sso (oi->interface->ifindex, &alldrouters6, IPV6_LEAVE_GROUP);
|
||||
|
||||
if ((prev_state != OSPF6_INTERFACE_DR &&
|
||||
prev_state != OSPF6_INTERFACE_BDR) &&
|
||||
(next_state == OSPF6_INTERFACE_DR ||
|
||||
@ -606,7 +640,7 @@ interface_up (struct thread *thread)
|
||||
oi->interface->name);
|
||||
|
||||
/* check physical interface is up */
|
||||
if (! if_is_up (oi->interface))
|
||||
if (! if_is_operative (oi->interface))
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_INTERFACE)
|
||||
zlog_debug ("Interface %s is down, can't execute [InterfaceUp]",
|
||||
@ -614,6 +648,16 @@ interface_up (struct thread *thread)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check interface has a link-local address */
|
||||
if (! (ospf6_interface_get_linklocal_address(oi->interface)
|
||||
|| if_is_loopback(oi->interface)))
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_INTERFACE)
|
||||
zlog_debug ("Interface %s has no link local address, can't execute [InterfaceUp]",
|
||||
oi->interface->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if already enabled, do nothing */
|
||||
if (oi->state > OSPF6_INTERFACE_DOWN)
|
||||
{
|
||||
@ -623,6 +667,14 @@ interface_up (struct thread *thread)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If no area assigned, return */
|
||||
if (oi->area == NULL)
|
||||
{
|
||||
zlog_debug ("%s: Not scheduleing Hello for %s as there is no area assigned yet", __func__,
|
||||
oi->interface->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Join AllSPFRouters */
|
||||
ospf6_sso (oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP);
|
||||
|
||||
@ -631,11 +683,13 @@ interface_up (struct thread *thread)
|
||||
|
||||
/* Schedule Hello */
|
||||
if (! CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
|
||||
thread_add_event (master, ospf6_hello_send, oi, 0);
|
||||
oi->thread_send_hello = thread_add_event (master, ospf6_hello_send, oi, 0);
|
||||
|
||||
/* decide next interface state */
|
||||
if (if_is_pointopoint (oi->interface))
|
||||
if ((if_is_pointopoint (oi->interface)) ||
|
||||
(oi->type == OSPF_IFTYPE_POINTOPOINT)) {
|
||||
ospf6_interface_state_change (OSPF6_INTERFACE_POINTTOPOINT, oi);
|
||||
}
|
||||
else if (oi->priority == 0)
|
||||
ospf6_interface_state_change (OSPF6_INTERFACE_DROTHER, oi);
|
||||
else
|
||||
@ -717,6 +771,9 @@ interface_down (struct thread *thread)
|
||||
zlog_debug ("Interface Event %s: [InterfaceDown]",
|
||||
oi->interface->name);
|
||||
|
||||
/* Stop Hellos */
|
||||
THREAD_OFF (oi->thread_send_hello);
|
||||
|
||||
/* Leave AllSPFRouters */
|
||||
if (oi->state > OSPF6_INTERFACE_DOWN)
|
||||
ospf6_sso (oi->interface->ifindex, &allspfrouters6, IPV6_LEAVE_GROUP);
|
||||
@ -728,6 +785,10 @@ interface_down (struct thread *thread)
|
||||
|
||||
list_delete_all_node (oi->neighbor_list);
|
||||
|
||||
/* When interface state is reset, also reset information about
|
||||
* DR election, as it is no longer valid. */
|
||||
oi->drouter = oi->prev_drouter = htonl(0);
|
||||
oi->bdrouter = oi->prev_bdrouter = htonl(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -758,7 +819,7 @@ ospf6_interface_show (struct vty *vty, struct interface *ifp)
|
||||
type = "UNKNOWN";
|
||||
|
||||
vty_out (vty, "%s is %s, type %s%s",
|
||||
ifp->name, updown[if_is_up (ifp)], type,
|
||||
ifp->name, updown[if_is_operative (ifp)], type,
|
||||
VNL);
|
||||
vty_out (vty, " Interface ID: %d%s", ifp->ifindex, VNL);
|
||||
|
||||
@ -1292,7 +1353,10 @@ DEFUN (ipv6_ospf6_priority,
|
||||
|
||||
oi->priority = strtol (argv[0], NULL, 10);
|
||||
|
||||
if (oi->area)
|
||||
if (oi->area &&
|
||||
(oi->state == OSPF6_INTERFACE_DROTHER ||
|
||||
oi->state == OSPF6_INTERFACE_BDR ||
|
||||
oi->state == OSPF6_INTERFACE_DR))
|
||||
ospf6_interface_state_change (dr_election (oi), oi);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
@ -1516,6 +1580,86 @@ DEFUN (no_ipv6_ospf6_advertise_prefix_list,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ipv6_ospf6_network,
|
||||
ipv6_ospf6_network_cmd,
|
||||
"ipv6 ospf6 network (broadcast|point-to-point)",
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"Network Type\n"
|
||||
"Specify OSPFv6 broadcast network\n"
|
||||
"Specify OSPF6 point-to-point network\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);
|
||||
|
||||
if (strncmp (argv[0], "b", 1) == 0)
|
||||
{
|
||||
if (oi->type == OSPF_IFTYPE_BROADCAST)
|
||||
return CMD_SUCCESS;
|
||||
|
||||
oi->type = OSPF_IFTYPE_BROADCAST;
|
||||
}
|
||||
else if (strncmp (argv[0], "point-to-p", 10) == 0)
|
||||
{
|
||||
if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
oi->type = OSPF_IFTYPE_POINTOPOINT;
|
||||
}
|
||||
|
||||
/* Reset the interface */
|
||||
thread_add_event (master, interface_down, oi, 0);
|
||||
thread_add_event (master, interface_up, oi, 0);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_ipv6_ospf6_network,
|
||||
no_ipv6_ospf6_network_cmd,
|
||||
"no ipv6 ospf6 network",
|
||||
NO_STR
|
||||
IP6_STR
|
||||
OSPF6_STR
|
||||
"Network Type\n"
|
||||
"Default to whatever interface type system specifies"
|
||||
)
|
||||
{
|
||||
struct ospf6_interface *oi;
|
||||
struct interface *ifp;
|
||||
int type;
|
||||
|
||||
ifp = (struct interface *) vty->index;
|
||||
assert (ifp);
|
||||
|
||||
oi = (struct ospf6_interface *) ifp->info;
|
||||
if (oi == NULL) {
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
type = ospf6_default_iftype (ifp);
|
||||
if (oi->type == type)
|
||||
{
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
oi->type = type;
|
||||
|
||||
/* Reset the interface */
|
||||
thread_add_event (master, interface_down, oi, 0);
|
||||
thread_add_event (master, interface_up, oi, 0);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
config_write_ospf6_interface (struct vty *vty)
|
||||
{
|
||||
@ -1575,6 +1719,11 @@ config_write_ospf6_interface (struct vty *vty)
|
||||
if (oi->mtu_ignore)
|
||||
vty_out (vty, " ipv6 ospf6 mtu-ignore%s", VNL);
|
||||
|
||||
if (oi->type == OSPF_IFTYPE_POINTOPOINT)
|
||||
vty_out (vty, " ipv6 ospf6 network point-to-point%s", VNL);
|
||||
else if (oi->type == OSPF_IFTYPE_BROADCAST)
|
||||
vty_out (vty, " ipv6 ospf6 network broadcast%s", VNL);
|
||||
|
||||
vty_out (vty, "!%s", VNL);
|
||||
}
|
||||
return 0;
|
||||
@ -1632,6 +1781,9 @@ ospf6_interface_init (void)
|
||||
|
||||
install_element (INTERFACE_NODE, &ipv6_ospf6_advertise_prefix_list_cmd);
|
||||
install_element (INTERFACE_NODE, &no_ipv6_ospf6_advertise_prefix_list_cmd);
|
||||
|
||||
install_element (INTERFACE_NODE, &ipv6_ospf6_network_cmd);
|
||||
install_element (INTERFACE_NODE, &no_ipv6_ospf6_network_cmd);
|
||||
}
|
||||
|
||||
DEFUN (debug_ospf6_interface,
|
||||
|
@ -56,6 +56,9 @@ struct ospf6_interface
|
||||
/* I/F transmission delay */
|
||||
u_int32_t transdelay;
|
||||
|
||||
/* Network Type */
|
||||
u_char type;
|
||||
|
||||
/* Router Priority */
|
||||
u_char priority;
|
||||
|
||||
|
@ -46,7 +46,7 @@
|
||||
#include "ospf6_abr.h"
|
||||
#include "ospf6_flood.h"
|
||||
#include "ospf6d.h"
|
||||
|
||||
#include "ospf6_spf.h"
|
||||
|
||||
unsigned char conf_debug_ospf6_brouter = 0;
|
||||
u_int32_t conf_debug_ospf6_brouter_specific_router_id;
|
||||
@ -56,6 +56,42 @@ u_int32_t conf_debug_ospf6_brouter_specific_area_id;
|
||||
/* RFC2740 3.4.3.1 Router-LSA */
|
||||
/******************************/
|
||||
|
||||
static char *
|
||||
ospf6_router_lsa_get_nbr_id (struct ospf6_lsa *lsa, char *buf, int buflen,
|
||||
int pos)
|
||||
{
|
||||
struct ospf6_router_lsa *router_lsa;
|
||||
struct ospf6_router_lsdesc *lsdesc;
|
||||
char *start, *end;
|
||||
char buf1[INET_ADDRSTRLEN], buf2[INET_ADDRSTRLEN];
|
||||
|
||||
if (lsa)
|
||||
{
|
||||
router_lsa = (struct ospf6_router_lsa *)
|
||||
((char *) lsa->header + sizeof (struct ospf6_lsa_header));
|
||||
start = (char *) router_lsa + sizeof (struct ospf6_router_lsa);
|
||||
end = (char *) lsa->header + ntohs (lsa->header->length);
|
||||
|
||||
lsdesc = (struct ospf6_router_lsdesc *)
|
||||
(start + pos*(sizeof (struct ospf6_router_lsdesc)));
|
||||
if ((char *)lsdesc < end)
|
||||
{
|
||||
if (buf && (buflen > INET_ADDRSTRLEN*2))
|
||||
{
|
||||
inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
|
||||
buf1, sizeof(buf1));
|
||||
inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
|
||||
buf2, sizeof(buf2));
|
||||
sprintf (buf, "%s/%s", buf2, buf1);
|
||||
}
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int
|
||||
ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
|
||||
{
|
||||
@ -104,6 +140,29 @@ ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ospf6_router_is_stub_router (struct ospf6_lsa *lsa)
|
||||
{
|
||||
struct ospf6_router_lsa *rtr_lsa;
|
||||
|
||||
if (lsa != NULL && OSPF6_LSA_IS_TYPE (ROUTER, lsa))
|
||||
{
|
||||
rtr_lsa = (struct ospf6_router_lsa *)
|
||||
((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
|
||||
|
||||
if (!OSPF6_OPT_ISSET (rtr_lsa->options, OSPF6_OPT_R))
|
||||
{
|
||||
return (OSPF6_IS_STUB_ROUTER);
|
||||
}
|
||||
else if (!OSPF6_OPT_ISSET (rtr_lsa->options, OSPF6_OPT_V6))
|
||||
{
|
||||
return (OSPF6_IS_STUB_ROUTER_V6);
|
||||
}
|
||||
}
|
||||
|
||||
return (OSPF6_NOT_STUB_ROUTER);
|
||||
}
|
||||
|
||||
int
|
||||
ospf6_router_lsa_originate (struct thread *thread)
|
||||
{
|
||||
@ -215,7 +274,7 @@ ospf6_router_lsa_originate (struct thread *thread)
|
||||
}
|
||||
|
||||
/* Point-to-Point interfaces */
|
||||
if (if_is_pointopoint (oi->interface))
|
||||
if (oi->type == OSPF_IFTYPE_POINTOPOINT)
|
||||
{
|
||||
for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
|
||||
{
|
||||
@ -233,7 +292,7 @@ ospf6_router_lsa_originate (struct thread *thread)
|
||||
}
|
||||
|
||||
/* Broadcast and NBMA interfaces */
|
||||
if (if_is_broadcast (oi->interface))
|
||||
else if (oi->type == OSPF_IFTYPE_BROADCAST)
|
||||
{
|
||||
/* If this router is not DR,
|
||||
and If this router not fully adjacent with DR,
|
||||
@ -261,6 +320,10 @@ ospf6_router_lsa_originate (struct thread *thread)
|
||||
|
||||
lsdesc++;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (0); /* Unknown interface type */
|
||||
}
|
||||
|
||||
/* Virtual links */
|
||||
/* xxx */
|
||||
@ -268,35 +331,26 @@ ospf6_router_lsa_originate (struct thread *thread)
|
||||
/* xxx */
|
||||
}
|
||||
|
||||
if ((caddr_t) lsdesc != (caddr_t) router_lsa +
|
||||
sizeof (struct ospf6_router_lsa))
|
||||
{
|
||||
/* Fill LSA Header */
|
||||
lsa_header->age = 0;
|
||||
lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
|
||||
lsa_header->id = htonl (link_state_id);
|
||||
lsa_header->adv_router = oa->ospf6->router_id;
|
||||
lsa_header->seqnum =
|
||||
ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
|
||||
lsa_header->adv_router, oa->lsdb);
|
||||
lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
|
||||
/* Fill LSA Header */
|
||||
lsa_header->age = 0;
|
||||
lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
|
||||
lsa_header->id = htonl (link_state_id);
|
||||
lsa_header->adv_router = oa->ospf6->router_id;
|
||||
lsa_header->seqnum =
|
||||
ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
|
||||
lsa_header->adv_router, oa->lsdb);
|
||||
lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
|
||||
|
||||
/* LSA checksum */
|
||||
ospf6_lsa_checksum (lsa_header);
|
||||
/* LSA checksum */
|
||||
ospf6_lsa_checksum (lsa_header);
|
||||
|
||||
/* create LSA */
|
||||
lsa = ospf6_lsa_create (lsa_header);
|
||||
/* create LSA */
|
||||
lsa = ospf6_lsa_create (lsa_header);
|
||||
|
||||
/* Originate */
|
||||
ospf6_lsa_originate_area (lsa, oa);
|
||||
/* Originate */
|
||||
ospf6_lsa_originate_area (lsa, oa);
|
||||
|
||||
link_state_id ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
|
||||
zlog_debug ("Nothing to describe in Router-LSA, suppress");
|
||||
}
|
||||
link_state_id ++;
|
||||
|
||||
/* Do premature-aging of rest, undesired Router-LSAs */
|
||||
type = ntohs (OSPF6_LSTYPE_ROUTER);
|
||||
@ -316,6 +370,36 @@ ospf6_router_lsa_originate (struct thread *thread)
|
||||
/* RFC2740 3.4.3.2 Network-LSA */
|
||||
/*******************************/
|
||||
|
||||
static char *
|
||||
ospf6_network_lsa_get_ar_id (struct ospf6_lsa *lsa, char *buf, int buflen,
|
||||
int pos)
|
||||
{
|
||||
char *start, *end, *current;
|
||||
struct ospf6_network_lsa *network_lsa;
|
||||
struct ospf6_network_lsdesc *lsdesc;
|
||||
|
||||
if (lsa)
|
||||
{
|
||||
network_lsa = (struct ospf6_network_lsa *)
|
||||
((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
|
||||
|
||||
start = (char *) network_lsa + sizeof (struct ospf6_network_lsa);
|
||||
end = (char *) lsa->header + ntohs (lsa->header->length);
|
||||
current = start + pos*(sizeof (struct ospf6_network_lsdesc));
|
||||
|
||||
if ((current + sizeof(struct ospf6_network_lsdesc)) <= end)
|
||||
{
|
||||
lsdesc = (struct ospf6_network_lsdesc *)current;
|
||||
if (buf)
|
||||
inet_ntop (AF_INET, &lsdesc->router_id, buf, buflen);
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (buf);
|
||||
}
|
||||
|
||||
static int
|
||||
ospf6_network_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
|
||||
{
|
||||
@ -462,6 +546,61 @@ ospf6_network_lsa_originate (struct thread *thread)
|
||||
/* RFC2740 3.4.3.6 Link-LSA */
|
||||
/****************************/
|
||||
|
||||
static char *
|
||||
ospf6_link_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf, int buflen,
|
||||
int pos)
|
||||
{
|
||||
char *start, *end, *current;
|
||||
struct ospf6_link_lsa *link_lsa;
|
||||
struct in6_addr in6;
|
||||
struct ospf6_prefix *prefix;
|
||||
int cnt = 0, prefixnum;
|
||||
|
||||
if (lsa)
|
||||
{
|
||||
link_lsa = (struct ospf6_link_lsa *)
|
||||
((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
|
||||
|
||||
if (pos == 0) {
|
||||
inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, buflen);
|
||||
return (buf);
|
||||
}
|
||||
|
||||
prefixnum = ntohl (link_lsa->prefix_num);
|
||||
if (pos > prefixnum)
|
||||
return (NULL);
|
||||
|
||||
start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
|
||||
end = (char *) lsa->header + ntohs (lsa->header->length);
|
||||
current = start;
|
||||
|
||||
do
|
||||
{
|
||||
prefix = (struct ospf6_prefix *) current;
|
||||
if (prefix->prefix_length == 0 ||
|
||||
current + OSPF6_PREFIX_SIZE (prefix) > end)
|
||||
{
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (cnt < pos)
|
||||
{
|
||||
current = start + pos*OSPF6_PREFIX_SIZE(prefix);
|
||||
cnt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset (&in6, 0, sizeof (in6));
|
||||
memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
|
||||
OSPF6_PREFIX_SPACE (prefix->prefix_length));
|
||||
inet_ntop (AF_INET6, &in6, buf, buflen);
|
||||
return (buf);
|
||||
}
|
||||
} while (current <= end);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
ospf6_link_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
|
||||
{
|
||||
@ -614,6 +753,56 @@ ospf6_link_lsa_originate (struct thread *thread)
|
||||
/*****************************************/
|
||||
/* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
|
||||
/*****************************************/
|
||||
static char *
|
||||
ospf6_intra_prefix_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
|
||||
int buflen, int pos)
|
||||
{
|
||||
char *start, *end, *current;
|
||||
struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
|
||||
struct in6_addr in6;
|
||||
int prefixnum, cnt = 0;
|
||||
struct ospf6_prefix *prefix;
|
||||
|
||||
if (lsa)
|
||||
{
|
||||
intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
|
||||
((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
|
||||
|
||||
prefixnum = ntohs (intra_prefix_lsa->prefix_num);
|
||||
if (pos > prefixnum)
|
||||
return (NULL);
|
||||
|
||||
start = (char *) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa);
|
||||
end = (char *) lsa->header + ntohs (lsa->header->length);
|
||||
current = start;
|
||||
|
||||
do
|
||||
{
|
||||
prefix = (struct ospf6_prefix *) current;
|
||||
if (prefix->prefix_length == 0 ||
|
||||
current + OSPF6_PREFIX_SIZE (prefix) > end)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (cnt < pos)
|
||||
{
|
||||
current = start + pos*OSPF6_PREFIX_SIZE(prefix);
|
||||
cnt++;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset (&in6, 0, sizeof (in6));
|
||||
memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
|
||||
OSPF6_PREFIX_SPACE (prefix->prefix_length));
|
||||
inet_ntop (AF_INET6, &in6, buf, buflen);
|
||||
sprintf(&buf[strlen(buf)], "/%d", prefix->prefix_length);
|
||||
return (buf);
|
||||
}
|
||||
} while (current <= end);
|
||||
}
|
||||
return (buf);
|
||||
}
|
||||
|
||||
static int
|
||||
ospf6_intra_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
|
||||
@ -1029,6 +1218,8 @@ ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
|
||||
struct ospf6_prefix *op;
|
||||
char *start, *current, *end;
|
||||
char buf[64];
|
||||
struct interface *ifp;
|
||||
int direct_connect = 0;
|
||||
|
||||
if (OSPF6_LSA_IS_MAXAGE (lsa))
|
||||
return;
|
||||
@ -1065,6 +1256,12 @@ ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
|
||||
return;
|
||||
}
|
||||
|
||||
if (intra_prefix_lsa->ref_adv_router == oa->ospf6->router_id)
|
||||
{
|
||||
/* the intra-prefix are directly connected */
|
||||
direct_connect = 1;
|
||||
}
|
||||
|
||||
prefix_num = ntohs (intra_prefix_lsa->prefix_num);
|
||||
start = (caddr_t) intra_prefix_lsa +
|
||||
sizeof (struct ospf6_intra_prefix_lsa);
|
||||
@ -1077,6 +1274,20 @@ ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
|
||||
if (end < current + OSPF6_PREFIX_SIZE (op))
|
||||
break;
|
||||
|
||||
/* Appendix A.4.1.1 */
|
||||
if (CHECK_FLAG(op->prefix_options, OSPF6_PREFIX_OPTION_NU) ||
|
||||
CHECK_FLAG(op->prefix_options, OSPF6_PREFIX_OPTION_LA))
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
|
||||
{
|
||||
ospf6_linkstate_prefix2str ((struct prefix *)OSPF6_PREFIX_BODY(op),
|
||||
buf, sizeof (buf));
|
||||
zlog_debug ("%s: Skipping Prefix %s has NU/LA option set",
|
||||
__func__, buf);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
route = ospf6_route_create ();
|
||||
|
||||
memset (&route->prefix, 0, sizeof (struct prefix));
|
||||
@ -1095,9 +1306,18 @@ ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
|
||||
route->path.cost = ls_entry->path.cost +
|
||||
ntohs (op->prefix_metric);
|
||||
|
||||
for (i = 0; ospf6_nexthop_is_set (&ls_entry->nexthop[i]) &&
|
||||
i < OSPF6_MULTI_PATH_LIMIT; i++)
|
||||
ospf6_nexthop_copy (&route->nexthop[i], &ls_entry->nexthop[i]);
|
||||
if (direct_connect)
|
||||
{
|
||||
ifp = if_lookup_prefix(&route->prefix);
|
||||
if (ifp)
|
||||
route->nexthop[0].ifindex = ifp->ifindex;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; ospf6_nexthop_is_set (&ls_entry->nexthop[i]) &&
|
||||
i < OSPF6_MULTI_PATH_LIMIT; i++)
|
||||
ospf6_nexthop_copy (&route->nexthop[i], &ls_entry->nexthop[i]);
|
||||
}
|
||||
|
||||
if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
|
||||
{
|
||||
@ -1342,6 +1562,10 @@ ospf6_intra_brouter_calculation (struct ospf6_area *oa)
|
||||
! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_B))
|
||||
continue;
|
||||
|
||||
if (! OSPF6_OPT_ISSET (brouter->path.options, OSPF6_OPT_V6) ||
|
||||
! OSPF6_OPT_ISSET (brouter->path.options, OSPF6_OPT_R))
|
||||
continue;
|
||||
|
||||
copy = ospf6_route_copy (brouter);
|
||||
copy->type = OSPF6_DEST_TYPE_ROUTER;
|
||||
copy->path.area_id = oa->area_id;
|
||||
@ -1419,28 +1643,36 @@ struct ospf6_lsa_handler router_handler =
|
||||
{
|
||||
OSPF6_LSTYPE_ROUTER,
|
||||
"Router",
|
||||
ospf6_router_lsa_show
|
||||
"Rtr",
|
||||
ospf6_router_lsa_show,
|
||||
ospf6_router_lsa_get_nbr_id
|
||||
};
|
||||
|
||||
struct ospf6_lsa_handler network_handler =
|
||||
{
|
||||
OSPF6_LSTYPE_NETWORK,
|
||||
"Network",
|
||||
ospf6_network_lsa_show
|
||||
"Net",
|
||||
ospf6_network_lsa_show,
|
||||
ospf6_network_lsa_get_ar_id
|
||||
};
|
||||
|
||||
struct ospf6_lsa_handler link_handler =
|
||||
{
|
||||
OSPF6_LSTYPE_LINK,
|
||||
"Link",
|
||||
ospf6_link_lsa_show
|
||||
"Lnk",
|
||||
ospf6_link_lsa_show,
|
||||
ospf6_link_lsa_get_prefix_str
|
||||
};
|
||||
|
||||
struct ospf6_lsa_handler intra_prefix_handler =
|
||||
{
|
||||
OSPF6_LSTYPE_INTRA_PREFIX,
|
||||
"Intra-Prefix",
|
||||
ospf6_intra_prefix_lsa_show
|
||||
"INP",
|
||||
ospf6_intra_prefix_lsa_show,
|
||||
ospf6_intra_prefix_lsa_get_prefix_str
|
||||
};
|
||||
|
||||
void
|
||||
|
@ -94,6 +94,13 @@ struct ospf6_router_lsdesc
|
||||
#define OSPF6_ROUTER_LSDESC_STUB_NETWORK 3
|
||||
#define OSPF6_ROUTER_LSDESC_VIRTUAL_LINK 4
|
||||
|
||||
enum stub_router_mode
|
||||
{
|
||||
OSPF6_NOT_STUB_ROUTER,
|
||||
OSPF6_IS_STUB_ROUTER,
|
||||
OSPF6_IS_STUB_ROUTER_V6,
|
||||
};
|
||||
|
||||
#define ROUTER_LSDESC_IS_TYPE(t,x) \
|
||||
((((struct ospf6_router_lsdesc *)(x))->type == \
|
||||
OSPF6_ROUTER_LSDESC_ ## t) ? 1 : 0)
|
||||
@ -149,32 +156,37 @@ struct ospf6_intra_prefix_lsa
|
||||
|
||||
#define OSPF6_ROUTER_LSA_SCHEDULE(oa) \
|
||||
do { \
|
||||
if (! (oa)->thread_router_lsa) \
|
||||
if (! (oa)->thread_router_lsa \
|
||||
&& CHECK_FLAG((oa)->flag, OSPF6_AREA_ENABLE)) \
|
||||
(oa)->thread_router_lsa = \
|
||||
thread_add_event (master, ospf6_router_lsa_originate, oa, 0); \
|
||||
} while (0)
|
||||
#define OSPF6_NETWORK_LSA_SCHEDULE(oi) \
|
||||
do { \
|
||||
if (! (oi)->thread_network_lsa) \
|
||||
if (! (oi)->thread_network_lsa \
|
||||
&& ! CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE)) \
|
||||
(oi)->thread_network_lsa = \
|
||||
thread_add_event (master, ospf6_network_lsa_originate, oi, 0); \
|
||||
} while (0)
|
||||
#define OSPF6_LINK_LSA_SCHEDULE(oi) \
|
||||
do { \
|
||||
if (! (oi)->thread_link_lsa) \
|
||||
if (! (oi)->thread_link_lsa \
|
||||
&& ! CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE)) \
|
||||
(oi)->thread_link_lsa = \
|
||||
thread_add_event (master, ospf6_link_lsa_originate, oi, 0); \
|
||||
} while (0)
|
||||
#define OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oa) \
|
||||
do { \
|
||||
if (! (oa)->thread_intra_prefix_lsa) \
|
||||
if (! (oa)->thread_intra_prefix_lsa \
|
||||
&& CHECK_FLAG((oa)->flag, OSPF6_AREA_ENABLE)) \
|
||||
(oa)->thread_intra_prefix_lsa = \
|
||||
thread_add_event (master, ospf6_intra_prefix_lsa_originate_stub, \
|
||||
oa, 0); \
|
||||
} while (0)
|
||||
#define OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi) \
|
||||
do { \
|
||||
if (! (oi)->thread_intra_prefix_lsa) \
|
||||
if (! (oi)->thread_intra_prefix_lsa \
|
||||
&& ! CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE)) \
|
||||
(oi)->thread_intra_prefix_lsa = \
|
||||
thread_add_event (master, ospf6_intra_prefix_lsa_originate_transit, \
|
||||
oi, 0); \
|
||||
@ -200,6 +212,7 @@ extern char *ospf6_router_lsdesc_lookup (u_char type, u_int32_t interface_id,
|
||||
extern char *ospf6_network_lsdesc_lookup (u_int32_t router_id,
|
||||
struct ospf6_lsa *lsa);
|
||||
|
||||
extern int ospf6_router_is_stub_router (struct ospf6_lsa *lsa);
|
||||
extern int ospf6_router_lsa_originate (struct thread *);
|
||||
extern int ospf6_network_lsa_originate (struct thread *);
|
||||
extern int ospf6_link_lsa_originate (struct thread *);
|
||||
|
@ -75,7 +75,9 @@ struct ospf6_lsa_handler unknown_handler =
|
||||
{
|
||||
OSPF6_LSTYPE_UNKNOWN,
|
||||
"Unknown",
|
||||
"Unk",
|
||||
ospf6_unknown_lsa_show,
|
||||
NULL,
|
||||
OSPF6_LSA_DEBUG,
|
||||
};
|
||||
|
||||
@ -118,6 +120,20 @@ ospf6_lstype_name (u_int16_t type)
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char *
|
||||
ospf6_lstype_short_name (u_int16_t type)
|
||||
{
|
||||
static char buf[8];
|
||||
struct ospf6_lsa_handler *handler;
|
||||
|
||||
handler = ospf6_get_lsa_handler (type);
|
||||
if (handler && handler != &unknown_handler)
|
||||
return handler->short_name;
|
||||
|
||||
snprintf (buf, sizeof (buf), "0x%04hx", ntohs (type));
|
||||
return buf;
|
||||
}
|
||||
|
||||
u_char
|
||||
ospf6_lstype_debug (u_int16_t type)
|
||||
{
|
||||
@ -139,11 +155,11 @@ ospf6_lsa_is_differ (struct ospf6_lsa *lsa1,
|
||||
|
||||
ospf6_lsa_age_current (lsa1);
|
||||
ospf6_lsa_age_current (lsa2);
|
||||
if (ntohs (lsa1->header->age) == MAXAGE &&
|
||||
ntohs (lsa2->header->age) != MAXAGE)
|
||||
if (ntohs (lsa1->header->age) == OSPF_LSA_MAXAGE &&
|
||||
ntohs (lsa2->header->age) != OSPF_LSA_MAXAGE)
|
||||
return 1;
|
||||
if (ntohs (lsa1->header->age) != MAXAGE &&
|
||||
ntohs (lsa2->header->age) == MAXAGE)
|
||||
if (ntohs (lsa1->header->age) != OSPF_LSA_MAXAGE &&
|
||||
ntohs (lsa2->header->age) == OSPF_LSA_MAXAGE)
|
||||
return 1;
|
||||
|
||||
/* compare body */
|
||||
@ -218,19 +234,19 @@ ospf6_lsa_age_current (struct ospf6_lsa *lsa)
|
||||
zlog_warn ("LSA: quagga_gettime failed, may fail LSA AGEs: %s",
|
||||
safe_strerror (errno));
|
||||
|
||||
if (ntohs (lsa->header->age) >= MAXAGE)
|
||||
if (ntohs (lsa->header->age) >= OSPF_LSA_MAXAGE)
|
||||
{
|
||||
/* ospf6_lsa_premature_aging () sets age to MAXAGE; when using
|
||||
relative time, we cannot compare against lsa birth time, so
|
||||
we catch this special case here. */
|
||||
lsa->header->age = htons (MAXAGE);
|
||||
return MAXAGE;
|
||||
lsa->header->age = htons (OSPF_LSA_MAXAGE);
|
||||
return OSPF_LSA_MAXAGE;
|
||||
}
|
||||
/* calculate age */
|
||||
ulage = now.tv_sec - lsa->birth.tv_sec;
|
||||
|
||||
/* if over MAXAGE, set to it */
|
||||
age = (ulage > MAXAGE ? MAXAGE : ulage);
|
||||
age = (ulage > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : ulage);
|
||||
|
||||
lsa->header->age = htons (age);
|
||||
return age;
|
||||
@ -243,8 +259,8 @@ ospf6_lsa_age_update_to_send (struct ospf6_lsa *lsa, u_int32_t transdelay)
|
||||
unsigned short age;
|
||||
|
||||
age = ospf6_lsa_age_current (lsa) + transdelay;
|
||||
if (age > MAXAGE)
|
||||
age = MAXAGE;
|
||||
if (age > OSPF_LSA_MAXAGE)
|
||||
age = OSPF_LSA_MAXAGE;
|
||||
lsa->header->age = htons (age);
|
||||
}
|
||||
|
||||
@ -258,7 +274,30 @@ ospf6_lsa_premature_aging (struct ospf6_lsa *lsa)
|
||||
THREAD_OFF (lsa->expire);
|
||||
THREAD_OFF (lsa->refresh);
|
||||
|
||||
lsa->header->age = htons (MAXAGE);
|
||||
/*
|
||||
* We clear the LSA from the neighbor retx lists now because it
|
||||
* will not get deleted later. Essentially, changing the age to
|
||||
* MaxAge will prevent this LSA from being matched with its
|
||||
* existing entries in the retx list thereby causing those entries
|
||||
* to be silently replaced with its MaxAged version, but with ever
|
||||
* increasing retx count causing this LSA to remain forever and
|
||||
* for the MaxAge remover thread to be called forever too.
|
||||
*
|
||||
* The reason the previous entry silently disappears is that when
|
||||
* entry is added to a neighbor's retx list, it replaces the existing
|
||||
* entry. But since the ospf6_lsdb_add() routine is generic and not aware
|
||||
* of the special semantics of retx count, the retx count is not
|
||||
* decremented when its replaced. Attempting to add the incr and decr
|
||||
* retx count routines as the hook_add and hook_remove for the retx lists
|
||||
* have a problem because the hook_remove routine is called for MaxAge
|
||||
* entries (as will be the case in a traditional LSDB, unlike in this case
|
||||
* where an LSDB is used as an efficient tree structure to store all kinds
|
||||
* of data) that are added instead of calling the hook_add routine.
|
||||
*/
|
||||
|
||||
ospf6_flood_clear (lsa);
|
||||
|
||||
lsa->header->age = htons (OSPF_LSA_MAXAGE);
|
||||
thread_execute (master, ospf6_lsa_expire, lsa, 0);
|
||||
}
|
||||
|
||||
@ -297,15 +336,15 @@ ospf6_lsa_compare (struct ospf6_lsa *a, struct ospf6_lsa *b)
|
||||
ageb = ospf6_lsa_age_current (b);
|
||||
|
||||
/* MaxAge check */
|
||||
if (agea == MAXAGE && ageb != MAXAGE)
|
||||
if (agea == OSPF_LSA_MAXAGE && ageb != OSPF_LSA_MAXAGE)
|
||||
return -1;
|
||||
else if (agea != MAXAGE && ageb == MAXAGE)
|
||||
else if (agea != OSPF_LSA_MAXAGE && ageb == OSPF_LSA_MAXAGE)
|
||||
return 1;
|
||||
|
||||
/* Age check */
|
||||
if (agea > ageb && agea - ageb >= MAX_AGE_DIFF)
|
||||
if (agea > ageb && agea - ageb >= OSPF_LSA_MAXAGE_DIFF)
|
||||
return 1;
|
||||
else if (agea < ageb && ageb - agea >= MAX_AGE_DIFF)
|
||||
else if (agea < ageb && ageb - agea >= OSPF_LSA_MAXAGE_DIFF)
|
||||
return -1;
|
||||
|
||||
/* neither recent */
|
||||
@ -348,17 +387,19 @@ ospf6_lsa_header_print (struct ospf6_lsa *lsa)
|
||||
void
|
||||
ospf6_lsa_show_summary_header (struct vty *vty)
|
||||
{
|
||||
vty_out (vty, "%-12s %-15s %-15s %4s %8s %4s %4s %-8s%s",
|
||||
vty_out (vty, "%-4s %-15s%-15s%4s %8s %30s%s",
|
||||
"Type", "LSId", "AdvRouter", "Age", "SeqNum",
|
||||
"Cksm", "Len", "Duration", VNL);
|
||||
"Payload", VNL);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa)
|
||||
{
|
||||
char adv_router[16], id[16];
|
||||
struct timeval now, res;
|
||||
char duration[16];
|
||||
int type;
|
||||
struct ospf6_lsa_handler *handler;
|
||||
char buf[64], tmpbuf[80];
|
||||
int cnt = 0;
|
||||
|
||||
assert (lsa);
|
||||
assert (lsa->header);
|
||||
@ -367,16 +408,38 @@ ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa)
|
||||
inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
|
||||
sizeof (adv_router));
|
||||
|
||||
quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
|
||||
timersub (&now, &lsa->installed, &res);
|
||||
timerstring (&res, duration, sizeof (duration));
|
||||
type = ntohs(lsa->header->type);
|
||||
handler = ospf6_get_lsa_handler (lsa->header->type);
|
||||
if ((type == OSPF6_LSTYPE_INTER_PREFIX) ||
|
||||
(type == OSPF6_LSTYPE_INTER_ROUTER) ||
|
||||
(type == OSPF6_LSTYPE_AS_EXTERNAL))
|
||||
{
|
||||
vty_out (vty, "%-4s %-15s%-15s%4hu %8lx %30s%s",
|
||||
ospf6_lstype_short_name (lsa->header->type),
|
||||
id, adv_router, ospf6_lsa_age_current (lsa),
|
||||
(u_long) ntohl (lsa->header->seqnum),
|
||||
handler->get_prefix_str(lsa, buf, sizeof(buf), 0), VNL);
|
||||
}
|
||||
else if (type != OSPF6_LSTYPE_UNKNOWN)
|
||||
{
|
||||
sprintf (tmpbuf, "%-4s %-15s%-15s%4hu %8lx",
|
||||
ospf6_lstype_short_name (lsa->header->type),
|
||||
id, adv_router, ospf6_lsa_age_current (lsa),
|
||||
(u_long) ntohl (lsa->header->seqnum));
|
||||
|
||||
vty_out (vty, "%-12s %-15s %-15s %4hu %8lx %04hx %4hu %8s%s",
|
||||
ospf6_lstype_name (lsa->header->type),
|
||||
id, adv_router, ospf6_lsa_age_current (lsa),
|
||||
(u_long) ntohl (lsa->header->seqnum),
|
||||
ntohs (lsa->header->checksum), ntohs (lsa->header->length),
|
||||
duration, VNL);
|
||||
while (handler->get_prefix_str(lsa, buf, sizeof(buf), cnt) != NULL)
|
||||
{
|
||||
vty_out (vty, "%s %30s%s", tmpbuf, buf, VNL);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vty_out (vty, "%-4s %-15s%-15s%4hu %8lx%s",
|
||||
ospf6_lstype_short_name (lsa->header->type),
|
||||
id, adv_router, ospf6_lsa_age_current (lsa),
|
||||
(u_long) ntohl (lsa->header->seqnum), VNL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -427,8 +490,11 @@ ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa)
|
||||
vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
|
||||
ntohs (lsa->header->checksum),
|
||||
ntohs (lsa->header->length), VNL);
|
||||
vty_out (vty, " Prev: %p This: %p Next: %p%s",
|
||||
lsa->prev, lsa, lsa->next, VNL);
|
||||
vty_out (vty, "Flag: %x %s", lsa->flag, VNL);
|
||||
vty_out (vty, "Lock: %d %s", lsa->lock, VNL);
|
||||
vty_out (vty, "ReTx Count: %d%s", lsa->retrans_count, VNL);
|
||||
vty_out (vty, "Threads: Expire: %x, Refresh: %x %s",
|
||||
lsa->expire, lsa->refresh, VNL);
|
||||
vty_out (vty, "%s", VNL);
|
||||
return;
|
||||
}
|
||||
@ -438,6 +504,8 @@ ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
|
||||
{
|
||||
char adv_router[64], id[64];
|
||||
struct ospf6_lsa_handler *handler;
|
||||
struct timeval now, res;
|
||||
char duration[16];
|
||||
|
||||
assert (lsa && lsa->header);
|
||||
|
||||
@ -445,6 +513,10 @@ ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
|
||||
inet_ntop (AF_INET, &lsa->header->adv_router,
|
||||
adv_router, sizeof (adv_router));
|
||||
|
||||
quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
|
||||
timersub (&now, &lsa->installed, &res);
|
||||
timerstring (&res, duration, sizeof (duration));
|
||||
|
||||
vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
|
||||
ospf6_lstype_name (lsa->header->type), VNL);
|
||||
vty_out (vty, "Link State ID: %s%s", id, VNL);
|
||||
@ -454,6 +526,7 @@ ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
|
||||
vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
|
||||
ntohs (lsa->header->checksum),
|
||||
ntohs (lsa->header->length), VNL);
|
||||
vty_out (vty, "Duration: %s%s", duration, VNL);
|
||||
|
||||
handler = ospf6_get_lsa_handler (lsa->header->type);
|
||||
if (handler->show == NULL)
|
||||
@ -558,6 +631,7 @@ ospf6_lsa_copy (struct ospf6_lsa *lsa)
|
||||
copy->received = lsa->received;
|
||||
copy->installed = lsa->installed;
|
||||
copy->lsdb = lsa->lsdb;
|
||||
copy->rn = NULL;
|
||||
|
||||
return copy;
|
||||
}
|
||||
@ -608,12 +682,12 @@ ospf6_lsa_expire (struct thread *thread)
|
||||
if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
|
||||
return 0; /* dbexchange will do something ... */
|
||||
|
||||
/* reflood lsa */
|
||||
ospf6_flood (NULL, lsa);
|
||||
|
||||
/* reinstall lsa */
|
||||
ospf6_install_lsa (lsa);
|
||||
|
||||
/* reflood lsa */
|
||||
ospf6_flood (NULL, lsa);
|
||||
|
||||
/* schedule maxage remover */
|
||||
ospf6_maxage_remove (ospf6);
|
||||
|
||||
@ -653,7 +727,7 @@ ospf6_lsa_refresh (struct thread *thread)
|
||||
new = ospf6_lsa_create (self->header);
|
||||
new->lsdb = old->lsdb;
|
||||
new->refresh = thread_add_timer (master, ospf6_lsa_refresh, new,
|
||||
LS_REFRESH_TIME);
|
||||
OSPF_LS_REFRESH_TIME);
|
||||
|
||||
/* store it in the LSDB for self-originated LSAs */
|
||||
ospf6_lsdb_add (ospf6_lsa_copy (new), lsdb_self);
|
||||
@ -664,9 +738,8 @@ ospf6_lsa_refresh (struct thread *thread)
|
||||
ospf6_lsa_header_print (new);
|
||||
}
|
||||
|
||||
ospf6_flood_clear (old);
|
||||
ospf6_flood (NULL, new);
|
||||
ospf6_install_lsa (new);
|
||||
ospf6_flood (NULL, new);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -725,7 +798,7 @@ ospf6_lsa_handler_name (struct ospf6_lsa_handler *h)
|
||||
unsigned int i;
|
||||
unsigned int size = strlen (h->name);
|
||||
|
||||
if (!strcmp(h->name, "Unknown") &&
|
||||
if (!strcmp(h->name, "unknown") &&
|
||||
h->type != OSPF6_LSTYPE_UNKNOWN)
|
||||
{
|
||||
snprintf (buf, sizeof (buf), "%#04hx", h->type);
|
||||
@ -745,7 +818,7 @@ ospf6_lsa_handler_name (struct ospf6_lsa_handler *h)
|
||||
|
||||
DEFUN (debug_ospf6_lsa_type,
|
||||
debug_ospf6_lsa_hex_cmd,
|
||||
"debug ospf6 lsa XXXX/0xXXXX",
|
||||
"debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)",
|
||||
DEBUG_STR
|
||||
OSPF6_STR
|
||||
"Debug Link State Advertisements (LSAs)\n"
|
||||
@ -754,44 +827,21 @@ DEFUN (debug_ospf6_lsa_type,
|
||||
{
|
||||
unsigned int i;
|
||||
struct ospf6_lsa_handler *handler = NULL;
|
||||
unsigned long val;
|
||||
char *endptr = NULL;
|
||||
u_int16_t type = 0;
|
||||
|
||||
assert (argc);
|
||||
|
||||
if ((strlen (argv[0]) == 6 && ! strncmp (argv[0], "0x", 2)) ||
|
||||
(strlen (argv[0]) == 4))
|
||||
{
|
||||
val = strtoul (argv[0], &endptr, 16);
|
||||
if (*endptr == '\0')
|
||||
type = val;
|
||||
}
|
||||
|
||||
for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
|
||||
{
|
||||
handler = vector_slot (ospf6_lsa_handler_vector, i);
|
||||
if (handler == NULL)
|
||||
continue;
|
||||
if (type && handler->type == type)
|
||||
if (strncmp (argv[0], ospf6_lsa_handler_name(handler), strlen(argv[0])) == 0)
|
||||
break;
|
||||
if (! strcasecmp (argv[0], handler->name))
|
||||
break;
|
||||
handler = NULL;
|
||||
}
|
||||
|
||||
if (type && handler == NULL)
|
||||
{
|
||||
handler = (struct ospf6_lsa_handler *)
|
||||
malloc (sizeof (struct ospf6_lsa_handler));
|
||||
memset (handler, 0, sizeof (struct ospf6_lsa_handler));
|
||||
handler->type = type;
|
||||
handler->name = "Unknown";
|
||||
handler->show = ospf6_unknown_lsa_show;
|
||||
vector_set_index (ospf6_lsa_handler_vector,
|
||||
handler->type & OSPF6_LSTYPE_FCODE_MASK, handler);
|
||||
}
|
||||
|
||||
if (handler == NULL)
|
||||
handler = &unknown_handler;
|
||||
|
||||
@ -799,7 +849,7 @@ DEFUN (debug_ospf6_lsa_type,
|
||||
{
|
||||
if (! strcmp (argv[1], "originate"))
|
||||
SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
|
||||
if (! strcmp (argv[1], "examin"))
|
||||
if (! strcmp (argv[1], "examine"))
|
||||
SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
|
||||
if (! strcmp (argv[1], "flooding"))
|
||||
SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD);
|
||||
@ -810,9 +860,18 @@ DEFUN (debug_ospf6_lsa_type,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
ALIAS (debug_ospf6_lsa_type,
|
||||
debug_ospf6_lsa_hex_detail_cmd,
|
||||
"debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown) (originate|examine|flooding)",
|
||||
DEBUG_STR
|
||||
OSPF6_STR
|
||||
"Debug Link State Advertisements (LSAs)\n"
|
||||
"Specify LS type as Hexadecimal\n"
|
||||
)
|
||||
|
||||
DEFUN (no_debug_ospf6_lsa_type,
|
||||
no_debug_ospf6_lsa_hex_cmd,
|
||||
"no debug ospf6 lsa XXXX/0xXXXX",
|
||||
"no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)",
|
||||
NO_STR
|
||||
DEBUG_STR
|
||||
OSPF6_STR
|
||||
@ -822,26 +881,15 @@ DEFUN (no_debug_ospf6_lsa_type,
|
||||
{
|
||||
u_int i;
|
||||
struct ospf6_lsa_handler *handler = NULL;
|
||||
unsigned long val;
|
||||
char *endptr = NULL;
|
||||
u_int16_t type = 0;
|
||||
|
||||
assert (argc);
|
||||
|
||||
if ((strlen (argv[0]) == 6 && ! strncmp (argv[0], "0x", 2)) ||
|
||||
(strlen (argv[0]) == 4))
|
||||
{
|
||||
val = strtoul (argv[0], &endptr, 16);
|
||||
if (*endptr == '\0')
|
||||
type = val;
|
||||
}
|
||||
|
||||
for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
|
||||
{
|
||||
handler = vector_slot (ospf6_lsa_handler_vector, i);
|
||||
if (handler == NULL)
|
||||
continue;
|
||||
if (type && handler->type == type)
|
||||
if (strncmp (argv[0], ospf6_lsa_handler_name(handler), strlen(argv[0])) == 0)
|
||||
break;
|
||||
if (! strcasecmp (argv[0], handler->name))
|
||||
break;
|
||||
@ -854,7 +902,7 @@ DEFUN (no_debug_ospf6_lsa_type,
|
||||
{
|
||||
if (! strcmp (argv[1], "originate"))
|
||||
UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
|
||||
if (! strcmp (argv[1], "examin"))
|
||||
if (! strcmp (argv[1], "examine"))
|
||||
UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
|
||||
if (! strcmp (argv[1], "flooding"))
|
||||
UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD);
|
||||
@ -862,120 +910,30 @@ DEFUN (no_debug_ospf6_lsa_type,
|
||||
else
|
||||
UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG);
|
||||
|
||||
if (handler->debug == 0 &&
|
||||
!strcmp(handler->name, "Unknown") && type != OSPF6_LSTYPE_UNKNOWN)
|
||||
{
|
||||
free (handler);
|
||||
vector_slot (ospf6_lsa_handler_vector, i) = NULL;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
struct cmd_element debug_ospf6_lsa_type_cmd;
|
||||
struct cmd_element debug_ospf6_lsa_type_detail_cmd;
|
||||
struct cmd_element no_debug_ospf6_lsa_type_cmd;
|
||||
struct cmd_element no_debug_ospf6_lsa_type_detail_cmd;
|
||||
ALIAS (no_debug_ospf6_lsa_type,
|
||||
no_debug_ospf6_lsa_hex_detail_cmd,
|
||||
"no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix) (originate|examine|flooding)",
|
||||
NO_STR
|
||||
DEBUG_STR
|
||||
OSPF6_STR
|
||||
"Debug Link State Advertisements (LSAs)\n"
|
||||
"Specify LS type as Hexadecimal\n"
|
||||
)
|
||||
|
||||
void
|
||||
install_element_ospf6_debug_lsa (void)
|
||||
{
|
||||
u_int i;
|
||||
struct ospf6_lsa_handler *handler;
|
||||
#define STRSIZE 256
|
||||
#define DOCSIZE 1024
|
||||
static char strbuf[STRSIZE];
|
||||
static char docbuf[DOCSIZE];
|
||||
static char detail_strbuf[STRSIZE];
|
||||
static char detail_docbuf[DOCSIZE];
|
||||
char *str, *no_str;
|
||||
char *doc, *no_doc;
|
||||
|
||||
strbuf[0] = '\0';
|
||||
no_str = &strbuf[strlen (strbuf)];
|
||||
strncat (strbuf, "no ", STRSIZE - strlen (strbuf));
|
||||
str = &strbuf[strlen (strbuf)];
|
||||
|
||||
strncat (strbuf, "debug ospf6 lsa (", STRSIZE - strlen (strbuf));
|
||||
for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
|
||||
{
|
||||
handler = vector_slot (ospf6_lsa_handler_vector, i);
|
||||
if (handler == NULL)
|
||||
continue;
|
||||
strncat (strbuf, ospf6_lsa_handler_name (handler),
|
||||
STRSIZE - strlen (strbuf));
|
||||
strncat (strbuf, "|", STRSIZE - strlen (strbuf));
|
||||
}
|
||||
strbuf[strlen (strbuf) - 1] = ')';
|
||||
strbuf[strlen (strbuf)] = '\0';
|
||||
|
||||
docbuf[0] = '\0';
|
||||
no_doc = &docbuf[strlen (docbuf)];
|
||||
strncat (docbuf, NO_STR, DOCSIZE - strlen (docbuf));
|
||||
doc = &docbuf[strlen (docbuf)];
|
||||
|
||||
strncat (docbuf, DEBUG_STR, DOCSIZE - strlen (docbuf));
|
||||
strncat (docbuf, OSPF6_STR, DOCSIZE - strlen (docbuf));
|
||||
strncat (docbuf, "Debug Link State Advertisements (LSAs)\n",
|
||||
DOCSIZE - strlen (docbuf));
|
||||
|
||||
for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
|
||||
{
|
||||
handler = vector_slot (ospf6_lsa_handler_vector, i);
|
||||
if (handler == NULL)
|
||||
continue;
|
||||
strncat (docbuf, "Debug ", DOCSIZE - strlen (docbuf));
|
||||
strncat (docbuf, handler->name, DOCSIZE - strlen (docbuf));
|
||||
strncat (docbuf, "-LSA\n", DOCSIZE - strlen (docbuf));
|
||||
}
|
||||
docbuf[strlen (docbuf)] = '\0';
|
||||
|
||||
debug_ospf6_lsa_type_cmd.string = str;
|
||||
debug_ospf6_lsa_type_cmd.func = debug_ospf6_lsa_type;
|
||||
debug_ospf6_lsa_type_cmd.doc = doc;
|
||||
|
||||
no_debug_ospf6_lsa_type_cmd.string = no_str;
|
||||
no_debug_ospf6_lsa_type_cmd.func = no_debug_ospf6_lsa_type;
|
||||
no_debug_ospf6_lsa_type_cmd.doc = no_doc;
|
||||
|
||||
strncpy (detail_strbuf, strbuf, STRSIZE);
|
||||
strncat (detail_strbuf, " (originate|examin|flooding)",
|
||||
STRSIZE - strlen (detail_strbuf));
|
||||
detail_strbuf[strlen (detail_strbuf)] = '\0';
|
||||
no_str = &detail_strbuf[0];
|
||||
str = &detail_strbuf[strlen ("no ")];
|
||||
|
||||
strncpy (detail_docbuf, docbuf, DOCSIZE);
|
||||
strncat (detail_docbuf, "Debug Originating LSA\n",
|
||||
DOCSIZE - strlen (detail_docbuf));
|
||||
strncat (detail_docbuf, "Debug Examining LSA\n",
|
||||
DOCSIZE - strlen (detail_docbuf));
|
||||
strncat (detail_docbuf, "Debug Flooding LSA\n",
|
||||
DOCSIZE - strlen (detail_docbuf));
|
||||
detail_docbuf[strlen (detail_docbuf)] = '\0';
|
||||
no_doc = &detail_docbuf[0];
|
||||
doc = &detail_docbuf[strlen (NO_STR)];
|
||||
|
||||
debug_ospf6_lsa_type_detail_cmd.string = str;
|
||||
debug_ospf6_lsa_type_detail_cmd.func = debug_ospf6_lsa_type;
|
||||
debug_ospf6_lsa_type_detail_cmd.doc = doc;
|
||||
|
||||
no_debug_ospf6_lsa_type_detail_cmd.string = no_str;
|
||||
no_debug_ospf6_lsa_type_detail_cmd.func = no_debug_ospf6_lsa_type;
|
||||
no_debug_ospf6_lsa_type_detail_cmd.doc = no_doc;
|
||||
|
||||
install_element (ENABLE_NODE, &debug_ospf6_lsa_hex_cmd);
|
||||
install_element (ENABLE_NODE, &debug_ospf6_lsa_type_cmd);
|
||||
install_element (ENABLE_NODE, &debug_ospf6_lsa_type_detail_cmd);
|
||||
install_element (ENABLE_NODE, &debug_ospf6_lsa_hex_detail_cmd);
|
||||
install_element (ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd);
|
||||
install_element (ENABLE_NODE, &no_debug_ospf6_lsa_type_cmd);
|
||||
install_element (ENABLE_NODE, &no_debug_ospf6_lsa_type_detail_cmd);
|
||||
install_element (ENABLE_NODE, &no_debug_ospf6_lsa_hex_detail_cmd);
|
||||
install_element (CONFIG_NODE, &debug_ospf6_lsa_hex_cmd);
|
||||
install_element (CONFIG_NODE, &debug_ospf6_lsa_type_cmd);
|
||||
install_element (CONFIG_NODE, &debug_ospf6_lsa_type_detail_cmd);
|
||||
install_element (CONFIG_NODE, &debug_ospf6_lsa_hex_detail_cmd);
|
||||
install_element (CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd);
|
||||
install_element (CONFIG_NODE, &no_debug_ospf6_lsa_type_cmd);
|
||||
install_element (CONFIG_NODE, &no_debug_ospf6_lsa_type_detail_cmd);
|
||||
install_element (CONFIG_NODE, &no_debug_ospf6_lsa_hex_detail_cmd);
|
||||
}
|
||||
|
||||
int
|
||||
@ -996,7 +954,7 @@ config_write_ospf6_debug_lsa (struct vty *vty)
|
||||
vty_out (vty, "debug ospf6 lsa %s originate%s",
|
||||
ospf6_lsa_handler_name (handler), VNL);
|
||||
if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN))
|
||||
vty_out (vty, "debug ospf6 lsa %s examin%s",
|
||||
vty_out (vty, "debug ospf6 lsa %s examine%s",
|
||||
ospf6_lsa_handler_name (handler), VNL);
|
||||
if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD))
|
||||
vty_out (vty, "debug ospf6 lsa %s flooding%s",
|
||||
|
@ -107,15 +107,16 @@ struct ospf6_lsa_header
|
||||
((L)->header->adv_router == (a) && (L)->header->id == (i) && \
|
||||
(L)->header->type == (t))
|
||||
#define OSPF6_LSA_IS_DIFFER(L1, L2) ospf6_lsa_is_differ (L1, L2)
|
||||
#define OSPF6_LSA_IS_MAXAGE(L) (ospf6_lsa_age_current (L) == MAXAGE)
|
||||
#define OSPF6_LSA_IS_MAXAGE(L) (ospf6_lsa_age_current (L) == OSPF_LSA_MAXAGE)
|
||||
#define OSPF6_LSA_IS_CHANGED(L1, L2) ospf6_lsa_is_changed (L1, L2)
|
||||
#define OSPF6_LSA_IS_SEQWRAP(L) ((L)->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER + 1))
|
||||
|
||||
|
||||
struct ospf6_lsa
|
||||
{
|
||||
char name[64]; /* dump string */
|
||||
|
||||
struct ospf6_lsa *prev;
|
||||
struct ospf6_lsa *next;
|
||||
struct route_node *rn;
|
||||
|
||||
unsigned char lock; /* reference counter */
|
||||
unsigned char flag; /* special meaning (e.g. floodback) */
|
||||
@ -140,12 +141,15 @@ struct ospf6_lsa
|
||||
#define OSPF6_LSA_FLOODBACK 0x02
|
||||
#define OSPF6_LSA_DUPLICATE 0x04
|
||||
#define OSPF6_LSA_IMPLIEDACK 0x08
|
||||
#define OSPF6_LSA_SEQWRAPPED 0x20
|
||||
|
||||
struct ospf6_lsa_handler
|
||||
{
|
||||
u_int16_t type; /* host byte order */
|
||||
const char *name;
|
||||
const char *short_name;
|
||||
int (*show) (struct vty *, struct ospf6_lsa *);
|
||||
char *(*get_prefix_str) (struct ospf6_lsa *, char *buf, int buflen, int pos);
|
||||
u_char debug;
|
||||
};
|
||||
|
||||
@ -208,6 +212,7 @@ extern struct ospf6_lsa_handler unknown_handler;
|
||||
|
||||
/* Function Prototypes */
|
||||
extern const char *ospf6_lstype_name (u_int16_t type);
|
||||
extern const char *ospf6_lstype_short_name (u_int16_t type);
|
||||
extern u_char ospf6_lstype_debug (u_int16_t type);
|
||||
extern int ospf6_lsa_is_differ (struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2);
|
||||
extern int ospf6_lsa_is_changed (struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2);
|
||||
|
@ -54,9 +54,12 @@ ospf6_lsdb_create (void *data)
|
||||
void
|
||||
ospf6_lsdb_delete (struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
ospf6_lsdb_remove_all (lsdb);
|
||||
route_table_finish (lsdb->table);
|
||||
XFREE (MTYPE_OSPF6_LSDB, lsdb);
|
||||
if (lsdb != NULL)
|
||||
{
|
||||
ospf6_lsdb_remove_all (lsdb);
|
||||
route_table_finish (lsdb->table);
|
||||
XFREE (MTYPE_OSPF6_LSDB, lsdb);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -70,7 +73,7 @@ ospf6_lsdb_set_key (struct prefix_ipv6 *key, void *value, int len)
|
||||
key->prefixlen += len * 8;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
_lsdb_count_assert (struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
@ -94,16 +97,16 @@ _lsdb_count_assert (struct ospf6_lsdb *lsdb)
|
||||
assert (num == lsdb->count);
|
||||
}
|
||||
#define ospf6_lsdb_count_assert(t) (_lsdb_count_assert (t))
|
||||
#else /*NDEBUG*/
|
||||
#else /*DEBUG*/
|
||||
#define ospf6_lsdb_count_assert(t) ((void) 0)
|
||||
#endif /*NDEBUG*/
|
||||
#endif /*DEBUG*/
|
||||
|
||||
void
|
||||
ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
struct prefix_ipv6 key;
|
||||
struct route_node *current, *nextnode, *prevnode;
|
||||
struct ospf6_lsa *next, *prev, *old = NULL;
|
||||
struct route_node *current;
|
||||
struct ospf6_lsa *old = NULL;
|
||||
|
||||
memset (&key, 0, sizeof (key));
|
||||
ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type));
|
||||
@ -114,55 +117,25 @@ ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
|
||||
current = route_node_get (lsdb->table, (struct prefix *) &key);
|
||||
old = current->info;
|
||||
current->info = lsa;
|
||||
lsa->rn = current;
|
||||
ospf6_lsa_lock (lsa);
|
||||
|
||||
if (old)
|
||||
if (!old)
|
||||
{
|
||||
if (old->prev)
|
||||
old->prev->next = lsa;
|
||||
if (old->next)
|
||||
old->next->prev = lsa;
|
||||
lsa->next = old->next;
|
||||
lsa->prev = old->prev;
|
||||
lsdb->count++;
|
||||
|
||||
if (OSPF6_LSA_IS_MAXAGE (lsa))
|
||||
{
|
||||
if (lsdb->hook_remove)
|
||||
(*lsdb->hook_remove) (lsa);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lsdb->hook_add)
|
||||
(*lsdb->hook_add) (lsa);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* next link */
|
||||
nextnode = current;
|
||||
route_lock_node (nextnode);
|
||||
do {
|
||||
nextnode = route_next (nextnode);
|
||||
} while (nextnode && nextnode->info == NULL);
|
||||
if (nextnode == NULL)
|
||||
lsa->next = NULL;
|
||||
else
|
||||
{
|
||||
next = nextnode->info;
|
||||
lsa->next = next;
|
||||
next->prev = lsa;
|
||||
route_unlock_node (nextnode);
|
||||
}
|
||||
|
||||
/* prev link */
|
||||
prevnode = current;
|
||||
route_lock_node (prevnode);
|
||||
do {
|
||||
prevnode = route_prev (prevnode);
|
||||
} while (prevnode && prevnode->info == NULL);
|
||||
if (prevnode == NULL)
|
||||
lsa->prev = NULL;
|
||||
else
|
||||
{
|
||||
prev = prevnode->info;
|
||||
lsa->prev = prev;
|
||||
prev->next = lsa;
|
||||
route_unlock_node (prevnode);
|
||||
}
|
||||
|
||||
lsdb->count++;
|
||||
}
|
||||
|
||||
if (old)
|
||||
{
|
||||
if (OSPF6_LSA_IS_CHANGED (old, lsa))
|
||||
{
|
||||
@ -187,20 +160,8 @@ ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
|
||||
(*lsdb->hook_add) (lsa);
|
||||
}
|
||||
}
|
||||
ospf6_lsa_unlock (old);
|
||||
}
|
||||
else if (OSPF6_LSA_IS_MAXAGE (lsa))
|
||||
{
|
||||
if (lsdb->hook_remove)
|
||||
(*lsdb->hook_remove) (lsa);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lsdb->hook_add)
|
||||
(*lsdb->hook_add) (lsa);
|
||||
}
|
||||
|
||||
if (old)
|
||||
ospf6_lsa_unlock (old);
|
||||
|
||||
ospf6_lsdb_count_assert (lsdb);
|
||||
}
|
||||
@ -220,19 +181,15 @@ ospf6_lsdb_remove (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
|
||||
node = route_node_lookup (lsdb->table, (struct prefix *) &key);
|
||||
assert (node && node->info == lsa);
|
||||
|
||||
if (lsa->prev)
|
||||
lsa->prev->next = lsa->next;
|
||||
if (lsa->next)
|
||||
lsa->next->prev = lsa->prev;
|
||||
|
||||
node->info = NULL;
|
||||
lsdb->count--;
|
||||
|
||||
if (lsdb->hook_remove)
|
||||
(*lsdb->hook_remove) (lsa);
|
||||
|
||||
route_unlock_node (node); /* to free the lookup lock */
|
||||
route_unlock_node (node); /* to free the original lock */
|
||||
ospf6_lsa_unlock (lsa);
|
||||
route_unlock_node (node);
|
||||
|
||||
ospf6_lsdb_count_assert (lsdb);
|
||||
}
|
||||
@ -255,6 +212,8 @@ ospf6_lsdb_lookup (u_int16_t type, u_int32_t id, u_int32_t adv_router,
|
||||
node = route_node_lookup (lsdb->table, (struct prefix *) &key);
|
||||
if (node == NULL || node->info == NULL)
|
||||
return NULL;
|
||||
|
||||
route_unlock_node (node);
|
||||
return (struct ospf6_lsa *) node->info;
|
||||
}
|
||||
|
||||
@ -306,21 +265,9 @@ ospf6_lsdb_lookup_next (u_int16_t type, u_int32_t id, u_int32_t adv_router,
|
||||
|
||||
if (prefix_same (&node->p, p))
|
||||
{
|
||||
struct route_node *prev = node;
|
||||
struct ospf6_lsa *lsa_prev;
|
||||
struct ospf6_lsa *lsa_next;
|
||||
|
||||
node = route_next (node);
|
||||
while (node && node->info == NULL)
|
||||
node = route_next (node);
|
||||
|
||||
lsa_prev = prev->info;
|
||||
lsa_next = (node ? node->info : NULL);
|
||||
assert (lsa_prev);
|
||||
assert (lsa_prev->next == lsa_next);
|
||||
if (lsa_next)
|
||||
assert (lsa_next->prev == lsa_prev);
|
||||
zlog_debug ("lsdb_lookup_next: assert OK with previous LSA");
|
||||
}
|
||||
|
||||
if (! node)
|
||||
@ -346,7 +293,6 @@ ospf6_lsdb_head (struct ospf6_lsdb *lsdb)
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
|
||||
route_unlock_node (node);
|
||||
if (node->info)
|
||||
ospf6_lsa_lock ((struct ospf6_lsa *) node->info);
|
||||
return (struct ospf6_lsa *) node->info;
|
||||
@ -355,12 +301,20 @@ ospf6_lsdb_head (struct ospf6_lsdb *lsdb)
|
||||
struct ospf6_lsa *
|
||||
ospf6_lsdb_next (struct ospf6_lsa *lsa)
|
||||
{
|
||||
struct ospf6_lsa *next = lsa->next;
|
||||
struct route_node *node = lsa->rn;
|
||||
struct ospf6_lsa *next = NULL;
|
||||
|
||||
do {
|
||||
node = route_next (node);
|
||||
} while (node && node->info == NULL);
|
||||
|
||||
if ((node != NULL) && (node->info != NULL))
|
||||
{
|
||||
next = node->info;
|
||||
ospf6_lsa_lock (next);
|
||||
}
|
||||
|
||||
ospf6_lsa_unlock (lsa);
|
||||
if (next)
|
||||
ospf6_lsa_lock (next);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
@ -390,8 +344,6 @@ ospf6_lsdb_type_router_head (u_int16_t type, u_int32_t adv_router,
|
||||
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
else
|
||||
route_unlock_node (node);
|
||||
|
||||
if (! prefix_match ((struct prefix *) &key, &node->p))
|
||||
return NULL;
|
||||
@ -406,18 +358,19 @@ struct ospf6_lsa *
|
||||
ospf6_lsdb_type_router_next (u_int16_t type, u_int32_t adv_router,
|
||||
struct ospf6_lsa *lsa)
|
||||
{
|
||||
struct ospf6_lsa *next = lsa->next;
|
||||
struct ospf6_lsa *next = ospf6_lsdb_next(lsa);
|
||||
|
||||
if (next)
|
||||
{
|
||||
if (next->header->type != type ||
|
||||
next->header->adv_router != adv_router)
|
||||
next = NULL;
|
||||
{
|
||||
route_unlock_node (next->rn);
|
||||
ospf6_lsa_unlock (next);
|
||||
next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (next)
|
||||
ospf6_lsa_lock (next);
|
||||
ospf6_lsa_unlock (lsa);
|
||||
return next;
|
||||
}
|
||||
|
||||
@ -444,8 +397,6 @@ ospf6_lsdb_type_head (u_int16_t type, struct ospf6_lsdb *lsdb)
|
||||
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
else
|
||||
route_unlock_node (node);
|
||||
|
||||
if (! prefix_match ((struct prefix *) &key, &node->p))
|
||||
return NULL;
|
||||
@ -459,17 +410,18 @@ ospf6_lsdb_type_head (u_int16_t type, struct ospf6_lsdb *lsdb)
|
||||
struct ospf6_lsa *
|
||||
ospf6_lsdb_type_next (u_int16_t type, struct ospf6_lsa *lsa)
|
||||
{
|
||||
struct ospf6_lsa *next = lsa->next;
|
||||
struct ospf6_lsa *next = ospf6_lsdb_next (lsa);
|
||||
|
||||
if (next)
|
||||
{
|
||||
if (next->header->type != type)
|
||||
next = NULL;
|
||||
{
|
||||
route_unlock_node (next->rn);
|
||||
ospf6_lsa_unlock (next);
|
||||
next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (next)
|
||||
ospf6_lsa_lock (next);
|
||||
ospf6_lsa_unlock (lsa);
|
||||
return next;
|
||||
}
|
||||
|
||||
@ -477,10 +429,61 @@ void
|
||||
ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
struct ospf6_lsa *lsa;
|
||||
|
||||
if (lsdb == NULL)
|
||||
return;
|
||||
|
||||
for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa))
|
||||
ospf6_lsdb_remove (lsa, lsdb);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_lsdb_lsa_unlock (struct ospf6_lsa *lsa)
|
||||
{
|
||||
if (lsa != NULL)
|
||||
{
|
||||
if (lsa->rn != NULL)
|
||||
route_unlock_node (lsa->rn);
|
||||
ospf6_lsa_unlock (lsa);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ospf6_lsdb_maxage_remover (struct ospf6_lsdb *lsdb)
|
||||
{
|
||||
int reschedule = 0;
|
||||
struct ospf6_lsa *lsa;
|
||||
|
||||
for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa))
|
||||
{
|
||||
if (! OSPF6_LSA_IS_MAXAGE (lsa))
|
||||
continue;
|
||||
if (lsa->retrans_count != 0)
|
||||
{
|
||||
reschedule = 1;
|
||||
continue;
|
||||
}
|
||||
if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type))
|
||||
zlog_debug ("Remove MaxAge %s", lsa->name);
|
||||
if (CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED))
|
||||
{
|
||||
UNSET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED);
|
||||
/*
|
||||
* lsa->header->age = 0;
|
||||
*/
|
||||
lsa->header->seqnum = htonl(OSPF_MAX_SEQUENCE_NUMBER + 1);
|
||||
ospf6_lsa_checksum (lsa->header);
|
||||
|
||||
THREAD_OFF(lsa->refresh);
|
||||
thread_execute (master, ospf6_lsa_refresh, lsa, 0);
|
||||
} else {
|
||||
ospf6_lsdb_remove (lsa, lsdb);
|
||||
}
|
||||
}
|
||||
|
||||
return (reschedule);
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_lsdb_show (struct vty *vty, int level,
|
||||
u_int16_t *type, u_int32_t *id, u_int32_t *adv_router,
|
||||
@ -551,7 +554,7 @@ ospf6_new_ls_id (u_int16_t type, u_int32_t adv_router,
|
||||
continue;
|
||||
if (ntohl (lsa->header->id) > id)
|
||||
{
|
||||
ospf6_lsa_unlock (lsa);
|
||||
ospf6_lsdb_lsa_unlock (lsa);
|
||||
break;
|
||||
}
|
||||
id++;
|
||||
@ -572,7 +575,7 @@ ospf6_new_ls_seqnum (u_int16_t type, u_int32_t id, u_int32_t adv_router,
|
||||
/* if current database copy not found, return InitialSequenceNumber */
|
||||
lsa = ospf6_lsdb_lookup (type, id, adv_router, lsdb);
|
||||
if (lsa == NULL)
|
||||
seqnum = INITIAL_SEQUENCE_NUMBER;
|
||||
seqnum = OSPF_INITIAL_SEQUENCE_NUMBER;
|
||||
else
|
||||
seqnum = (signed long) ntohl (lsa->header->seqnum) + 1;
|
||||
|
||||
|
@ -34,21 +34,6 @@ struct ospf6_lsdb
|
||||
void (*hook_remove) (struct ospf6_lsa *);
|
||||
};
|
||||
|
||||
#define OSPF6_LSDB_MAXAGE_REMOVER(lsdb) \
|
||||
do { \
|
||||
struct ospf6_lsa *lsa; \
|
||||
for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa)) \
|
||||
{ \
|
||||
if (! OSPF6_LSA_IS_MAXAGE (lsa)) \
|
||||
continue; \
|
||||
if (lsa->retrans_count != 0) \
|
||||
continue; \
|
||||
if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type)) \
|
||||
zlog_debug ("Remove MaxAge %s", lsa->name); \
|
||||
ospf6_lsdb_remove (lsa, lsdb); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Function Prototypes */
|
||||
extern struct ospf6_lsdb *ospf6_lsdb_create (void *data);
|
||||
extern void ospf6_lsdb_delete (struct ospf6_lsdb *lsdb);
|
||||
@ -79,6 +64,7 @@ extern struct ospf6_lsa *ospf6_lsdb_type_next (u_int16_t type,
|
||||
struct ospf6_lsa *lsa);
|
||||
|
||||
extern void ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb);
|
||||
extern void ospf6_lsdb_lsa_unlock (struct ospf6_lsa *lsa);
|
||||
|
||||
#define OSPF6_LSDB_SHOW_LEVEL_NORMAL 0
|
||||
#define OSPF6_LSDB_SHOW_LEVEL_DETAIL 1
|
||||
@ -94,5 +80,6 @@ extern u_int32_t ospf6_new_ls_id (u_int16_t type, u_int32_t adv_router,
|
||||
extern u_int32_t ospf6_new_ls_seqnum (u_int16_t type, u_int32_t id,
|
||||
u_int32_t adv_router,
|
||||
struct ospf6_lsdb *lsdb);
|
||||
extern int ospf6_lsdb_maxage_remover (struct ospf6_lsdb *lsdb);
|
||||
|
||||
#endif /* OSPF6_LSDB_H */
|
||||
|
@ -41,6 +41,8 @@
|
||||
#include "ospf6_message.h"
|
||||
#include "ospf6_asbr.h"
|
||||
#include "ospf6_lsa.h"
|
||||
#include "ospf6_interface.h"
|
||||
#include "ospf6_zebra.h"
|
||||
|
||||
/* Default configuration file name for ospf6d. */
|
||||
#define OSPF6_DEFAULT_CONFIG "ospf6d.conf"
|
||||
@ -134,12 +136,16 @@ Report bugs to %s\n", progname, ZEBRA_BUG_ADDRESS);
|
||||
static void __attribute__ ((noreturn))
|
||||
ospf6_exit (int status)
|
||||
{
|
||||
extern struct ospf6 *ospf6;
|
||||
extern struct zclient *zclient;
|
||||
struct listnode *node;
|
||||
struct interface *ifp;
|
||||
|
||||
if (ospf6)
|
||||
ospf6_delete (ospf6);
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp))
|
||||
if (ifp->info != NULL)
|
||||
ospf6_interface_delete(ifp->info);
|
||||
|
||||
ospf6_message_terminate ();
|
||||
ospf6_asbr_terminate ();
|
||||
ospf6_lsa_terminate ();
|
||||
|
@ -517,20 +517,20 @@ ospf6_dbdesc_recv_master (struct ospf6_header *oh,
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
|
||||
zlog_debug ("Add request (No database copy)");
|
||||
ospf6_lsdb_add (his, on->request_list);
|
||||
ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
|
||||
}
|
||||
else if (ospf6_lsa_compare (his, mine) < 0)
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
|
||||
zlog_debug ("Add request (Received MoreRecent)");
|
||||
ospf6_lsdb_add (his, on->request_list);
|
||||
ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
|
||||
zlog_debug ("Discard (Existing MoreRecent)");
|
||||
ospf6_lsa_delete (his);
|
||||
}
|
||||
ospf6_lsa_delete (his);
|
||||
}
|
||||
|
||||
assert (p == OSPF6_MESSAGE_END (oh));
|
||||
@ -539,7 +539,7 @@ ospf6_dbdesc_recv_master (struct ospf6_header *oh,
|
||||
on->dbdesc_seqnum ++;
|
||||
|
||||
/* schedule send lsreq */
|
||||
if (on->thread_send_lsreq == NULL)
|
||||
if (on->request_list->count && (on->thread_send_lsreq == NULL))
|
||||
on->thread_send_lsreq =
|
||||
thread_add_event (master, ospf6_lsreq_send, on, 0);
|
||||
|
||||
@ -735,10 +735,9 @@ ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
|
||||
zlog_debug ("Add request-list: %s", his->name);
|
||||
ospf6_lsdb_add (his, on->request_list);
|
||||
ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
|
||||
}
|
||||
else
|
||||
ospf6_lsa_delete (his);
|
||||
ospf6_lsa_delete (his);
|
||||
}
|
||||
|
||||
assert (p == OSPF6_MESSAGE_END (oh));
|
||||
@ -747,7 +746,8 @@ ospf6_dbdesc_recv_slave (struct ospf6_header *oh,
|
||||
on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
|
||||
|
||||
/* schedule send lsreq */
|
||||
if (on->thread_send_lsreq == NULL)
|
||||
if ((on->thread_send_lsreq == NULL) &&
|
||||
(on->request_list->count))
|
||||
on->thread_send_lsreq =
|
||||
thread_add_event (master, ospf6_lsreq_send, on, 0);
|
||||
|
||||
@ -1282,7 +1282,7 @@ ospf6_rxpacket_examin (struct ospf6_interface *oi, struct ospf6_header *oh, cons
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
|
||||
{
|
||||
if (oh->area_id == BACKBONE_AREA_ID)
|
||||
if (oh->area_id == OSPF_AREA_BACKBONE)
|
||||
zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__);
|
||||
else
|
||||
zlog_debug
|
||||
@ -1351,19 +1351,6 @@ ospf6_lsupdate_recv (struct in6_addr *src, struct in6_addr *dst,
|
||||
|
||||
assert (p == OSPF6_MESSAGE_END (oh));
|
||||
|
||||
/* RFC2328 Section 10.9: When the neighbor responds to these requests
|
||||
with the proper Link State Update packet(s), the Link state request
|
||||
list is truncated and a new Link State Request packet is sent. */
|
||||
/* send new Link State Request packet if this LS Update packet
|
||||
can be recognized as a response to our previous LS Request */
|
||||
if (! IN6_IS_ADDR_MULTICAST (dst) &&
|
||||
(on->state == OSPF6_NEIGHBOR_EXCHANGE ||
|
||||
on->state == OSPF6_NEIGHBOR_LOADING))
|
||||
{
|
||||
THREAD_OFF (on->thread_send_lsreq);
|
||||
on->thread_send_lsreq =
|
||||
thread_add_event (master, ospf6_lsreq_send, on, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1556,7 +1543,7 @@ ospf6_receive (struct thread *thread)
|
||||
}
|
||||
|
||||
oi = ospf6_interface_lookup_by_ifindex (ifindex);
|
||||
if (oi == NULL || oi->area == NULL)
|
||||
if (oi == NULL || oi->area == NULL || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
|
||||
{
|
||||
zlog_debug ("Message received on disabled interface");
|
||||
return 0;
|
||||
@ -1785,6 +1772,7 @@ ospf6_dbdesc_send (struct thread *thread)
|
||||
struct ospf6_dbdesc *dbdesc;
|
||||
u_char *p;
|
||||
struct ospf6_lsa *lsa;
|
||||
struct in6_addr *dst;
|
||||
|
||||
on = (struct ospf6_neighbor *) THREAD_ARG (thread);
|
||||
on->thread_send_dbdesc = (struct thread *) NULL;
|
||||
@ -1809,7 +1797,8 @@ ospf6_dbdesc_send (struct thread *thread)
|
||||
sizeof (struct ospf6_header));
|
||||
|
||||
/* if this is initial one, initialize sequence number for DbDesc */
|
||||
if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
|
||||
if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT) &&
|
||||
(on->dbdesc_seqnum == 0))
|
||||
{
|
||||
struct timeval tv;
|
||||
if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
|
||||
@ -1837,7 +1826,7 @@ ospf6_dbdesc_send (struct thread *thread)
|
||||
if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
|
||||
ospf6_packet_max(on->ospf6_if))
|
||||
{
|
||||
ospf6_lsa_unlock (lsa);
|
||||
ospf6_lsdb_lsa_unlock (lsa);
|
||||
break;
|
||||
}
|
||||
memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
|
||||
@ -1848,8 +1837,14 @@ ospf6_dbdesc_send (struct thread *thread)
|
||||
oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
|
||||
oh->length = htons (p - sendbuf);
|
||||
|
||||
ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
|
||||
on->ospf6_if, oh);
|
||||
|
||||
if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
|
||||
dst = &allspfrouters6;
|
||||
else
|
||||
dst = &on->linklocal_addr;
|
||||
|
||||
ospf6_send (on->ospf6_if->linklocal_addr, dst, on->ospf6_if, oh);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1871,7 +1866,7 @@ ospf6_dbdesc_send_newone (struct thread *thread)
|
||||
{
|
||||
if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
|
||||
{
|
||||
ospf6_lsa_unlock (lsa);
|
||||
ospf6_lsdb_lsa_unlock (lsa);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1900,7 +1895,7 @@ ospf6_lsreq_send (struct thread *thread)
|
||||
struct ospf6_header *oh;
|
||||
struct ospf6_lsreq_entry *e;
|
||||
u_char *p;
|
||||
struct ospf6_lsa *lsa;
|
||||
struct ospf6_lsa *lsa, *last_req;
|
||||
|
||||
on = (struct ospf6_neighbor *) THREAD_ARG (thread);
|
||||
on->thread_send_lsreq = (struct thread *) NULL;
|
||||
@ -1922,13 +1917,9 @@ ospf6_lsreq_send (struct thread *thread)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set next thread */
|
||||
on->thread_send_lsreq =
|
||||
thread_add_timer (master, ospf6_lsreq_send, on,
|
||||
on->ospf6_if->rxmt_interval);
|
||||
|
||||
memset (sendbuf, 0, iobuflen);
|
||||
oh = (struct ospf6_header *) sendbuf;
|
||||
last_req = NULL;
|
||||
|
||||
/* set Request entries in lsreq */
|
||||
p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
|
||||
@ -1938,7 +1929,7 @@ ospf6_lsreq_send (struct thread *thread)
|
||||
/* MTU check */
|
||||
if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
|
||||
{
|
||||
ospf6_lsa_unlock (lsa);
|
||||
ospf6_lsdb_lsa_unlock (lsa);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1947,13 +1938,37 @@ ospf6_lsreq_send (struct thread *thread)
|
||||
e->id = lsa->header->id;
|
||||
e->adv_router = lsa->header->adv_router;
|
||||
p += sizeof (struct ospf6_lsreq_entry);
|
||||
last_req = lsa;
|
||||
}
|
||||
|
||||
if (last_req != NULL)
|
||||
{
|
||||
if (on->last_ls_req != NULL)
|
||||
{
|
||||
ospf6_lsa_unlock (on->last_ls_req);
|
||||
}
|
||||
ospf6_lsa_lock (last_req);
|
||||
on->last_ls_req = last_req;
|
||||
}
|
||||
|
||||
oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
|
||||
oh->length = htons (p - sendbuf);
|
||||
|
||||
ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
|
||||
if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
|
||||
ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
|
||||
on->ospf6_if, oh);
|
||||
else
|
||||
ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
|
||||
on->ospf6_if, oh);
|
||||
|
||||
/* set next thread */
|
||||
if (on->request_list->count != 0)
|
||||
{
|
||||
on->thread_send_lsreq =
|
||||
thread_add_timer (master, ospf6_lsreq_send, on,
|
||||
on->ospf6_if->rxmt_interval);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1964,7 +1979,7 @@ ospf6_lsupdate_send_neighbor (struct thread *thread)
|
||||
struct ospf6_header *oh;
|
||||
struct ospf6_lsupdate *lsupdate;
|
||||
u_char *p;
|
||||
int num;
|
||||
int lsa_cnt;
|
||||
struct ospf6_lsa *lsa;
|
||||
|
||||
on = (struct ospf6_neighbor *) THREAD_ARG (thread);
|
||||
@ -1981,22 +1996,13 @@ ospf6_lsupdate_send_neighbor (struct thread *thread)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if we have nothing to send, return */
|
||||
if (on->lsupdate_list->count == 0 &&
|
||||
on->retrans_list->count == 0)
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
|
||||
zlog_debug ("Quit to send (nothing to send)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset (sendbuf, 0, iobuflen);
|
||||
oh = (struct ospf6_header *) sendbuf;
|
||||
lsupdate = (struct ospf6_lsupdate *)
|
||||
((caddr_t) oh + sizeof (struct ospf6_header));
|
||||
|
||||
p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
|
||||
num = 0;
|
||||
lsa_cnt = 0;
|
||||
|
||||
/* lsupdate_list lists those LSA which doesn't need to be
|
||||
retransmitted. remove those from the list */
|
||||
@ -2005,58 +2011,85 @@ ospf6_lsupdate_send_neighbor (struct thread *thread)
|
||||
{
|
||||
/* MTU check */
|
||||
if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
|
||||
> ospf6_packet_max(on->ospf6_if))
|
||||
{
|
||||
ospf6_lsa_unlock (lsa);
|
||||
break;
|
||||
}
|
||||
> ospf6_packet_max(on->ospf6_if))
|
||||
{
|
||||
ospf6_lsdb_lsa_unlock (lsa);
|
||||
break;
|
||||
}
|
||||
|
||||
ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
|
||||
memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
|
||||
p += OSPF6_LSA_SIZE (lsa->header);
|
||||
num++;
|
||||
lsa_cnt++;
|
||||
|
||||
assert (lsa->lock == 2);
|
||||
ospf6_lsdb_remove (lsa, on->lsupdate_list);
|
||||
}
|
||||
|
||||
if (lsa_cnt)
|
||||
{
|
||||
oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
|
||||
oh->length = htons (p - sendbuf);
|
||||
lsupdate->lsa_number = htonl (lsa_cnt);
|
||||
|
||||
if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) ||
|
||||
(on->ospf6_if->state == OSPF6_INTERFACE_DR) ||
|
||||
(on->ospf6_if->state == OSPF6_INTERFACE_BDR))
|
||||
ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
|
||||
on->ospf6_if, oh);
|
||||
else
|
||||
ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
|
||||
on->ospf6_if, oh);
|
||||
}
|
||||
|
||||
/* The addresses used for retransmissions are different from those sent the
|
||||
first time and so we need to separate them here.
|
||||
*/
|
||||
memset (sendbuf, 0, iobuflen);
|
||||
oh = (struct ospf6_header *) sendbuf;
|
||||
lsupdate = (struct ospf6_lsupdate *)
|
||||
((caddr_t) oh + sizeof (struct ospf6_header));
|
||||
p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
|
||||
lsa_cnt = 0;
|
||||
|
||||
for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
|
||||
lsa = ospf6_lsdb_next (lsa))
|
||||
{
|
||||
/* MTU check */
|
||||
if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
|
||||
> ospf6_packet_max(on->ospf6_if))
|
||||
{
|
||||
ospf6_lsa_unlock (lsa);
|
||||
break;
|
||||
}
|
||||
> ospf6_packet_max(on->ospf6_if))
|
||||
{
|
||||
ospf6_lsdb_lsa_unlock (lsa);
|
||||
break;
|
||||
}
|
||||
|
||||
ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
|
||||
memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
|
||||
p += OSPF6_LSA_SIZE (lsa->header);
|
||||
num++;
|
||||
lsa_cnt++;
|
||||
}
|
||||
|
||||
lsupdate->lsa_number = htonl (num);
|
||||
|
||||
oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
|
||||
oh->length = htons (p - sendbuf);
|
||||
|
||||
ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
|
||||
on->ospf6_if, oh);
|
||||
|
||||
if (on->lsupdate_list->count != 0 ||
|
||||
on->retrans_list->count != 0)
|
||||
if (lsa_cnt)
|
||||
{
|
||||
if (on->lsupdate_list->count != 0)
|
||||
on->thread_send_lsupdate =
|
||||
thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
|
||||
oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
|
||||
oh->length = htons (p - sendbuf);
|
||||
lsupdate->lsa_number = htonl (lsa_cnt);
|
||||
|
||||
if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
|
||||
ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
|
||||
on->ospf6_if, oh);
|
||||
else
|
||||
on->thread_send_lsupdate =
|
||||
thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
|
||||
on->ospf6_if->rxmt_interval);
|
||||
ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
|
||||
on->ospf6_if, oh);
|
||||
}
|
||||
|
||||
if (on->lsupdate_list->count != 0)
|
||||
on->thread_send_lsupdate =
|
||||
thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
|
||||
else if (on->retrans_list->count != 0)
|
||||
on->thread_send_lsupdate =
|
||||
thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
|
||||
on->ospf6_if->rxmt_interval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2067,7 +2100,7 @@ ospf6_lsupdate_send_interface (struct thread *thread)
|
||||
struct ospf6_header *oh;
|
||||
struct ospf6_lsupdate *lsupdate;
|
||||
u_char *p;
|
||||
int num;
|
||||
int lsa_cnt;
|
||||
struct ospf6_lsa *lsa;
|
||||
|
||||
oi = (struct ospf6_interface *) THREAD_ARG (thread);
|
||||
@ -2088,41 +2121,46 @@ ospf6_lsupdate_send_interface (struct thread *thread)
|
||||
memset (sendbuf, 0, iobuflen);
|
||||
oh = (struct ospf6_header *) sendbuf;
|
||||
lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
|
||||
sizeof (struct ospf6_header));
|
||||
sizeof (struct ospf6_header));
|
||||
|
||||
p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
|
||||
num = 0;
|
||||
lsa_cnt = 0;
|
||||
|
||||
for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
|
||||
lsa = ospf6_lsdb_next (lsa))
|
||||
{
|
||||
/* MTU check */
|
||||
if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
|
||||
> ospf6_packet_max(oi))
|
||||
{
|
||||
ospf6_lsa_unlock (lsa);
|
||||
break;
|
||||
}
|
||||
> ospf6_packet_max(oi))
|
||||
{
|
||||
ospf6_lsdb_lsa_unlock (lsa);
|
||||
break;
|
||||
}
|
||||
|
||||
ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
|
||||
memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
|
||||
p += OSPF6_LSA_SIZE (lsa->header);
|
||||
num++;
|
||||
lsa_cnt++;
|
||||
|
||||
assert (lsa->lock == 2);
|
||||
ospf6_lsdb_remove (lsa, oi->lsupdate_list);
|
||||
}
|
||||
|
||||
lsupdate->lsa_number = htonl (num);
|
||||
if (lsa_cnt)
|
||||
{
|
||||
lsupdate->lsa_number = htonl (lsa_cnt);
|
||||
|
||||
oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
|
||||
oh->length = htons (p - sendbuf);
|
||||
oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
|
||||
oh->length = htons (p - sendbuf);
|
||||
|
||||
if (oi->state == OSPF6_INTERFACE_DR ||
|
||||
oi->state == OSPF6_INTERFACE_BDR)
|
||||
ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
|
||||
else
|
||||
ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
|
||||
if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
|
||||
(oi->state == OSPF6_INTERFACE_DR) ||
|
||||
(oi->state == OSPF6_INTERFACE_BDR))
|
||||
ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
|
||||
else
|
||||
ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
|
||||
|
||||
}
|
||||
|
||||
if (oi->lsupdate_list->count > 0)
|
||||
{
|
||||
@ -2140,6 +2178,7 @@ ospf6_lsack_send_neighbor (struct thread *thread)
|
||||
struct ospf6_header *oh;
|
||||
u_char *p;
|
||||
struct ospf6_lsa *lsa;
|
||||
int lsa_cnt = 0;
|
||||
|
||||
on = (struct ospf6_neighbor *) THREAD_ARG (thread);
|
||||
on->thread_send_lsack = (struct thread *) NULL;
|
||||
@ -2166,16 +2205,16 @@ ospf6_lsack_send_neighbor (struct thread *thread)
|
||||
{
|
||||
/* MTU check */
|
||||
if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
|
||||
{
|
||||
/* if we run out of packet size/space here,
|
||||
better to try again soon. */
|
||||
THREAD_OFF (on->thread_send_lsack);
|
||||
on->thread_send_lsack =
|
||||
thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
|
||||
{
|
||||
/* if we run out of packet size/space here,
|
||||
better to try again soon. */
|
||||
THREAD_OFF (on->thread_send_lsack);
|
||||
on->thread_send_lsack =
|
||||
thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
|
||||
|
||||
ospf6_lsa_unlock (lsa);
|
||||
break;
|
||||
}
|
||||
ospf6_lsdb_lsa_unlock (lsa);
|
||||
break;
|
||||
}
|
||||
|
||||
ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
|
||||
memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
|
||||
@ -2183,13 +2222,24 @@ ospf6_lsack_send_neighbor (struct thread *thread)
|
||||
|
||||
assert (lsa->lock == 2);
|
||||
ospf6_lsdb_remove (lsa, on->lsack_list);
|
||||
lsa_cnt++;
|
||||
}
|
||||
|
||||
oh->type = OSPF6_MESSAGE_TYPE_LSACK;
|
||||
oh->length = htons (p - sendbuf);
|
||||
if (lsa_cnt)
|
||||
{
|
||||
oh->type = OSPF6_MESSAGE_TYPE_LSACK;
|
||||
oh->length = htons (p - sendbuf);
|
||||
|
||||
ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
|
||||
on->ospf6_if, oh);
|
||||
}
|
||||
|
||||
if (on->thread_send_lsack == NULL && on->lsack_list->count > 0)
|
||||
{
|
||||
on->thread_send_lsack =
|
||||
thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
|
||||
}
|
||||
|
||||
ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
|
||||
on->ospf6_if, oh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2200,6 +2250,7 @@ ospf6_lsack_send_interface (struct thread *thread)
|
||||
struct ospf6_header *oh;
|
||||
u_char *p;
|
||||
struct ospf6_lsa *lsa;
|
||||
int lsa_cnt = 0;
|
||||
|
||||
oi = (struct ospf6_interface *) THREAD_ARG (thread);
|
||||
oi->thread_send_lsack = (struct thread *) NULL;
|
||||
@ -2226,16 +2277,16 @@ ospf6_lsack_send_interface (struct thread *thread)
|
||||
{
|
||||
/* MTU check */
|
||||
if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
|
||||
{
|
||||
/* if we run out of packet size/space here,
|
||||
better to try again soon. */
|
||||
THREAD_OFF (oi->thread_send_lsack);
|
||||
oi->thread_send_lsack =
|
||||
thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
|
||||
{
|
||||
/* if we run out of packet size/space here,
|
||||
better to try again soon. */
|
||||
THREAD_OFF (oi->thread_send_lsack);
|
||||
oi->thread_send_lsack =
|
||||
thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
|
||||
|
||||
ospf6_lsa_unlock (lsa);
|
||||
break;
|
||||
}
|
||||
ospf6_lsdb_lsa_unlock (lsa);
|
||||
break;
|
||||
}
|
||||
|
||||
ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
|
||||
memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
|
||||
@ -2243,16 +2294,21 @@ ospf6_lsack_send_interface (struct thread *thread)
|
||||
|
||||
assert (lsa->lock == 2);
|
||||
ospf6_lsdb_remove (lsa, oi->lsack_list);
|
||||
lsa_cnt++;
|
||||
}
|
||||
|
||||
oh->type = OSPF6_MESSAGE_TYPE_LSACK;
|
||||
oh->length = htons (p - sendbuf);
|
||||
if (lsa_cnt)
|
||||
{
|
||||
oh->type = OSPF6_MESSAGE_TYPE_LSACK;
|
||||
oh->length = htons (p - sendbuf);
|
||||
|
||||
if (oi->state == OSPF6_INTERFACE_DR ||
|
||||
oi->state == OSPF6_INTERFACE_BDR)
|
||||
ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
|
||||
else
|
||||
ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
|
||||
if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
|
||||
(oi->state == OSPF6_INTERFACE_DR) ||
|
||||
(oi->state == OSPF6_INTERFACE_BDR))
|
||||
ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
|
||||
else
|
||||
ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
|
||||
}
|
||||
|
||||
if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
|
||||
{
|
||||
|
@ -98,7 +98,6 @@ ospf6_neighbor_create (u_int32_t router_id, struct ospf6_interface *oi)
|
||||
on->retrans_list = ospf6_lsdb_create (on);
|
||||
|
||||
on->dbdesc_list = ospf6_lsdb_create (on);
|
||||
on->lsreq_list = ospf6_lsdb_create (on);
|
||||
on->lsupdate_list = ospf6_lsdb_create (on);
|
||||
on->lsack_list = ospf6_lsdb_create (on);
|
||||
|
||||
@ -121,7 +120,6 @@ ospf6_neighbor_delete (struct ospf6_neighbor *on)
|
||||
}
|
||||
|
||||
ospf6_lsdb_remove_all (on->dbdesc_list);
|
||||
ospf6_lsdb_remove_all (on->lsreq_list);
|
||||
ospf6_lsdb_remove_all (on->lsupdate_list);
|
||||
ospf6_lsdb_remove_all (on->lsack_list);
|
||||
|
||||
@ -130,7 +128,6 @@ ospf6_neighbor_delete (struct ospf6_neighbor *on)
|
||||
ospf6_lsdb_delete (on->retrans_list);
|
||||
|
||||
ospf6_lsdb_delete (on->dbdesc_list);
|
||||
ospf6_lsdb_delete (on->lsreq_list);
|
||||
ospf6_lsdb_delete (on->lsupdate_list);
|
||||
ospf6_lsdb_delete (on->lsack_list);
|
||||
|
||||
@ -145,7 +142,7 @@ ospf6_neighbor_delete (struct ospf6_neighbor *on)
|
||||
}
|
||||
|
||||
static void
|
||||
ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on)
|
||||
ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on, int event)
|
||||
{
|
||||
u_char prev_state;
|
||||
|
||||
@ -161,11 +158,23 @@ ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on)
|
||||
/* log */
|
||||
if (IS_OSPF6_DEBUG_NEIGHBOR (STATE))
|
||||
{
|
||||
zlog_debug ("Neighbor state change %s: [%s]->[%s]", on->name,
|
||||
zlog_debug ("Neighbor state change %s: [%s]->[%s] (%s)", on->name,
|
||||
ospf6_neighbor_state_str[prev_state],
|
||||
ospf6_neighbor_state_str[next_state]);
|
||||
ospf6_neighbor_state_str[next_state],
|
||||
ospf6_neighbor_event_string(event));
|
||||
}
|
||||
|
||||
/* Optionally notify about adjacency changes */
|
||||
if (CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags,
|
||||
OSPF6_LOG_ADJACENCY_CHANGES) &&
|
||||
(CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags,
|
||||
OSPF6_LOG_ADJACENCY_DETAIL) ||
|
||||
(next_state == OSPF6_NEIGHBOR_FULL) || (next_state < prev_state)))
|
||||
zlog_notice("AdjChg: Nbr %s: %s -> %s (%s)", on->name,
|
||||
ospf6_neighbor_state_str[prev_state],
|
||||
ospf6_neighbor_state_str[next_state],
|
||||
ospf6_neighbor_event_string(event));
|
||||
|
||||
if (prev_state == OSPF6_NEIGHBOR_FULL || next_state == OSPF6_NEIGHBOR_FULL)
|
||||
{
|
||||
OSPF6_ROUTER_LSA_SCHEDULE (on->ospf6_if->area);
|
||||
@ -226,7 +235,8 @@ hello_received (struct thread *thread)
|
||||
on->ospf6_if->dead_interval);
|
||||
|
||||
if (on->state <= OSPF6_NEIGHBOR_DOWN)
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_INIT, on);
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_INIT, on,
|
||||
OSPF6_NEIGHBOR_EVENT_HELLO_RCVD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -249,11 +259,13 @@ twoway_received (struct thread *thread)
|
||||
|
||||
if (! need_adjacency (on))
|
||||
{
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on);
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on,
|
||||
OSPF6_NEIGHBOR_EVENT_TWOWAY_RCVD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on);
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on,
|
||||
OSPF6_NEIGHBOR_EVENT_TWOWAY_RCVD);
|
||||
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
|
||||
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
|
||||
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
|
||||
@ -330,7 +342,8 @@ negotiation_done (struct thread *thread)
|
||||
}
|
||||
|
||||
UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXCHANGE, on);
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXCHANGE, on,
|
||||
OSPF6_NEIGHBOR_EVENT_NEGOTIATION_DONE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -358,13 +371,45 @@ exchange_done (struct thread *thread)
|
||||
*/
|
||||
|
||||
if (on->request_list->count == 0)
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_FULL, on);
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_FULL, on,
|
||||
OSPF6_NEIGHBOR_EVENT_EXCHANGE_DONE);
|
||||
else
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_LOADING, on);
|
||||
{
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_LOADING, on,
|
||||
OSPF6_NEIGHBOR_EVENT_EXCHANGE_DONE);
|
||||
|
||||
if (on->thread_send_lsreq == NULL)
|
||||
on->thread_send_lsreq =
|
||||
thread_add_event (master, ospf6_lsreq_send, on, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check loading state. */
|
||||
void
|
||||
ospf6_check_nbr_loading (struct ospf6_neighbor *on)
|
||||
{
|
||||
|
||||
/* RFC2328 Section 10.9: When the neighbor responds to these requests
|
||||
with the proper Link State Update packet(s), the Link state request
|
||||
list is truncated and a new Link State Request packet is sent.
|
||||
*/
|
||||
if ((on->state == OSPF6_NEIGHBOR_LOADING) ||
|
||||
(on->state == OSPF6_NEIGHBOR_EXCHANGE))
|
||||
{
|
||||
if (on->request_list->count == 0)
|
||||
thread_add_event (master, loading_done, on, 0);
|
||||
else if (on->last_ls_req == NULL)
|
||||
{
|
||||
if (on->thread_send_lsreq != NULL)
|
||||
THREAD_OFF (on->thread_send_lsreq);
|
||||
on->thread_send_lsreq =
|
||||
thread_add_event (master, ospf6_lsreq_send, on, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
loading_done (struct thread *thread)
|
||||
{
|
||||
@ -381,7 +426,8 @@ loading_done (struct thread *thread)
|
||||
|
||||
assert (on->request_list->count == 0);
|
||||
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_FULL, on);
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_FULL, on,
|
||||
OSPF6_NEIGHBOR_EVENT_LOADING_DONE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -400,7 +446,8 @@ adj_ok (struct thread *thread)
|
||||
|
||||
if (on->state == OSPF6_NEIGHBOR_TWOWAY && need_adjacency (on))
|
||||
{
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on);
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on,
|
||||
OSPF6_NEIGHBOR_EVENT_ADJ_OK);
|
||||
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
|
||||
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
|
||||
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
|
||||
@ -413,7 +460,8 @@ adj_ok (struct thread *thread)
|
||||
else if (on->state >= OSPF6_NEIGHBOR_EXSTART &&
|
||||
! need_adjacency (on))
|
||||
{
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on);
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on,
|
||||
OSPF6_NEIGHBOR_EVENT_ADJ_OK);
|
||||
ospf6_lsdb_remove_all (on->summary_list);
|
||||
ospf6_lsdb_remove_all (on->request_list);
|
||||
for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
|
||||
@ -442,7 +490,8 @@ seqnumber_mismatch (struct thread *thread)
|
||||
if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
|
||||
zlog_debug ("Neighbor Event %s: *SeqNumberMismatch*", on->name);
|
||||
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on);
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on,
|
||||
OSPF6_NEIGHBOR_EVENT_SEQNUMBER_MISMATCH);
|
||||
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
|
||||
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
|
||||
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
|
||||
@ -457,6 +506,8 @@ seqnumber_mismatch (struct thread *thread)
|
||||
}
|
||||
|
||||
THREAD_OFF (on->thread_send_dbdesc);
|
||||
on->dbdesc_seqnum++; /* Incr seqnum as per RFC2328, sec 10.3 */
|
||||
|
||||
on->thread_send_dbdesc =
|
||||
thread_add_event (master, ospf6_dbdesc_send, on, 0);
|
||||
|
||||
@ -478,7 +529,8 @@ bad_lsreq (struct thread *thread)
|
||||
if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
|
||||
zlog_debug ("Neighbor Event %s: *BadLSReq*", on->name);
|
||||
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on);
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on,
|
||||
OSPF6_NEIGHBOR_EVENT_BAD_LSREQ);
|
||||
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
|
||||
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
|
||||
SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
|
||||
@ -493,6 +545,8 @@ bad_lsreq (struct thread *thread)
|
||||
}
|
||||
|
||||
THREAD_OFF (on->thread_send_dbdesc);
|
||||
on->dbdesc_seqnum++; /* Incr seqnum as per RFC2328, sec 10.3 */
|
||||
|
||||
on->thread_send_dbdesc =
|
||||
thread_add_event (master, ospf6_dbdesc_send, on, 0);
|
||||
|
||||
@ -514,7 +568,8 @@ oneway_received (struct thread *thread)
|
||||
if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
|
||||
zlog_debug ("Neighbor Event %s: *1Way-Received*", on->name);
|
||||
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_INIT, on);
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_INIT, on,
|
||||
OSPF6_NEIGHBOR_EVENT_ONEWAY_RCVD);
|
||||
thread_add_event (master, neighbor_change, on->ospf6_if, 0);
|
||||
|
||||
ospf6_lsdb_remove_all (on->summary_list);
|
||||
@ -549,7 +604,8 @@ inactivity_timer (struct thread *thread)
|
||||
on->drouter = on->prev_drouter = 0;
|
||||
on->bdrouter = on->prev_bdrouter = 0;
|
||||
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_DOWN, on);
|
||||
ospf6_neighbor_state_change (OSPF6_NEIGHBOR_DOWN, on,
|
||||
OSPF6_NEIGHBOR_EVENT_INACTIVITY_TIMER);
|
||||
thread_add_event (master, neighbor_change, on->ospf6_if, 0);
|
||||
|
||||
listnode_delete (on->ospf6_if->neighbor_list, on);
|
||||
@ -727,10 +783,10 @@ ospf6_neighbor_show_detail (struct vty *vty, struct ospf6_neighbor *on)
|
||||
timersub (&on->thread_send_lsreq->u.sands, &now, &res);
|
||||
timerstring (&res, duration, sizeof (duration));
|
||||
vty_out (vty, " %d Pending LSAs for LSReq in Time %s [thread %s]%s",
|
||||
on->lsreq_list->count, duration,
|
||||
on->request_list->count, duration,
|
||||
(on->thread_send_lsreq ? "on" : "off"),
|
||||
VNL);
|
||||
for (lsa = ospf6_lsdb_head (on->lsreq_list); lsa;
|
||||
for (lsa = ospf6_lsdb_head (on->request_list); lsa;
|
||||
lsa = ospf6_lsdb_next (lsa))
|
||||
vty_out (vty, " %s%s", lsa->name, VNL);
|
||||
|
||||
|
@ -86,6 +86,8 @@ struct ospf6_neighbor
|
||||
struct ospf6_lsdb *lsupdate_list;
|
||||
struct ospf6_lsdb *lsack_list;
|
||||
|
||||
struct ospf6_lsa *last_ls_req;
|
||||
|
||||
/* Inactivity timer */
|
||||
struct thread *inactivity_timer;
|
||||
|
||||
@ -106,6 +108,44 @@ struct ospf6_neighbor
|
||||
#define OSPF6_NEIGHBOR_LOADING 7
|
||||
#define OSPF6_NEIGHBOR_FULL 8
|
||||
|
||||
/* Neighbor Events */
|
||||
#define OSPF6_NEIGHBOR_EVENT_NO_EVENT 0
|
||||
#define OSPF6_NEIGHBOR_EVENT_HELLO_RCVD 1
|
||||
#define OSPF6_NEIGHBOR_EVENT_TWOWAY_RCVD 2
|
||||
#define OSPF6_NEIGHBOR_EVENT_NEGOTIATION_DONE 3
|
||||
#define OSPF6_NEIGHBOR_EVENT_EXCHANGE_DONE 4
|
||||
#define OSPF6_NEIGHBOR_EVENT_LOADING_DONE 5
|
||||
#define OSPF6_NEIGHBOR_EVENT_ADJ_OK 6
|
||||
#define OSPF6_NEIGHBOR_EVENT_SEQNUMBER_MISMATCH 7
|
||||
#define OSPF6_NEIGHBOR_EVENT_BAD_LSREQ 8
|
||||
#define OSPF6_NEIGHBOR_EVENT_ONEWAY_RCVD 9
|
||||
#define OSPF6_NEIGHBOR_EVENT_INACTIVITY_TIMER 10
|
||||
#define OSPF6_NEIGHBOR_EVENT_MAX_EVENT 11
|
||||
|
||||
static const char *ospf6_neighbor_event_str[] =
|
||||
{
|
||||
"NoEvent",
|
||||
"HelloReceived",
|
||||
"2-WayReceived",
|
||||
"NegotiationDone",
|
||||
"ExchangeDone",
|
||||
"LoadingDone",
|
||||
"AdjOK?",
|
||||
"SeqNumberMismatch",
|
||||
"BadLSReq",
|
||||
"1-WayReceived",
|
||||
"InactivityTimer",
|
||||
};
|
||||
|
||||
static const char *ospf6_neighbor_event_string (int event)
|
||||
{
|
||||
#define OSPF6_NEIGHBOR_UNKNOWN_EVENT_STRING "UnknownEvent"
|
||||
|
||||
if (event < OSPF6_NEIGHBOR_EVENT_MAX_EVENT)
|
||||
return ospf6_neighbor_event_str[event];
|
||||
return OSPF6_NEIGHBOR_UNKNOWN_EVENT_STRING;
|
||||
}
|
||||
|
||||
extern const char *ospf6_neighbor_state_str[];
|
||||
|
||||
|
||||
@ -130,6 +170,7 @@ extern int seqnumber_mismatch (struct thread *);
|
||||
extern int bad_lsreq (struct thread *);
|
||||
extern int oneway_received (struct thread *);
|
||||
extern int inactivity_timer (struct thread *);
|
||||
extern void ospf6_check_nbr_loading (struct ospf6_neighbor *);
|
||||
|
||||
extern void ospf6_neighbor_init (void);
|
||||
extern int config_write_ospf6_debug_neighbor (struct vty *vty);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "sockopt.h"
|
||||
#include "privs.h"
|
||||
|
||||
#include "libospf.h"
|
||||
#include "ospf6_proto.h"
|
||||
#include "ospf6_network.h"
|
||||
|
||||
@ -205,7 +206,7 @@ ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst,
|
||||
smsghdr.msg_name = (caddr_t) &dst_sin6;
|
||||
smsghdr.msg_namelen = sizeof (struct sockaddr_in6);
|
||||
smsghdr.msg_control = (caddr_t) cmsgbuf;
|
||||
smsghdr.msg_controllen = sizeof (cmsgbuf);
|
||||
smsghdr.msg_controllen = scmsgp->cmsg_len;
|
||||
|
||||
retval = sendmsg (ospf6_sock, &smsghdr, 0);
|
||||
if (retval != iov_totallen (message))
|
||||
|
@ -26,33 +26,12 @@
|
||||
/* OSPF protocol version */
|
||||
#define OSPFV3_VERSION 3
|
||||
|
||||
/* OSPF protocol number. */
|
||||
#ifndef IPPROTO_OSPFIGP
|
||||
#define IPPROTO_OSPFIGP 89
|
||||
#endif
|
||||
|
||||
/* TOS field normaly null */
|
||||
#define DEFAULT_TOS_VALUE 0x0
|
||||
|
||||
/* Architectural Constants */
|
||||
#define LS_REFRESH_TIME 1800 /* 30 min */
|
||||
#define MIN_LS_INTERVAL 5
|
||||
#define MIN_LS_ARRIVAL 1
|
||||
#define MAXAGE 3600 /* 1 hour */
|
||||
#define CHECK_AGE 300 /* 5 min */
|
||||
#define MAX_AGE_DIFF 900 /* 15 min */
|
||||
#define LS_INFINITY 0xffffff /* 24-bit binary value */
|
||||
#define INITIAL_SEQUENCE_NUMBER 0x80000001 /* signed 32-bit integer */
|
||||
#define MAX_SEQUENCE_NUMBER 0x7fffffff /* signed 32-bit integer */
|
||||
|
||||
#define ALLSPFROUTERS6 "ff02::5"
|
||||
#define ALLDROUTERS6 "ff02::6"
|
||||
|
||||
/* Configurable Constants */
|
||||
|
||||
#define DEFAULT_HELLO_INTERVAL 10
|
||||
#define DEFAULT_ROUTER_DEAD_INTERVAL 40
|
||||
|
||||
#define OSPF6_ROUTER_BIT_W (1 << 3)
|
||||
#define OSPF6_ROUTER_BIT_V (1 << 2)
|
||||
#define OSPF6_ROUTER_BIT_E (1 << 1)
|
||||
|
@ -304,7 +304,7 @@ ospf6_route_lookup_bestmatch (struct prefix *prefix,
|
||||
return route;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
route_table_assert (struct ospf6_route_table *table)
|
||||
{
|
||||
@ -350,7 +350,7 @@ route_table_assert (struct ospf6_route_table *table)
|
||||
#define ospf6_route_table_assert(t) (route_table_assert (t))
|
||||
#else
|
||||
#define ospf6_route_table_assert(t) ((void) 0)
|
||||
#endif /*NDEBUG*/
|
||||
#endif /*DEBUG*/
|
||||
|
||||
struct ospf6_route *
|
||||
ospf6_route_add (struct ospf6_route *route,
|
||||
|
@ -377,6 +377,36 @@ ospf6_spf_table_finish (struct ospf6_route_table *result_table)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *ospf6_spf_reason_str[] =
|
||||
{
|
||||
"R+",
|
||||
"R-",
|
||||
"N+",
|
||||
"N-",
|
||||
"L+",
|
||||
"L-",
|
||||
"R*",
|
||||
"N*",
|
||||
};
|
||||
|
||||
void ospf6_spf_reason_string (unsigned int reason, char *buf, int size)
|
||||
{
|
||||
int bit;
|
||||
int len = 0;
|
||||
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
for (bit = 0; bit <= (sizeof(ospf6_spf_reason_str) / sizeof(char *)); bit++)
|
||||
{
|
||||
if ((reason & (1 << bit)) && (len < size))
|
||||
{
|
||||
len += snprintf((buf + len), (size - len), "%s%s",
|
||||
(len > 0) ? ", " : "", ospf6_spf_reason_str[bit]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* RFC2328 16.1. Calculating the shortest-path tree for an area */
|
||||
/* RFC2740 3.8.1. Calculating the shortest path tree for an area */
|
||||
void
|
||||
@ -424,6 +454,11 @@ ospf6_spf_calculation (u_int32_t router_id,
|
||||
if (ospf6_spf_install (v, result_table) < 0)
|
||||
continue;
|
||||
|
||||
/* Skip overloaded routers */
|
||||
if ((OSPF6_LSA_IS_TYPE (ROUTER, v->lsa) &&
|
||||
ospf6_router_is_stub_router (v->lsa)))
|
||||
continue;
|
||||
|
||||
/* For each LS description in the just-added vertex V's LSA */
|
||||
size = (VERTEX_IS_TYPE (ROUTER, v) ?
|
||||
sizeof (struct ospf6_router_lsdesc) :
|
||||
@ -506,39 +541,146 @@ static int
|
||||
ospf6_spf_calculation_thread (struct thread *t)
|
||||
{
|
||||
struct ospf6_area *oa;
|
||||
struct ospf6 *ospf6;
|
||||
struct timeval start, end, runtime;
|
||||
struct listnode *node;
|
||||
struct ospf6_route *route;
|
||||
int areas_processed = 0;
|
||||
char rbuf[32];
|
||||
|
||||
oa = (struct ospf6_area *) THREAD_ARG (t);
|
||||
oa->thread_spf_calculation = NULL;
|
||||
|
||||
if (IS_OSPF6_DEBUG_SPF (PROCESS))
|
||||
zlog_debug ("SPF calculation for Area %s", oa->name);
|
||||
if (IS_OSPF6_DEBUG_SPF (DATABASE))
|
||||
ospf6_spf_log_database (oa);
|
||||
ospf6 = (struct ospf6 *)THREAD_ARG (t);
|
||||
ospf6->t_spf_calc = NULL;
|
||||
|
||||
/* execute SPF calculation */
|
||||
quagga_gettime (QUAGGA_CLK_MONOTONIC, &start);
|
||||
ospf6_spf_calculation (oa->ospf6->router_id, oa->spf_table, oa);
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa))
|
||||
{
|
||||
|
||||
if (oa == ospf6->backbone)
|
||||
continue;
|
||||
|
||||
if (IS_OSPF6_DEBUG_SPF (PROCESS))
|
||||
zlog_debug ("SPF calculation for Area %s", oa->name);
|
||||
if (IS_OSPF6_DEBUG_SPF (DATABASE))
|
||||
ospf6_spf_log_database (oa);
|
||||
|
||||
ospf6_spf_calculation (ospf6->router_id, oa->spf_table, oa);
|
||||
ospf6_intra_route_calculation (oa);
|
||||
ospf6_intra_brouter_calculation (oa);
|
||||
|
||||
areas_processed++;
|
||||
}
|
||||
|
||||
if (ospf6->backbone)
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_SPF (PROCESS))
|
||||
zlog_debug ("SPF calculation for Backbone area %s",
|
||||
ospf6->backbone->name);
|
||||
if (IS_OSPF6_DEBUG_SPF (DATABASE))
|
||||
ospf6_spf_log_database(ospf6->backbone);
|
||||
|
||||
ospf6_spf_calculation(ospf6->router_id, ospf6->backbone->spf_table,
|
||||
ospf6->backbone);
|
||||
ospf6_intra_route_calculation(ospf6->backbone);
|
||||
ospf6_intra_brouter_calculation(ospf6->backbone);
|
||||
areas_processed++;
|
||||
}
|
||||
|
||||
/* Redo summaries if required */
|
||||
for (route = ospf6_route_head (ospf6->route_table); route;
|
||||
route = ospf6_route_next (route))
|
||||
ospf6_abr_originate_summary(route);
|
||||
|
||||
quagga_gettime (QUAGGA_CLK_MONOTONIC, &end);
|
||||
timersub (&end, &start, &runtime);
|
||||
|
||||
ospf6->ts_spf_duration = runtime;
|
||||
|
||||
ospf6_spf_reason_string(ospf6->spf_reason, rbuf, sizeof(rbuf));
|
||||
|
||||
if (IS_OSPF6_DEBUG_SPF (PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
|
||||
zlog_debug ("SPF runtime: %ld sec %ld usec",
|
||||
runtime.tv_sec, runtime.tv_usec);
|
||||
|
||||
ospf6_intra_route_calculation (oa);
|
||||
ospf6_intra_brouter_calculation (oa);
|
||||
|
||||
zlog_info("SPF processing: # Areas: %d, SPF runtime: %ld sec %ld usec, "
|
||||
"Reason: %s\n", areas_processed, runtime.tv_sec, runtime.tv_usec,
|
||||
rbuf);
|
||||
ospf6->last_spf_reason = ospf6->spf_reason;
|
||||
ospf6_reset_spf_reason(ospf6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add schedule for SPF calculation. To avoid frequenst SPF calc, we
|
||||
set timer for SPF calc. */
|
||||
void
|
||||
ospf6_spf_schedule (struct ospf6_area *oa)
|
||||
ospf6_spf_schedule (struct ospf6 *ospf6, unsigned int reason)
|
||||
{
|
||||
if (oa->thread_spf_calculation)
|
||||
unsigned long delay, elapsed, ht;
|
||||
struct timeval now, result;
|
||||
|
||||
ospf6_set_spf_reason(ospf6, reason);
|
||||
|
||||
if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
|
||||
{
|
||||
char rbuf[32];
|
||||
ospf6_spf_reason_string(reason, rbuf, sizeof(rbuf));
|
||||
zlog_debug ("SPF: calculation timer scheduled (reason %s)", rbuf);
|
||||
}
|
||||
|
||||
/* OSPF instance does not exist. */
|
||||
if (ospf6 == NULL)
|
||||
return;
|
||||
oa->thread_spf_calculation =
|
||||
thread_add_event (master, ospf6_spf_calculation_thread, oa, 0);
|
||||
|
||||
/* SPF calculation timer is already scheduled. */
|
||||
if (ospf6->t_spf_calc)
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
|
||||
zlog_debug ("SPF: calculation timer is already scheduled: %p",
|
||||
ospf6->t_spf_calc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX Monotic timers: we only care about relative time here. */
|
||||
now = recent_relative_time ();
|
||||
timersub (&now, &ospf6->ts_spf, &result);
|
||||
|
||||
elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
|
||||
ht = ospf6->spf_holdtime * ospf6->spf_hold_multiplier;
|
||||
|
||||
if (ht > ospf6->spf_max_holdtime)
|
||||
ht = ospf6->spf_max_holdtime;
|
||||
|
||||
/* Get SPF calculation delay time. */
|
||||
if (elapsed < ht)
|
||||
{
|
||||
/* Got an event within the hold time of last SPF. We need to
|
||||
* increase the hold_multiplier, if it's not already at/past
|
||||
* maximum value, and wasn't already increased..
|
||||
*/
|
||||
if (ht < ospf6->spf_max_holdtime)
|
||||
ospf6->spf_hold_multiplier++;
|
||||
|
||||
/* always honour the SPF initial delay */
|
||||
if ( (ht - elapsed) < ospf6->spf_delay)
|
||||
delay = ospf6->spf_delay;
|
||||
else
|
||||
delay = ht - elapsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Event is past required hold-time of last SPF */
|
||||
delay = ospf6->spf_delay;
|
||||
ospf6->spf_hold_multiplier = 1;
|
||||
}
|
||||
|
||||
if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
|
||||
zlog_debug ("SPF: calculation timer delay = %ld", delay);
|
||||
|
||||
zlog_info ("SPF: Scheduled in %ld msec", delay);
|
||||
|
||||
ospf6->t_spf_calc =
|
||||
thread_add_timer_msec (master, ospf6_spf_calculation_thread, ospf6, delay);
|
||||
}
|
||||
|
||||
void
|
||||
@ -666,6 +808,59 @@ DEFUN (no_debug_ospf6_spf_database,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
ospf6_timers_spf_set (struct vty *vty, unsigned int delay,
|
||||
unsigned int hold,
|
||||
unsigned int max)
|
||||
{
|
||||
struct ospf6 *ospf = vty->index;
|
||||
|
||||
ospf->spf_delay = delay;
|
||||
ospf->spf_holdtime = hold;
|
||||
ospf->spf_max_holdtime = max;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ospf6_timers_throttle_spf,
|
||||
ospf6_timers_throttle_spf_cmd,
|
||||
"timers throttle spf <0-600000> <0-600000> <0-600000>",
|
||||
"Adjust routing timers\n"
|
||||
"Throttling adaptive timer\n"
|
||||
"OSPF6 SPF timers\n"
|
||||
"Delay (msec) from first change received till SPF calculation\n"
|
||||
"Initial hold time (msec) between consecutive SPF calculations\n"
|
||||
"Maximum hold time (msec)\n")
|
||||
{
|
||||
unsigned int delay, hold, max;
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
vty_out (vty, "Insufficient arguments%s", VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
VTY_GET_INTEGER_RANGE ("SPF delay timer", delay, argv[0], 0, 600000);
|
||||
VTY_GET_INTEGER_RANGE ("SPF hold timer", hold, argv[1], 0, 600000);
|
||||
VTY_GET_INTEGER_RANGE ("SPF max-hold timer", max, argv[2], 0, 600000);
|
||||
|
||||
return ospf6_timers_spf_set (vty, delay, hold, max);
|
||||
}
|
||||
|
||||
DEFUN (no_ospf6_timers_throttle_spf,
|
||||
no_ospf6_timers_throttle_spf_cmd,
|
||||
"no timers throttle spf",
|
||||
NO_STR
|
||||
"Adjust routing timers\n"
|
||||
"Throttling adaptive timer\n"
|
||||
"OSPF6 SPF timers\n")
|
||||
{
|
||||
return ospf6_timers_spf_set (vty,
|
||||
OSPF_SPF_DELAY_DEFAULT,
|
||||
OSPF_SPF_HOLDTIME_DEFAULT,
|
||||
OSPF_SPF_MAX_HOLDTIME_DEFAULT);
|
||||
}
|
||||
|
||||
int
|
||||
config_write_ospf6_debug_spf (struct vty *vty)
|
||||
{
|
||||
@ -678,6 +873,19 @@ config_write_ospf6_debug_spf (struct vty *vty)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ospf6_spf_config_write (struct vty *vty)
|
||||
{
|
||||
|
||||
if (ospf6->spf_delay != OSPF_SPF_DELAY_DEFAULT ||
|
||||
ospf6->spf_holdtime != OSPF_SPF_HOLDTIME_DEFAULT ||
|
||||
ospf6->spf_max_holdtime != OSPF_SPF_MAX_HOLDTIME_DEFAULT)
|
||||
vty_out (vty, " timers throttle spf %d %d %d%s",
|
||||
ospf6->spf_delay, ospf6->spf_holdtime,
|
||||
ospf6->spf_max_holdtime, VTY_NEWLINE);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
install_element_ospf6_debug_spf (void)
|
||||
{
|
||||
@ -698,6 +906,6 @@ install_element_ospf6_debug_spf (void)
|
||||
void
|
||||
ospf6_spf_init (void)
|
||||
{
|
||||
install_element (OSPF6_NODE, &ospf6_timers_throttle_spf_cmd);
|
||||
install_element (OSPF6_NODE, &no_ospf6_timers_throttle_spf_cmd);
|
||||
}
|
||||
|
||||
|
||||
|
@ -22,6 +22,8 @@
|
||||
#ifndef OSPF6_SPF_H
|
||||
#define OSPF6_SPF_H
|
||||
|
||||
#include "ospf6_top.h"
|
||||
|
||||
/* Debug option */
|
||||
extern unsigned char conf_debug_ospf6_spf;
|
||||
#define OSPF6_DEBUG_SPF_PROCESS 0x01
|
||||
@ -77,18 +79,86 @@ struct ospf6_vertex
|
||||
#define VERTEX_IS_TYPE(t, v) \
|
||||
((v)->type == OSPF6_VERTEX_TYPE_ ## t ? 1 : 0)
|
||||
|
||||
/* What triggered the SPF? */
|
||||
#define OSPF6_SPF_FLAGS_ROUTER_LSA_ADDED (1 << 0)
|
||||
#define OSPF6_SPF_FLAGS_ROUTER_LSA_REMOVED (1 << 1)
|
||||
#define OSPF6_SPF_FLAGS_NETWORK_LSA_ADDED (1 << 2)
|
||||
#define OSPF6_SPF_FLAGS_NETWORK_LSA_REMOVED (1 << 3)
|
||||
#define OSPF6_SPF_FLAGS_LINK_LSA_ADDED (1 << 4)
|
||||
#define OSPF6_SPF_FLAGS_LINK_LSA_REMOVED (1 << 5)
|
||||
#define OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED (1 << 6)
|
||||
#define OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED (1 << 7)
|
||||
|
||||
static inline void
|
||||
ospf6_set_spf_reason (struct ospf6* ospf, unsigned int reason)
|
||||
{
|
||||
ospf->spf_reason |= reason;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ospf6_reset_spf_reason (struct ospf6 *ospf)
|
||||
{
|
||||
ospf->spf_reason = 0;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
ospf6_lsadd_to_spf_reason (struct ospf6_lsa *lsa)
|
||||
{
|
||||
unsigned int reason = 0;
|
||||
|
||||
switch (ntohs (lsa->header->type))
|
||||
{
|
||||
case OSPF6_LSTYPE_ROUTER:
|
||||
reason = OSPF6_SPF_FLAGS_ROUTER_LSA_ADDED;
|
||||
break;
|
||||
case OSPF6_LSTYPE_NETWORK:
|
||||
reason = OSPF6_SPF_FLAGS_NETWORK_LSA_ADDED;
|
||||
break;
|
||||
case OSPF6_LSTYPE_LINK:
|
||||
reason = OSPF6_SPF_FLAGS_LINK_LSA_ADDED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (reason);
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
ospf6_lsremove_to_spf_reason (struct ospf6_lsa *lsa)
|
||||
{
|
||||
unsigned int reason = 0;
|
||||
|
||||
switch (ntohs (lsa->header->type))
|
||||
{
|
||||
case OSPF6_LSTYPE_ROUTER:
|
||||
reason = OSPF6_SPF_FLAGS_ROUTER_LSA_REMOVED;
|
||||
break;
|
||||
case OSPF6_LSTYPE_NETWORK:
|
||||
reason = OSPF6_SPF_FLAGS_NETWORK_LSA_REMOVED;
|
||||
break;
|
||||
case OSPF6_LSTYPE_LINK:
|
||||
reason = OSPF6_SPF_FLAGS_LINK_LSA_REMOVED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (reason);
|
||||
}
|
||||
|
||||
extern void ospf6_spf_table_finish (struct ospf6_route_table *result_table);
|
||||
extern void ospf6_spf_calculation (u_int32_t router_id,
|
||||
struct ospf6_route_table *result_table,
|
||||
struct ospf6_area *oa);
|
||||
extern void ospf6_spf_schedule (struct ospf6_area *oa);
|
||||
extern void ospf6_spf_schedule (struct ospf6 *ospf, unsigned int reason);
|
||||
|
||||
extern void ospf6_spf_display_subtree (struct vty *vty, const char *prefix,
|
||||
int rest, struct ospf6_vertex *v);
|
||||
|
||||
extern void ospf6_spf_config_write (struct vty *vty);
|
||||
extern int config_write_ospf6_debug_spf (struct vty *vty);
|
||||
extern void install_element_ospf6_debug_spf (void);
|
||||
extern void ospf6_spf_init (void);
|
||||
extern void ospf6_spf_reason_string (unsigned int reason, char *buf, int size);
|
||||
|
||||
#endif /* OSPF6_SPF_H */
|
||||
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "ospf6_asbr.h"
|
||||
#include "ospf6_abr.h"
|
||||
#include "ospf6_intra.h"
|
||||
#include "ospf6_spf.h"
|
||||
#include "ospf6d.h"
|
||||
|
||||
/* global ospf6d variable */
|
||||
@ -127,6 +128,11 @@ ospf6_create (void)
|
||||
o->lsdb->hook_add = ospf6_top_lsdb_hook_add;
|
||||
o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove;
|
||||
|
||||
o->spf_delay = OSPF_SPF_DELAY_DEFAULT;
|
||||
o->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
|
||||
o->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
|
||||
o->spf_hold_multiplier = 1;
|
||||
|
||||
o->route_table = OSPF6_ROUTE_TABLE_CREATE (GLOBAL, ROUTES);
|
||||
o->route_table->scope = o;
|
||||
o->route_table->hook_add = ospf6_top_route_hook_add;
|
||||
@ -155,6 +161,8 @@ ospf6_delete (struct ospf6 *o)
|
||||
|
||||
for (ALL_LIST_ELEMENTS (o->area_list, node, nnode, oa))
|
||||
ospf6_area_delete (oa);
|
||||
|
||||
|
||||
list_delete (o->area_list);
|
||||
|
||||
ospf6_lsdb_delete (o->lsdb);
|
||||
@ -196,13 +204,20 @@ ospf6_disable (struct ospf6 *o)
|
||||
for (ALL_LIST_ELEMENTS (o->area_list, node, nnode, oa))
|
||||
ospf6_area_disable (oa);
|
||||
|
||||
/* XXX: This also changes persistent settings */
|
||||
ospf6_asbr_redistribute_reset();
|
||||
|
||||
ospf6_lsdb_remove_all (o->lsdb);
|
||||
ospf6_route_remove_all (o->route_table);
|
||||
ospf6_route_remove_all (o->brouter_table);
|
||||
|
||||
THREAD_OFF(o->maxage_remover);
|
||||
THREAD_OFF(o->t_spf_calc);
|
||||
THREAD_OFF(o->t_ase_calc);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
ospf6_maxage_remover (struct thread *thread)
|
||||
{
|
||||
struct ospf6 *o = (struct ospf6 *) THREAD_ARG (thread);
|
||||
@ -210,6 +225,7 @@ ospf6_maxage_remover (struct thread *thread)
|
||||
struct ospf6_interface *oi;
|
||||
struct ospf6_neighbor *on;
|
||||
struct listnode *i, *j, *k;
|
||||
int reschedule = 0;
|
||||
|
||||
o->maxage_remover = (struct thread *) NULL;
|
||||
|
||||
@ -221,8 +237,9 @@ ospf6_maxage_remover (struct thread *thread)
|
||||
{
|
||||
if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
|
||||
on->state != OSPF6_NEIGHBOR_LOADING)
|
||||
continue;
|
||||
continue;
|
||||
|
||||
ospf6_maxage_remove (o);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -231,11 +248,28 @@ ospf6_maxage_remover (struct thread *thread)
|
||||
for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa))
|
||||
{
|
||||
for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi))
|
||||
OSPF6_LSDB_MAXAGE_REMOVER (oi->lsdb);
|
||||
{
|
||||
if (ospf6_lsdb_maxage_remover (oi->lsdb))
|
||||
{
|
||||
reschedule = 1;
|
||||
}
|
||||
}
|
||||
|
||||
OSPF6_LSDB_MAXAGE_REMOVER (oa->lsdb);
|
||||
if (ospf6_lsdb_maxage_remover (oa->lsdb))
|
||||
{
|
||||
reschedule = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ospf6_lsdb_maxage_remover (o->lsdb))
|
||||
{
|
||||
reschedule = 1;
|
||||
}
|
||||
|
||||
if (reschedule)
|
||||
{
|
||||
ospf6_maxage_remove (o);
|
||||
}
|
||||
OSPF6_LSDB_MAXAGE_REMOVER (o->lsdb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -244,7 +278,8 @@ void
|
||||
ospf6_maxage_remove (struct ospf6 *o)
|
||||
{
|
||||
if (o && ! o->maxage_remover)
|
||||
o->maxage_remover = thread_add_event (master, ospf6_maxage_remover, o, 0);
|
||||
o->maxage_remover = thread_add_timer (master, ospf6_maxage_remover, o,
|
||||
OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT);
|
||||
}
|
||||
|
||||
/* start ospf6 */
|
||||
@ -256,8 +291,6 @@ DEFUN (router_ospf6,
|
||||
{
|
||||
if (ospf6 == NULL)
|
||||
ospf6 = ospf6_create ();
|
||||
if (CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
|
||||
ospf6_enable (ospf6);
|
||||
|
||||
/* set current ospf point. */
|
||||
vty->node = OSPF6_NODE;
|
||||
@ -273,10 +306,13 @@ DEFUN (no_router_ospf6,
|
||||
NO_STR
|
||||
OSPF6_ROUTER_STR)
|
||||
{
|
||||
if (ospf6 == NULL || CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
|
||||
vty_out (vty, "OSPFv3 is not running%s", VNL);
|
||||
if (ospf6 == NULL)
|
||||
vty_out (vty, "OSPFv3 is not configured%s", VNL);
|
||||
else
|
||||
ospf6_disable (ospf6);
|
||||
{
|
||||
ospf6_delete (ospf6);
|
||||
ospf6 = NULL;
|
||||
}
|
||||
|
||||
/* return to config node . */
|
||||
vty->node = CONFIG_NODE;
|
||||
@ -312,6 +348,56 @@ DEFUN (ospf6_router_id,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ospf6_log_adjacency_changes,
|
||||
ospf6_log_adjacency_changes_cmd,
|
||||
"log-adjacency-changes",
|
||||
"Log changes in adjacency state\n")
|
||||
{
|
||||
struct ospf6 *ospf6 = vty->index;
|
||||
|
||||
SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ospf6_log_adjacency_changes_detail,
|
||||
ospf6_log_adjacency_changes_detail_cmd,
|
||||
"log-adjacency-changes detail",
|
||||
"Log changes in adjacency state\n"
|
||||
"Log all state changes\n")
|
||||
{
|
||||
struct ospf6 *ospf6 = vty->index;
|
||||
|
||||
SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
|
||||
SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_ospf6_log_adjacency_changes,
|
||||
no_ospf6_log_adjacency_changes_cmd,
|
||||
"no log-adjacency-changes",
|
||||
NO_STR
|
||||
"Log changes in adjacency state\n")
|
||||
{
|
||||
struct ospf6 *ospf6 = vty->index;
|
||||
|
||||
UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
|
||||
UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_ospf6_log_adjacency_changes_detail,
|
||||
no_ospf6_log_adjacency_changes_detail_cmd,
|
||||
"no log-adjacency-changes detail",
|
||||
NO_STR
|
||||
"Log changes in adjacency state\n"
|
||||
"Log all state changes\n")
|
||||
{
|
||||
struct ospf6 *ospf6 = vty->index;
|
||||
|
||||
UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ospf6_interface_area,
|
||||
ospf6_interface_area_cmd,
|
||||
"interface IFNAME area A.B.C.D",
|
||||
@ -359,8 +445,12 @@ DEFUN (ospf6_interface_area,
|
||||
|
||||
SET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
|
||||
|
||||
/* ospf6 process is currently disabled, not much more to do */
|
||||
if (CHECK_FLAG (o->flag, OSPF6_DISABLED))
|
||||
return CMD_SUCCESS;
|
||||
|
||||
/* start up */
|
||||
thread_add_event (master, interface_up, oi, 0);
|
||||
ospf6_interface_enable (oi);
|
||||
|
||||
/* If the router is ABR, originate summary routes */
|
||||
if (ospf6_is_router_abr (o))
|
||||
@ -438,13 +528,109 @@ DEFUN (no_ospf6_interface_area,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ospf6_stub_router_admin,
|
||||
ospf6_stub_router_admin_cmd,
|
||||
"stub-router administrative",
|
||||
"Make router a stub router\n"
|
||||
"Advertise inability to be a transit router\n"
|
||||
"Administratively applied, for an indefinite period\n")
|
||||
{
|
||||
struct listnode *node;
|
||||
struct ospf6_area *oa;
|
||||
|
||||
if (!CHECK_FLAG (ospf6->flag, OSPF6_STUB_ROUTER))
|
||||
{
|
||||
for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
|
||||
{
|
||||
OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_V6);
|
||||
OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_R);
|
||||
OSPF6_ROUTER_LSA_SCHEDULE (oa);
|
||||
}
|
||||
SET_FLAG (ospf6->flag, OSPF6_STUB_ROUTER);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_ospf6_stub_router_admin,
|
||||
no_ospf6_stub_router_admin_cmd,
|
||||
"no stub-router administrative",
|
||||
NO_STR
|
||||
"Make router a stub router\n"
|
||||
"Advertise ability to be a transit router\n"
|
||||
"Administratively applied, for an indefinite period\n")
|
||||
{
|
||||
struct listnode *node;
|
||||
struct ospf6_area *oa;
|
||||
|
||||
if (CHECK_FLAG (ospf6->flag, OSPF6_STUB_ROUTER))
|
||||
{
|
||||
for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
|
||||
{
|
||||
OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
|
||||
OSPF6_OPT_SET (oa->options, OSPF6_OPT_R);
|
||||
OSPF6_ROUTER_LSA_SCHEDULE (oa);
|
||||
}
|
||||
UNSET_FLAG (ospf6->flag, OSPF6_STUB_ROUTER);
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ospf6_stub_router_startup,
|
||||
ospf6_stub_router_startup_cmd,
|
||||
"stub-router on-startup <5-86400>",
|
||||
"Make router a stub router\n"
|
||||
"Advertise inability to be a transit router\n"
|
||||
"Automatically advertise as stub-router on startup of OSPF6\n"
|
||||
"Time (seconds) to advertise self as stub-router\n")
|
||||
{
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_ospf6_stub_router_startup,
|
||||
no_ospf6_stub_router_startup_cmd,
|
||||
"no stub-router on-startup",
|
||||
NO_STR
|
||||
"Make router a stub router\n"
|
||||
"Advertise inability to be a transit router\n"
|
||||
"Automatically advertise as stub-router on startup of OSPF6\n"
|
||||
"Time (seconds) to advertise self as stub-router\n")
|
||||
{
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (ospf6_stub_router_shutdown,
|
||||
ospf6_stub_router_shutdown_cmd,
|
||||
"stub-router on-shutdown <5-86400>",
|
||||
"Make router a stub router\n"
|
||||
"Advertise inability to be a transit router\n"
|
||||
"Automatically advertise as stub-router before shutdown\n"
|
||||
"Time (seconds) to advertise self as stub-router\n")
|
||||
{
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (no_ospf6_stub_router_shutdown,
|
||||
no_ospf6_stub_router_shutdown_cmd,
|
||||
"no stub-router on-shutdown",
|
||||
NO_STR
|
||||
"Make router a stub router\n"
|
||||
"Advertise inability to be a transit router\n"
|
||||
"Automatically advertise as stub-router before shutdown\n"
|
||||
"Time (seconds) to advertise self as stub-router\n")
|
||||
{
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
ospf6_show (struct vty *vty, struct ospf6 *o)
|
||||
{
|
||||
struct listnode *n;
|
||||
struct ospf6_area *oa;
|
||||
char router_id[16], duration[32];
|
||||
struct timeval now, running;
|
||||
struct timeval now, running, result;
|
||||
char buf[32], rbuf[32];
|
||||
|
||||
/* process id, router id */
|
||||
inet_ntop (AF_INET, &o->router_id, router_id, sizeof (router_id));
|
||||
@ -460,6 +646,35 @@ ospf6_show (struct vty *vty, struct ospf6 *o)
|
||||
/* Redistribute configuration */
|
||||
/* XXX */
|
||||
|
||||
/* Show SPF parameters */
|
||||
vty_out(vty, " Initial SPF scheduling delay %d millisec(s)%s"
|
||||
" Minimum hold time between consecutive SPFs %d millsecond(s)%s"
|
||||
" Maximum hold time between consecutive SPFs %d millsecond(s)%s"
|
||||
" Hold time multiplier is currently %d%s",
|
||||
o->spf_delay, VNL,
|
||||
o->spf_holdtime, VNL,
|
||||
o->spf_max_holdtime, VNL,
|
||||
o->spf_hold_multiplier, VNL);
|
||||
|
||||
vty_out(vty, " SPF algorithm ");
|
||||
if (o->ts_spf.tv_sec || o->ts_spf.tv_usec)
|
||||
{
|
||||
timersub(&now, &o->ts_spf, &result);
|
||||
timerstring(&result, buf, sizeof(buf));
|
||||
ospf6_spf_reason_string(o->last_spf_reason, rbuf, sizeof(rbuf));
|
||||
vty_out(vty, "last executed %s ago, reason %s%s", buf, rbuf, VNL);
|
||||
vty_out (vty, " Last SPF duration %ld sec %ld usec%s",
|
||||
o->ts_spf_duration.tv_sec, o->ts_spf_duration.tv_usec, VNL);
|
||||
}
|
||||
else
|
||||
vty_out(vty, "has not been run$%s", VNL);
|
||||
threadtimer_string(now, o->t_spf_calc, buf, sizeof(buf));
|
||||
vty_out (vty, " SPF timer %s%s%s",
|
||||
(o->t_spf_calc ? "due in " : "is "), buf, VNL);
|
||||
|
||||
if (CHECK_FLAG (o->flag, OSPF6_STUB_ROUTER))
|
||||
vty_out (vty, " Router Is Stub Router%s", VNL);
|
||||
|
||||
/* LSAs */
|
||||
vty_out (vty, " Number of AS scoped LSAs is %u%s",
|
||||
o->lsdb->count, VNL);
|
||||
@ -468,6 +683,16 @@ ospf6_show (struct vty *vty, struct ospf6 *o)
|
||||
vty_out (vty, " Number of areas in this router is %u%s",
|
||||
listcount (o->area_list), VNL);
|
||||
|
||||
if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES))
|
||||
{
|
||||
if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_DETAIL))
|
||||
vty_out(vty, " All adjacency changes are logged%s",VTY_NEWLINE);
|
||||
else
|
||||
vty_out(vty, " Adjacency changes are logged%s",VTY_NEWLINE);
|
||||
}
|
||||
|
||||
vty_out (vty, "%s",VTY_NEWLINE);
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (o->area_list, n, oa))
|
||||
ospf6_area_show (vty, oa);
|
||||
}
|
||||
@ -628,6 +853,16 @@ DEFUN (show_ipv6_ospf6_route_type_detail,
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
ospf6_stub_router_config_write (struct vty *vty)
|
||||
{
|
||||
if (CHECK_FLAG (ospf6->flag, OSPF6_STUB_ROUTER))
|
||||
{
|
||||
vty_out (vty, " stub-router administrative%s", VNL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* OSPF configuration write function. */
|
||||
static int
|
||||
config_write_ospf6 (struct vty *vty)
|
||||
@ -640,16 +875,25 @@ config_write_ospf6 (struct vty *vty)
|
||||
/* OSPFv6 configuration. */
|
||||
if (ospf6 == NULL)
|
||||
return CMD_SUCCESS;
|
||||
if (CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
|
||||
return CMD_SUCCESS;
|
||||
|
||||
inet_ntop (AF_INET, &ospf6->router_id_static, router_id, sizeof (router_id));
|
||||
vty_out (vty, "router ospf6%s", VNL);
|
||||
if (ospf6->router_id_static != 0)
|
||||
vty_out (vty, " router-id %s%s", router_id, VNL);
|
||||
|
||||
/* log-adjacency-changes flag print. */
|
||||
if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES))
|
||||
{
|
||||
vty_out(vty, " log-adjacency-changes");
|
||||
if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL))
|
||||
vty_out(vty, " detail");
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
}
|
||||
|
||||
ospf6_stub_router_config_write (vty);
|
||||
ospf6_redistribute_config_write (vty);
|
||||
ospf6_area_config_write (vty);
|
||||
ospf6_spf_config_write (vty);
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, j, oa))
|
||||
{
|
||||
@ -700,8 +944,20 @@ ospf6_top_init (void)
|
||||
|
||||
install_default (OSPF6_NODE);
|
||||
install_element (OSPF6_NODE, &ospf6_router_id_cmd);
|
||||
install_element (OSPF6_NODE, &ospf6_log_adjacency_changes_cmd);
|
||||
install_element (OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd);
|
||||
install_element (OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd);
|
||||
install_element (OSPF6_NODE, &no_ospf6_log_adjacency_changes_detail_cmd);
|
||||
install_element (OSPF6_NODE, &ospf6_interface_area_cmd);
|
||||
install_element (OSPF6_NODE, &no_ospf6_interface_area_cmd);
|
||||
install_element (OSPF6_NODE, &ospf6_stub_router_admin_cmd);
|
||||
install_element (OSPF6_NODE, &no_ospf6_stub_router_admin_cmd);
|
||||
/* For a later time
|
||||
install_element (OSPF6_NODE, &ospf6_stub_router_startup_cmd);
|
||||
install_element (OSPF6_NODE, &no_ospf6_stub_router_startup_cmd);
|
||||
install_element (OSPF6_NODE, &ospf6_stub_router_shutdown_cmd);
|
||||
install_element (OSPF6_NODE, &no_ospf6_stub_router_shutdown_cmd);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,6 +38,7 @@ struct ospf6
|
||||
|
||||
/* list of areas */
|
||||
struct list *area_list;
|
||||
struct ospf6_area *backbone;
|
||||
|
||||
/* AS scope link state database */
|
||||
struct ospf6_lsdb *lsdb;
|
||||
@ -59,10 +60,30 @@ struct ospf6
|
||||
|
||||
u_char flag;
|
||||
|
||||
/* Configured flags */
|
||||
u_char config_flags;
|
||||
#define OSPF6_LOG_ADJACENCY_CHANGES (1 << 0)
|
||||
#define OSPF6_LOG_ADJACENCY_DETAIL (1 << 1)
|
||||
|
||||
/* SPF parameters */
|
||||
unsigned int spf_delay; /* SPF delay time. */
|
||||
unsigned int spf_holdtime; /* SPF hold time. */
|
||||
unsigned int spf_max_holdtime; /* SPF maximum-holdtime */
|
||||
unsigned int spf_hold_multiplier; /* Adaptive multiplier for hold time */
|
||||
unsigned int spf_reason; /* reason bits while scheduling SPF */
|
||||
|
||||
struct timeval ts_spf; /* SPF calculation time stamp. */
|
||||
struct timeval ts_spf_duration; /* Execution time of last SPF */
|
||||
unsigned int last_spf_reason; /* Last SPF reason */
|
||||
|
||||
/* Threads */
|
||||
struct thread *t_spf_calc; /* SPF calculation timer. */
|
||||
struct thread *t_ase_calc; /* ASE calculation timer. */
|
||||
struct thread *maxage_remover;
|
||||
};
|
||||
|
||||
#define OSPF6_DISABLED 0x01
|
||||
#define OSPF6_STUB_ROUTER 0x02
|
||||
|
||||
/* global pointer for OSPF top data structure */
|
||||
extern struct ospf6 *ospf6;
|
||||
|
@ -117,7 +117,9 @@ ospf6_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length)
|
||||
ifp->name, ifp->ifindex, ifp->mtu6);
|
||||
|
||||
#if 0
|
||||
/* Why is this commented out? */
|
||||
/* XXX: ospf6_interface_if_del is not the right way to handle this,
|
||||
* because among other thinkable issues, it will also clear all
|
||||
* settings as they are contained in the struct ospf6_interface. */
|
||||
ospf6_interface_if_del (ifp);
|
||||
#endif /*0*/
|
||||
|
||||
@ -163,8 +165,10 @@ ospf6_zebra_if_address_update_add (int command, struct zclient *zclient,
|
||||
buf, sizeof (buf)), c->address->prefixlen);
|
||||
|
||||
if (c->address->family == AF_INET6)
|
||||
ospf6_interface_connected_route_update (c->ifp);
|
||||
|
||||
{
|
||||
ospf6_interface_state_update (c->ifp);
|
||||
ospf6_interface_connected_route_update (c->ifp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -186,7 +190,10 @@ ospf6_zebra_if_address_update_delete (int command, struct zclient *zclient,
|
||||
buf, sizeof (buf)), c->address->prefixlen);
|
||||
|
||||
if (c->address->family == AF_INET6)
|
||||
ospf6_interface_connected_route_update (c->ifp);
|
||||
{
|
||||
ospf6_interface_connected_route_update (c->ifp);
|
||||
ospf6_interface_state_update (c->ifp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -24,6 +24,9 @@
|
||||
|
||||
#define OSPF6_DAEMON_VERSION "0.9.7r"
|
||||
|
||||
#include "libospf.h"
|
||||
#include "thread.h"
|
||||
|
||||
/* global variables */
|
||||
extern struct thread_master *master;
|
||||
|
||||
@ -98,6 +101,17 @@ extern struct thread_master *master;
|
||||
zlog_warn ("strftime error"); \
|
||||
} while (0)
|
||||
|
||||
#define threadtimer_string(now, t, buf, size) \
|
||||
do { \
|
||||
struct timeval result; \
|
||||
if (!t) \
|
||||
snprintf(buf, size, "inactive"); \
|
||||
else { \
|
||||
timersub(&t->u.sands, &now, &result); \
|
||||
timerstring(&result, buf, size); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* for commands */
|
||||
#define OSPF6_AREA_STR "Area information\n"
|
||||
#define OSPF6_AREA_ID_STR "Area ID (as an IPv4 notation)\n"
|
||||
|
@ -140,14 +140,6 @@ struct ospf_interface
|
||||
|
||||
/* OSPF Network Type. */
|
||||
u_char type;
|
||||
#define OSPF_IFTYPE_NONE 0
|
||||
#define OSPF_IFTYPE_POINTOPOINT 1
|
||||
#define OSPF_IFTYPE_BROADCAST 2
|
||||
#define OSPF_IFTYPE_NBMA 3
|
||||
#define OSPF_IFTYPE_POINTOMULTIPOINT 4
|
||||
#define OSPF_IFTYPE_VIRTUALLINK 5
|
||||
#define OSPF_IFTYPE_LOOPBACK 6
|
||||
#define OSPF_IFTYPE_MAX 7
|
||||
|
||||
/* State of Interface State Machine. */
|
||||
u_char state;
|
||||
|
@ -200,7 +200,7 @@ ospf_new (void)
|
||||
new->spf_hold_multiplier = 1;
|
||||
|
||||
/* MaxAge init. */
|
||||
new->maxage_delay = OSFP_LSA_MAXAGE_REMOVE_DELAY_DEFAULT;
|
||||
new->maxage_delay = OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT;
|
||||
new->maxage_lsa = route_table_init();
|
||||
new->t_maxage_walker =
|
||||
thread_add_timer (master, ospf_lsa_maxage_walker,
|
||||
|
@ -24,22 +24,13 @@
|
||||
#define _ZEBRA_OSPFD_H
|
||||
|
||||
#include <zebra.h>
|
||||
#include "libospf.h"
|
||||
|
||||
#include "filter.h"
|
||||
#include "log.h"
|
||||
|
||||
#define OSPF_VERSION 2
|
||||
|
||||
/* Default protocol, port number. */
|
||||
#ifndef IPPROTO_OSPFIGP
|
||||
#define IPPROTO_OSPFIGP 89
|
||||
#endif /* IPPROTO_OSPFIGP */
|
||||
|
||||
/* IP precedence. */
|
||||
#ifndef IPTOS_PREC_INTERNETCONTROL
|
||||
#define IPTOS_PREC_INTERNETCONTROL 0xC0
|
||||
#endif /* IPTOS_PREC_INTERNETCONTROL */
|
||||
|
||||
/* VTY port number. */
|
||||
#define OSPF_VTY_PORT 2604
|
||||
|
||||
@ -50,29 +41,11 @@
|
||||
/* Default configuration file name for ospfd. */
|
||||
#define OSPF_DEFAULT_CONFIG "ospfd.conf"
|
||||
|
||||
/* Architectual Constants */
|
||||
#ifdef DEBUG
|
||||
#define OSPF_LS_REFRESH_TIME 60
|
||||
#else
|
||||
#define OSPF_LS_REFRESH_TIME 1800
|
||||
#endif
|
||||
#define OSPF_MIN_LS_INTERVAL 5
|
||||
#define OSPF_MIN_LS_ARRIVAL 1
|
||||
#define OSPF_LSA_INITIAL_AGE 0 /* useful for debug */
|
||||
#define OSPF_LSA_MAXAGE 3600
|
||||
#define OSPF_CHECK_AGE 300
|
||||
#define OSPF_LSA_MAXAGE_DIFF 900
|
||||
#define OSPF_LS_INFINITY 0xffffff
|
||||
#define OSPF_DEFAULT_DESTINATION 0x00000000 /* 0.0.0.0 */
|
||||
#define OSPF_INITIAL_SEQUENCE_NUMBER 0x80000001
|
||||
#define OSPF_MAX_SEQUENCE_NUMBER 0x7fffffff
|
||||
|
||||
#define OSPF_NSSA_TRANS_STABLE_DEFAULT 40
|
||||
|
||||
#define OSPF_ALLSPFROUTERS 0xe0000005 /* 224.0.0.5 */
|
||||
#define OSPF_ALLDROUTERS 0xe0000006 /* 224.0.0.6 */
|
||||
|
||||
#define OSPF_AREA_BACKBONE 0x00000000 /* 0.0.0.0 */
|
||||
|
||||
/* OSPF Authentication Type. */
|
||||
#define OSPF_AUTH_NULL 0
|
||||
@ -85,30 +58,6 @@
|
||||
been given or not in VLink command handlers */
|
||||
#define OSPF_AUTH_CMD_NOTSEEN -2
|
||||
|
||||
/* OSPF SPF timer values. */
|
||||
#define OSPF_SPF_DELAY_DEFAULT 200
|
||||
#define OSPF_SPF_HOLDTIME_DEFAULT 1000
|
||||
#define OSPF_SPF_MAX_HOLDTIME_DEFAULT 10000
|
||||
|
||||
/* OSPF interface default values. */
|
||||
#define OSPF_OUTPUT_COST_DEFAULT 10
|
||||
#define OSPF_OUTPUT_COST_INFINITE UINT16_MAX
|
||||
#define OSPF_ROUTER_DEAD_INTERVAL_DEFAULT 40
|
||||
#define OSPF_ROUTER_DEAD_INTERVAL_MINIMAL 1
|
||||
#define OSPF_HELLO_INTERVAL_DEFAULT 10
|
||||
#define OSPF_ROUTER_PRIORITY_DEFAULT 1
|
||||
#define OSPF_RETRANSMIT_INTERVAL_DEFAULT 5
|
||||
#define OSPF_TRANSMIT_DELAY_DEFAULT 1
|
||||
#define OSPF_DEFAULT_BANDWIDTH 10000 /* Kbps */
|
||||
|
||||
#define OSPF_DEFAULT_REF_BANDWIDTH 100000 /* Kbps */
|
||||
|
||||
#define OSPF_POLL_INTERVAL_DEFAULT 60
|
||||
#define OSPF_NEIGHBOR_PRIORITY_DEFAULT 0
|
||||
|
||||
#define OSPF_MTU_IGNORE_DEFAULT 0
|
||||
#define OSPF_FAST_HELLO_DEFAULT 0
|
||||
|
||||
/* OSPF options. */
|
||||
#define OSPF_OPTION_T 0x01 /* TOS. */
|
||||
#define OSPF_OPTION_E 0x02
|
||||
@ -262,10 +211,8 @@ struct ospf
|
||||
struct thread *t_opaque_lsa_self; /* Type-11 Opaque-LSAs origin event. */
|
||||
#endif /* HAVE_OPAQUE_LSA */
|
||||
|
||||
#define OSFP_LSA_MAXAGE_REMOVE_DELAY_DEFAULT 60
|
||||
unsigned int maxage_delay; /* Delay on Maxage remover timer, sec */
|
||||
struct thread *t_maxage; /* MaxAge LSA remover timer. */
|
||||
#define OSPF_LSA_MAXAGE_CHECK_INTERVAL 30
|
||||
struct thread *t_maxage_walker; /* MaxAge LSA checking timer. */
|
||||
|
||||
struct thread *t_deferred_shutdown; /* deferred/stub-router shutdown timer*/
|
||||
|
Loading…
Reference in New Issue
Block a user