mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-13 22:57:45 +00:00
Merge pull request #1566 from chiragshah6/ospfv3_dev
ospf6d: Fix External routes ECMP
This commit is contained in:
commit
0c6a8fb9ec
@ -901,6 +901,7 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
|
||||
|
||||
ospf6_route_copy_nexthops(route, abr_entry);
|
||||
|
||||
|
||||
/* (7) If the routes are identical, copy the next hops over to existing
|
||||
route. ospf6's route table implementation will otherwise string both
|
||||
routes, but keep the older one as the best route since the routes
|
||||
@ -910,6 +911,12 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
|
||||
|
||||
if (old && (ospf6_route_cmp(route, old) == 0)) {
|
||||
ospf6_route_merge_nexthops(old, route);
|
||||
|
||||
if (is_debug)
|
||||
zlog_debug("%s: Update route: %s nh count %u",
|
||||
__PRETTY_FUNCTION__,
|
||||
buf, listcount(route->nh_list));
|
||||
|
||||
/* Update RIB/FIB */
|
||||
if (table->hook_add)
|
||||
(*table->hook_add)(old);
|
||||
@ -918,7 +925,8 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
|
||||
ospf6_route_delete(route);
|
||||
} else {
|
||||
if (is_debug)
|
||||
zlog_debug("Install route: %s", buf);
|
||||
zlog_debug("Install route: %s nh count %u",
|
||||
buf, listcount(route->nh_list));
|
||||
/* ospf6_ia_add_nw_route (table, &prefix, route); */
|
||||
ospf6_route_add(route, table);
|
||||
}
|
||||
|
@ -117,7 +117,9 @@ static void ospf6_area_lsdb_hook_remove(struct ospf6_lsa *lsa)
|
||||
|
||||
static void ospf6_area_route_hook_add(struct ospf6_route *route)
|
||||
{
|
||||
struct ospf6_route *copy = ospf6_route_copy(route);
|
||||
struct ospf6_route *copy;
|
||||
|
||||
copy = ospf6_route_copy(route);
|
||||
ospf6_route_add(copy, ospf6->route_table);
|
||||
}
|
||||
|
||||
|
@ -173,11 +173,136 @@ static route_tag_t ospf6_as_external_lsa_get_tag(struct ospf6_lsa *lsa)
|
||||
return ntohl(network_order);
|
||||
}
|
||||
|
||||
void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
|
||||
struct ospf6_route *route)
|
||||
{
|
||||
struct ospf6_route *old_route;
|
||||
struct ospf6_path *ecmp_path, *o_path = NULL;
|
||||
struct listnode *anode;
|
||||
struct listnode *nnode, *rnode, *rnext;
|
||||
struct ospf6_nexthop *nh, *rnh;
|
||||
char buf[PREFIX2STR_BUFFER];
|
||||
bool route_found = false;
|
||||
|
||||
for (old_route = old; old_route; old_route = old_route->next) {
|
||||
if (ospf6_route_is_same(old_route, route) &&
|
||||
(old_route->path.type == route->path.type) &&
|
||||
(old_route->path.cost == route->path.cost) &&
|
||||
(old_route->path.u.cost_e2 == route->path.u.cost_e2)) {
|
||||
|
||||
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||
prefix2str(&old_route->prefix, buf,
|
||||
sizeof(buf));
|
||||
zlog_debug("%s: old route %s path cost %u [%u]",
|
||||
__PRETTY_FUNCTION__, buf,
|
||||
old_route->path.cost,
|
||||
ospf6_route_is_same(old_route,
|
||||
route));
|
||||
}
|
||||
route_found = true;
|
||||
/* check if this path exists already in
|
||||
* route->paths list, if so, replace nh_list
|
||||
* from asbr_entry.
|
||||
*/
|
||||
for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
|
||||
o_path)) {
|
||||
if ((o_path->origin.id == route->path.origin.id)
|
||||
&& (o_path->origin.adv_router ==
|
||||
route->path.origin.adv_router))
|
||||
break;
|
||||
}
|
||||
/* If path is not found in old_route paths's list,
|
||||
* add a new path to route paths list and merge
|
||||
* nexthops in route->path->nh_list.
|
||||
* Otherwise replace existing path's nh_list.
|
||||
*/
|
||||
if (o_path == NULL) {
|
||||
ecmp_path = ospf6_path_dup(&route->path);
|
||||
|
||||
/* Add a nh_list to new ecmp path */
|
||||
ospf6_copy_nexthops(ecmp_path->nh_list,
|
||||
route->nh_list);
|
||||
/* Merge nexthop to existing route's nh_list */
|
||||
ospf6_route_merge_nexthops(old_route, route);
|
||||
|
||||
/* Update RIB/FIB */
|
||||
if (ospf6->route_table->hook_add)
|
||||
(*ospf6->route_table->hook_add)
|
||||
(old_route);
|
||||
|
||||
/* Add the new path to route's path list */
|
||||
listnode_add_sort(old_route->paths, ecmp_path);
|
||||
|
||||
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||
prefix2str(&route->prefix, buf,
|
||||
sizeof(buf));
|
||||
zlog_debug("%s: route %s another path added with nh %u, Paths %u",
|
||||
__PRETTY_FUNCTION__, buf,
|
||||
listcount(ecmp_path->nh_list),
|
||||
old_route->paths ?
|
||||
listcount(old_route->paths)
|
||||
: 0);
|
||||
}
|
||||
} else {
|
||||
for (ALL_LIST_ELEMENTS_RO(o_path->nh_list,
|
||||
nnode, nh)) {
|
||||
for (ALL_LIST_ELEMENTS(
|
||||
old_route->nh_list,
|
||||
rnode, rnext, rnh)) {
|
||||
if (!ospf6_nexthop_is_same(rnh,
|
||||
nh))
|
||||
continue;
|
||||
|
||||
listnode_delete(
|
||||
old_route->nh_list,
|
||||
rnh);
|
||||
ospf6_nexthop_delete(rnh);
|
||||
}
|
||||
}
|
||||
list_delete_all_node(o_path->nh_list);
|
||||
ospf6_copy_nexthops(o_path->nh_list,
|
||||
route->nh_list);
|
||||
|
||||
/* Merge nexthop to existing route's nh_list */
|
||||
ospf6_route_merge_nexthops(old_route,
|
||||
route);
|
||||
|
||||
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||
prefix2str(&route->prefix,
|
||||
buf, sizeof(buf));
|
||||
zlog_debug("%s: existing route %s with effective nh count %u",
|
||||
__PRETTY_FUNCTION__, buf,
|
||||
old_route->nh_list ?
|
||||
listcount(old_route->nh_list)
|
||||
: 0);
|
||||
}
|
||||
|
||||
/* Update RIB/FIB */
|
||||
if (ospf6->route_table->hook_add)
|
||||
(*ospf6->route_table->hook_add)
|
||||
(old_route);
|
||||
|
||||
}
|
||||
/* Delete the new route its info added to existing
|
||||
* route.
|
||||
*/
|
||||
ospf6_route_delete(route);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!route_found) {
|
||||
/* Add new route to existing node in ospf6 route table. */
|
||||
ospf6_route_add(route, ospf6->route_table);
|
||||
}
|
||||
}
|
||||
|
||||
void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa)
|
||||
{
|
||||
struct ospf6_as_external_lsa *external;
|
||||
struct prefix asbr_id;
|
||||
struct ospf6_route *asbr_entry, *route;
|
||||
struct ospf6_route *asbr_entry, *route, *old;
|
||||
struct ospf6_path *path;
|
||||
char buf[PREFIX2STR_BUFFER];
|
||||
|
||||
external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
|
||||
@ -245,12 +370,34 @@ void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa)
|
||||
|
||||
ospf6_route_copy_nexthops(route, asbr_entry);
|
||||
|
||||
path = ospf6_path_dup(&route->path);
|
||||
ospf6_copy_nexthops(path->nh_list, asbr_entry->nh_list);
|
||||
listnode_add_sort(route->paths, path);
|
||||
|
||||
|
||||
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||
prefix2str(&route->prefix, buf, sizeof(buf));
|
||||
zlog_debug("AS-External route add: %s", buf);
|
||||
zlog_debug("%s: AS-External %u route add %s cost %u(%u) nh %u",
|
||||
__PRETTY_FUNCTION__,
|
||||
(route->path.type == OSPF6_PATH_TYPE_EXTERNAL1)
|
||||
? 1 : 2, buf, route->path.cost,
|
||||
route->path.u.cost_e2,
|
||||
listcount(route->nh_list));
|
||||
}
|
||||
|
||||
old = ospf6_route_lookup(&route->prefix, ospf6->route_table);
|
||||
if (!old) {
|
||||
/* Add the new route to ospf6 instance route table. */
|
||||
ospf6_route_add(route, ospf6->route_table);
|
||||
} else {
|
||||
/* RFC 2328 16.4 (6)
|
||||
* ECMP: Keep new equal preference path in current
|
||||
* route's path list, update zebra with new effective
|
||||
* list along with addition of ECMP path.
|
||||
*/
|
||||
ospf6_asbr_update_route_ecmp_path(old, route);
|
||||
}
|
||||
|
||||
ospf6_route_add(route, ospf6->route_table);
|
||||
}
|
||||
|
||||
void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
|
||||
@ -291,16 +438,126 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa)
|
||||
nroute = ospf6_route_next(route);
|
||||
if (route->type != OSPF6_DEST_TYPE_NETWORK)
|
||||
continue;
|
||||
if (route->path.origin.type != lsa->header->type)
|
||||
continue;
|
||||
if (route->path.origin.id != lsa->header->id)
|
||||
continue;
|
||||
if (route->path.origin.adv_router != lsa->header->adv_router)
|
||||
|
||||
/* Route has multiple ECMP paths remove,
|
||||
* matching path and update effective route's nh list.
|
||||
*/
|
||||
if (listcount(route->paths) > 1) {
|
||||
struct listnode *anode, *anext;
|
||||
struct listnode *nnode, *rnode, *rnext;
|
||||
struct ospf6_nexthop *nh, *rnh;
|
||||
struct ospf6_path *o_path;
|
||||
bool nh_updated = false;
|
||||
|
||||
/* Iterate all paths of route to find maching with LSA
|
||||
* remove from route path list. If route->path is same,
|
||||
* replace from paths list.
|
||||
*/
|
||||
for (ALL_LIST_ELEMENTS(route->paths, anode, anext,
|
||||
o_path)) {
|
||||
if (o_path->origin.type != lsa->header->type)
|
||||
continue;
|
||||
if (o_path->origin.id != lsa->header->id)
|
||||
continue;
|
||||
if (o_path->origin.adv_router !=
|
||||
lsa->header->adv_router)
|
||||
continue;
|
||||
|
||||
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||
prefix2str(&prefix, buf, sizeof(buf));
|
||||
zlog_debug(
|
||||
"%s: route %s path found with nh %u",
|
||||
__PRETTY_FUNCTION__, buf,
|
||||
listcount(o_path->nh_list));
|
||||
}
|
||||
|
||||
/* Remove found path's nh_list from
|
||||
* the route's nh_list.
|
||||
*/
|
||||
for (ALL_LIST_ELEMENTS_RO(o_path->nh_list,
|
||||
nnode, nh)) {
|
||||
for (ALL_LIST_ELEMENTS(route->nh_list,
|
||||
rnode, rnext, rnh)) {
|
||||
if (!ospf6_nexthop_is_same(rnh,
|
||||
nh))
|
||||
continue;
|
||||
listnode_delete(route->nh_list,
|
||||
rnh);
|
||||
ospf6_nexthop_delete(rnh);
|
||||
}
|
||||
}
|
||||
/* Delete the path from route's path list */
|
||||
listnode_delete(route->paths, o_path);
|
||||
ospf6_path_free(o_path);
|
||||
nh_updated = true;
|
||||
}
|
||||
|
||||
if (nh_updated) {
|
||||
/* Iterate all paths and merge nexthop,
|
||||
* unlesss any of the nexthop similar to
|
||||
* ones deleted as part of path deletion.
|
||||
*/
|
||||
|
||||
for (ALL_LIST_ELEMENTS(route->paths, anode,
|
||||
anext, o_path)) {
|
||||
ospf6_merge_nexthops(route->nh_list,
|
||||
o_path->nh_list);
|
||||
}
|
||||
|
||||
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||
prefix2str(&route->prefix, buf,
|
||||
sizeof(buf));
|
||||
zlog_debug("%s: AS-External %u route %s update paths %u nh %u"
|
||||
, __PRETTY_FUNCTION__,
|
||||
(route->path.type ==
|
||||
OSPF6_PATH_TYPE_EXTERNAL1)
|
||||
? 1 : 2, buf,
|
||||
listcount(route->paths),
|
||||
listcount(route->nh_list));
|
||||
}
|
||||
|
||||
/* Update RIB/FIB w/ effective nh_list */
|
||||
if (ospf6->route_table->hook_add)
|
||||
(*ospf6->route_table->hook_add)(route);
|
||||
|
||||
/* route's path is similar to lsa header,
|
||||
* replace route's path with route's
|
||||
* paths list head.
|
||||
*/
|
||||
if (route->path.origin.id == lsa->header->id &&
|
||||
route->path.origin.adv_router ==
|
||||
lsa->header->adv_router) {
|
||||
struct ospf6_path *h_path;
|
||||
|
||||
h_path = (struct ospf6_path *)
|
||||
listgetdata(listhead(route->paths));
|
||||
route->path.origin.type =
|
||||
h_path->origin.type;
|
||||
route->path.origin.id =
|
||||
h_path->origin.id;
|
||||
route->path.origin.adv_router =
|
||||
h_path->origin.adv_router;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
||||
} else {
|
||||
if (route->path.origin.type != lsa->header->type)
|
||||
continue;
|
||||
if (route->path.origin.id != lsa->header->id)
|
||||
continue;
|
||||
if (route->path.origin.adv_router !=
|
||||
lsa->header->adv_router)
|
||||
continue;
|
||||
}
|
||||
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||
prefix2str(&route->prefix, buf, sizeof(buf));
|
||||
zlog_debug("AS-External route remove: %s", buf);
|
||||
zlog_debug("%s: AS-External %u route remove %s cost %u(%u) nh %u",
|
||||
__PRETTY_FUNCTION__,
|
||||
route->path.type == OSPF6_PATH_TYPE_EXTERNAL1
|
||||
? 1 : 2, buf, route->path.cost,
|
||||
route->path.u.cost_e2,
|
||||
listcount(route->nh_list));
|
||||
}
|
||||
ospf6_route_remove(route, ospf6->route_table);
|
||||
}
|
||||
|
@ -93,5 +93,7 @@ extern void ospf6_asbr_send_externals_to_area(struct ospf6_area *);
|
||||
|
||||
extern int config_write_ospf6_debug_asbr(struct vty *vty);
|
||||
extern void install_element_ospf6_debug_asbr(void);
|
||||
extern void ospf6_asbr_update_route_ecmp_path(struct ospf6_route *old,
|
||||
struct ospf6_route *route);
|
||||
|
||||
#endif /* OSPF6_ASBR_H */
|
||||
|
@ -1404,7 +1404,8 @@ void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa)
|
||||
|
||||
if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
|
||||
prefix2str(&route->prefix, buf, sizeof(buf));
|
||||
zlog_debug(" route %s add", buf);
|
||||
zlog_debug(" route %s add with nh count %u", buf,
|
||||
listcount(route->nh_list));
|
||||
}
|
||||
|
||||
ospf6_route_add(route, oa->route_table);
|
||||
|
@ -41,4 +41,5 @@ DEFINE_MTYPE(OSPF6D, OSPF6_VERTEX, "OSPF6 vertex")
|
||||
DEFINE_MTYPE(OSPF6D, OSPF6_SPFTREE, "OSPF6 SPF tree")
|
||||
DEFINE_MTYPE(OSPF6D, OSPF6_NEXTHOP, "OSPF6 nexthop")
|
||||
DEFINE_MTYPE(OSPF6D, OSPF6_EXTERNAL_INFO, "OSPF6 ext. info")
|
||||
DEFINE_MTYPE(OSPF6D, OSPF6_PATH, "OSPF6 Path")
|
||||
DEFINE_MTYPE(OSPF6D, OSPF6_OTHER, "OSPF6 other")
|
||||
|
@ -40,6 +40,7 @@ DECLARE_MTYPE(OSPF6_VERTEX)
|
||||
DECLARE_MTYPE(OSPF6_SPFTREE)
|
||||
DECLARE_MTYPE(OSPF6_NEXTHOP)
|
||||
DECLARE_MTYPE(OSPF6_EXTERNAL_INFO)
|
||||
DECLARE_MTYPE(OSPF6_PATH)
|
||||
DECLARE_MTYPE(OSPF6_OTHER)
|
||||
|
||||
#endif /* _QUAGGA_OSPF6_MEMORY_H */
|
||||
|
@ -215,7 +215,7 @@ void ospf6_copy_nexthops(struct list *dst, struct list *src)
|
||||
if (ospf6_nexthop_is_set(nh)) {
|
||||
nh_new = ospf6_nexthop_create();
|
||||
ospf6_nexthop_copy(nh_new, nh);
|
||||
listnode_add(dst, nh_new);
|
||||
listnode_add_sort(dst, nh_new);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -231,7 +231,7 @@ void ospf6_merge_nexthops(struct list *dst, struct list *src)
|
||||
if (!ospf6_route_find_nexthop(dst, nh)) {
|
||||
nh_new = ospf6_nexthop_create();
|
||||
ospf6_nexthop_copy(nh_new, nh);
|
||||
listnode_add(dst, nh_new);
|
||||
listnode_add_sort(dst, nh_new);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -338,7 +338,7 @@ int ospf6_route_get_first_nh_index(struct ospf6_route *route)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int ospf6_nexthop_cmp(struct ospf6_nexthop *a, struct ospf6_nexthop *b)
|
||||
int ospf6_nexthop_cmp(struct ospf6_nexthop *a, struct ospf6_nexthop *b)
|
||||
{
|
||||
if (a->ifindex < b->ifindex)
|
||||
return -1;
|
||||
@ -351,6 +351,36 @@ static int ospf6_nexthop_cmp(struct ospf6_nexthop *a, struct ospf6_nexthop *b)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ospf6_path_cmp(struct ospf6_path *a, struct ospf6_path *b)
|
||||
{
|
||||
if (a->origin.adv_router < b->origin.adv_router)
|
||||
return -1;
|
||||
else if (a->origin.adv_router > b->origin.adv_router)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ospf6_path_free(struct ospf6_path *op)
|
||||
{
|
||||
if (op->nh_list)
|
||||
list_delete_and_null(&op->nh_list);
|
||||
XFREE(MTYPE_OSPF6_PATH, op);
|
||||
}
|
||||
|
||||
struct ospf6_path *ospf6_path_dup(struct ospf6_path *path)
|
||||
{
|
||||
struct ospf6_path *new;
|
||||
|
||||
new = XCALLOC(MTYPE_OSPF6_PATH, sizeof(struct ospf6_path));
|
||||
memcpy(new, path, sizeof(struct ospf6_path));
|
||||
new->nh_list = list_new();
|
||||
new->nh_list->cmp = (int (*)(void *, void *))ospf6_nexthop_cmp;
|
||||
new->nh_list->del = (void (*) (void *))ospf6_nexthop_delete;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
struct ospf6_route *ospf6_route_create(void)
|
||||
{
|
||||
struct ospf6_route *route;
|
||||
@ -358,6 +388,9 @@ struct ospf6_route *ospf6_route_create(void)
|
||||
route->nh_list = list_new();
|
||||
route->nh_list->cmp = (int (*)(void *, void *))ospf6_nexthop_cmp;
|
||||
route->nh_list->del = (void (*) (void *))ospf6_nexthop_delete;
|
||||
route->paths = list_new();
|
||||
route->paths->cmp = (int (*)(void *, void *))ospf6_path_cmp;
|
||||
route->paths->del = (void (*)(void *))ospf6_path_free;
|
||||
return route;
|
||||
}
|
||||
|
||||
@ -366,6 +399,8 @@ void ospf6_route_delete(struct ospf6_route *route)
|
||||
if (route) {
|
||||
if (route->nh_list)
|
||||
list_delete_and_null(&route->nh_list);
|
||||
if (route->paths)
|
||||
list_delete_and_null(&route->paths);
|
||||
XFREE(MTYPE_OSPF6_ROUTE, route);
|
||||
}
|
||||
}
|
||||
@ -464,7 +499,13 @@ ospf6_route_lookup_identical(struct ospf6_route *route,
|
||||
|
||||
for (target = ospf6_route_lookup(&route->prefix, table); target;
|
||||
target = target->next) {
|
||||
if (ospf6_route_is_identical(target, route))
|
||||
if (target->type == route->type &&
|
||||
(memcmp(&target->prefix, &route->prefix,
|
||||
sizeof(struct prefix)) == 0) &&
|
||||
target->path.type == route->path.type &&
|
||||
target->path.cost == route->path.cost &&
|
||||
target->path.u.cost_e2 == route->path.u.cost_e2 &&
|
||||
ospf6_route_cmp_nexthops(target, route) == 0)
|
||||
return target;
|
||||
}
|
||||
return NULL;
|
||||
@ -1083,6 +1124,7 @@ void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route)
|
||||
vty_out(vty, "Metric: %d (%d)\n", route->path.cost,
|
||||
route->path.u.cost_e2);
|
||||
|
||||
vty_out(vty, "Paths count: %u\n", route->paths->count);
|
||||
vty_out(vty, "Nexthop count: %u\n", route->nh_list->count);
|
||||
/* Nexthops */
|
||||
vty_out(vty, "Nexthop:\n");
|
||||
|
@ -96,6 +96,9 @@ struct ospf6_path {
|
||||
u_int32_t cost_config;
|
||||
} u;
|
||||
u_int32_t tag;
|
||||
|
||||
/* nh list for this path */
|
||||
struct list *nh_list;
|
||||
};
|
||||
|
||||
#define OSPF6_PATH_TYPE_NONE 0
|
||||
@ -149,6 +152,9 @@ struct ospf6_route {
|
||||
/* path */
|
||||
struct ospf6_path path;
|
||||
|
||||
/* List of Paths. */
|
||||
struct list *paths;
|
||||
|
||||
/* nexthop */
|
||||
struct list *nh_list;
|
||||
};
|
||||
@ -256,6 +262,7 @@ extern void ospf6_linkstate_prefix2str(struct prefix *prefix, char *buf,
|
||||
int size);
|
||||
|
||||
extern struct ospf6_nexthop *ospf6_nexthop_create(void);
|
||||
extern int ospf6_nexthop_cmp(struct ospf6_nexthop *a, struct ospf6_nexthop *b);
|
||||
extern void ospf6_nexthop_delete(struct ospf6_nexthop *nh);
|
||||
extern void ospf6_clear_nexthops(struct list *nh_list);
|
||||
extern int ospf6_num_nexthops(struct list *nh_list);
|
||||
@ -331,5 +338,7 @@ extern int config_write_ospf6_debug_route(struct vty *vty);
|
||||
extern void install_element_ospf6_debug_route(void);
|
||||
extern void ospf6_route_init(void);
|
||||
extern void ospf6_clean(void);
|
||||
extern void ospf6_path_free(struct ospf6_path *op);
|
||||
extern struct ospf6_path *ospf6_path_dup(struct ospf6_path *path);
|
||||
|
||||
#endif /* OSPF6_ROUTE_H */
|
||||
|
@ -145,6 +145,7 @@ static struct ospf6_vertex *ospf6_vertex_create(struct ospf6_lsa *lsa)
|
||||
v->options[2] = *(u_char *)(OSPF6_LSA_HEADER_END(lsa->header) + 3);
|
||||
|
||||
v->nh_list = list_new();
|
||||
v->nh_list->cmp = (int (*)(void *, void *))ospf6_nexthop_cmp;
|
||||
v->nh_list->del = (void (*) (void *))ospf6_nexthop_delete;
|
||||
|
||||
v->parent = NULL;
|
||||
|
@ -95,6 +95,13 @@ static void ospf6_top_route_hook_remove(struct ospf6_route *route)
|
||||
|
||||
static void ospf6_top_brouter_hook_add(struct ospf6_route *route)
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||
char buf[PREFIX2STR_BUFFER];
|
||||
|
||||
prefix2str(&route->prefix, buf, sizeof(buf));
|
||||
zlog_debug("%s: brouter %s add with nh count %u",
|
||||
__PRETTY_FUNCTION__, buf, listcount(route->nh_list));
|
||||
}
|
||||
ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix));
|
||||
ospf6_asbr_lsentry_add(route);
|
||||
ospf6_abr_originate_summary(route);
|
||||
@ -102,6 +109,13 @@ static void ospf6_top_brouter_hook_add(struct ospf6_route *route)
|
||||
|
||||
static void ospf6_top_brouter_hook_remove(struct ospf6_route *route)
|
||||
{
|
||||
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL)) {
|
||||
char buf[PREFIX2STR_BUFFER];
|
||||
|
||||
prefix2str(&route->prefix, buf, sizeof(buf));
|
||||
zlog_debug("%s: brouter %s del with nh count %u",
|
||||
__PRETTY_FUNCTION__, buf, listcount(route->nh_list));
|
||||
}
|
||||
route->flag |= OSPF6_ROUTE_REMOVE;
|
||||
ospf6_abr_examin_brouter(ADV_ROUTER_IN_PREFIX(&route->prefix));
|
||||
ospf6_asbr_lsentry_remove(route);
|
||||
|
Loading…
Reference in New Issue
Block a user