mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 10:08:41 +00:00
ospf6d: add support for NSSA Type-7 address ranges
Implement NSSA address ranges as specified by RFC 3101: NSSA border routers may be configured with Type-7 address ranges. Each Type-7 address range is defined as an [address,mask] pair. Many separate Type-7 networks may fall into a single Type-7 address range, just as a subnetted network is composed of many separate subnets. NSSA border routers may aggregate Type-7 routes by advertising a single Type-5 LSA for each Type-7 address range. The Type-5 LSA resulting from a Type-7 address range match will be distributed to all Type-5 capable areas. Syntax: area A.B.C.D nssa range X:X::X:X/M [<not-advertise|cost (0-16777215)>] Example: router ospf6 ospf6 router-id 1.1.1.1 area 1 nssa area 1 nssa range 2001:db8:1000::/64 area 1 nssa range 2001:db8:2000::/64 ! Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
parent
2ad3c6dbbe
commit
3c77bc809f
@ -204,6 +204,21 @@ OSPF6 area
|
||||
existence of a default route in the RIB that wasn't learned via the OSPF
|
||||
protocol.
|
||||
|
||||
.. clicmd:: area A.B.C.D nssa range X:X::X:X/M [<not-advertise|cost (0-16777215)>]
|
||||
|
||||
.. clicmd:: area (0-4294967295) nssa range X:X::X:X/M [<not-advertise|cost (0-16777215)>]
|
||||
|
||||
Summarize a group of external subnets into a single Type-7 LSA, which is
|
||||
then translated to a Type-5 LSA and avertised to the backbone.
|
||||
This command can only be used at the area boundary (NSSA ABR router).
|
||||
|
||||
By default, the metric of the summary route is calculated as the highest
|
||||
metric among the summarized routes. The `cost` option, however, can be used
|
||||
to set an explicit metric.
|
||||
|
||||
The `not-advertise` option, when present, prevents the summary route from
|
||||
being advertised, effectively filtering the summarized routes.
|
||||
|
||||
.. clicmd:: area A.B.C.D export-list NAME
|
||||
|
||||
.. clicmd:: area (0-4294967295) export-list NAME
|
||||
|
@ -593,10 +593,14 @@ void ospf6_abr_range_reset_cost(struct ospf6 *ospf6)
|
||||
struct ospf6_area *oa;
|
||||
struct ospf6_route *range;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
|
||||
for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
|
||||
for (range = ospf6_route_head(oa->range_table); range;
|
||||
range = ospf6_route_next(range))
|
||||
OSPF6_ABR_RANGE_CLEAR_COST(range);
|
||||
for (range = ospf6_route_head(oa->nssa_range_table); range;
|
||||
range = ospf6_route_next(range))
|
||||
OSPF6_ABR_RANGE_CLEAR_COST(range);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range,
|
||||
@ -607,10 +611,19 @@ static inline uint32_t ospf6_abr_range_compute_cost(struct ospf6_route *range,
|
||||
|
||||
for (ro = ospf6_route_match_head(&range->prefix, o->route_table); ro;
|
||||
ro = ospf6_route_match_next(&range->prefix, ro)) {
|
||||
if (ro->path.area_id == range->path.area_id
|
||||
&& (ro->path.type == OSPF6_PATH_TYPE_INTRA)
|
||||
&& !CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE))
|
||||
cost = MAX(cost, ro->path.cost);
|
||||
if (CHECK_FLAG(ro->flag, OSPF6_ROUTE_REMOVE))
|
||||
continue;
|
||||
if (ro->path.area_id != range->path.area_id)
|
||||
continue;
|
||||
if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)
|
||||
&& ro->path.type != OSPF6_PATH_TYPE_EXTERNAL1
|
||||
&& ro->path.type != OSPF6_PATH_TYPE_EXTERNAL2)
|
||||
continue;
|
||||
if (!CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)
|
||||
&& ro->path.type != OSPF6_PATH_TYPE_INTRA)
|
||||
continue;
|
||||
|
||||
cost = MAX(cost, ro->path.cost);
|
||||
}
|
||||
|
||||
return cost;
|
||||
@ -659,6 +672,8 @@ void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6)
|
||||
int summary_orig = 0;
|
||||
|
||||
assert(range->type == OSPF6_DEST_TYPE_RANGE);
|
||||
oa = ospf6_area_lookup(range->path.area_id, ospf6);
|
||||
assert(oa);
|
||||
|
||||
/* update range's cost and active flag */
|
||||
cost = ospf6_abr_range_compute_cost(range, ospf6);
|
||||
@ -687,8 +702,26 @@ void ospf6_abr_range_update(struct ospf6_route *range, struct ospf6 *ospf6)
|
||||
if (IS_OSPF6_DEBUG_ABR)
|
||||
zlog_debug("%s: range %pFX update", __func__, &range->prefix);
|
||||
|
||||
for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
|
||||
summary_orig += ospf6_abr_originate_summary_to_area(range, oa);
|
||||
if (CHECK_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE)) {
|
||||
if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
|
||||
&& !CHECK_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
|
||||
ospf6_nssa_lsa_originate(range, oa, true);
|
||||
summary_orig = 1;
|
||||
} else {
|
||||
struct ospf6_lsa *lsa;
|
||||
|
||||
lsa = ospf6_lsdb_lookup(range->path.origin.type,
|
||||
range->path.origin.id,
|
||||
ospf6->router_id, oa->lsdb);
|
||||
if (lsa)
|
||||
ospf6_lsa_premature_aging(lsa);
|
||||
}
|
||||
} else {
|
||||
for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa)) {
|
||||
summary_orig +=
|
||||
ospf6_abr_originate_summary_to_area(range, oa);
|
||||
}
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(range->flag, OSPF6_ROUTE_ACTIVE_SUMMARY)
|
||||
&& summary_orig) {
|
||||
|
@ -306,6 +306,8 @@ struct ospf6_area *ospf6_area_create(uint32_t area_id, struct ospf6 *o, int df)
|
||||
|
||||
oa->range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
|
||||
oa->range_table->scope = oa;
|
||||
oa->nssa_range_table = OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
|
||||
oa->nssa_range_table->scope = oa;
|
||||
oa->summary_prefix = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_PREFIXES);
|
||||
oa->summary_prefix->scope = oa;
|
||||
oa->summary_router = OSPF6_ROUTE_TABLE_CREATE(AREA, SUMMARY_ROUTERS);
|
||||
@ -360,6 +362,7 @@ void ospf6_area_delete(struct ospf6_area *oa)
|
||||
ospf6_route_table_delete(oa->route_table);
|
||||
|
||||
ospf6_route_table_delete(oa->range_table);
|
||||
ospf6_route_table_delete(oa->nssa_range_table);
|
||||
ospf6_route_table_delete(oa->summary_prefix);
|
||||
ospf6_route_table_delete(oa->summary_router);
|
||||
|
||||
@ -691,6 +694,22 @@ void ospf6_area_config_write(struct vty *vty, struct ospf6 *ospf6)
|
||||
vty_out(vty, " no-summary");
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
for (range = ospf6_route_head(oa->nssa_range_table); range;
|
||||
range = ospf6_route_next(range)) {
|
||||
vty_out(vty, " area %s nssa range %pFX", oa->name,
|
||||
&range->prefix);
|
||||
|
||||
if (CHECK_FLAG(range->flag,
|
||||
OSPF6_ROUTE_DO_NOT_ADVERTISE)) {
|
||||
vty_out(vty, " not-advertise");
|
||||
} else {
|
||||
if (range->path.u.cost_config
|
||||
!= OSPF_AREA_RANGE_COST_UNSPEC)
|
||||
vty_out(vty, " cost %u",
|
||||
range->path.u.cost_config);
|
||||
}
|
||||
vty_out(vty, "\n");
|
||||
}
|
||||
if (PREFIX_NAME_IN(oa))
|
||||
vty_out(vty, " area %s filter-list prefix %s in\n",
|
||||
oa->name, PREFIX_NAME_IN(oa));
|
||||
|
@ -46,6 +46,7 @@ struct ospf6_area {
|
||||
/* Summary routes to be originated (includes Configured Address Ranges)
|
||||
*/
|
||||
struct ospf6_route_table *range_table;
|
||||
struct ospf6_route_table *nssa_range_table;
|
||||
struct ospf6_route_table *summary_prefix;
|
||||
struct ospf6_route_table *summary_router;
|
||||
|
||||
|
@ -49,6 +49,9 @@
|
||||
#include "ospf6_asbr.h"
|
||||
#include "ospf6d.h"
|
||||
#include "ospf6_nssa.h"
|
||||
#ifndef VTYSH_EXTRACT_PL
|
||||
#include "ospf6d/ospf6_nssa_clippy.c"
|
||||
#endif
|
||||
|
||||
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_LSA, "OSPF6 LSA");
|
||||
unsigned char config_debug_ospf6_nssa = 0;
|
||||
@ -412,6 +415,7 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area,
|
||||
struct ospf6 *ospf6 = area->ospf6;
|
||||
ptrdiff_t tag_offset = 0;
|
||||
route_tag_t network_order;
|
||||
struct ospf6_route *range;
|
||||
|
||||
if (IS_OSPF6_DEBUG_NSSA)
|
||||
zlog_debug("%s : Start", __func__);
|
||||
@ -423,6 +427,25 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* find the translated Type-5 for this Type-7 */
|
||||
nssa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
|
||||
type7->header);
|
||||
prefix.family = AF_INET6;
|
||||
prefix.prefixlen = nssa->prefix.prefix_length;
|
||||
ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa, &nssa->prefix);
|
||||
|
||||
/* Check if the Type-7 LSA should be suppressed by aggregation. */
|
||||
range = ospf6_route_lookup_bestmatch(&prefix, area->nssa_range_table);
|
||||
if (range && !prefix_same(&prefix, &range->prefix)
|
||||
&& !CHECK_FLAG(range->flag, OSPF6_ROUTE_REMOVE)) {
|
||||
if (IS_OSPF6_DEBUG_NSSA)
|
||||
zlog_debug(
|
||||
"%s: LSA %s suppressed by range %pFX of area %s",
|
||||
__func__, type7->name, &range->prefix,
|
||||
area->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* prepare buffer */
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
lsa_header = (struct ospf6_lsa_header *)buffer;
|
||||
@ -439,14 +462,6 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area,
|
||||
|
||||
memcpy(extnew, ext, sizeof(struct ospf6_as_external_lsa));
|
||||
|
||||
/* find the translated Type-5 for this Type-7 */
|
||||
nssa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
|
||||
type7->header);
|
||||
|
||||
prefix.family = AF_INET6;
|
||||
prefix.prefixlen = nssa->prefix.prefix_length;
|
||||
ospf6_prefix_in6_addr(&prefix.u.prefix6, nssa, &nssa->prefix);
|
||||
|
||||
/* set Prefix */
|
||||
memcpy(new_ptr, old_ptr, OSPF6_PREFIX_SPACE(ext->prefix.prefix_length));
|
||||
ospf6_prefix_apply_mask(&extnew->prefix);
|
||||
@ -600,7 +615,6 @@ static void ospf6_abr_translate_nssa(struct ospf6_area *area, struct ospf6_lsa *
|
||||
/* Incoming Type-7 or later aggregated Type-7
|
||||
*
|
||||
* LSA is skipped if P-bit is off.
|
||||
* LSA is aggregated if within range.
|
||||
*
|
||||
* The Type-7 is translated, Installed/Approved as a Type-5 into
|
||||
* global LSDB, then Flooded through AS
|
||||
@ -732,6 +746,32 @@ static void ospf6_abr_process_nssa_translates(struct ospf6 *ospf6)
|
||||
zlog_debug("%s : Stop", __func__);
|
||||
}
|
||||
|
||||
static void ospf6_abr_send_nssa_aggregates(struct ospf6 *ospf6)
|
||||
{
|
||||
struct listnode *node;
|
||||
struct ospf6_area *area;
|
||||
struct ospf6_route *range;
|
||||
|
||||
if (IS_OSPF6_DEBUG_NSSA)
|
||||
zlog_debug("%s: Start", __func__);
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, area)) {
|
||||
if (area->NSSATranslatorState == OSPF6_NSSA_TRANSLATE_DISABLED)
|
||||
continue;
|
||||
|
||||
if (IS_OSPF6_DEBUG_NSSA)
|
||||
zlog_debug("%s: looking at area %pI4", __func__,
|
||||
&area->area_id);
|
||||
|
||||
for (range = ospf6_route_head(area->nssa_range_table); range;
|
||||
range = ospf6_route_next(range))
|
||||
ospf6_abr_range_update(range, ospf6);
|
||||
}
|
||||
|
||||
if (IS_OSPF6_DEBUG_NSSA)
|
||||
zlog_debug("%s: Stop", __func__);
|
||||
}
|
||||
|
||||
static void ospf6_abr_remove_unapproved_translates(struct ospf6 *ospf6)
|
||||
{
|
||||
struct ospf6_lsa *lsa;
|
||||
@ -862,6 +902,11 @@ static void ospf6_abr_nssa_task(struct ospf6 *ospf6)
|
||||
|
||||
ospf6_abr_unapprove_translates(ospf6);
|
||||
|
||||
/* Originate Type-7 aggregates */
|
||||
if (IS_OSPF6_DEBUG_NSSA)
|
||||
zlog_debug("ospf6_abr_nssa_task(): send NSSA aggregates");
|
||||
ospf6_abr_send_nssa_aggregates(ospf6);
|
||||
|
||||
/* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or
|
||||
* Aggregate as Type-7
|
||||
* Install or Approve in Type-5 Global LSDB
|
||||
@ -1097,6 +1142,13 @@ int ospf6_area_nssa_unset(struct ospf6 *ospf6, struct ospf6_area *area)
|
||||
UNSET_FLAG(area->flag, OSPF6_AREA_NSSA);
|
||||
if (IS_OSPF6_DEBUG_NSSA)
|
||||
zlog_debug("area %s nssa reset", area->name);
|
||||
|
||||
/* Clear the table of NSSA ranges. */
|
||||
ospf6_route_table_delete(area->nssa_range_table);
|
||||
area->nssa_range_table =
|
||||
OSPF6_ROUTE_TABLE_CREATE(AREA, PREFIX_RANGES);
|
||||
area->nssa_range_table->scope = area;
|
||||
|
||||
ospf6_area_nssa_update(area);
|
||||
}
|
||||
|
||||
@ -1240,6 +1292,106 @@ void ospf6_abr_check_translate_nssa(struct ospf6_area *area,
|
||||
}
|
||||
}
|
||||
|
||||
DEFPY (area_nssa_range,
|
||||
area_nssa_range_cmd,
|
||||
"area <A.B.C.D|(0-4294967295)>$area nssa range X:X::X:X/M$prefix [<not-advertise$not_adv|cost (0-16777215)$cost>]",
|
||||
"OSPF6 area parameters\n"
|
||||
"OSPF6 area ID in IP address format\n"
|
||||
"OSPF6 area ID as a decimal value\n"
|
||||
"Configure OSPF6 area as nssa\n"
|
||||
"Configured address range\n"
|
||||
"Specify IPv6 prefix\n"
|
||||
"Do not advertise\n"
|
||||
"User specified metric for this range\n"
|
||||
"Advertised metric for this range\n")
|
||||
{
|
||||
struct ospf6_area *oa;
|
||||
struct ospf6_route *range;
|
||||
|
||||
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
|
||||
|
||||
OSPF6_CMD_AREA_GET(area, oa, ospf6);
|
||||
|
||||
if (!IS_AREA_NSSA(oa)) {
|
||||
vty_out(vty, "%% First configure %s as an NSSA area\n", area);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
range = ospf6_route_lookup((struct prefix *)prefix,
|
||||
oa->nssa_range_table);
|
||||
if (range == NULL) {
|
||||
range = ospf6_route_create(ospf6);
|
||||
range->type = OSPF6_DEST_TYPE_RANGE;
|
||||
SET_FLAG(range->flag, OSPF6_ROUTE_NSSA_RANGE);
|
||||
prefix_copy(&range->prefix, prefix);
|
||||
range->path.area_id = oa->area_id;
|
||||
range->path.metric_type = 2;
|
||||
range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC;
|
||||
range->path.origin.type = htons(OSPF6_LSTYPE_TYPE_7);
|
||||
range->path.origin.id = htonl(ospf6->external_id++);
|
||||
range->path.origin.adv_router = ospf6->router_id;
|
||||
ospf6_route_add(range, oa->nssa_range_table);
|
||||
}
|
||||
|
||||
/* process "not-advertise" */
|
||||
if (not_adv)
|
||||
SET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
|
||||
else
|
||||
UNSET_FLAG(range->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE);
|
||||
|
||||
/* process "cost" */
|
||||
if (!cost_str)
|
||||
cost = OSPF_AREA_RANGE_COST_UNSPEC;
|
||||
range->path.u.cost_config = cost;
|
||||
|
||||
/* Redo summaries if required */
|
||||
if (ospf6_check_and_set_router_abr(ospf6))
|
||||
ospf6_schedule_abr_task(ospf6);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFPY (no_area_nssa_range,
|
||||
no_area_nssa_range_cmd,
|
||||
"no area <A.B.C.D|(0-4294967295)>$area nssa range X:X::X:X/M$prefix [<not-advertise|cost (0-16777215)>]",
|
||||
NO_STR
|
||||
"OSPF6 area parameters\n"
|
||||
"OSPF6 area ID in IP address format\n"
|
||||
"OSPF6 area ID as a decimal value\n"
|
||||
"Configure OSPF6 area as nssa\n"
|
||||
"Configured address range\n"
|
||||
"Specify IPv6 prefix\n"
|
||||
"Do not advertise\n"
|
||||
"User specified metric for this range\n"
|
||||
"Advertised metric for this range\n")
|
||||
{
|
||||
struct ospf6_area *oa;
|
||||
struct ospf6_route *range;
|
||||
|
||||
VTY_DECLVAR_CONTEXT(ospf6, ospf6);
|
||||
|
||||
OSPF6_CMD_AREA_GET(area, oa, ospf6);
|
||||
|
||||
range = ospf6_route_lookup((struct prefix *)prefix,
|
||||
oa->nssa_range_table);
|
||||
if (range == NULL) {
|
||||
vty_out(vty, "%% range %s does not exists.\n", prefix_str);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
if (ospf6_check_and_set_router_abr(oa->ospf6)) {
|
||||
/* Blow away the aggregated LSA and route */
|
||||
SET_FLAG(range->flag, OSPF6_ROUTE_REMOVE);
|
||||
|
||||
/* Redo summaries if required */
|
||||
thread_execute(master, ospf6_abr_task_timer, ospf6, 0);
|
||||
}
|
||||
|
||||
ospf6_route_remove(range, oa->nssa_range_table);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(debug_ospf6_nssa, debug_ospf6_nssa_cmd,
|
||||
"debug ospf6 nssa",
|
||||
DEBUG_STR
|
||||
@ -1269,6 +1421,9 @@ void config_write_ospf6_debug_nssa(struct vty *vty)
|
||||
|
||||
void install_element_ospf6_debug_nssa(void)
|
||||
{
|
||||
install_element(OSPF6_NODE, &area_nssa_range_cmd);
|
||||
install_element(OSPF6_NODE, &no_area_nssa_range_cmd);
|
||||
|
||||
install_element(ENABLE_NODE, &debug_ospf6_nssa_cmd);
|
||||
install_element(ENABLE_NODE, &no_debug_ospf6_nssa_cmd);
|
||||
install_element(CONFIG_NODE, &debug_ospf6_nssa_cmd);
|
||||
|
@ -186,7 +186,7 @@ struct ospf6_route {
|
||||
struct timeval changed;
|
||||
|
||||
/* flag */
|
||||
uint8_t flag;
|
||||
uint16_t flag;
|
||||
|
||||
/* Prefix Options */
|
||||
uint8_t prefix_options;
|
||||
@ -221,14 +221,15 @@ struct ospf6_route {
|
||||
#define OSPF6_DEST_TYPE_RANGE 5
|
||||
#define OSPF6_DEST_TYPE_MAX 6
|
||||
|
||||
#define OSPF6_ROUTE_CHANGE 0x01
|
||||
#define OSPF6_ROUTE_ADD 0x02
|
||||
#define OSPF6_ROUTE_REMOVE 0x04
|
||||
#define OSPF6_ROUTE_BEST 0x08
|
||||
#define OSPF6_ROUTE_ACTIVE_SUMMARY 0x10
|
||||
#define OSPF6_ROUTE_DO_NOT_ADVERTISE 0x20
|
||||
#define OSPF6_ROUTE_WAS_REMOVED 0x40
|
||||
#define OSPF6_ROUTE_BLACKHOLE_ADDED 0x80
|
||||
#define OSPF6_ROUTE_CHANGE 0x0001
|
||||
#define OSPF6_ROUTE_ADD 0x0002
|
||||
#define OSPF6_ROUTE_REMOVE 0x0004
|
||||
#define OSPF6_ROUTE_BEST 0x0008
|
||||
#define OSPF6_ROUTE_ACTIVE_SUMMARY 0x0010
|
||||
#define OSPF6_ROUTE_DO_NOT_ADVERTISE 0x0020
|
||||
#define OSPF6_ROUTE_WAS_REMOVED 0x0040
|
||||
#define OSPF6_ROUTE_BLACKHOLE_ADDED 0x0080
|
||||
#define OSPF6_ROUTE_NSSA_RANGE 0x0100
|
||||
struct ospf6;
|
||||
|
||||
struct ospf6_route_table {
|
||||
|
@ -99,6 +99,7 @@ clippy_scan += \
|
||||
ospf6d/ospf6_lsa.c \
|
||||
ospf6d/ospf6_gr_helper.c \
|
||||
ospf6d/ospf6_gr.c \
|
||||
ospf6d/ospf6_nssa.c \
|
||||
ospf6d/ospf6_route.c \
|
||||
# end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user