2002-12-13 21:15:29 +01:00
|
|
|
/* OSPF SPF calculation.
|
2017-05-13 10:25:29 +02:00
|
|
|
* Copyright (C) 1999, 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 this program; see the file COPYING; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
|
2017-01-17 22:05:56 +01:00
|
|
|
#include "monotime.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
#include "thread.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "hash.h"
|
|
|
|
#include "linklist.h"
|
|
|
|
#include "prefix.h"
|
|
|
|
#include "if.h"
|
|
|
|
#include "table.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "sockunion.h" /* for inet_ntop () */
|
|
|
|
|
|
|
|
#include "ospfd/ospfd.h"
|
|
|
|
#include "ospfd/ospf_interface.h"
|
|
|
|
#include "ospfd/ospf_ism.h"
|
|
|
|
#include "ospfd/ospf_asbr.h"
|
|
|
|
#include "ospfd/ospf_lsa.h"
|
|
|
|
#include "ospfd/ospf_lsdb.h"
|
|
|
|
#include "ospfd/ospf_neighbor.h"
|
|
|
|
#include "ospfd/ospf_nsm.h"
|
|
|
|
#include "ospfd/ospf_spf.h"
|
|
|
|
#include "ospfd/ospf_route.h"
|
|
|
|
#include "ospfd/ospf_ia.h"
|
|
|
|
#include "ospfd/ospf_ase.h"
|
|
|
|
#include "ospfd/ospf_abr.h"
|
|
|
|
#include "ospfd/ospf_dump.h"
|
2018-01-18 19:11:11 +01:00
|
|
|
#include "ospfd/ospf_sr.h"
|
2020-08-05 10:44:21 +02:00
|
|
|
#include "ospfd/ospf_ti_lfa.h"
|
2018-08-21 15:36:28 +02:00
|
|
|
#include "ospfd/ospf_errors.h"
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2015-05-20 01:36:05 +02:00
|
|
|
/* Variables to ensure a SPF scheduled log message is printed only once */
|
|
|
|
|
|
|
|
static unsigned int spf_reason_flags = 0;
|
|
|
|
|
2019-01-31 02:58:52 +01:00
|
|
|
/* dummy vertex to flag "in spftree" */
|
|
|
|
static const struct vertex vertex_in_spftree = {};
|
|
|
|
#define LSA_SPF_IN_SPFTREE (struct vertex *)&vertex_in_spftree
|
|
|
|
#define LSA_SPF_NOT_EXPLORED NULL
|
|
|
|
|
2014-10-09 15:19:51 +02:00
|
|
|
static void ospf_clear_spf_reason_flags(void)
|
2015-05-20 01:36:05 +02:00
|
|
|
{
|
|
|
|
spf_reason_flags = 0;
|
|
|
|
}
|
|
|
|
|
2014-10-09 15:19:51 +02:00
|
|
|
static void ospf_spf_set_reason(ospf_spf_reason_t reason)
|
2015-05-20 01:36:05 +02:00
|
|
|
{
|
2014-10-09 15:19:51 +02:00
|
|
|
spf_reason_flags |= 1 << reason;
|
2015-05-20 01:36:05 +02:00
|
|
|
}
|
|
|
|
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
static void ospf_vertex_free(void *);
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* Heap related functions, for the managment of the candidates, to
|
|
|
|
* be used with pqueue.
|
|
|
|
*/
|
2019-01-31 02:58:52 +01:00
|
|
|
static int vertex_cmp(const struct vertex *v1, const struct vertex *v2)
|
2005-02-23 12:29:02 +01:00
|
|
|
{
|
2019-01-31 02:58:52 +01:00
|
|
|
if (v1->distance != v2->distance)
|
|
|
|
return v1->distance - v2->distance;
|
|
|
|
|
|
|
|
if (v1->type != v2->type) {
|
|
|
|
switch (v1->type) {
|
|
|
|
case OSPF_VERTEX_NETWORK:
|
|
|
|
return -1;
|
|
|
|
case OSPF_VERTEX_ROUTER:
|
|
|
|
return 1;
|
|
|
|
}
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
}
|
|
|
|
return 0;
|
2005-02-23 12:29:02 +01:00
|
|
|
}
|
2019-01-31 02:58:52 +01:00
|
|
|
DECLARE_SKIPLIST_NONUNIQ(vertex_pqueue, struct vertex, pqi, vertex_cmp)
|
2005-02-23 12:29:02 +01:00
|
|
|
|
2019-01-31 02:58:52 +01:00
|
|
|
static void lsdb_clean_stat(struct ospf_lsdb *lsdb)
|
2005-02-23 12:29:02 +01:00
|
|
|
{
|
2019-01-31 02:58:52 +01:00
|
|
|
struct route_table *table;
|
|
|
|
struct route_node *rn;
|
|
|
|
struct ospf_lsa *lsa;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = OSPF_MIN_LSA; i < OSPF_MAX_LSA; i++) {
|
|
|
|
table = lsdb->type[i].db;
|
|
|
|
for (rn = route_top(table); rn; rn = route_next(rn))
|
|
|
|
if ((lsa = (rn->info)) != NULL)
|
|
|
|
lsa->stat = LSA_SPF_NOT_EXPLORED;
|
|
|
|
}
|
2005-02-23 12:29:02 +01:00
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2005-05-06 23:37:42 +02:00
|
|
|
static struct vertex_nexthop *vertex_nexthop_new(void)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
return XCALLOC(MTYPE_OSPF_NEXTHOP, sizeof(struct vertex_nexthop));
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void vertex_nexthop_free(struct vertex_nexthop *nh)
|
|
|
|
{
|
|
|
|
XFREE(MTYPE_OSPF_NEXTHOP, nh);
|
|
|
|
}
|
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* Free the canonical nexthop objects for an area, ie the nexthop objects
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
* attached to the first-hop router vertices, and any intervening network
|
|
|
|
* vertices.
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
*/
|
|
|
|
static void ospf_canonical_nexthops_free(struct vertex *root)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
struct listnode *node, *nnode;
|
|
|
|
struct vertex *child;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
for (ALL_LIST_ELEMENTS(root->children, node, nnode, child)) {
|
|
|
|
struct listnode *n2, *nn2;
|
|
|
|
struct vertex_parent *vp;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* router vertices through an attached network each
|
2005-11-11 13:10:03 +01:00
|
|
|
* have a distinct (canonical / not inherited) nexthop
|
|
|
|
* which must be freed.
|
|
|
|
*
|
|
|
|
* A network vertex can only have router vertices as its
|
|
|
|
* children, so only one level of recursion is possible.
|
|
|
|
*/
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
if (child->type == OSPF_VERTEX_NETWORK)
|
|
|
|
ospf_canonical_nexthops_free(child);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-11-11 13:10:03 +01:00
|
|
|
/* Free child nexthops pointing back to this root vertex */
|
2020-10-26 12:27:09 +01:00
|
|
|
for (ALL_LIST_ELEMENTS(child->parents, n2, nn2, vp)) {
|
2017-08-15 03:57:46 +02:00
|
|
|
if (vp->parent == root && vp->nexthop) {
|
2005-11-11 13:10:03 +01:00
|
|
|
vertex_nexthop_free(vp->nexthop);
|
2017-08-15 03:57:46 +02:00
|
|
|
vp->nexthop = NULL;
|
2020-08-05 10:44:21 +02:00
|
|
|
if (vp->local_nexthop) {
|
|
|
|
vertex_nexthop_free(vp->local_nexthop);
|
|
|
|
vp->local_nexthop = NULL;
|
|
|
|
}
|
2017-08-15 03:57:46 +02:00
|
|
|
}
|
2020-10-26 12:27:09 +01:00
|
|
|
}
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
}
|
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* TODO: Parent list should be excised, in favour of maintaining only
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
* vertex_nexthop, with refcounts.
|
|
|
|
*/
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
static struct vertex_parent *vertex_parent_new(struct vertex *v, int backlink,
|
2020-08-05 10:44:21 +02:00
|
|
|
struct vertex_nexthop *hop,
|
|
|
|
struct vertex_nexthop *lhop)
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
{
|
|
|
|
struct vertex_parent *new;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
new = XMALLOC(MTYPE_OSPF_VERTEX_PARENT, sizeof(struct vertex_parent));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
new->parent = v;
|
|
|
|
new->backlink = backlink;
|
|
|
|
new->nexthop = hop;
|
2020-08-05 10:44:21 +02:00
|
|
|
new->local_nexthop = lhop;
|
2020-08-05 16:16:57 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
return new;
|
|
|
|
}
|
2003-06-07 01:27:04 +02:00
|
|
|
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
static void vertex_parent_free(void *p)
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
{
|
|
|
|
XFREE(MTYPE_OSPF_VERTEX_PARENT, p);
|
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2020-08-05 10:44:21 +02:00
|
|
|
int vertex_parent_cmp(void *aa, void *bb)
|
2019-04-16 21:33:06 +02:00
|
|
|
{
|
|
|
|
struct vertex_parent *a = aa, *b = bb;
|
|
|
|
return IPV4_ADDR_CMP(&a->nexthop->router, &b->nexthop->router);
|
|
|
|
}
|
|
|
|
|
2020-08-25 16:13:08 +02:00
|
|
|
static struct vertex *ospf_vertex_new(struct ospf_area *area,
|
|
|
|
struct ospf_lsa *lsa)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct vertex *new;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
new = XCALLOC(MTYPE_OSPF_VERTEX, sizeof(struct vertex));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
new->flags = 0;
|
|
|
|
new->type = lsa->data->type;
|
|
|
|
new->id = lsa->data->id;
|
|
|
|
new->lsa = lsa->data;
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
new->children = list_new();
|
|
|
|
new->parents = list_new();
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
new->parents->del = vertex_parent_free;
|
2019-04-16 21:33:06 +02:00
|
|
|
new->parents->cmp = vertex_parent_cmp;
|
2019-01-31 02:58:52 +01:00
|
|
|
new->lsa_p = lsa;
|
|
|
|
|
|
|
|
lsa->stat = new;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-25 16:13:08 +02:00
|
|
|
listnode_add(area->spf_vertex_list, new);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2020-10-21 19:56:26 +02:00
|
|
|
zlog_debug("%s: Created %s vertex %pI4", __func__,
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
new->type == OSPF_VERTEX_ROUTER ? "Router"
|
|
|
|
: "Network",
|
2020-10-21 19:56:26 +02:00
|
|
|
&new->lsa->id);
|
2020-08-05 16:16:57 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
static void ospf_vertex_free(void *data)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
struct vertex *v = data;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2020-10-21 19:56:26 +02:00
|
|
|
zlog_debug("%s: Free %s vertex %pI4", __func__,
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
|
2020-10-21 19:56:26 +02:00
|
|
|
&v->lsa->id);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
if (v->children)
|
2018-10-02 11:39:51 +02:00
|
|
|
list_delete(&v->children);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
if (v->parents)
|
2018-10-02 11:39:51 +02:00
|
|
|
list_delete(&v->parents);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
v->lsa = NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
XFREE(MTYPE_OSPF_VERTEX, v);
|
|
|
|
}
|
|
|
|
|
2004-10-08 10:17:22 +02:00
|
|
|
static void ospf_vertex_dump(const char *msg, struct vertex *v,
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
int print_parents, int print_children)
|
2004-08-31 19:28:41 +02:00
|
|
|
{
|
|
|
|
if (!IS_DEBUG_OSPF_EVENT)
|
|
|
|
return;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-10-21 19:56:26 +02:00
|
|
|
zlog_debug("%s %s vertex %pI4 distance %u flags %u", msg,
|
2004-08-31 19:28:41 +02:00
|
|
|
v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
|
2020-10-21 19:56:26 +02:00
|
|
|
&v->lsa->id, v->distance, (unsigned int)v->flags);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
if (print_parents) {
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
struct listnode *node;
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
struct vertex_parent *vp;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO(v->parents, node, vp)) {
|
|
|
|
if (vp) {
|
|
|
|
zlog_debug(
|
2021-03-10 02:00:45 +01:00
|
|
|
"parent %pI4 backlink %d nexthop %pI4 lsa pos %d",
|
|
|
|
&vp->parent->lsa->id, vp->backlink,
|
|
|
|
&vp->nexthop->router,
|
2020-08-07 14:13:07 +02:00
|
|
|
vp->nexthop->lsa_pos);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
}
|
2004-08-31 19:28:41 +02:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2004-08-31 19:28:41 +02:00
|
|
|
if (print_children) {
|
2004-09-23 21:18:23 +02:00
|
|
|
struct listnode *cnode;
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
struct vertex *cv;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO(v->children, cnode, cv))
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
ospf_vertex_dump(" child:", cv, 0, 0);
|
2004-08-31 19:28:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Add a vertex to the list of children in each of its parents. */
|
2002-12-13 21:15:29 +01:00
|
|
|
static void ospf_vertex_add_parent(struct vertex *v)
|
|
|
|
{
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
struct vertex_parent *vp;
|
2004-09-23 21:18:23 +02:00
|
|
|
struct listnode *node;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
assert(v && v->parents);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO(v->parents, node, vp)) {
|
|
|
|
assert(vp->parent && vp->parent->children);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* No need to add two links from the same parent. */
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
if (listnode_lookup(vp->parent->children, v) == NULL)
|
|
|
|
listnode_add(vp->parent->children, v);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2020-08-05 10:44:21 +02:00
|
|
|
/* Find a vertex according to its router id */
|
|
|
|
struct vertex *ospf_spf_vertex_find(struct in_addr id, struct list *vertex_list)
|
|
|
|
{
|
|
|
|
struct listnode *node;
|
|
|
|
struct vertex *found;
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(vertex_list, node, found)) {
|
|
|
|
if (found->id.s_addr == id.s_addr)
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-10-22 12:05:39 +02:00
|
|
|
/* Find a vertex parent according to its router id */
|
|
|
|
struct vertex_parent *ospf_spf_vertex_parent_find(struct in_addr id,
|
|
|
|
struct vertex *vertex)
|
|
|
|
{
|
|
|
|
struct listnode *node;
|
|
|
|
struct vertex_parent *found;
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(vertex->parents, node, found)) {
|
|
|
|
if (found->parent->id.s_addr == id.s_addr)
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-10-26 12:27:09 +01:00
|
|
|
struct vertex *ospf_spf_vertex_by_nexthop(struct vertex *root,
|
|
|
|
struct in_addr *nexthop)
|
|
|
|
{
|
|
|
|
struct listnode *node;
|
|
|
|
struct vertex *child;
|
|
|
|
struct vertex_parent *vertex_parent;
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(root->children, node, child)) {
|
|
|
|
vertex_parent = ospf_spf_vertex_parent_find(root->id, child);
|
|
|
|
if (vertex_parent->nexthop->router.s_addr == nexthop->s_addr)
|
|
|
|
return child;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-08-05 10:44:21 +02:00
|
|
|
/* Create a deep copy of a SPF vertex without children and parents */
|
|
|
|
static struct vertex *ospf_spf_vertex_copy(struct vertex *vertex)
|
|
|
|
{
|
|
|
|
struct vertex *copy;
|
|
|
|
|
|
|
|
copy = XCALLOC(MTYPE_OSPF_VERTEX, sizeof(struct vertex));
|
|
|
|
|
|
|
|
memcpy(copy, vertex, sizeof(struct vertex));
|
|
|
|
copy->parents = list_new();
|
|
|
|
copy->parents->del = vertex_parent_free;
|
|
|
|
copy->parents->cmp = vertex_parent_cmp;
|
|
|
|
copy->children = list_new();
|
|
|
|
|
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create a deep copy of a SPF vertex_parent */
|
|
|
|
static struct vertex_parent *
|
|
|
|
ospf_spf_vertex_parent_copy(struct vertex_parent *vertex_parent)
|
|
|
|
{
|
|
|
|
struct vertex_parent *vertex_parent_copy;
|
|
|
|
struct vertex_nexthop *nexthop_copy, *local_nexthop_copy;
|
|
|
|
|
|
|
|
vertex_parent_copy =
|
|
|
|
XCALLOC(MTYPE_OSPF_VERTEX, sizeof(struct vertex_parent));
|
2020-10-26 12:27:09 +01:00
|
|
|
|
|
|
|
nexthop_copy = vertex_nexthop_new();
|
|
|
|
local_nexthop_copy = vertex_nexthop_new();
|
2020-08-05 10:44:21 +02:00
|
|
|
|
|
|
|
memcpy(vertex_parent_copy, vertex_parent, sizeof(struct vertex_parent));
|
|
|
|
memcpy(nexthop_copy, vertex_parent->nexthop,
|
|
|
|
sizeof(struct vertex_nexthop));
|
|
|
|
memcpy(local_nexthop_copy, vertex_parent->local_nexthop,
|
|
|
|
sizeof(struct vertex_nexthop));
|
|
|
|
|
|
|
|
vertex_parent_copy->nexthop = nexthop_copy;
|
|
|
|
vertex_parent_copy->local_nexthop = local_nexthop_copy;
|
|
|
|
|
|
|
|
return vertex_parent_copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create a deep copy of a SPF tree */
|
|
|
|
void ospf_spf_copy(struct vertex *vertex, struct list *vertex_list)
|
|
|
|
{
|
|
|
|
struct listnode *node;
|
|
|
|
struct vertex *vertex_copy, *child, *child_copy, *parent_copy;
|
|
|
|
struct vertex_parent *vertex_parent, *vertex_parent_copy;
|
|
|
|
|
|
|
|
/* First check if the node is already in the vertex list */
|
|
|
|
vertex_copy = ospf_spf_vertex_find(vertex->id, vertex_list);
|
|
|
|
if (!vertex_copy) {
|
|
|
|
vertex_copy = ospf_spf_vertex_copy(vertex);
|
|
|
|
listnode_add(vertex_list, vertex_copy);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy all parents, create parent nodes if necessary */
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(vertex->parents, node, vertex_parent)) {
|
|
|
|
parent_copy = ospf_spf_vertex_find(vertex_parent->parent->id,
|
|
|
|
vertex_list);
|
|
|
|
if (!parent_copy) {
|
|
|
|
parent_copy =
|
|
|
|
ospf_spf_vertex_copy(vertex_parent->parent);
|
|
|
|
listnode_add(vertex_list, parent_copy);
|
|
|
|
}
|
|
|
|
vertex_parent_copy = ospf_spf_vertex_parent_copy(vertex_parent);
|
|
|
|
vertex_parent_copy->parent = parent_copy;
|
|
|
|
listnode_add(vertex_copy->parents, vertex_parent_copy);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy all children, create child nodes if necessary */
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(vertex->children, node, child)) {
|
|
|
|
child_copy = ospf_spf_vertex_find(child->id, vertex_list);
|
|
|
|
if (!child_copy) {
|
|
|
|
child_copy = ospf_spf_vertex_copy(child);
|
|
|
|
listnode_add(vertex_list, child_copy);
|
|
|
|
}
|
|
|
|
listnode_add(vertex_copy->children, child_copy);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Finally continue copying with child nodes */
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(vertex->children, node, child))
|
|
|
|
ospf_spf_copy(child, vertex_list);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ospf_spf_remove_branch(struct vertex_parent *vertex_parent,
|
|
|
|
struct vertex *child,
|
|
|
|
struct list *vertex_list)
|
|
|
|
{
|
|
|
|
struct listnode *node, *nnode, *inner_node, *inner_nnode;
|
|
|
|
struct vertex *grandchild;
|
|
|
|
struct vertex_parent *vertex_parent_found;
|
|
|
|
bool has_more_links = false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* First check if there are more nexthops for that parent to that child
|
|
|
|
*/
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(child->parents, node, vertex_parent_found)) {
|
|
|
|
if (vertex_parent_found->parent->id.s_addr
|
|
|
|
== vertex_parent->parent->id.s_addr
|
|
|
|
&& vertex_parent_found->nexthop->router.s_addr
|
|
|
|
!= vertex_parent->nexthop->router.s_addr)
|
|
|
|
has_more_links = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No more links from that parent? Then delete the child from its
|
|
|
|
* children list.
|
|
|
|
*/
|
|
|
|
if (!has_more_links)
|
|
|
|
listnode_delete(vertex_parent->parent->children, child);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Delete the vertex_parent from the child parents list, this needs to
|
|
|
|
* be done anyway.
|
|
|
|
*/
|
|
|
|
listnode_delete(child->parents, vertex_parent);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Are there actually more parents left? If not, then delete the child!
|
|
|
|
* This is done by recursively removing the links to the grandchildren,
|
|
|
|
* such that finally the child can be removed without leaving unused
|
|
|
|
* partial branches.
|
|
|
|
*/
|
|
|
|
if (child->parents->count == 0) {
|
|
|
|
for (ALL_LIST_ELEMENTS(child->children, node, nnode,
|
|
|
|
grandchild)) {
|
|
|
|
for (ALL_LIST_ELEMENTS(grandchild->parents, inner_node,
|
|
|
|
inner_nnode,
|
|
|
|
vertex_parent_found)) {
|
|
|
|
ospf_spf_remove_branch(vertex_parent_found,
|
|
|
|
grandchild, vertex_list);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
listnode_delete(vertex_list, child);
|
|
|
|
ospf_vertex_free(child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-26 12:27:09 +01:00
|
|
|
static int ospf_spf_remove_link(struct vertex *vertex, struct list *vertex_list,
|
|
|
|
struct router_lsa_link *link)
|
2020-08-05 10:44:21 +02:00
|
|
|
{
|
|
|
|
struct listnode *node, *inner_node;
|
|
|
|
struct vertex *child;
|
|
|
|
struct vertex_parent *vertex_parent;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Identify the node who shares a subnet (given by the link) with a
|
|
|
|
* child and remove the branch of this particular child.
|
|
|
|
*/
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(vertex->children, node, child)) {
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(child->parents, inner_node,
|
|
|
|
vertex_parent)) {
|
|
|
|
if ((vertex_parent->local_nexthop->router.s_addr
|
|
|
|
& link->link_data.s_addr)
|
|
|
|
== (link->link_id.s_addr
|
|
|
|
& link->link_data.s_addr)) {
|
|
|
|
ospf_spf_remove_branch(vertex_parent, child,
|
|
|
|
vertex_list);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No link found yet, move on recursively */
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(vertex->children, node, child)) {
|
|
|
|
if (ospf_spf_remove_link(child, vertex_list, link) == 0)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* link was not removed yet */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-10-26 12:27:09 +01:00
|
|
|
void ospf_spf_remove_resource(struct vertex *vertex, struct list *vertex_list,
|
|
|
|
struct protected_resource *resource)
|
|
|
|
{
|
|
|
|
struct listnode *node, *nnode;
|
|
|
|
struct vertex *found;
|
|
|
|
struct vertex_parent *vertex_parent;
|
|
|
|
|
|
|
|
switch (resource->type) {
|
|
|
|
case OSPF_TI_LFA_LINK_PROTECTION:
|
|
|
|
ospf_spf_remove_link(vertex, vertex_list, resource->link);
|
|
|
|
break;
|
|
|
|
case OSPF_TI_LFA_NODE_PROTECTION:
|
|
|
|
found = ospf_spf_vertex_find(resource->router_id, vertex_list);
|
|
|
|
if (!found)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove the node by removing all links from its parents. Note
|
|
|
|
* that the child is automatically removed here with the last
|
|
|
|
* link from a parent, hence no explicit removal of the node.
|
|
|
|
*/
|
|
|
|
for (ALL_LIST_ELEMENTS(found->parents, node, nnode,
|
|
|
|
vertex_parent))
|
|
|
|
ospf_spf_remove_branch(vertex_parent, found,
|
|
|
|
vertex_list);
|
|
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* do nothing */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-07 14:13:07 +02:00
|
|
|
static void ospf_spf_init(struct ospf_area *area, struct ospf_lsa *root_lsa,
|
2020-08-17 15:04:41 +02:00
|
|
|
bool is_dry_run, bool is_root_node)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2020-08-25 16:13:08 +02:00
|
|
|
struct list *vertex_list;
|
2002-12-13 21:15:29 +01:00
|
|
|
struct vertex *v;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-25 16:13:08 +02:00
|
|
|
/* Create vertex list */
|
|
|
|
vertex_list = list_new();
|
|
|
|
vertex_list->del = ospf_vertex_free;
|
|
|
|
area->spf_vertex_list = vertex_list;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-25 16:13:08 +02:00
|
|
|
/* Create root node. */
|
|
|
|
v = ospf_vertex_new(area, root_lsa);
|
2002-12-13 21:15:29 +01:00
|
|
|
area->spf = v;
|
2020-08-25 16:13:08 +02:00
|
|
|
|
2020-08-07 14:13:07 +02:00
|
|
|
area->spf_dry_run = is_dry_run;
|
2020-08-17 15:04:41 +02:00
|
|
|
area->spf_root_node = is_root_node;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Reset ABR and ASBR router counts. */
|
|
|
|
area->abr_count = 0;
|
|
|
|
area->asbr_count = 0;
|
|
|
|
}
|
|
|
|
|
2004-04-08 09:43:45 +02:00
|
|
|
/* return index of link back to V from W, or -1 if no link found */
|
2002-12-13 21:15:29 +01:00
|
|
|
static int ospf_lsa_has_link(struct lsa_header *w, struct lsa_header *v)
|
|
|
|
{
|
2004-10-08 10:17:22 +02:00
|
|
|
unsigned int i, length;
|
2002-12-13 21:15:29 +01:00
|
|
|
struct router_lsa *rl;
|
|
|
|
struct network_lsa *nl;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* In case of W is Network LSA. */
|
|
|
|
if (w->type == OSPF_NETWORK_LSA) {
|
|
|
|
if (v->type == OSPF_NETWORK_LSA)
|
2004-04-08 09:43:45 +02:00
|
|
|
return -1;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
nl = (struct network_lsa *)w;
|
|
|
|
length = (ntohs(w->length) - OSPF_LSA_HEADER_SIZE - 4) / 4;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
if (IPV4_ADDR_SAME(&nl->routers[i], &v->id))
|
2004-04-08 09:43:45 +02:00
|
|
|
return i;
|
|
|
|
return -1;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* In case of W is Router LSA. */
|
|
|
|
if (w->type == OSPF_ROUTER_LSA) {
|
|
|
|
rl = (struct router_lsa *)w;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
length = ntohs(w->length);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-06-07 01:27:04 +02:00
|
|
|
for (i = 0; i < ntohs(rl->links)
|
|
|
|
&& length >= sizeof(struct router_lsa);
|
|
|
|
i++, length -= 12) {
|
2002-12-13 21:15:29 +01:00
|
|
|
switch (rl->link[i].type) {
|
|
|
|
case LSA_LINK_TYPE_POINTOPOINT:
|
|
|
|
case LSA_LINK_TYPE_VIRTUALLINK:
|
|
|
|
/* Router LSA ID. */
|
|
|
|
if (v->type == OSPF_ROUTER_LSA
|
|
|
|
&& IPV4_ADDR_SAME(&rl->link[i].link_id,
|
|
|
|
&v->id)) {
|
2004-04-08 09:43:45 +02:00
|
|
|
return i;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LSA_LINK_TYPE_TRANSIT:
|
|
|
|
/* Network LSA ID. */
|
|
|
|
if (v->type == OSPF_NETWORK_LSA
|
|
|
|
&& IPV4_ADDR_SAME(&rl->link[i].link_id,
|
|
|
|
&v->id)) {
|
2004-04-08 09:43:45 +02:00
|
|
|
return i;
|
2003-06-07 01:27:04 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
break;
|
|
|
|
case LSA_LINK_TYPE_STUB:
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
/* Stub can't lead anywhere, carry on */
|
2002-12-13 21:15:29 +01:00
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-04-08 09:43:45 +02:00
|
|
|
return -1;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* Find the next link after prev_link from v to w. If prev_link is
|
2004-08-31 19:28:41 +02:00
|
|
|
* NULL, return the first link from v to w. Ignore stub and virtual links;
|
|
|
|
* these link types will never be returned.
|
|
|
|
*/
|
2005-05-06 23:37:42 +02:00
|
|
|
static struct router_lsa_link *
|
2002-12-13 21:15:29 +01:00
|
|
|
ospf_get_next_link(struct vertex *v, struct vertex *w,
|
2003-06-07 01:27:04 +02:00
|
|
|
struct router_lsa_link *prev_link)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t *p;
|
|
|
|
uint8_t *lim;
|
|
|
|
uint8_t lsa_type = LSA_LINK_TYPE_TRANSIT;
|
2002-12-13 21:15:29 +01:00
|
|
|
struct router_lsa_link *l;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2009-07-27 12:42:31 +02:00
|
|
|
if (w->type == OSPF_VERTEX_ROUTER)
|
|
|
|
lsa_type = LSA_LINK_TYPE_POINTOPOINT;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
if (prev_link == NULL)
|
2018-03-27 21:13:34 +02:00
|
|
|
p = ((uint8_t *)v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
|
2002-12-13 21:15:29 +01:00
|
|
|
else {
|
2018-03-27 21:13:34 +02:00
|
|
|
p = (uint8_t *)prev_link;
|
2011-08-23 09:36:27 +02:00
|
|
|
p += (OSPF_ROUTER_LSA_LINK_SIZE
|
|
|
|
+ (prev_link->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2003-06-07 01:27:04 +02:00
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
lim = ((uint8_t *)v->lsa) + ntohs(v->lsa->length);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
while (p < lim) {
|
|
|
|
l = (struct router_lsa_link *)p;
|
|
|
|
|
2011-08-23 09:36:27 +02:00
|
|
|
p += (OSPF_ROUTER_LSA_LINK_SIZE
|
|
|
|
+ (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2009-07-27 12:42:31 +02:00
|
|
|
if (l->m[0].type != lsa_type)
|
2003-06-07 01:27:04 +02:00
|
|
|
continue;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
if (IPV4_ADDR_SAME(&l->link_id, &w->id))
|
2003-06-07 01:27:04 +02:00
|
|
|
return l;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-01-24 15:51:51 +01:00
|
|
|
static void ospf_spf_flush_parents(struct vertex *w)
|
|
|
|
{
|
|
|
|
struct vertex_parent *vp;
|
|
|
|
struct listnode *ln, *nn;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2007-01-24 15:51:51 +01:00
|
|
|
/* delete the existing nexthops */
|
|
|
|
for (ALL_LIST_ELEMENTS(w->parents, ln, nn, vp)) {
|
|
|
|
list_delete_node(w->parents, ln);
|
|
|
|
vertex_parent_free(vp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-05 11:10:31 +02:00
|
|
|
/*
|
|
|
|
* Consider supplied next-hop for inclusion to the supplied list of
|
|
|
|
* equal-cost next-hops, adjust list as neccessary.
|
2003-06-07 01:23:36 +02:00
|
|
|
*/
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
static void ospf_spf_add_parent(struct vertex *v, struct vertex *w,
|
2007-01-24 15:51:51 +01:00
|
|
|
struct vertex_nexthop *newhop,
|
2020-08-05 10:44:21 +02:00
|
|
|
struct vertex_nexthop *newlhop,
|
2007-02-26 18:14:48 +01:00
|
|
|
unsigned int distance)
|
2003-06-07 01:23:36 +02:00
|
|
|
{
|
2012-07-23 18:17:57 +02:00
|
|
|
struct vertex_parent *vp, *wp;
|
|
|
|
struct listnode *node;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2007-05-07 18:38:35 +02:00
|
|
|
/* we must have a newhop, and a distance */
|
2007-02-26 18:14:48 +01:00
|
|
|
assert(v && w && newhop);
|
2007-05-07 18:38:35 +02:00
|
|
|
assert(distance);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* IFF w has already been assigned a distance, then we shouldn't get
|
|
|
|
* here unless callers have determined V(l)->W is shortest /
|
|
|
|
* equal-shortest path (0 is a special case distance (no distance yet
|
|
|
|
* assigned)).
|
2007-01-24 15:51:51 +01:00
|
|
|
*/
|
2007-05-07 18:38:35 +02:00
|
|
|
if (w->distance)
|
|
|
|
assert(distance <= w->distance);
|
|
|
|
else
|
|
|
|
w->distance = distance;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2021-03-10 02:00:45 +01:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
|
|
|
zlog_debug("%s: Adding %pI4 as parent of %pI4", __func__,
|
|
|
|
&v->lsa->id, &w->lsa->id);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* Adding parent for a new, better path: flush existing parents from W.
|
2007-01-24 15:51:51 +01:00
|
|
|
*/
|
2007-02-26 18:14:48 +01:00
|
|
|
if (distance < w->distance) {
|
2007-03-23 12:17:28 +01:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
|
|
|
zlog_debug(
|
|
|
|
"%s: distance %d better than %d, flushing existing parents",
|
|
|
|
__func__, distance, w->distance);
|
2007-01-24 15:51:51 +01:00
|
|
|
ospf_spf_flush_parents(w);
|
2007-02-26 18:14:48 +01:00
|
|
|
w->distance = distance;
|
2007-01-24 15:51:51 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* new parent is <= existing parents, add it to parent list (if nexthop
|
2012-07-23 18:17:57 +02:00
|
|
|
* not on parent list)
|
|
|
|
*/
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(w->parents, node, wp)) {
|
|
|
|
if (memcmp(newhop, wp->nexthop, sizeof(*newhop)) == 0) {
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
|
|
|
zlog_debug(
|
|
|
|
"%s: ... nexthop already on parent list, skipping add",
|
|
|
|
__func__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-05 10:44:21 +02:00
|
|
|
vp = vertex_parent_new(v, ospf_lsa_has_link(w->lsa, v->lsa), newhop,
|
|
|
|
newlhop);
|
2019-04-16 21:33:06 +02:00
|
|
|
listnode_add_sort(w->parents, vp);
|
2003-06-07 01:27:04 +02:00
|
|
|
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-08-07 14:13:07 +02:00
|
|
|
static int match_stub_prefix(struct lsa_header *lsa, struct in_addr v_link_addr,
|
|
|
|
struct in_addr w_link_addr)
|
|
|
|
{
|
|
|
|
uint8_t *p, *lim;
|
|
|
|
struct router_lsa_link *l = NULL;
|
|
|
|
struct in_addr masked_lsa_addr;
|
|
|
|
|
|
|
|
if (lsa->type != OSPF_ROUTER_LSA)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
p = ((uint8_t *)lsa) + OSPF_LSA_HEADER_SIZE + 4;
|
|
|
|
lim = ((uint8_t *)lsa) + ntohs(lsa->length);
|
|
|
|
|
|
|
|
while (p < lim) {
|
|
|
|
l = (struct router_lsa_link *)p;
|
|
|
|
p += (OSPF_ROUTER_LSA_LINK_SIZE
|
|
|
|
+ (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
|
|
|
|
|
|
|
|
if (l->m[0].type != LSA_LINK_TYPE_STUB)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
masked_lsa_addr.s_addr =
|
|
|
|
(l->link_id.s_addr & l->link_data.s_addr);
|
|
|
|
|
|
|
|
/* check that both links belong to the same stub subnet */
|
|
|
|
if ((masked_lsa_addr.s_addr
|
|
|
|
== (v_link_addr.s_addr & l->link_data.s_addr))
|
|
|
|
&& (masked_lsa_addr.s_addr
|
|
|
|
== (w_link_addr.s_addr & l->link_data.s_addr)))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* 16.1.1. Calculate nexthop from root through V (parent) to
|
2007-02-26 18:14:48 +01:00
|
|
|
* vertex W (destination), with given distance from root->W.
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
*
|
|
|
|
* The link must be supplied if V is the root vertex. In all other cases
|
|
|
|
* it may be NULL.
|
2007-02-26 18:14:48 +01:00
|
|
|
*
|
|
|
|
* Note that this function may fail, hence the state of the destination
|
|
|
|
* vertex, W, should /not/ be modified in a dependent manner until
|
|
|
|
* this function returns. This function will update the W vertex with the
|
|
|
|
* provided distance as appropriate.
|
2004-08-31 19:28:41 +02:00
|
|
|
*/
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
static unsigned int ospf_nexthop_calculation(struct ospf_area *area,
|
2007-02-26 18:14:48 +01:00
|
|
|
struct vertex *v, struct vertex *w,
|
|
|
|
struct router_lsa_link *l,
|
2012-07-07 17:06:11 +02:00
|
|
|
unsigned int distance, int lsa_pos)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
struct listnode *node, *nnode;
|
2020-08-05 10:44:21 +02:00
|
|
|
struct vertex_nexthop *nh, *lnh;
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
struct vertex_parent *vp;
|
2004-08-31 19:28:41 +02:00
|
|
|
unsigned int added = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2012-07-07 17:06:11 +02:00
|
|
|
if (IS_DEBUG_OSPF_EVENT) {
|
|
|
|
zlog_debug("ospf_nexthop_calculation(): Start");
|
|
|
|
ospf_vertex_dump("V (parent):", v, 1, 1);
|
2004-08-31 19:28:41 +02:00
|
|
|
ospf_vertex_dump("W (dest) :", w, 1, 1);
|
2012-07-07 17:06:11 +02:00
|
|
|
zlog_debug("V->W distance: %d", distance);
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
if (v == area->spf) {
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* 16.1.1 para 4. In the first case, the parent vertex (V) is
|
|
|
|
* the root (the calculating router itself). This means that
|
|
|
|
* the destination is either a directly connected network or
|
|
|
|
* directly connected router. The outgoing interface in this
|
|
|
|
* case is simply the OSPF interface connecting to the
|
|
|
|
* destination network/router.
|
|
|
|
*/
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
/* we *must* be supplied with the link data */
|
|
|
|
assert(l != NULL);
|
2012-07-07 17:06:11 +02:00
|
|
|
|
2021-03-10 02:00:45 +01:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2012-07-07 17:06:11 +02:00
|
|
|
zlog_debug(
|
2021-03-10 02:00:45 +01:00
|
|
|
"%s: considering link type:%d link_id:%pI4 link_data:%pI4",
|
|
|
|
__func__, l->m[0].type, &l->link_id,
|
|
|
|
&l->link_data);
|
2012-07-07 17:06:11 +02:00
|
|
|
|
|
|
|
if (w->type == OSPF_VERTEX_ROUTER) {
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* l is a link from v to w l2 will be link from w to v
|
2017-07-17 14:03:14 +02:00
|
|
|
*/
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
struct router_lsa_link *l2 = NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT) {
|
2020-11-28 21:35:18 +01:00
|
|
|
struct ospf_interface *oi = NULL;
|
|
|
|
struct in_addr nexthop = {.s_addr = 0};
|
|
|
|
|
2020-12-16 16:02:29 +01:00
|
|
|
if (area->spf_root_node) {
|
|
|
|
oi = ospf_if_lookup_by_lsa_pos(area,
|
|
|
|
lsa_pos);
|
|
|
|
if (!oi) {
|
|
|
|
zlog_debug(
|
2021-03-10 02:00:45 +01:00
|
|
|
"%s: OI not found in LSA: lsa_pos: %d link_id:%pI4 link_data:%pI4",
|
2020-12-16 16:02:29 +01:00
|
|
|
__func__, lsa_pos,
|
2021-03-10 02:00:45 +01:00
|
|
|
&l->link_id,
|
|
|
|
&l->link_data);
|
2020-12-16 16:02:29 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2020-11-28 21:35:18 +01:00
|
|
|
}
|
2020-08-17 15:04:41 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* If the destination is a router which connects
|
|
|
|
* to the calculating router via a
|
|
|
|
* Point-to-MultiPoint network, the
|
|
|
|
* destination's next hop IP address(es) can be
|
|
|
|
* determined by examining the destination's
|
|
|
|
* router-LSA: each link pointing back to the
|
|
|
|
* calculating router and having a Link Data
|
|
|
|
* field belonging to the Point-to-MultiPoint
|
|
|
|
* network provides an IP address of the next
|
|
|
|
* hop router.
|
|
|
|
*
|
|
|
|
* At this point l is a link from V to W, and V
|
|
|
|
* is the root ("us"). If it is a point-to-
|
|
|
|
* multipoint interface, then look through the
|
|
|
|
* links in the opposite direction (W to V).
|
|
|
|
* If any of them have an address that lands
|
|
|
|
* within the subnet declared by the PtMP link,
|
|
|
|
* then that link is a constituent of the PtMP
|
|
|
|
* link, and its address is a nexthop address
|
|
|
|
* for V.
|
2020-08-07 14:13:07 +02:00
|
|
|
*
|
|
|
|
* Note for point-to-point interfaces:
|
|
|
|
*
|
|
|
|
* Having nexthop = 0 (as proposed in the RFC)
|
|
|
|
* is tempting, but NOT acceptable. It breaks
|
|
|
|
* AS-External routes with a forwarding address,
|
|
|
|
* since ospf_ase_complete_direct_routes() will
|
|
|
|
* mistakenly assume we've reached the last hop
|
|
|
|
* and should place the forwarding address as
|
|
|
|
* nexthop. Also, users may configure multi-
|
|
|
|
* access links in p2p mode, so we need the IP
|
|
|
|
* to ARP the nexthop.
|
|
|
|
*
|
2020-08-17 15:04:41 +02:00
|
|
|
* If the calculating router is the SPF root
|
|
|
|
* node and the link is P2P then access the
|
|
|
|
* interface information directly. This can be
|
|
|
|
* crucial when e.g. IP unnumbered is used
|
|
|
|
* where 'correct' nexthop information are not
|
|
|
|
* available via Router LSAs.
|
|
|
|
*
|
|
|
|
* Otherwise handle P2P and P2MP the same way
|
|
|
|
* as described above using a reverse lookup to
|
|
|
|
* figure out the nexthop.
|
2020-08-05 16:16:57 +02:00
|
|
|
*/
|
2020-12-16 16:02:29 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* HACK: we don't know (yet) how to distinguish
|
|
|
|
* between P2P and P2MP interfaces by just
|
|
|
|
* looking at LSAs, which is important for
|
|
|
|
* TI-LFA since you want to do SPF calculations
|
|
|
|
* from the perspective of other nodes. Since
|
|
|
|
* TI-LFA is currently not implemented for P2MP
|
|
|
|
* we just check here if it is enabled and then
|
|
|
|
* blindly assume that P2P is used. Ultimately
|
|
|
|
* the interface code needs to be removed
|
|
|
|
* somehow.
|
|
|
|
*/
|
|
|
|
if (area->ospf->ti_lfa_enabled
|
|
|
|
|| (oi && oi->type == OSPF_IFTYPE_POINTOPOINT)) {
|
2020-11-28 21:35:18 +01:00
|
|
|
struct ospf_neighbor *nbr_w = NULL;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-11-28 21:35:18 +01:00
|
|
|
/* Calculating node is root node, link
|
|
|
|
* is P2P */
|
|
|
|
if (area->spf_root_node) {
|
2020-08-17 15:04:41 +02:00
|
|
|
nbr_w = ospf_nbr_lookup_by_routerid(
|
|
|
|
oi->nbrs, &l->link_id);
|
|
|
|
if (nbr_w) {
|
|
|
|
added = 1;
|
|
|
|
nexthop = nbr_w->src;
|
|
|
|
}
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-11-28 21:35:18 +01:00
|
|
|
/* Reverse lookup */
|
|
|
|
if (!added) {
|
|
|
|
while ((l2 = ospf_get_next_link(
|
|
|
|
w, v, l2))) {
|
|
|
|
if (match_stub_prefix(
|
|
|
|
v->lsa,
|
|
|
|
l->link_data,
|
|
|
|
l2->link_data)) {
|
|
|
|
added = 1;
|
|
|
|
nexthop =
|
|
|
|
l2->link_data;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-12-16 16:02:29 +01:00
|
|
|
} else if (oi && oi->type
|
2020-11-28 21:35:18 +01:00
|
|
|
== OSPF_IFTYPE_POINTOMULTIPOINT) {
|
|
|
|
struct prefix_ipv4 la;
|
|
|
|
|
|
|
|
la.family = AF_INET;
|
|
|
|
la.prefixlen = oi->address->prefixlen;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* V links to W on PtMP interface;
|
|
|
|
* find the interface address on W
|
|
|
|
*/
|
2020-08-17 15:04:41 +02:00
|
|
|
while ((l2 = ospf_get_next_link(w, v,
|
|
|
|
l2))) {
|
2020-11-28 21:35:18 +01:00
|
|
|
la.prefix = l2->link_data;
|
|
|
|
|
|
|
|
if (prefix_cmp((struct prefix
|
|
|
|
*)&la,
|
|
|
|
oi->address)
|
|
|
|
!= 0)
|
|
|
|
continue;
|
|
|
|
added = 1;
|
|
|
|
nexthop = l2->link_data;
|
|
|
|
break;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-07 17:06:11 +02:00
|
|
|
if (added) {
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
nh = vertex_nexthop_new();
|
2012-07-07 17:06:11 +02:00
|
|
|
nh->router = nexthop;
|
2020-08-07 14:13:07 +02:00
|
|
|
nh->lsa_pos = lsa_pos;
|
2020-08-05 10:44:21 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Since v is the root the nexthop and
|
|
|
|
* local nexthop are the same.
|
|
|
|
*/
|
|
|
|
lnh = vertex_nexthop_new();
|
|
|
|
memcpy(lnh, nh,
|
|
|
|
sizeof(struct vertex_nexthop));
|
|
|
|
|
|
|
|
ospf_spf_add_parent(v, w, nh, lnh,
|
|
|
|
distance);
|
2007-01-24 15:51:51 +01:00
|
|
|
return 1;
|
2017-07-17 14:03:14 +02:00
|
|
|
} else
|
2012-07-07 17:06:11 +02:00
|
|
|
zlog_info(
|
2020-11-28 21:35:18 +01:00
|
|
|
"%s: could not determine nexthop for link %s",
|
2020-12-16 16:02:29 +01:00
|
|
|
__func__, oi ? oi->ifp->name : "");
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
} /* end point-to-point link from V to W */
|
|
|
|
else if (l->m[0].type == LSA_LINK_TYPE_VIRTUALLINK) {
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* VLink implementation limitations:
|
|
|
|
* a) vl_data can only reference one nexthop,
|
|
|
|
* so no ECMP to backbone through VLinks.
|
|
|
|
* Though transit-area summaries may be
|
|
|
|
* considered, and those can be ECMP.
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
* b) We can only use /one/ VLink, even if
|
2020-08-05 16:16:57 +02:00
|
|
|
* multiple ones exist this router through
|
|
|
|
* multiple transit-areas.
|
2017-07-17 14:03:14 +02:00
|
|
|
*/
|
2020-08-07 14:13:07 +02:00
|
|
|
|
|
|
|
struct ospf_vl_data *vl_data;
|
|
|
|
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
vl_data = ospf_vl_lookup(area->ospf, NULL,
|
|
|
|
l->link_id);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
if (vl_data
|
|
|
|
&& CHECK_FLAG(vl_data->flags,
|
|
|
|
OSPF_VL_FLAG_APPROVED)) {
|
|
|
|
nh = vertex_nexthop_new();
|
|
|
|
nh->router = vl_data->nexthop.router;
|
2020-08-07 14:13:07 +02:00
|
|
|
nh->lsa_pos = vl_data->nexthop.lsa_pos;
|
2020-08-05 10:44:21 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Since v is the root the nexthop and
|
|
|
|
* local nexthop are the same.
|
|
|
|
*/
|
|
|
|
lnh = vertex_nexthop_new();
|
|
|
|
memcpy(lnh, nh,
|
|
|
|
sizeof(struct vertex_nexthop));
|
|
|
|
|
|
|
|
ospf_spf_add_parent(v, w, nh, lnh,
|
|
|
|
distance);
|
2007-01-24 15:51:51 +01:00
|
|
|
return 1;
|
2017-07-17 14:03:14 +02:00
|
|
|
} else
|
2007-01-24 15:51:51 +01:00
|
|
|
zlog_info(
|
2020-03-27 12:35:23 +01:00
|
|
|
"ospf_nexthop_calculation(): vl_data for VL link not found");
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
} /* end virtual-link from V to W */
|
2007-01-24 15:51:51 +01:00
|
|
|
return 0;
|
2004-08-31 19:28:41 +02:00
|
|
|
} /* end W is a Router vertex */
|
2017-07-17 14:03:14 +02:00
|
|
|
else {
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
assert(w->type == OSPF_VERTEX_NETWORK);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2012-07-07 17:06:11 +02:00
|
|
|
nh = vertex_nexthop_new();
|
|
|
|
nh->router.s_addr = 0; /* Nexthop not required */
|
2020-08-07 14:13:07 +02:00
|
|
|
nh->lsa_pos = lsa_pos;
|
2020-08-05 10:44:21 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Since v is the root the nexthop and
|
|
|
|
* local nexthop are the same.
|
|
|
|
*/
|
|
|
|
lnh = vertex_nexthop_new();
|
|
|
|
memcpy(lnh, nh, sizeof(struct vertex_nexthop));
|
|
|
|
|
|
|
|
ospf_spf_add_parent(v, w, nh, lnh, distance);
|
2012-07-07 17:06:11 +02:00
|
|
|
return 1;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2004-08-31 19:28:41 +02:00
|
|
|
} /* end V is the root */
|
|
|
|
/* Check if W's parent is a network connected to root. */
|
2002-12-13 21:15:29 +01:00
|
|
|
else if (v->type == OSPF_VERTEX_NETWORK) {
|
2004-08-31 19:28:41 +02:00
|
|
|
/* See if any of V's parents are the root. */
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
for (ALL_LIST_ELEMENTS(v->parents, node, nnode, vp)) {
|
2020-08-05 16:16:57 +02:00
|
|
|
if (vp->parent == area->spf) {
|
|
|
|
/*
|
|
|
|
* 16.1.1 para 5. ...the parent vertex is a
|
|
|
|
* network that directly connects the
|
|
|
|
* calculating router to the destination
|
|
|
|
* router. The list of next hops is then
|
|
|
|
* determined by examining the destination's
|
|
|
|
* router-LSA ...
|
2017-07-17 14:03:14 +02:00
|
|
|
*/
|
|
|
|
|
2004-08-31 19:28:41 +02:00
|
|
|
assert(w->type == OSPF_VERTEX_ROUTER);
|
2003-06-07 01:27:04 +02:00
|
|
|
while ((l = ospf_get_next_link(w, v, l))) {
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* ... For each link in the router-LSA
|
|
|
|
* that points back to the parent
|
|
|
|
* network, the link's Link Data field
|
|
|
|
* provides the IP address of a next hop
|
|
|
|
* router. The outgoing interface to use
|
|
|
|
* can then be derived from the next
|
|
|
|
* hop IP address (or it can be
|
|
|
|
* inherited from the parent network).
|
2017-07-17 14:03:14 +02:00
|
|
|
*/
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
nh = vertex_nexthop_new();
|
|
|
|
nh->router = l->link_data;
|
2020-08-07 14:13:07 +02:00
|
|
|
nh->lsa_pos = vp->nexthop->lsa_pos;
|
2020-08-05 10:44:21 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Since v is the root the nexthop and
|
|
|
|
* local nexthop are the same.
|
|
|
|
*/
|
|
|
|
lnh = vertex_nexthop_new();
|
|
|
|
memcpy(lnh, nh,
|
|
|
|
sizeof(struct vertex_nexthop));
|
|
|
|
|
2007-01-24 15:51:51 +01:00
|
|
|
added = 1;
|
2020-08-05 10:44:21 +02:00
|
|
|
ospf_spf_add_parent(v, w, nh, lnh,
|
|
|
|
distance);
|
2012-07-07 17:06:11 +02:00
|
|
|
}
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* Note lack of return is deliberate. See next
|
|
|
|
* comment.
|
|
|
|
*/
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2012-07-07 17:06:11 +02:00
|
|
|
}
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* NB: This code is non-trivial.
|
2017-07-17 14:03:14 +02:00
|
|
|
*
|
2012-08-06 13:17:12 +02:00
|
|
|
* E.g. it is not enough to know that V connects to the root. It
|
2020-08-05 16:16:57 +02:00
|
|
|
* is also important that the while above, looping through all
|
|
|
|
* links from W->V found at least one link, so that we know
|
|
|
|
* there is bi-directional connectivity between V and W (which
|
|
|
|
* need not be the case, e.g. when OSPF has not yet converged
|
|
|
|
* fully). Otherwise, if we /always/ return here, without having
|
|
|
|
* checked that root->V->-W actually resulted in a valid nexthop
|
|
|
|
* being created, then we we will prevent SPF from finding/using
|
|
|
|
* higher cost paths.
|
2017-07-17 14:03:14 +02:00
|
|
|
*
|
2012-08-06 13:17:12 +02:00
|
|
|
* It is important, if root->V->W has not been added, that we
|
2020-08-05 16:16:57 +02:00
|
|
|
* continue through to the intervening-router nexthop code
|
|
|
|
* below. So as to ensure other paths to V may be used. This
|
|
|
|
* avoids unnecessary blackholes while OSPF is converging.
|
2017-07-17 14:03:14 +02:00
|
|
|
*
|
2012-08-06 13:17:12 +02:00
|
|
|
* I.e. we may have arrived at this function, examining V -> W,
|
2020-08-05 16:16:57 +02:00
|
|
|
* via workable paths other than root -> V, and it's important
|
|
|
|
* to avoid getting "confused" by non-working root->V->W path
|
|
|
|
* - it's important to *not* lose the working non-root paths,
|
|
|
|
* just because of a non-viable root->V->W.
|
2017-07-17 14:03:14 +02:00
|
|
|
*/
|
2012-08-06 13:17:12 +02:00
|
|
|
if (added)
|
2007-01-24 15:51:51 +01:00
|
|
|
return added;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2012-07-07 17:06:11 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* 16.1.1 para 4. If there is at least one intervening router in the
|
2012-07-07 17:06:11 +02:00
|
|
|
* current shortest path between the destination and the root, the
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
* destination simply inherits the set of next hops from the
|
|
|
|
* parent.
|
|
|
|
*/
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
|
|
|
zlog_debug("%s: Intervening routers, adding parent(s)",
|
|
|
|
__func__);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
for (ALL_LIST_ELEMENTS(v->parents, node, nnode, vp)) {
|
|
|
|
added = 1;
|
2020-08-05 10:44:21 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The nexthop is inherited, but the local nexthop still needs
|
|
|
|
* to be created.
|
|
|
|
*/
|
|
|
|
if (l) {
|
|
|
|
lnh = vertex_nexthop_new();
|
|
|
|
lnh->router = l->link_data;
|
|
|
|
lnh->lsa_pos = lsa_pos;
|
|
|
|
} else {
|
|
|
|
lnh = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ospf_spf_add_parent(v, w, vp->nexthop, lnh, distance);
|
2004-08-31 19:28:41 +02:00
|
|
|
}
|
2012-07-07 17:06:11 +02:00
|
|
|
|
2012-08-06 13:17:12 +02:00
|
|
|
return added;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2020-10-26 12:27:09 +01:00
|
|
|
static int ospf_spf_is_protected_resource(struct ospf_area *area,
|
|
|
|
struct router_lsa_link *link,
|
|
|
|
struct lsa_header *lsa)
|
2020-08-05 10:44:21 +02:00
|
|
|
{
|
2020-10-26 12:27:09 +01:00
|
|
|
uint8_t *p, *lim;
|
2020-08-05 10:44:21 +02:00
|
|
|
struct router_lsa_link *p_link;
|
2020-10-26 12:27:09 +01:00
|
|
|
struct router_lsa_link *l = NULL;
|
|
|
|
struct in_addr router_id;
|
|
|
|
int link_type;
|
2020-08-05 10:44:21 +02:00
|
|
|
|
2020-10-26 12:27:09 +01:00
|
|
|
if (!area->spf_protected_resource)
|
2020-08-05 10:44:21 +02:00
|
|
|
return 0;
|
|
|
|
|
2020-10-26 12:27:09 +01:00
|
|
|
link_type = link->m[0].type;
|
|
|
|
|
|
|
|
switch (area->spf_protected_resource->type) {
|
|
|
|
case OSPF_TI_LFA_LINK_PROTECTION:
|
|
|
|
p_link = area->spf_protected_resource->link;
|
|
|
|
if (!p_link)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* For P2P: check if the link belongs to the same subnet */
|
|
|
|
if (link_type == LSA_LINK_TYPE_POINTOPOINT
|
|
|
|
&& (p_link->link_id.s_addr & p_link->link_data.s_addr)
|
|
|
|
== (link->link_data.s_addr
|
|
|
|
& p_link->link_data.s_addr))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* For stub: check if this the same subnet */
|
|
|
|
if (link_type == LSA_LINK_TYPE_STUB
|
|
|
|
&& (p_link->link_id.s_addr == link->link_id.s_addr)
|
|
|
|
&& (p_link->link_data.s_addr == link->link_data.s_addr))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case OSPF_TI_LFA_NODE_PROTECTION:
|
|
|
|
router_id = area->spf_protected_resource->router_id;
|
|
|
|
if (router_id.s_addr == INADDR_ANY)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* For P2P: check if the link leads to the protected node */
|
|
|
|
if (link_type == LSA_LINK_TYPE_POINTOPOINT
|
|
|
|
&& link->link_id.s_addr == router_id.s_addr)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* The rest is about stub links! */
|
|
|
|
if (link_type != LSA_LINK_TYPE_STUB)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if there's a P2P link in the router LSA with the
|
|
|
|
* corresponding link data in the same subnet.
|
|
|
|
*/
|
|
|
|
|
|
|
|
p = ((uint8_t *)lsa) + OSPF_LSA_HEADER_SIZE + 4;
|
|
|
|
lim = ((uint8_t *)lsa) + ntohs(lsa->length);
|
|
|
|
|
|
|
|
while (p < lim) {
|
|
|
|
l = (struct router_lsa_link *)p;
|
|
|
|
p += (OSPF_ROUTER_LSA_LINK_SIZE
|
|
|
|
+ (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
|
|
|
|
|
|
|
|
/* We only care about P2P with the proper link id */
|
|
|
|
if ((l->m[0].type != LSA_LINK_TYPE_POINTOPOINT)
|
|
|
|
|| (l->link_id.s_addr != router_id.s_addr))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Link data in the subnet given by the link? */
|
|
|
|
if ((link->link_id.s_addr & link->link_data.s_addr)
|
|
|
|
== (l->link_data.s_addr & link->link_data.s_addr))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case OSPF_TI_LFA_UNDEFINED_PROTECTION:
|
|
|
|
break;
|
|
|
|
}
|
2020-08-05 10:44:21 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-10-13 13:53:04 +02:00
|
|
|
/*
|
|
|
|
* For TI-LFA we need the reverse SPF for Q spaces. The reverse SPF is created
|
|
|
|
* by honoring the weight of the reverse 'edge', e.g. the edge from W to V, and
|
|
|
|
* NOT the weight of the 'edge' from V to W as usual. Hence we need to find the
|
|
|
|
* corresponding link in the LSA of W and extract the particular weight.
|
|
|
|
*
|
|
|
|
* TODO: Only P2P supported by now!
|
|
|
|
*/
|
|
|
|
static uint16_t get_reverse_distance(struct vertex *v,
|
|
|
|
struct router_lsa_link *l,
|
|
|
|
struct ospf_lsa *w_lsa)
|
|
|
|
{
|
|
|
|
uint8_t *p, *lim;
|
|
|
|
struct router_lsa_link *w_link;
|
|
|
|
uint16_t distance = 0;
|
|
|
|
|
2020-11-24 16:40:23 +01:00
|
|
|
assert(w_lsa && w_lsa->data);
|
|
|
|
|
2020-10-13 13:53:04 +02:00
|
|
|
p = ((uint8_t *)w_lsa->data) + OSPF_LSA_HEADER_SIZE + 4;
|
|
|
|
lim = ((uint8_t *)w_lsa->data) + ntohs(w_lsa->data->length);
|
|
|
|
|
|
|
|
while (p < lim) {
|
|
|
|
w_link = (struct router_lsa_link *)p;
|
|
|
|
p += (OSPF_ROUTER_LSA_LINK_SIZE
|
|
|
|
+ (w_link->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
|
|
|
|
|
|
|
|
/* Only care about P2P with link ID equal to V's router id */
|
|
|
|
if (w_link->m[0].type == LSA_LINK_TYPE_POINTOPOINT
|
|
|
|
&& w_link->link_id.s_addr == v->id.s_addr) {
|
|
|
|
distance = ntohs(w_link->m[0].metric);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This might happen if the LSA for W is not complete yet. In this
|
|
|
|
* case we take the weight of the 'forward' link from V. When the LSA
|
|
|
|
* for W is completed the reverse SPF is run again anyway.
|
|
|
|
*/
|
|
|
|
if (distance == 0)
|
|
|
|
distance = ntohs(l->m[0].metric);
|
|
|
|
|
2020-11-24 16:40:23 +01:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
|
|
|
zlog_debug("%s: reversed distance is %u", __func__, distance);
|
2020-10-13 13:53:04 +02:00
|
|
|
|
|
|
|
return distance;
|
|
|
|
}
|
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* RFC2328 16.1 (2).
|
|
|
|
* v is on the SPF tree. Examine the links in v's LSA. Update the list of
|
|
|
|
* candidates with any vertices not already on the list. If a lower-cost path
|
|
|
|
* is found to a vertex already on the candidate list, store the new cost.
|
2004-08-31 19:28:41 +02:00
|
|
|
*/
|
2020-08-05 16:16:57 +02:00
|
|
|
static void ospf_spf_next(struct vertex *v, struct ospf_area *area,
|
2019-01-31 02:58:52 +01:00
|
|
|
struct vertex_pqueue_head *candidate)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
|
|
|
struct ospf_lsa *w_lsa = NULL;
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t *p;
|
|
|
|
uint8_t *lim;
|
2002-12-13 21:15:29 +01:00
|
|
|
struct router_lsa_link *l = NULL;
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
struct in_addr *r;
|
2012-07-07 17:06:11 +02:00
|
|
|
int type = 0, lsa_pos = -1, lsa_pos_next = 0;
|
2020-10-13 13:53:04 +02:00
|
|
|
uint16_t link_distance;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* If this is a router-LSA, and bit V of the router-LSA (see Section
|
|
|
|
* A.4.2:RFC2328) is set, set Area A's TransitCapability to true.
|
|
|
|
*/
|
2002-12-13 21:15:29 +01:00
|
|
|
if (v->type == OSPF_VERTEX_ROUTER) {
|
|
|
|
if (IS_ROUTER_LSA_VIRTUAL((struct router_lsa *)v->lsa))
|
|
|
|
area->transit = OSPF_TRANSIT_TRUE;
|
2003-06-07 01:27:04 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2007-03-23 12:17:28 +01:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2020-10-21 19:56:26 +02:00
|
|
|
zlog_debug("%s: Next vertex of %s vertex %pI4", __func__,
|
2002-12-13 21:15:29 +01:00
|
|
|
v->type == OSPF_VERTEX_ROUTER ? "Router" : "Network",
|
2020-10-21 19:56:26 +02:00
|
|
|
&v->lsa->id);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
p = ((uint8_t *)v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
|
|
|
|
lim = ((uint8_t *)v->lsa) + ntohs(v->lsa->length);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
while (p < lim) {
|
|
|
|
struct vertex *w;
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
unsigned int distance;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* In case of V is Router-LSA. */
|
|
|
|
if (v->lsa->type == OSPF_ROUTER_LSA) {
|
|
|
|
l = (struct router_lsa_link *)p;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
lsa_pos = lsa_pos_next; /* LSA link position */
|
2012-07-07 17:06:11 +02:00
|
|
|
lsa_pos_next++;
|
2020-08-07 14:13:07 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
p += (OSPF_ROUTER_LSA_LINK_SIZE
|
2004-12-08 19:43:03 +01:00
|
|
|
+ (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* (a) If this is a link to a stub network, examine the
|
|
|
|
* next link in V's LSA. Links to stub networks will
|
|
|
|
* be considered in the second stage of the shortest
|
|
|
|
* path calculation.
|
|
|
|
*/
|
2004-12-08 19:43:03 +01:00
|
|
|
if ((type = l->m[0].type) == LSA_LINK_TYPE_STUB)
|
2002-12-13 21:15:29 +01:00
|
|
|
continue;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 10:44:21 +02:00
|
|
|
/*
|
2020-10-26 12:27:09 +01:00
|
|
|
* Don't process TI-LFA protected resources.
|
2020-08-05 10:44:21 +02:00
|
|
|
*
|
|
|
|
* TODO: Replace this by a proper solution, e.g. remove
|
|
|
|
* corresponding links from the LSDB and run the SPF
|
|
|
|
* algo with the stripped-down LSDB.
|
|
|
|
*/
|
2020-10-26 12:27:09 +01:00
|
|
|
if (ospf_spf_is_protected_resource(area, l, v->lsa))
|
2020-08-05 10:44:21 +02:00
|
|
|
continue;
|
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* (b) Otherwise, W is a transit vertex (router or
|
|
|
|
* transit network). Look up the vertex W's LSA
|
|
|
|
* (router-LSA or network-LSA) in Area A's link state
|
|
|
|
* database.
|
|
|
|
*/
|
2002-12-13 21:15:29 +01:00
|
|
|
switch (type) {
|
|
|
|
case LSA_LINK_TYPE_POINTOPOINT:
|
|
|
|
case LSA_LINK_TYPE_VIRTUALLINK:
|
2020-08-05 16:16:57 +02:00
|
|
|
if (type == LSA_LINK_TYPE_VIRTUALLINK
|
|
|
|
&& IS_DEBUG_OSPF_EVENT)
|
|
|
|
zlog_debug(
|
2020-10-21 19:56:26 +02:00
|
|
|
"looking up LSA through VL: %pI4",
|
|
|
|
&l->link_id);
|
2020-08-05 16:16:57 +02:00
|
|
|
w_lsa = ospf_lsa_lookup(area->ospf, area,
|
2017-08-25 22:51:12 +02:00
|
|
|
OSPF_ROUTER_LSA,
|
2003-06-07 01:27:04 +02:00
|
|
|
l->link_id, l->link_id);
|
2020-08-05 16:16:57 +02:00
|
|
|
if (w_lsa && IS_DEBUG_OSPF_EVENT)
|
2020-10-21 19:56:26 +02:00
|
|
|
zlog_debug("found Router LSA %pI4",
|
|
|
|
&l->link_id);
|
2017-07-17 14:03:14 +02:00
|
|
|
break;
|
2002-12-13 21:15:29 +01:00
|
|
|
case LSA_LINK_TYPE_TRANSIT:
|
2004-12-08 19:43:03 +01:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2012-07-07 17:06:11 +02:00
|
|
|
zlog_debug(
|
2020-10-21 19:56:26 +02:00
|
|
|
"Looking up Network LSA, ID: %pI4",
|
|
|
|
&l->link_id);
|
2002-12-13 21:15:29 +01:00
|
|
|
w_lsa = ospf_lsa_lookup_by_id(
|
|
|
|
area, OSPF_NETWORK_LSA, l->link_id);
|
2020-08-05 16:16:57 +02:00
|
|
|
if (w_lsa && IS_DEBUG_OSPF_EVENT)
|
|
|
|
zlog_debug("found the LSA");
|
2002-12-13 21:15:29 +01:00
|
|
|
break;
|
|
|
|
default:
|
2018-09-13 20:56:04 +02:00
|
|
|
flog_warn(EC_OSPF_LSA,
|
2018-08-21 15:36:28 +02:00
|
|
|
"Invalid LSA link type %d", type);
|
2002-12-13 21:15:29 +01:00
|
|
|
continue;
|
|
|
|
}
|
2019-06-12 22:32:30 +02:00
|
|
|
|
2020-10-13 13:53:04 +02:00
|
|
|
/*
|
|
|
|
* For TI-LFA we might need the reverse SPF.
|
|
|
|
* Currently only works with P2P!
|
|
|
|
*/
|
|
|
|
if (type == LSA_LINK_TYPE_POINTOPOINT
|
|
|
|
&& area->spf_reversed)
|
|
|
|
link_distance =
|
|
|
|
get_reverse_distance(v, l, w_lsa);
|
|
|
|
else
|
|
|
|
link_distance = ntohs(l->m[0].metric);
|
|
|
|
|
2019-06-12 22:32:30 +02:00
|
|
|
/* step (d) below */
|
2020-10-13 13:53:04 +02:00
|
|
|
distance = v->distance + link_distance;
|
2002-12-13 21:15:29 +01:00
|
|
|
} else {
|
|
|
|
/* In case of V is Network-LSA. */
|
2003-06-07 01:27:04 +02:00
|
|
|
r = (struct in_addr *)p;
|
2002-12-13 21:15:29 +01:00
|
|
|
p += sizeof(struct in_addr);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Lookup the vertex W's LSA. */
|
|
|
|
w_lsa = ospf_lsa_lookup_by_id(area, OSPF_ROUTER_LSA,
|
2017-07-17 14:03:14 +02:00
|
|
|
*r);
|
2020-08-05 16:16:57 +02:00
|
|
|
if (w_lsa && IS_DEBUG_OSPF_EVENT)
|
2020-10-21 19:56:26 +02:00
|
|
|
zlog_debug("found Router LSA %pI4",
|
|
|
|
&w_lsa->data->id);
|
2019-06-12 22:32:30 +02:00
|
|
|
|
|
|
|
/* step (d) below */
|
|
|
|
distance = v->distance;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* (b cont.) If the LSA does not exist, or its LS age is equal
|
|
|
|
* to MaxAge, or it does not have a link back to vertex V,
|
|
|
|
* examine the next link in V's LSA.[23]
|
|
|
|
*/
|
2007-03-23 12:17:28 +01:00
|
|
|
if (w_lsa == NULL) {
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
|
|
|
zlog_debug("No LSA found");
|
|
|
|
continue;
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (IS_LSA_MAXAGE(w_lsa)) {
|
2007-03-23 12:17:28 +01:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
|
|
|
zlog_debug("LSA is MaxAge");
|
|
|
|
continue;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
if (ospf_lsa_has_link(w_lsa->data, v->lsa) < 0) {
|
2007-03-23 12:17:28 +01:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
|
|
|
zlog_debug("The LSA doesn't have a link back");
|
|
|
|
continue;
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* (c) If vertex W is already on the shortest-path tree, examine
|
|
|
|
* the next link in the LSA.
|
|
|
|
*/
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
if (w_lsa->stat == LSA_SPF_IN_SPFTREE) {
|
2003-06-07 01:27:04 +02:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
zlog_debug("The LSA is already in SPF");
|
2002-12-13 21:15:29 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* (d) Calculate the link state cost D of the resulting path
|
|
|
|
* from the root to vertex W. D is equal to the sum of the link
|
|
|
|
* state cost of the (already calculated) shortest path to
|
|
|
|
* vertex V and the advertised cost of the link between vertices
|
|
|
|
* V and W. If D is:
|
|
|
|
*/
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2019-06-12 22:32:30 +02:00
|
|
|
/* calculate link cost D -- moved above */
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Is there already vertex W in candidate list? */
|
2005-02-23 12:29:02 +01:00
|
|
|
if (w_lsa->stat == LSA_SPF_NOT_EXPLORED) {
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
/* prepare vertex W. */
|
2020-08-25 16:13:08 +02:00
|
|
|
w = ospf_vertex_new(area, w_lsa);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-02-23 12:29:02 +01:00
|
|
|
/* Calculate nexthop to W. */
|
|
|
|
if (ospf_nexthop_calculation(area, v, w, l, distance,
|
2012-07-07 17:06:11 +02:00
|
|
|
lsa_pos))
|
2019-01-31 02:58:52 +01:00
|
|
|
vertex_pqueue_add(candidate, w);
|
2005-02-23 12:29:02 +01:00
|
|
|
else if (IS_DEBUG_OSPF_EVENT)
|
|
|
|
zlog_debug("Nexthop Calc failed");
|
2019-01-31 02:58:52 +01:00
|
|
|
} else if (w_lsa->stat != LSA_SPF_IN_SPFTREE) {
|
|
|
|
w = w_lsa->stat;
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
if (w->distance < distance) {
|
2005-02-23 12:29:02 +01:00
|
|
|
continue;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
else if (w->distance == distance) {
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* Found an equal-cost path to W.
|
|
|
|
* Calculate nexthop of to W from V.
|
|
|
|
*/
|
2012-07-07 17:06:11 +02:00
|
|
|
ospf_nexthop_calculation(area, v, w, l,
|
|
|
|
distance, lsa_pos);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
else {
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* Found a lower-cost path to W.
|
2007-01-24 15:51:51 +01:00
|
|
|
* nexthop_calculation is conditional, if it
|
2020-08-05 16:16:57 +02:00
|
|
|
* finds valid nexthop it will call
|
|
|
|
* spf_add_parents, which will flush the old
|
|
|
|
* parents.
|
2017-07-17 14:03:14 +02:00
|
|
|
*/
|
2019-01-31 02:58:52 +01:00
|
|
|
vertex_pqueue_del(candidate, w);
|
|
|
|
ospf_nexthop_calculation(area, v, w, l,
|
2020-08-07 14:13:07 +02:00
|
|
|
distance, lsa_pos);
|
2019-01-31 02:58:52 +01:00
|
|
|
vertex_pqueue_add(candidate, w);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2005-02-23 12:29:02 +01:00
|
|
|
} /* end W is already on the candidate list */
|
|
|
|
} /* end loop over the links in V's LSA */
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
static void ospf_spf_dump(struct vertex *v, int i)
|
2017-07-17 14:03:14 +02:00
|
|
|
{
|
2002-12-13 21:15:29 +01:00
|
|
|
struct listnode *cnode;
|
|
|
|
struct listnode *nnode;
|
|
|
|
struct vertex_parent *parent;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
if (v->type == OSPF_VERTEX_ROUTER) {
|
2005-02-23 12:29:02 +01:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2020-10-21 19:56:26 +02:00
|
|
|
zlog_debug("SPF Result: %d [R] %pI4", i,
|
|
|
|
&v->lsa->id);
|
2017-07-17 14:03:14 +02:00
|
|
|
} else {
|
2005-02-23 12:29:02 +01:00
|
|
|
struct network_lsa *lsa = (struct network_lsa *)v->lsa;
|
2007-03-23 12:17:28 +01:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2020-10-21 19:56:26 +02:00
|
|
|
zlog_debug("SPF Result: %d [N] %pI4/%d", i,
|
|
|
|
&v->lsa->id,
|
2007-03-23 12:17:28 +01:00
|
|
|
ip_masklen(lsa->mask));
|
2005-02-23 12:29:02 +01:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2012-07-07 17:06:11 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO(v->parents, nnode, parent)) {
|
2020-10-21 19:56:26 +02:00
|
|
|
zlog_debug(" nexthop %p %pI4 %d",
|
|
|
|
(void *)parent->nexthop,
|
|
|
|
&parent->nexthop->router,
|
2020-08-07 14:13:07 +02:00
|
|
|
parent->nexthop->lsa_pos);
|
2004-08-31 19:28:41 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-12-08 19:43:03 +01:00
|
|
|
i++;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
for (ALL_LIST_ELEMENTS_RO(v->children, cnode, v))
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
ospf_spf_dump(v, i);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2020-08-12 13:58:54 +02:00
|
|
|
void ospf_spf_print(struct vty *vty, struct vertex *v, int i)
|
|
|
|
{
|
|
|
|
struct listnode *cnode;
|
|
|
|
struct listnode *nnode;
|
|
|
|
struct vertex_parent *parent;
|
|
|
|
|
|
|
|
if (v->type == OSPF_VERTEX_ROUTER) {
|
2020-08-05 10:44:21 +02:00
|
|
|
vty_out(vty, "SPF Result: depth %d [R] %pI4\n", i, &v->lsa->id);
|
2020-08-12 13:58:54 +02:00
|
|
|
} else {
|
|
|
|
struct network_lsa *lsa = (struct network_lsa *)v->lsa;
|
2020-10-21 19:56:26 +02:00
|
|
|
vty_out(vty, "SPF Result: depth %d [N] %pI4/%d\n", i,
|
|
|
|
&v->lsa->id, ip_masklen(lsa->mask));
|
2020-08-12 13:58:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(v->parents, nnode, parent)) {
|
2020-08-05 10:44:21 +02:00
|
|
|
vty_out(vty,
|
|
|
|
" nexthop %pI4 lsa pos %d -- local nexthop %pI4 lsa pos %d\n",
|
|
|
|
&parent->nexthop->router, parent->nexthop->lsa_pos,
|
|
|
|
&parent->local_nexthop->router,
|
|
|
|
parent->local_nexthop->lsa_pos);
|
2020-08-12 13:58:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
i++;
|
|
|
|
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(v->children, cnode, v))
|
|
|
|
ospf_spf_print(vty, v, i);
|
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Second stage of SPF calculation. */
|
2003-06-07 01:27:04 +02:00
|
|
|
static void ospf_spf_process_stubs(struct ospf_area *area, struct vertex *v,
|
2008-09-04 14:52:07 +02:00
|
|
|
struct route_table *rt, int parent_is_root)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
struct listnode *cnode, *cnnode;
|
2002-12-13 21:15:29 +01:00
|
|
|
struct vertex *child;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-06-07 01:27:04 +02:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2020-10-21 19:56:26 +02:00
|
|
|
zlog_debug("ospf_process_stub():processing stubs for area %pI4",
|
|
|
|
&area->area_id);
|
2020-08-05 16:16:57 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
if (v->type == OSPF_VERTEX_ROUTER) {
|
2018-03-27 21:13:34 +02:00
|
|
|
uint8_t *p;
|
|
|
|
uint8_t *lim;
|
2002-12-13 21:15:29 +01:00
|
|
|
struct router_lsa_link *l;
|
2020-08-05 16:16:57 +02:00
|
|
|
struct router_lsa *router_lsa;
|
2012-07-07 17:06:12 +02:00
|
|
|
int lsa_pos = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-06-07 01:27:04 +02:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2012-07-07 17:06:11 +02:00
|
|
|
zlog_debug(
|
2020-10-21 19:56:26 +02:00
|
|
|
"ospf_process_stubs():processing router LSA, id: %pI4",
|
|
|
|
&v->lsa->id);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
router_lsa = (struct router_lsa *)v->lsa;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2003-06-07 01:27:04 +02:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2012-07-07 17:06:11 +02:00
|
|
|
zlog_debug(
|
2004-12-08 19:43:03 +01:00
|
|
|
"ospf_process_stubs(): we have %d links to process",
|
2020-08-05 16:16:57 +02:00
|
|
|
ntohs(router_lsa->links));
|
|
|
|
|
2018-03-27 21:13:34 +02:00
|
|
|
p = ((uint8_t *)v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
|
|
|
|
lim = ((uint8_t *)v->lsa) + ntohs(v->lsa->length);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
while (p < lim) {
|
|
|
|
l = (struct router_lsa_link *)p;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2011-08-23 09:36:27 +02:00
|
|
|
p += (OSPF_ROUTER_LSA_LINK_SIZE
|
|
|
|
+ (l->m[0].tos_count * OSPF_ROUTER_LSA_TOS_SIZE));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-10-26 12:27:09 +01:00
|
|
|
/* Don't process TI-LFA protected resources */
|
2020-08-05 10:44:21 +02:00
|
|
|
if (l->m[0].type == LSA_LINK_TYPE_STUB
|
2020-10-26 12:27:09 +01:00
|
|
|
&& !ospf_spf_is_protected_resource(area, l, v->lsa))
|
2012-07-07 17:06:12 +02:00
|
|
|
ospf_intra_add_stub(rt, l, v, area,
|
|
|
|
parent_is_root, lsa_pos);
|
|
|
|
lsa_pos++;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2004-12-08 19:43:03 +01:00
|
|
|
ospf_vertex_dump("ospf_process_stubs(): after examining links: ", v, 1,
|
2003-06-07 01:27:04 +02:00
|
|
|
1);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2011-08-23 09:36:27 +02:00
|
|
|
for (ALL_LIST_ELEMENTS(v->children, cnode, cnnode, child)) {
|
|
|
|
if (CHECK_FLAG(child->flags, OSPF_VERTEX_PROCESSED))
|
|
|
|
continue;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* The first level of routers connected to the root
|
2012-07-07 17:06:12 +02:00
|
|
|
* should have 'parent_is_root' set, including those
|
2008-09-04 14:52:07 +02:00
|
|
|
* connected via a network vertex.
|
|
|
|
*/
|
|
|
|
if (area->spf == v)
|
|
|
|
parent_is_root = 1;
|
|
|
|
else if (v->type == OSPF_VERTEX_ROUTER)
|
|
|
|
parent_is_root = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2008-09-04 14:52:07 +02:00
|
|
|
ospf_spf_process_stubs(area, child, rt, parent_is_root);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
SET_FLAG(child->flags, OSPF_VERTEX_PROCESSED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ospf_rtrs_free(struct route_table *rtrs)
|
|
|
|
{
|
|
|
|
struct route_node *rn;
|
2004-09-23 21:18:23 +02:00
|
|
|
struct list *or_list;
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
struct ospf_route * or ;
|
|
|
|
struct listnode *node, *nnode;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
zlog_debug("Route: Router Routing Table free");
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
for (rn = route_top(rtrs); rn; rn = route_next(rn))
|
|
|
|
if ((or_list = rn->info) != NULL) {
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
for (ALL_LIST_ELEMENTS(or_list, node, nnode, or))
|
|
|
|
ospf_route_free(or);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2018-10-02 11:39:51 +02:00
|
|
|
list_delete(&or_list);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2003-06-07 01:27:04 +02:00
|
|
|
/* Unlock the node. */
|
|
|
|
rn->info = NULL;
|
|
|
|
route_unlock_node(rn);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2020-08-05 16:16:57 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
route_table_finish(rtrs);
|
|
|
|
}
|
|
|
|
|
2020-08-25 16:13:08 +02:00
|
|
|
void ospf_spf_cleanup(struct vertex *spf, struct list *vertex_list)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Free nexthop information, canonical versions of which are
|
|
|
|
* attached the first level of router vertices attached to the
|
|
|
|
* root vertex, see ospf_nexthop_calculation.
|
|
|
|
*/
|
2020-08-05 10:44:21 +02:00
|
|
|
if (spf)
|
|
|
|
ospf_canonical_nexthops_free(spf);
|
2020-08-25 16:13:08 +02:00
|
|
|
|
|
|
|
/* Free SPF vertices list with deconstructor ospf_vertex_free. */
|
2020-08-05 10:44:21 +02:00
|
|
|
if (vertex_list)
|
|
|
|
list_delete(&vertex_list);
|
2020-08-25 16:13:08 +02:00
|
|
|
}
|
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/* Calculating the shortest-path tree for an area, see RFC2328 16.1. */
|
2020-08-07 14:13:07 +02:00
|
|
|
void ospf_spf_calculate(struct ospf_area *area, struct ospf_lsa *root_lsa,
|
|
|
|
struct route_table *new_table,
|
2020-08-17 15:04:41 +02:00
|
|
|
struct route_table *new_rtrs, bool is_dry_run,
|
|
|
|
bool is_root_node)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2019-01-31 02:58:52 +01:00
|
|
|
struct vertex_pqueue_head candidate;
|
2005-02-23 12:29:02 +01:00
|
|
|
struct vertex *v;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT) {
|
|
|
|
zlog_debug("ospf_spf_calculate: Start");
|
2020-10-21 19:56:26 +02:00
|
|
|
zlog_debug("ospf_spf_calculate: running Dijkstra for area %pI4",
|
|
|
|
&area->area_id);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* If the router LSA of the root is not yet allocated, return this
|
|
|
|
* area's calculation. In the 'usual' case the root_lsa is the
|
|
|
|
* self-originated router LSA of the node itself.
|
|
|
|
*/
|
|
|
|
if (!root_lsa) {
|
2008-09-04 14:52:07 +02:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2012-07-07 17:06:11 +02:00
|
|
|
zlog_debug(
|
2020-10-21 19:56:26 +02:00
|
|
|
"ospf_spf_calculate: Skip area %pI4's calculation due to empty root LSA",
|
|
|
|
&area->area_id);
|
2008-09-04 14:52:07 +02:00
|
|
|
return;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/* Initialize the algorithm's data structures, see RFC2328 16.1. (1). */
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* This function scans all the LSA database and set the stat field to
|
|
|
|
* LSA_SPF_NOT_EXPLORED.
|
|
|
|
*/
|
2019-01-31 02:58:52 +01:00
|
|
|
lsdb_clean_stat(area->lsdb);
|
2020-08-05 16:16:57 +02:00
|
|
|
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
/* Create a new heap for the candidates. */
|
2019-01-31 02:58:52 +01:00
|
|
|
vertex_pqueue_init(&candidate);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* Initialize the shortest-path tree to only the root (which is usually
|
|
|
|
* the router doing the calculation).
|
|
|
|
*/
|
2020-08-17 15:04:41 +02:00
|
|
|
ospf_spf_init(area, root_lsa, is_dry_run, is_root_node);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2019-07-01 19:26:05 +02:00
|
|
|
/* Set Area A's TransitCapability to false. */
|
2002-12-13 21:15:29 +01:00
|
|
|
area->transit = OSPF_TRANSIT_FALSE;
|
|
|
|
area->shortcut_capability = 1;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* Use the root vertex for the start of the SPF algorithm and make it
|
|
|
|
* part of the tree.
|
|
|
|
*/
|
|
|
|
v = area->spf;
|
|
|
|
v->lsa_p->stat = LSA_SPF_IN_SPFTREE;
|
|
|
|
|
2017-07-17 14:03:14 +02:00
|
|
|
for (;;) {
|
2002-12-13 21:15:29 +01:00
|
|
|
/* RFC2328 16.1. (2). */
|
2020-08-05 16:16:57 +02:00
|
|
|
ospf_spf_next(v, area, &candidate);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* RFC2328 16.1. (3). */
|
2019-01-31 02:58:52 +01:00
|
|
|
v = vertex_pqueue_pop(&candidate);
|
|
|
|
if (!v)
|
2020-08-05 16:16:57 +02:00
|
|
|
/* No more vertices left. */
|
2019-01-31 02:58:52 +01:00
|
|
|
break;
|
2020-08-05 16:16:57 +02:00
|
|
|
|
2019-01-31 02:58:52 +01:00
|
|
|
v->lsa_p->stat = LSA_SPF_IN_SPFTREE;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
ospf_vertex_add_parent(v);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* RFC2328 16.1. (4). */
|
|
|
|
if (v->type == OSPF_VERTEX_ROUTER)
|
|
|
|
ospf_intra_add_router(new_rtrs, v, area);
|
2017-07-17 14:03:14 +02:00
|
|
|
else
|
2002-12-13 21:15:29 +01:00
|
|
|
ospf_intra_add_transit(new_table, v, area);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/* Iterate back to (2), see RFC2328 16.1. (5). */
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
if (IS_DEBUG_OSPF_EVENT) {
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
ospf_spf_dump(area->spf, 0);
|
2002-12-13 21:15:29 +01:00
|
|
|
ospf_route_table_dump(new_table);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2015-05-20 01:36:05 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* Second stage of SPF calculation procedure's, add leaves to the tree
|
|
|
|
* for stub networks.
|
|
|
|
*/
|
2005-10-18 Paul Jakma <paul.jakma@sun.com>
* (general) SPF memory management cleanup and fix for rare
double-free bug.
* ospf_spf.h: (struct vertex_parent) New struct to hold parent
specific data, eg the backlink and the parent vertex pointer,
and point to the appropriate general struct vertex_nexthop.
(struct vertex_nexthop) remove parent vertex pointer, so
this struct can be shared across vertices.
(struct vertex) rename list child to list children. Remove
list of nexthops, replace with list of vertex_parents.
* ospf_spf.c: (update_stat) trivial, remove cast from void *.
(vertex_nexthop_new) remove init of parent - field is gone
from struct vertex_nexthop.
(ospf_canonical_nexthops_free) Remove the canonical
vertex_nexthop memory objects. These are the vertex_nexthops
attached to the first level of router vertices from the root.
(vertex_parent_new) new function, create a vertex_parent.
(vertex_parent_free) ditto, but free it.
(ospf_vertex_new) Update to match changes to struct vertex.
(ospf_vertex_free) Recursively free a struct vertex and its
children. The parent list is used as a reference count.
vertex_nexthops must be free seperately, if required.
(ospf_vertex_dump) update to match struct vertex changes.
Print out backlink of parents too.
(ospf_vertex_add_parent) ditto.
(ospf_lsa_has_link) update comment.
(ospf_nexthop_add_unique) removed, not needed anymore.
(ospf_nexthop_merge) ditto.
(ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent.
Simplified to just create vertex_parent and add it.
(ospf_spf_flush_parents) new function, flush out the parent
list.
(ospf_nexthop_calculation) Take the relevant route_lsa_link
as an argument, which simplifies things and removes the need
for the hack in ospf_nexthop_add_unique - ospf_spf_next
already knew exactly which link the cost calculated was for.
Update to match struct vertex changes too.
(ospf_spf_next) Don't create a vertex for W unnecessarily, if
it's there's a vertex already created for W, use it, and
hence there's no need to free it either.
Update some manipulation/comparisons of distance to match.
Flush the parent list if a lower cost path is found.
(ospf_spf_route_free) unused, removed.
(ospf_spf_dump) match the struct vertex changes, and dump the
ifname if possible.
(ospf_spf_calculate) At end of SPF, free the canonical nexthops
and call ospf_vertex_free on the root vertex to free the
entire tree.
* ospf_interface.c: (ospf_vl_set_params) match struct vertex
changes.
* ospf_route.c: (ospf_intra_route_add) ditto
(ospf_route_copy_nexthops_from_vertex) ditto
* memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
|
|
|
ospf_spf_process_stubs(area, area->spf, new_table, 0);
|
2015-05-20 01:36:05 +02:00
|
|
|
|
2017-01-18 01:30:43 +01:00
|
|
|
ospf_vertex_dump(__func__, area->spf, 0, 1);
|
2002-12-13 21:15:29 +01:00
|
|
|
|
2016-10-11 01:35:43 +02:00
|
|
|
/* Increment SPF Calculation Counter. */
|
|
|
|
area->spf_calculation++;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
monotime(&area->ospf->ts_spf);
|
2015-05-20 01:36:05 +02:00
|
|
|
area->ts_spf = area->ospf->ts_spf;
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
zlog_debug("ospf_spf_calculate: Stop. %zd vertices",
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
mtype_stats_alloc(MTYPE_OSPF_VERTEX));
|
2020-08-05 10:44:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ospf_spf_calculate_area(struct ospf *ospf, struct ospf_area *area,
|
|
|
|
struct route_table *new_table,
|
|
|
|
struct route_table *new_rtrs)
|
|
|
|
{
|
|
|
|
ospf_spf_calculate(area, area->router_lsa_self, new_table, new_rtrs,
|
|
|
|
false, true);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 10:44:21 +02:00
|
|
|
if (ospf->ti_lfa_enabled)
|
2020-10-26 12:27:09 +01:00
|
|
|
ospf_ti_lfa_compute(area, new_table,
|
|
|
|
ospf->ti_lfa_protection_type);
|
2020-08-05 10:44:21 +02:00
|
|
|
|
|
|
|
ospf_spf_cleanup(area->spf, area->spf_vertex_list);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|
2014-06-04 06:53:35 +02:00
|
|
|
|
2020-08-05 10:44:21 +02:00
|
|
|
void ospf_spf_calculate_areas(struct ospf *ospf, struct route_table *new_table,
|
|
|
|
struct route_table *new_rtrs)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2005-04-07 Paul Jakma <paul.jakma@sun.com>
* (global): Fix up list loops to match changes in lib/linklist,
and some basic auditing of usage.
* configure.ac: define QUAGGA_NO_DEPRECATED_INTERFACES
* HACKING: Add notes about deprecating interfaces and commands.
* lib/linklist.h: Add usage comments.
Rename getdata macro to listgetdata.
Rename nextnode to listnextnode and fix its odd behaviour to be
less dangerous.
Make listgetdata macro assert node is not null, NULL list entries
should be bug condition.
ALL_LIST_ELEMENTS, new macro, forward-referencing macro for use
with for loop, Suggested by Jim Carlson of Sun.
Add ALL_LIST_ELEMENTS_RO for cases which obviously do not need the
"safety" of previous macro.
LISTNODE_ADD and DELETE macros renamed to ATTACH, DETACH, to
distinguish from the similarly named functions, and reflect their
effect better.
Add a QUAGGA_NO_DEPRECATED_INTERFACES define guarded section
with the old defines which were modified above,
for backwards compatibility - guarded to prevent Quagga using it..
* lib/linklist.c: fix up for linklist.h changes.
* ospf6d/ospf6_abr.c: (ospf6_abr_examin_brouter) change to a single
scan of the area list, rather than scanning all areas first for
INTER_ROUTER and then again for INTER_NETWORK. According to
16.2, the scan should be area specific anyway, and further
ospf6d does not seem to implement 16.3 anyway.
2005-04-07 09:30:20 +02:00
|
|
|
struct ospf_area *area;
|
|
|
|
struct listnode *node, *nnode;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-01-23 18:16:03 +01:00
|
|
|
/* Calculate SPF for each area. */
|
|
|
|
for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
|
2017-06-06 17:36:00 +02:00
|
|
|
/* Do backbone last, so as to first discover intra-area paths
|
2020-08-05 16:16:57 +02:00
|
|
|
* for any back-bone virtual-links */
|
2017-06-06 17:36:00 +02:00
|
|
|
if (ospf->backbone && ospf->backbone == area)
|
|
|
|
continue;
|
2015-05-20 01:36:05 +02:00
|
|
|
|
2020-08-05 10:44:21 +02:00
|
|
|
ospf_spf_calculate_area(ospf, area, new_table, new_rtrs);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
[ospfd] Fix SPF of virtual-links
2006-04-24 Paul Jakma <paul.jakma@sun.com>
* (general) More Virtual-link fixes, again with much help in
testing / debug from Juergen Kammer. Primarily in SPF.
* ospf_spf.h: Add guard. ospf_interface.h will include this
header.
* ospf_interface.h: Modify ospf_vl_lookup definition to take
struct ospf as argument, so as to allow for NULL area
argument.
(struct ospf_vl_data) Remove out_oi, instead add a struct
vertex_nexthop, to use as initial nexthop for backbone paths
through a vlink.
* ospf_interface.c: (ospf_vl_lookup) Modified to allow
NULL area to be passed to indicate "any" (first) area.
Add extra debug.
(ospf_vl_set_params) vl_oi -> nexthop. Add extra debug.
(ospf_vl_up_check) Fix debug, inet_ntoa returns a static
buffer..
* ospf_route.c: (ospf_intra_add_router) Vlinks dont go through
backbone, don't bother checking.
* ospf_spf.c: (static struct list vertex_list) Record vertices
that will need to be freed.
(cmp) Order network before router vertices, as required,
wasn't implemented.
(vertex_nexthop_free) Mild additional robustness check.
(vertex_parent_free) Take void argument, as this function
is passed as list deconstructor for vertex parent list.
(ospf_vertex_new) More debug. Set deconstructor for parent
list. Track allocated vertices on the vertex_list.
(ospf_vertex_free) Get rid of the tricky recursive cleanup of
vertices. Now frees only the given vertex.
(ospf_vertex_add_parent) Fix assert.
(ospf_nexthop_calculation) Fix calculation of nexthop for
VLink vertices, lookup the vl_data and use its previously
recorded nexthop information.
(ospf_spf_calculate) Vertices are freed simply by deleting
vertex_list nodes and letting ospf_vertex_free as deconstructor
work per-node.
(ospf_spf_calculate_timer) Trivial optimisation, leave
backbone SPF calculation till last to reduce SPF churn on
VLink updates.
* ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup
(no_ospf_area_vlink_cmd) ditto.
(show_ip_ospf_interface_sub) For Vlinks, the peer address is
more interesting than the output interface.
2006-05-04 09:32:57 +02:00
|
|
|
/* SPF for backbone, if required */
|
2020-08-05 10:44:21 +02:00
|
|
|
if (ospf->backbone)
|
|
|
|
ospf_spf_calculate_area(ospf, ospf->backbone, new_table,
|
|
|
|
new_rtrs);
|
2020-08-05 16:16:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Worker for SPF calculation scheduler. */
|
|
|
|
static int ospf_spf_calculate_schedule_worker(struct thread *thread)
|
|
|
|
{
|
|
|
|
struct ospf *ospf = THREAD_ARG(thread);
|
|
|
|
struct route_table *new_table, *new_rtrs;
|
|
|
|
struct timeval start_time, spf_start_time;
|
|
|
|
unsigned long ia_time, prune_time, rt_time;
|
|
|
|
unsigned long abr_time, total_spf_time, spf_time;
|
|
|
|
char rbuf[32]; /* reason_buf */
|
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
|
|
|
zlog_debug("SPF: Timer (SPF calculation expire)");
|
|
|
|
|
|
|
|
ospf->t_spf_calc = NULL;
|
|
|
|
|
|
|
|
ospf_vl_unapprove(ospf);
|
|
|
|
|
|
|
|
/* Execute SPF for each area including backbone, see RFC 2328 16.1. */
|
|
|
|
monotime(&spf_start_time);
|
|
|
|
new_table = route_table_init(); /* routing table */
|
|
|
|
new_rtrs = route_table_init(); /* ABR/ASBR routing table */
|
2020-08-05 10:44:21 +02:00
|
|
|
ospf_spf_calculate_areas(ospf, new_table, new_rtrs);
|
2014-10-09 15:19:51 +02:00
|
|
|
spf_time = monotime_since(&spf_start_time, NULL);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2014-10-09 15:19:51 +02:00
|
|
|
ospf_vl_shut_unapproved(ospf);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/* Calculate inter-area routes, see RFC 2328 16.2. */
|
2017-01-18 01:30:43 +01:00
|
|
|
monotime(&start_time);
|
2014-10-09 15:19:51 +02:00
|
|
|
ospf_ia_routing(ospf, new_table, new_rtrs);
|
2017-01-23 18:16:03 +01:00
|
|
|
ia_time = monotime_since(&start_time, NULL);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/* Get rid of transit networks and routers we cannot reach anyway. */
|
2017-01-18 01:30:43 +01:00
|
|
|
monotime(&start_time);
|
2002-12-13 21:15:29 +01:00
|
|
|
ospf_prune_unreachable_networks(new_table);
|
|
|
|
ospf_prune_unreachable_routers(new_rtrs);
|
2017-01-23 18:16:03 +01:00
|
|
|
prune_time = monotime_since(&start_time, NULL);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/* Note: RFC 2328 16.3. is apparently missing. */
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* Calculate AS external routes, see RFC 2328 16.4.
|
|
|
|
* There is a dedicated routing table for external routes which is not
|
|
|
|
* handled here directly
|
|
|
|
*/
|
|
|
|
ospf_ase_calculate_schedule(ospf);
|
2003-03-25 06:07:42 +01:00
|
|
|
ospf_ase_calculate_timer_add(ospf);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-08-25 22:51:12 +02:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
|
|
|
zlog_debug(
|
|
|
|
"%s: ospf install new route, vrf %s id %u new_table count %lu",
|
2020-03-06 15:23:22 +01:00
|
|
|
__func__, ospf_vrf_id_to_name(ospf->vrf_id),
|
2017-08-25 22:51:12 +02:00
|
|
|
ospf->vrf_id, new_table->count);
|
2020-08-05 16:16:57 +02:00
|
|
|
|
2014-10-09 15:19:51 +02:00
|
|
|
/* Update routing table. */
|
2017-01-23 18:16:03 +01:00
|
|
|
monotime(&start_time);
|
2003-03-25 06:07:42 +01:00
|
|
|
ospf_route_install(ospf, new_table);
|
2017-01-23 18:16:03 +01:00
|
|
|
rt_time = monotime_since(&start_time, NULL);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/* Free old ABR/ASBR routing table */
|
|
|
|
if (ospf->old_rtrs)
|
2003-03-25 06:07:42 +01:00
|
|
|
/* ospf_route_delete (ospf->old_rtrs); */
|
|
|
|
ospf_rtrs_free(ospf->old_rtrs);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/* Update ABR/ASBR routing table */
|
2003-03-25 06:07:42 +01:00
|
|
|
ospf->old_rtrs = ospf->new_rtrs;
|
|
|
|
ospf->new_rtrs = new_rtrs;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/* ABRs may require additional changes, see RFC 2328 16.7. */
|
2017-01-18 01:30:43 +01:00
|
|
|
monotime(&start_time);
|
2020-11-19 08:23:14 +01:00
|
|
|
if (IS_OSPF_ABR(ospf)) {
|
|
|
|
if (ospf->anyNSSA)
|
|
|
|
ospf_abr_nssa_check_status(ospf);
|
2003-03-25 06:07:42 +01:00
|
|
|
ospf_abr_task(ospf);
|
2020-11-19 08:23:14 +01:00
|
|
|
}
|
2017-01-23 18:16:03 +01:00
|
|
|
abr_time = monotime_since(&start_time, NULL);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-01-18 19:11:11 +01:00
|
|
|
/* Schedule Segment Routing update */
|
2020-03-20 11:34:52 +01:00
|
|
|
ospf_sr_update_task(ospf);
|
2018-01-18 19:11:11 +01:00
|
|
|
|
2014-10-09 15:19:51 +02:00
|
|
|
total_spf_time =
|
2017-01-23 18:16:03 +01:00
|
|
|
monotime_since(&spf_start_time, &ospf->ts_spf_duration);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-06-06 17:36:00 +02:00
|
|
|
rbuf[0] = '\0';
|
|
|
|
if (spf_reason_flags) {
|
|
|
|
if (spf_reason_flags & SPF_FLAG_ROUTER_LSA_INSTALL)
|
2020-10-21 19:56:26 +02:00
|
|
|
strlcat(rbuf, "R, ", sizeof(rbuf));
|
2017-06-06 17:36:00 +02:00
|
|
|
if (spf_reason_flags & SPF_FLAG_NETWORK_LSA_INSTALL)
|
2020-10-21 19:56:26 +02:00
|
|
|
strlcat(rbuf, "N, ", sizeof(rbuf));
|
2017-06-06 17:36:00 +02:00
|
|
|
if (spf_reason_flags & SPF_FLAG_SUMMARY_LSA_INSTALL)
|
2020-10-21 19:56:26 +02:00
|
|
|
strlcat(rbuf, "S, ", sizeof(rbuf));
|
2017-06-06 17:36:00 +02:00
|
|
|
if (spf_reason_flags & SPF_FLAG_ASBR_SUMMARY_LSA_INSTALL)
|
2020-10-21 19:56:26 +02:00
|
|
|
strlcat(rbuf, "AS, ", sizeof(rbuf));
|
2014-10-09 15:19:51 +02:00
|
|
|
if (spf_reason_flags & SPF_FLAG_ABR_STATUS_CHANGE)
|
2020-10-21 19:56:26 +02:00
|
|
|
strlcat(rbuf, "ABR, ", sizeof(rbuf));
|
2014-10-09 15:19:51 +02:00
|
|
|
if (spf_reason_flags & SPF_FLAG_ASBR_STATUS_CHANGE)
|
2020-10-21 19:56:26 +02:00
|
|
|
strlcat(rbuf, "ASBR, ", sizeof(rbuf));
|
2017-06-06 17:36:00 +02:00
|
|
|
if (spf_reason_flags & SPF_FLAG_MAXAGE)
|
2020-10-21 19:56:26 +02:00
|
|
|
strlcat(rbuf, "M, ", sizeof(rbuf));
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-06-06 17:36:00 +02:00
|
|
|
size_t rbuflen = strlen(rbuf);
|
|
|
|
if (rbuflen >= 2)
|
|
|
|
rbuf[rbuflen - 2] = '\0'; /* skip the last ", " */
|
2017-07-17 14:03:14 +02:00
|
|
|
else
|
2017-06-06 17:36:00 +02:00
|
|
|
rbuf[0] = '\0';
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
if (IS_DEBUG_OSPF_EVENT) {
|
2004-12-08 19:43:03 +01:00
|
|
|
zlog_info("SPF Processing Time(usecs): %ld", total_spf_time);
|
2020-03-24 17:38:20 +01:00
|
|
|
zlog_info(" SPF Time: %ld", spf_time);
|
|
|
|
zlog_info(" InterArea: %ld", ia_time);
|
|
|
|
zlog_info(" Prune: %ld", prune_time);
|
|
|
|
zlog_info(" RouteInstall: %ld", rt_time);
|
2014-10-09 15:19:51 +02:00
|
|
|
if (IS_OSPF_ABR(ospf))
|
2020-03-24 17:38:20 +01:00
|
|
|
zlog_info(" ABR: %ld (%d areas)",
|
2020-08-05 10:44:21 +02:00
|
|
|
abr_time, ospf->areas->count);
|
2014-10-09 15:19:51 +02:00
|
|
|
zlog_info("Reason(s) for SPF: %s", rbuf);
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2015-05-20 01:36:05 +02:00
|
|
|
ospf_clear_spf_reason_flags();
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* Add schedule for SPF calculation. To avoid frequenst SPF calc, we set timer
|
|
|
|
* for SPF calc.
|
|
|
|
*/
|
2014-10-09 15:19:51 +02:00
|
|
|
void ospf_spf_calculate_schedule(struct ospf *ospf, ospf_spf_reason_t reason)
|
2002-12-13 21:15:29 +01:00
|
|
|
{
|
2005-10-21 Paul Jakma <paul.jakma@sun.com>
* (general) SPF millisecond resolution timer with adaptive,
linear back-off holdtime. Prettification of ospf_timer_dump.
* ospf_dump.c: (ospf_timeval_dump) new function. The guts of
ospf_timer_dump, but made to be more dynamic in printing out
the relative timeval, sliding the precision printed out
according to the value.
(ospf_timer_dump) guts moved to ospf_timeval_dump.
* ospf_dump.h: export ospf_timeval_dump.
* ospf_flood.c: (ospf_flood) remove gettimeofday, use
the libzebra exported recent_time instead, as it's not
terribly critical to have time exactly right - the dropped
LSA will be retransmited to us if we don't ACK it.
* ospf_packet.c: (ospf_ls_upd_timer) Ditto, but here we're
not transmitting, just putting LSA back on update transmit list.
* ospfd.h: delay and holdtimes should be unsigned.
Add spf_max_holdtime and spf_hold_multiplier.
Update default defines for delay and hold time to be in msec.
(struct ospf) change the SPF timestamp to a struct timeval.
Remove ospf_timers_spf_(un)?set.
* ospfd.c: (ospf_timers_spf_{set,unset}) removed.
(ospf_new) initialise spf_max_holdtime and spf_hold_multiplier
* ospf_spf.c: (ospf_spf_calculate) SPF timestamp is a timeval
now, update with gettimeofday.
(ospf_spf_calculate_schedule) Change SPF timers to millisecond
resolution.
Make the holdtime be adaptive, with a linear increase in
holdtime ever consecutive SPF run which occurs within holdtime
of previous SPF, bounded by spf_max_holdtime.
* ospf_vty.c: Update spf timers commands.
(ospf_timers_spf_set) trivial helper.
(ospf_timers_throttle_spf_cmd) new command to set SPF delay,
initial hold and max hold times with millisecond resolution.
(ospf_timers_spf_cmd) Deprecated. Accept the old values,
convert to msec, truncate to new limits.
(no_ospf_timers_throttle_spf_cmd) set timers to defaults.
(no_ospf_timers_spf_cmd) deprecated form, same as previous.
(show_ip_ospf_cmd) Display SPF parameters and times.
(show_ip_ospf_neighbour_header) Centralise the 'sh ip os ne'
header.
(show_ip_ospf_neighbor_sub) Fix the field widths. Get rid of
the multiple spaces which were making the lines even longer.
(show_ip_ospf_neighbor_cmd) Use show_ip_ospf_neighbour_header
(show_ip_ospf_neighbor_all_cmd) ditto and fix the field
widths for NBMA neighbours.
(show_ip_ospf_neighbor_int) Use header function.
(show_ip_ospf_nbr_nbma_detail_sub) use sizeof for timebuf,
local array - safer.
(show_ip_ospf_neighbor_detail_sub) ditto
(ospf_vty_init) install the new SPF throttle timer commands.
2005-10-21 11:23:12 +02:00
|
|
|
unsigned long delay, elapsed, ht;
|
2002-12-13 21:15:29 +01:00
|
|
|
|
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
zlog_debug("SPF: calculation timer scheduled");
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* OSPF instance does not exist. */
|
2003-03-25 06:07:42 +01:00
|
|
|
if (ospf == NULL)
|
2002-12-13 21:15:29 +01:00
|
|
|
return;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2014-10-09 15:19:51 +02:00
|
|
|
ospf_spf_set_reason(reason);
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* SPF calculation timer is already scheduled. */
|
2003-03-25 06:07:42 +01:00
|
|
|
if (ospf->t_spf_calc) {
|
2002-12-13 21:15:29 +01:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2004-12-08 19:43:03 +01:00
|
|
|
zlog_debug(
|
|
|
|
"SPF: calculation timer is already scheduled: %p",
|
2015-03-03 08:51:53 +01:00
|
|
|
(void *)ospf->t_spf_calc);
|
2002-12-13 21:15:29 +01:00
|
|
|
return;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-01-17 22:05:56 +01:00
|
|
|
elapsed = monotime_since(&ospf->ts_spf, NULL) / 1000;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-10-21 Paul Jakma <paul.jakma@sun.com>
* (general) SPF millisecond resolution timer with adaptive,
linear back-off holdtime. Prettification of ospf_timer_dump.
* ospf_dump.c: (ospf_timeval_dump) new function. The guts of
ospf_timer_dump, but made to be more dynamic in printing out
the relative timeval, sliding the precision printed out
according to the value.
(ospf_timer_dump) guts moved to ospf_timeval_dump.
* ospf_dump.h: export ospf_timeval_dump.
* ospf_flood.c: (ospf_flood) remove gettimeofday, use
the libzebra exported recent_time instead, as it's not
terribly critical to have time exactly right - the dropped
LSA will be retransmited to us if we don't ACK it.
* ospf_packet.c: (ospf_ls_upd_timer) Ditto, but here we're
not transmitting, just putting LSA back on update transmit list.
* ospfd.h: delay and holdtimes should be unsigned.
Add spf_max_holdtime and spf_hold_multiplier.
Update default defines for delay and hold time to be in msec.
(struct ospf) change the SPF timestamp to a struct timeval.
Remove ospf_timers_spf_(un)?set.
* ospfd.c: (ospf_timers_spf_{set,unset}) removed.
(ospf_new) initialise spf_max_holdtime and spf_hold_multiplier
* ospf_spf.c: (ospf_spf_calculate) SPF timestamp is a timeval
now, update with gettimeofday.
(ospf_spf_calculate_schedule) Change SPF timers to millisecond
resolution.
Make the holdtime be adaptive, with a linear increase in
holdtime ever consecutive SPF run which occurs within holdtime
of previous SPF, bounded by spf_max_holdtime.
* ospf_vty.c: Update spf timers commands.
(ospf_timers_spf_set) trivial helper.
(ospf_timers_throttle_spf_cmd) new command to set SPF delay,
initial hold and max hold times with millisecond resolution.
(ospf_timers_spf_cmd) Deprecated. Accept the old values,
convert to msec, truncate to new limits.
(no_ospf_timers_throttle_spf_cmd) set timers to defaults.
(no_ospf_timers_spf_cmd) deprecated form, same as previous.
(show_ip_ospf_cmd) Display SPF parameters and times.
(show_ip_ospf_neighbour_header) Centralise the 'sh ip os ne'
header.
(show_ip_ospf_neighbor_sub) Fix the field widths. Get rid of
the multiple spaces which were making the lines even longer.
(show_ip_ospf_neighbor_cmd) Use show_ip_ospf_neighbour_header
(show_ip_ospf_neighbor_all_cmd) ditto and fix the field
widths for NBMA neighbours.
(show_ip_ospf_neighbor_int) Use header function.
(show_ip_ospf_nbr_nbma_detail_sub) use sizeof for timebuf,
local array - safer.
(show_ip_ospf_neighbor_detail_sub) ditto
(ospf_vty_init) install the new SPF throttle timer commands.
2005-10-21 11:23:12 +02:00
|
|
|
ht = ospf->spf_holdtime * ospf->spf_hold_multiplier;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-10-21 Paul Jakma <paul.jakma@sun.com>
* (general) SPF millisecond resolution timer with adaptive,
linear back-off holdtime. Prettification of ospf_timer_dump.
* ospf_dump.c: (ospf_timeval_dump) new function. The guts of
ospf_timer_dump, but made to be more dynamic in printing out
the relative timeval, sliding the precision printed out
according to the value.
(ospf_timer_dump) guts moved to ospf_timeval_dump.
* ospf_dump.h: export ospf_timeval_dump.
* ospf_flood.c: (ospf_flood) remove gettimeofday, use
the libzebra exported recent_time instead, as it's not
terribly critical to have time exactly right - the dropped
LSA will be retransmited to us if we don't ACK it.
* ospf_packet.c: (ospf_ls_upd_timer) Ditto, but here we're
not transmitting, just putting LSA back on update transmit list.
* ospfd.h: delay and holdtimes should be unsigned.
Add spf_max_holdtime and spf_hold_multiplier.
Update default defines for delay and hold time to be in msec.
(struct ospf) change the SPF timestamp to a struct timeval.
Remove ospf_timers_spf_(un)?set.
* ospfd.c: (ospf_timers_spf_{set,unset}) removed.
(ospf_new) initialise spf_max_holdtime and spf_hold_multiplier
* ospf_spf.c: (ospf_spf_calculate) SPF timestamp is a timeval
now, update with gettimeofday.
(ospf_spf_calculate_schedule) Change SPF timers to millisecond
resolution.
Make the holdtime be adaptive, with a linear increase in
holdtime ever consecutive SPF run which occurs within holdtime
of previous SPF, bounded by spf_max_holdtime.
* ospf_vty.c: Update spf timers commands.
(ospf_timers_spf_set) trivial helper.
(ospf_timers_throttle_spf_cmd) new command to set SPF delay,
initial hold and max hold times with millisecond resolution.
(ospf_timers_spf_cmd) Deprecated. Accept the old values,
convert to msec, truncate to new limits.
(no_ospf_timers_throttle_spf_cmd) set timers to defaults.
(no_ospf_timers_spf_cmd) deprecated form, same as previous.
(show_ip_ospf_cmd) Display SPF parameters and times.
(show_ip_ospf_neighbour_header) Centralise the 'sh ip os ne'
header.
(show_ip_ospf_neighbor_sub) Fix the field widths. Get rid of
the multiple spaces which were making the lines even longer.
(show_ip_ospf_neighbor_cmd) Use show_ip_ospf_neighbour_header
(show_ip_ospf_neighbor_all_cmd) ditto and fix the field
widths for NBMA neighbours.
(show_ip_ospf_neighbor_int) Use header function.
(show_ip_ospf_nbr_nbma_detail_sub) use sizeof for timebuf,
local array - safer.
(show_ip_ospf_neighbor_detail_sub) ditto
(ospf_vty_init) install the new SPF throttle timer commands.
2005-10-21 11:23:12 +02:00
|
|
|
if (ht > ospf->spf_max_holdtime)
|
|
|
|
ht = ospf->spf_max_holdtime;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
/* Get SPF calculation delay time. */
|
2005-10-21 Paul Jakma <paul.jakma@sun.com>
* (general) SPF millisecond resolution timer with adaptive,
linear back-off holdtime. Prettification of ospf_timer_dump.
* ospf_dump.c: (ospf_timeval_dump) new function. The guts of
ospf_timer_dump, but made to be more dynamic in printing out
the relative timeval, sliding the precision printed out
according to the value.
(ospf_timer_dump) guts moved to ospf_timeval_dump.
* ospf_dump.h: export ospf_timeval_dump.
* ospf_flood.c: (ospf_flood) remove gettimeofday, use
the libzebra exported recent_time instead, as it's not
terribly critical to have time exactly right - the dropped
LSA will be retransmited to us if we don't ACK it.
* ospf_packet.c: (ospf_ls_upd_timer) Ditto, but here we're
not transmitting, just putting LSA back on update transmit list.
* ospfd.h: delay and holdtimes should be unsigned.
Add spf_max_holdtime and spf_hold_multiplier.
Update default defines for delay and hold time to be in msec.
(struct ospf) change the SPF timestamp to a struct timeval.
Remove ospf_timers_spf_(un)?set.
* ospfd.c: (ospf_timers_spf_{set,unset}) removed.
(ospf_new) initialise spf_max_holdtime and spf_hold_multiplier
* ospf_spf.c: (ospf_spf_calculate) SPF timestamp is a timeval
now, update with gettimeofday.
(ospf_spf_calculate_schedule) Change SPF timers to millisecond
resolution.
Make the holdtime be adaptive, with a linear increase in
holdtime ever consecutive SPF run which occurs within holdtime
of previous SPF, bounded by spf_max_holdtime.
* ospf_vty.c: Update spf timers commands.
(ospf_timers_spf_set) trivial helper.
(ospf_timers_throttle_spf_cmd) new command to set SPF delay,
initial hold and max hold times with millisecond resolution.
(ospf_timers_spf_cmd) Deprecated. Accept the old values,
convert to msec, truncate to new limits.
(no_ospf_timers_throttle_spf_cmd) set timers to defaults.
(no_ospf_timers_spf_cmd) deprecated form, same as previous.
(show_ip_ospf_cmd) Display SPF parameters and times.
(show_ip_ospf_neighbour_header) Centralise the 'sh ip os ne'
header.
(show_ip_ospf_neighbor_sub) Fix the field widths. Get rid of
the multiple spaces which were making the lines even longer.
(show_ip_ospf_neighbor_cmd) Use show_ip_ospf_neighbour_header
(show_ip_ospf_neighbor_all_cmd) ditto and fix the field
widths for NBMA neighbours.
(show_ip_ospf_neighbor_int) Use header function.
(show_ip_ospf_nbr_nbma_detail_sub) use sizeof for timebuf,
local array - safer.
(show_ip_ospf_neighbor_detail_sub) ditto
(ospf_vty_init) install the new SPF throttle timer commands.
2005-10-21 11:23:12 +02:00
|
|
|
if (elapsed < ht) {
|
2020-08-05 16:16:57 +02:00
|
|
|
/*
|
|
|
|
* Got an event within the hold time of last SPF. We need to
|
2005-10-21 Paul Jakma <paul.jakma@sun.com>
* (general) SPF millisecond resolution timer with adaptive,
linear back-off holdtime. Prettification of ospf_timer_dump.
* ospf_dump.c: (ospf_timeval_dump) new function. The guts of
ospf_timer_dump, but made to be more dynamic in printing out
the relative timeval, sliding the precision printed out
according to the value.
(ospf_timer_dump) guts moved to ospf_timeval_dump.
* ospf_dump.h: export ospf_timeval_dump.
* ospf_flood.c: (ospf_flood) remove gettimeofday, use
the libzebra exported recent_time instead, as it's not
terribly critical to have time exactly right - the dropped
LSA will be retransmited to us if we don't ACK it.
* ospf_packet.c: (ospf_ls_upd_timer) Ditto, but here we're
not transmitting, just putting LSA back on update transmit list.
* ospfd.h: delay and holdtimes should be unsigned.
Add spf_max_holdtime and spf_hold_multiplier.
Update default defines for delay and hold time to be in msec.
(struct ospf) change the SPF timestamp to a struct timeval.
Remove ospf_timers_spf_(un)?set.
* ospfd.c: (ospf_timers_spf_{set,unset}) removed.
(ospf_new) initialise spf_max_holdtime and spf_hold_multiplier
* ospf_spf.c: (ospf_spf_calculate) SPF timestamp is a timeval
now, update with gettimeofday.
(ospf_spf_calculate_schedule) Change SPF timers to millisecond
resolution.
Make the holdtime be adaptive, with a linear increase in
holdtime ever consecutive SPF run which occurs within holdtime
of previous SPF, bounded by spf_max_holdtime.
* ospf_vty.c: Update spf timers commands.
(ospf_timers_spf_set) trivial helper.
(ospf_timers_throttle_spf_cmd) new command to set SPF delay,
initial hold and max hold times with millisecond resolution.
(ospf_timers_spf_cmd) Deprecated. Accept the old values,
convert to msec, truncate to new limits.
(no_ospf_timers_throttle_spf_cmd) set timers to defaults.
(no_ospf_timers_spf_cmd) deprecated form, same as previous.
(show_ip_ospf_cmd) Display SPF parameters and times.
(show_ip_ospf_neighbour_header) Centralise the 'sh ip os ne'
header.
(show_ip_ospf_neighbor_sub) Fix the field widths. Get rid of
the multiple spaces which were making the lines even longer.
(show_ip_ospf_neighbor_cmd) Use show_ip_ospf_neighbour_header
(show_ip_ospf_neighbor_all_cmd) ditto and fix the field
widths for NBMA neighbours.
(show_ip_ospf_neighbor_int) Use header function.
(show_ip_ospf_nbr_nbma_detail_sub) use sizeof for timebuf,
local array - safer.
(show_ip_ospf_neighbor_detail_sub) ditto
(ospf_vty_init) install the new SPF throttle timer commands.
2005-10-21 11:23:12 +02:00
|
|
|
* increase the hold_multiplier, if it's not already at/past
|
2020-08-05 16:16:57 +02:00
|
|
|
* maximum value, and wasn't already increased.
|
2005-10-21 Paul Jakma <paul.jakma@sun.com>
* (general) SPF millisecond resolution timer with adaptive,
linear back-off holdtime. Prettification of ospf_timer_dump.
* ospf_dump.c: (ospf_timeval_dump) new function. The guts of
ospf_timer_dump, but made to be more dynamic in printing out
the relative timeval, sliding the precision printed out
according to the value.
(ospf_timer_dump) guts moved to ospf_timeval_dump.
* ospf_dump.h: export ospf_timeval_dump.
* ospf_flood.c: (ospf_flood) remove gettimeofday, use
the libzebra exported recent_time instead, as it's not
terribly critical to have time exactly right - the dropped
LSA will be retransmited to us if we don't ACK it.
* ospf_packet.c: (ospf_ls_upd_timer) Ditto, but here we're
not transmitting, just putting LSA back on update transmit list.
* ospfd.h: delay and holdtimes should be unsigned.
Add spf_max_holdtime and spf_hold_multiplier.
Update default defines for delay and hold time to be in msec.
(struct ospf) change the SPF timestamp to a struct timeval.
Remove ospf_timers_spf_(un)?set.
* ospfd.c: (ospf_timers_spf_{set,unset}) removed.
(ospf_new) initialise spf_max_holdtime and spf_hold_multiplier
* ospf_spf.c: (ospf_spf_calculate) SPF timestamp is a timeval
now, update with gettimeofday.
(ospf_spf_calculate_schedule) Change SPF timers to millisecond
resolution.
Make the holdtime be adaptive, with a linear increase in
holdtime ever consecutive SPF run which occurs within holdtime
of previous SPF, bounded by spf_max_holdtime.
* ospf_vty.c: Update spf timers commands.
(ospf_timers_spf_set) trivial helper.
(ospf_timers_throttle_spf_cmd) new command to set SPF delay,
initial hold and max hold times with millisecond resolution.
(ospf_timers_spf_cmd) Deprecated. Accept the old values,
convert to msec, truncate to new limits.
(no_ospf_timers_throttle_spf_cmd) set timers to defaults.
(no_ospf_timers_spf_cmd) deprecated form, same as previous.
(show_ip_ospf_cmd) Display SPF parameters and times.
(show_ip_ospf_neighbour_header) Centralise the 'sh ip os ne'
header.
(show_ip_ospf_neighbor_sub) Fix the field widths. Get rid of
the multiple spaces which were making the lines even longer.
(show_ip_ospf_neighbor_cmd) Use show_ip_ospf_neighbour_header
(show_ip_ospf_neighbor_all_cmd) ditto and fix the field
widths for NBMA neighbours.
(show_ip_ospf_neighbor_int) Use header function.
(show_ip_ospf_nbr_nbma_detail_sub) use sizeof for timebuf,
local array - safer.
(show_ip_ospf_neighbor_detail_sub) ditto
(ospf_vty_init) install the new SPF throttle timer commands.
2005-10-21 11:23:12 +02:00
|
|
|
*/
|
|
|
|
if (ht < ospf->spf_max_holdtime)
|
|
|
|
ospf->spf_hold_multiplier++;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2005-10-21 Paul Jakma <paul.jakma@sun.com>
* (general) SPF millisecond resolution timer with adaptive,
linear back-off holdtime. Prettification of ospf_timer_dump.
* ospf_dump.c: (ospf_timeval_dump) new function. The guts of
ospf_timer_dump, but made to be more dynamic in printing out
the relative timeval, sliding the precision printed out
according to the value.
(ospf_timer_dump) guts moved to ospf_timeval_dump.
* ospf_dump.h: export ospf_timeval_dump.
* ospf_flood.c: (ospf_flood) remove gettimeofday, use
the libzebra exported recent_time instead, as it's not
terribly critical to have time exactly right - the dropped
LSA will be retransmited to us if we don't ACK it.
* ospf_packet.c: (ospf_ls_upd_timer) Ditto, but here we're
not transmitting, just putting LSA back on update transmit list.
* ospfd.h: delay and holdtimes should be unsigned.
Add spf_max_holdtime and spf_hold_multiplier.
Update default defines for delay and hold time to be in msec.
(struct ospf) change the SPF timestamp to a struct timeval.
Remove ospf_timers_spf_(un)?set.
* ospfd.c: (ospf_timers_spf_{set,unset}) removed.
(ospf_new) initialise spf_max_holdtime and spf_hold_multiplier
* ospf_spf.c: (ospf_spf_calculate) SPF timestamp is a timeval
now, update with gettimeofday.
(ospf_spf_calculate_schedule) Change SPF timers to millisecond
resolution.
Make the holdtime be adaptive, with a linear increase in
holdtime ever consecutive SPF run which occurs within holdtime
of previous SPF, bounded by spf_max_holdtime.
* ospf_vty.c: Update spf timers commands.
(ospf_timers_spf_set) trivial helper.
(ospf_timers_throttle_spf_cmd) new command to set SPF delay,
initial hold and max hold times with millisecond resolution.
(ospf_timers_spf_cmd) Deprecated. Accept the old values,
convert to msec, truncate to new limits.
(no_ospf_timers_throttle_spf_cmd) set timers to defaults.
(no_ospf_timers_spf_cmd) deprecated form, same as previous.
(show_ip_ospf_cmd) Display SPF parameters and times.
(show_ip_ospf_neighbour_header) Centralise the 'sh ip os ne'
header.
(show_ip_ospf_neighbor_sub) Fix the field widths. Get rid of
the multiple spaces which were making the lines even longer.
(show_ip_ospf_neighbor_cmd) Use show_ip_ospf_neighbour_header
(show_ip_ospf_neighbor_all_cmd) ditto and fix the field
widths for NBMA neighbours.
(show_ip_ospf_neighbor_int) Use header function.
(show_ip_ospf_nbr_nbma_detail_sub) use sizeof for timebuf,
local array - safer.
(show_ip_ospf_neighbor_detail_sub) ditto
(ospf_vty_init) install the new SPF throttle timer commands.
2005-10-21 11:23:12 +02:00
|
|
|
/* always honour the SPF initial delay */
|
|
|
|
if ((ht - elapsed) < ospf->spf_delay)
|
2003-06-07 01:27:04 +02:00
|
|
|
delay = ospf->spf_delay;
|
2002-12-13 21:15:29 +01:00
|
|
|
else
|
2005-10-21 Paul Jakma <paul.jakma@sun.com>
* (general) SPF millisecond resolution timer with adaptive,
linear back-off holdtime. Prettification of ospf_timer_dump.
* ospf_dump.c: (ospf_timeval_dump) new function. The guts of
ospf_timer_dump, but made to be more dynamic in printing out
the relative timeval, sliding the precision printed out
according to the value.
(ospf_timer_dump) guts moved to ospf_timeval_dump.
* ospf_dump.h: export ospf_timeval_dump.
* ospf_flood.c: (ospf_flood) remove gettimeofday, use
the libzebra exported recent_time instead, as it's not
terribly critical to have time exactly right - the dropped
LSA will be retransmited to us if we don't ACK it.
* ospf_packet.c: (ospf_ls_upd_timer) Ditto, but here we're
not transmitting, just putting LSA back on update transmit list.
* ospfd.h: delay and holdtimes should be unsigned.
Add spf_max_holdtime and spf_hold_multiplier.
Update default defines for delay and hold time to be in msec.
(struct ospf) change the SPF timestamp to a struct timeval.
Remove ospf_timers_spf_(un)?set.
* ospfd.c: (ospf_timers_spf_{set,unset}) removed.
(ospf_new) initialise spf_max_holdtime and spf_hold_multiplier
* ospf_spf.c: (ospf_spf_calculate) SPF timestamp is a timeval
now, update with gettimeofday.
(ospf_spf_calculate_schedule) Change SPF timers to millisecond
resolution.
Make the holdtime be adaptive, with a linear increase in
holdtime ever consecutive SPF run which occurs within holdtime
of previous SPF, bounded by spf_max_holdtime.
* ospf_vty.c: Update spf timers commands.
(ospf_timers_spf_set) trivial helper.
(ospf_timers_throttle_spf_cmd) new command to set SPF delay,
initial hold and max hold times with millisecond resolution.
(ospf_timers_spf_cmd) Deprecated. Accept the old values,
convert to msec, truncate to new limits.
(no_ospf_timers_throttle_spf_cmd) set timers to defaults.
(no_ospf_timers_spf_cmd) deprecated form, same as previous.
(show_ip_ospf_cmd) Display SPF parameters and times.
(show_ip_ospf_neighbour_header) Centralise the 'sh ip os ne'
header.
(show_ip_ospf_neighbor_sub) Fix the field widths. Get rid of
the multiple spaces which were making the lines even longer.
(show_ip_ospf_neighbor_cmd) Use show_ip_ospf_neighbour_header
(show_ip_ospf_neighbor_all_cmd) ditto and fix the field
widths for NBMA neighbours.
(show_ip_ospf_neighbor_int) Use header function.
(show_ip_ospf_nbr_nbma_detail_sub) use sizeof for timebuf,
local array - safer.
(show_ip_ospf_neighbor_detail_sub) ditto
(ospf_vty_init) install the new SPF throttle timer commands.
2005-10-21 11:23:12 +02:00
|
|
|
delay = ht - elapsed;
|
2002-12-13 21:15:29 +01:00
|
|
|
} else {
|
2005-10-21 Paul Jakma <paul.jakma@sun.com>
* (general) SPF millisecond resolution timer with adaptive,
linear back-off holdtime. Prettification of ospf_timer_dump.
* ospf_dump.c: (ospf_timeval_dump) new function. The guts of
ospf_timer_dump, but made to be more dynamic in printing out
the relative timeval, sliding the precision printed out
according to the value.
(ospf_timer_dump) guts moved to ospf_timeval_dump.
* ospf_dump.h: export ospf_timeval_dump.
* ospf_flood.c: (ospf_flood) remove gettimeofday, use
the libzebra exported recent_time instead, as it's not
terribly critical to have time exactly right - the dropped
LSA will be retransmited to us if we don't ACK it.
* ospf_packet.c: (ospf_ls_upd_timer) Ditto, but here we're
not transmitting, just putting LSA back on update transmit list.
* ospfd.h: delay and holdtimes should be unsigned.
Add spf_max_holdtime and spf_hold_multiplier.
Update default defines for delay and hold time to be in msec.
(struct ospf) change the SPF timestamp to a struct timeval.
Remove ospf_timers_spf_(un)?set.
* ospfd.c: (ospf_timers_spf_{set,unset}) removed.
(ospf_new) initialise spf_max_holdtime and spf_hold_multiplier
* ospf_spf.c: (ospf_spf_calculate) SPF timestamp is a timeval
now, update with gettimeofday.
(ospf_spf_calculate_schedule) Change SPF timers to millisecond
resolution.
Make the holdtime be adaptive, with a linear increase in
holdtime ever consecutive SPF run which occurs within holdtime
of previous SPF, bounded by spf_max_holdtime.
* ospf_vty.c: Update spf timers commands.
(ospf_timers_spf_set) trivial helper.
(ospf_timers_throttle_spf_cmd) new command to set SPF delay,
initial hold and max hold times with millisecond resolution.
(ospf_timers_spf_cmd) Deprecated. Accept the old values,
convert to msec, truncate to new limits.
(no_ospf_timers_throttle_spf_cmd) set timers to defaults.
(no_ospf_timers_spf_cmd) deprecated form, same as previous.
(show_ip_ospf_cmd) Display SPF parameters and times.
(show_ip_ospf_neighbour_header) Centralise the 'sh ip os ne'
header.
(show_ip_ospf_neighbor_sub) Fix the field widths. Get rid of
the multiple spaces which were making the lines even longer.
(show_ip_ospf_neighbor_cmd) Use show_ip_ospf_neighbour_header
(show_ip_ospf_neighbor_all_cmd) ditto and fix the field
widths for NBMA neighbours.
(show_ip_ospf_neighbor_int) Use header function.
(show_ip_ospf_nbr_nbma_detail_sub) use sizeof for timebuf,
local array - safer.
(show_ip_ospf_neighbor_detail_sub) ditto
(ospf_vty_init) install the new SPF throttle timer commands.
2005-10-21 11:23:12 +02:00
|
|
|
/* Event is past required hold-time of last SPF */
|
|
|
|
delay = ospf->spf_delay;
|
|
|
|
ospf->spf_hold_multiplier = 1;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2002-12-13 21:15:29 +01:00
|
|
|
if (IS_DEBUG_OSPF_EVENT)
|
2017-12-26 18:45:25 +01:00
|
|
|
zlog_debug("SPF: calculation timer delay = %ld msec", delay);
|
2015-05-20 01:36:05 +02:00
|
|
|
|
2017-05-05 23:22:25 +02:00
|
|
|
ospf->t_spf_calc = NULL;
|
2020-08-05 16:16:57 +02:00
|
|
|
thread_add_timer_msec(master, ospf_spf_calculate_schedule_worker, ospf,
|
|
|
|
delay, &ospf->t_spf_calc);
|
2002-12-13 21:15:29 +01:00
|
|
|
}
|