forked from Mirror/frr
ospf6d: spf calculation w/ multiple router lsas
An OSPFv3 enabled Router can originate or receive multiple Link State-IDs for Router LSAs. As per RFC 5340 A 4.3, more than one Router LSAs, from given Vertex is considered (as concatenated) single large Router LSA. Created hidden show command to simulate concatenated large LSA from advertising/self Router LSAs. Ticket:CM-19329 Reviewed By: Testing Done: Simulate 160 subinterfaces between R1 === R2--R3, This triggers R1 and R2 to generate multiple link state IDs for Router LSAs. During SPF calculation only aggregated single router LSA processed and SPF tree formed. Signed-off-by: Chirag Shah <chirag@cumulusnetworks.com>
This commit is contained in:
parent
c1927369d6
commit
da086a3ba6
|
@ -221,6 +221,7 @@ struct ospf6_area *ospf6_area_create(u_int32_t area_id, struct ospf6 *o, int df)
|
|||
oa->lsdb->hook_add = ospf6_area_lsdb_hook_add;
|
||||
oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove;
|
||||
oa->lsdb_self = ospf6_lsdb_create(oa);
|
||||
oa->temp_router_lsa_lsdb = ospf6_lsdb_create(oa);
|
||||
|
||||
oa->spf_table = OSPF6_ROUTE_TABLE_CREATE(AREA, SPF_RESULTS);
|
||||
oa->spf_table->scope = oa;
|
||||
|
@ -279,6 +280,7 @@ void ospf6_area_delete(struct ospf6_area *oa)
|
|||
|
||||
ospf6_lsdb_delete(oa->lsdb);
|
||||
ospf6_lsdb_delete(oa->lsdb_self);
|
||||
ospf6_lsdb_delete(oa->temp_router_lsa_lsdb);
|
||||
|
||||
ospf6_spf_table_finish(oa->spf_table);
|
||||
ospf6_route_table_delete(oa->spf_table);
|
||||
|
|
|
@ -55,6 +55,7 @@ struct ospf6_area {
|
|||
|
||||
struct ospf6_lsdb *lsdb;
|
||||
struct ospf6_lsdb *lsdb_self;
|
||||
struct ospf6_lsdb *temp_router_lsa_lsdb;
|
||||
|
||||
struct ospf6_route_table *spf_table;
|
||||
struct ospf6_route_table *route_table;
|
||||
|
|
|
@ -191,7 +191,7 @@ int ospf6_lsa_is_changed(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
|
|||
|
||||
/* ospf6 age functions */
|
||||
/* calculate birth */
|
||||
static void ospf6_lsa_age_set(struct ospf6_lsa *lsa)
|
||||
void ospf6_lsa_age_set(struct ospf6_lsa *lsa)
|
||||
{
|
||||
struct timeval now;
|
||||
|
||||
|
|
|
@ -252,5 +252,6 @@ extern void ospf6_lsa_terminate(void);
|
|||
|
||||
extern int config_write_ospf6_debug_lsa(struct vty *vty);
|
||||
extern void install_element_ospf6_debug_lsa(void);
|
||||
extern void ospf6_lsa_age_set(struct ospf6_lsa *lsa);
|
||||
|
||||
#endif /* OSPF6_LSA_H */
|
||||
|
|
|
@ -163,21 +163,20 @@ static void ospf6_vertex_delete(struct ospf6_vertex *v)
|
|||
}
|
||||
|
||||
static struct ospf6_lsa *ospf6_lsdesc_lsa(caddr_t lsdesc,
|
||||
struct ospf6_vertex *v,
|
||||
uint32_t link_id)
|
||||
struct ospf6_vertex *v)
|
||||
{
|
||||
struct ospf6_lsa *lsa;
|
||||
struct ospf6_lsa *lsa = NULL;
|
||||
u_int16_t type = 0;
|
||||
u_int32_t id = 0, adv_router = 0;
|
||||
|
||||
if (VERTEX_IS_TYPE(NETWORK, v)) {
|
||||
type = htons(OSPF6_LSTYPE_ROUTER);
|
||||
id = link_id;
|
||||
id = htonl(0);
|
||||
adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID(lsdesc);
|
||||
} else {
|
||||
if (ROUTER_LSDESC_IS_TYPE(POINTTOPOINT, lsdesc)) {
|
||||
type = htons(OSPF6_LSTYPE_ROUTER);
|
||||
id = link_id;
|
||||
id = htonl(0);
|
||||
adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID(lsdesc);
|
||||
} else if (ROUTER_LSDESC_IS_TYPE(TRANSIT_NETWORK, lsdesc)) {
|
||||
type = htons(OSPF6_LSTYPE_NETWORK);
|
||||
|
@ -186,19 +185,22 @@ static struct ospf6_lsa *ospf6_lsdesc_lsa(caddr_t lsdesc,
|
|||
}
|
||||
}
|
||||
|
||||
lsa = ospf6_lsdb_lookup(type, id, adv_router, v->area->lsdb);
|
||||
|
||||
if (type == htons(OSPF6_LSTYPE_NETWORK))
|
||||
lsa = ospf6_lsdb_lookup(type, id, adv_router, v->area->lsdb);
|
||||
else
|
||||
lsa = ospf6_create_single_router_lsa(v->area, v->area->lsdb,
|
||||
adv_router);
|
||||
if (IS_OSPF6_DEBUG_SPF(PROCESS)) {
|
||||
char ibuf[16], abuf[16];
|
||||
inet_ntop(AF_INET, &id, ibuf, sizeof(ibuf));
|
||||
inet_ntop(AF_INET, &adv_router, abuf, sizeof(abuf));
|
||||
if (lsa)
|
||||
zlog_debug(" Link to: %s , V %s id %u", lsa->name,
|
||||
v->name, link_id);
|
||||
zlog_debug(" Link to: %s len %u, V %s", lsa->name,
|
||||
ntohs(lsa->header->length), v->name);
|
||||
else
|
||||
zlog_debug(" Link to: [%s Id:%s Adv:%s] No LSA , V %s id %u",
|
||||
zlog_debug(" Link to: [%s Id:%s Adv:%s] No LSA , V %s",
|
||||
ospf6_lstype_name(type), ibuf, abuf,
|
||||
v->name, link_id);
|
||||
v->name);
|
||||
}
|
||||
|
||||
return lsa;
|
||||
|
@ -461,17 +463,14 @@ void ospf6_spf_calculation(u_int32_t router_id,
|
|||
struct ospf6_vertex *root, *v, *w;
|
||||
int size;
|
||||
caddr_t lsdesc;
|
||||
struct ospf6_lsa *lsa, *self_rtr_lsa = NULL, *rtr_lsa = NULL;
|
||||
const struct route_node *end = NULL;
|
||||
struct ospf6_lsa *lsa;
|
||||
struct in6_addr address;
|
||||
struct ospf6_lsdb *lsdb = NULL;
|
||||
|
||||
ospf6_spf_table_finish(result_table);
|
||||
|
||||
/* Install the calculating router itself as the root of the SPF tree */
|
||||
/* construct root vertex */
|
||||
lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_ROUTER), htonl(0), router_id,
|
||||
oa->lsdb_self);
|
||||
lsa = ospf6_create_single_router_lsa(oa, oa->lsdb_self, router_id);
|
||||
if (lsa == NULL) {
|
||||
if (IS_OSPF6_DEBUG_SPF(PROCESS))
|
||||
zlog_debug("%s: No router LSA for area %s\n", __func__,
|
||||
|
@ -479,8 +478,6 @@ void ospf6_spf_calculation(u_int32_t router_id,
|
|||
return;
|
||||
}
|
||||
|
||||
self_rtr_lsa = lsa;
|
||||
|
||||
/* initialize */
|
||||
candidate_list = pqueue_create();
|
||||
candidate_list->cmp = ospf6_vertex_cmp;
|
||||
|
@ -510,139 +507,63 @@ void ospf6_spf_calculation(u_int32_t router_id,
|
|||
&& ospf6_router_is_stub_router(v->lsa)))
|
||||
continue;
|
||||
|
||||
if (VERTEX_IS_TYPE(ROUTER, v)) {
|
||||
/* First fetch root Router LSAs from lsdb_self */
|
||||
if (v->lsa == self_rtr_lsa)
|
||||
lsdb = oa->lsdb_self;
|
||||
else
|
||||
lsdb = v->area->lsdb;
|
||||
/* For each LS description in the just-added vertex V's LSA */
|
||||
size = (VERTEX_IS_TYPE(ROUTER, v)
|
||||
? sizeof(struct ospf6_router_lsdesc)
|
||||
: sizeof(struct ospf6_network_lsdesc));
|
||||
for (lsdesc = OSPF6_LSA_HEADER_END(v->lsa->header) + 4;
|
||||
lsdesc + size <= OSPF6_LSA_END(v->lsa->header);
|
||||
lsdesc += size) {
|
||||
lsa = ospf6_lsdesc_lsa(lsdesc, v);
|
||||
if (lsa == NULL)
|
||||
continue;
|
||||
|
||||
/* Iterating multiple ROUTER LSAs from same adv router
|
||||
* with different Link State ID */
|
||||
end = ospf6_lsdb_head(lsdb, 2,
|
||||
htons(OSPF6_LSTYPE_ROUTER),
|
||||
v->lsa->header->adv_router,
|
||||
&rtr_lsa);
|
||||
while (rtr_lsa) {
|
||||
if (IS_OSPF6_DEBUG_SPF(PROCESS))
|
||||
zlog_debug("%s: Next LSA %s to process"
|
||||
,__PRETTY_FUNCTION__,
|
||||
rtr_lsa->name);
|
||||
size = sizeof(struct ospf6_router_lsdesc);
|
||||
/* For each LS description in the just-added vertex V's LSA */
|
||||
for (lsdesc = OSPF6_LSA_HEADER_END(
|
||||
rtr_lsa->header) + 4;
|
||||
lsdesc + size <= OSPF6_LSA_END(
|
||||
rtr_lsa->header);
|
||||
lsdesc += size) {
|
||||
lsa = ospf6_lsdesc_lsa(lsdesc, v,
|
||||
rtr_lsa->header->id);
|
||||
if (lsa == NULL)
|
||||
continue;
|
||||
if (OSPF6_LSA_IS_MAXAGE(lsa))
|
||||
continue;
|
||||
|
||||
if (OSPF6_LSA_IS_MAXAGE(lsa))
|
||||
continue;
|
||||
if (!ospf6_lsdesc_backlink(lsa, lsdesc, v))
|
||||
continue;
|
||||
|
||||
if (!ospf6_lsdesc_backlink(lsa,
|
||||
lsdesc, v))
|
||||
continue;
|
||||
|
||||
w = ospf6_vertex_create(lsa);
|
||||
w->area = oa;
|
||||
w->parent = v;
|
||||
w->link_id = rtr_lsa->header->id;
|
||||
|
||||
if (VERTEX_IS_TYPE(ROUTER, v)) {
|
||||
w->cost = v->cost
|
||||
+ ROUTER_LSDESC_GET_METRIC(lsdesc);
|
||||
w->hops =
|
||||
v->hops
|
||||
+ (VERTEX_IS_TYPE(NETWORK, w)
|
||||
? 0 : 1);
|
||||
} else /* NETWORK */ {
|
||||
w->cost = v->cost;
|
||||
w->hops = v->hops + 1;
|
||||
}
|
||||
|
||||
/* nexthop calculation */
|
||||
if (w->hops == 0)
|
||||
ospf6_add_nexthop(w->nh_list,
|
||||
ROUTER_LSDESC_GET_IFID(lsdesc)
|
||||
, NULL);
|
||||
else if (w->hops == 1 && v->hops == 0)
|
||||
ospf6_nexthop_calc(w, v, lsdesc);
|
||||
else {
|
||||
ospf6_copy_nexthops(w->nh_list,
|
||||
v->nh_list);
|
||||
}
|
||||
|
||||
/* add new candidate to the candidate_list */
|
||||
if (IS_OSPF6_DEBUG_SPF(PROCESS))
|
||||
zlog_debug(
|
||||
" New candidate: %s hops %d cost %d",
|
||||
w->name, w->hops,
|
||||
w->cost);
|
||||
pqueue_enqueue(w, candidate_list);
|
||||
}
|
||||
/* Fetch next Link state ID Router LSA */
|
||||
rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
|
||||
}
|
||||
} else {
|
||||
/* For each LS description in the just-added vertex V's LSA */
|
||||
size = (VERTEX_IS_TYPE(ROUTER, v)
|
||||
? sizeof(struct ospf6_router_lsdesc)
|
||||
: sizeof(struct ospf6_network_lsdesc));
|
||||
for (lsdesc = OSPF6_LSA_HEADER_END(v->lsa->header) + 4;
|
||||
lsdesc + size <= OSPF6_LSA_END(v->lsa->header);
|
||||
lsdesc += size) {
|
||||
lsa = ospf6_lsdesc_lsa(lsdesc, v, v->link_id);
|
||||
if (lsa == NULL)
|
||||
continue;
|
||||
|
||||
if (OSPF6_LSA_IS_MAXAGE(lsa))
|
||||
continue;
|
||||
|
||||
if (!ospf6_lsdesc_backlink(lsa, lsdesc, v))
|
||||
continue;
|
||||
|
||||
w = ospf6_vertex_create(lsa);
|
||||
w->area = oa;
|
||||
w->parent = v;
|
||||
if (VERTEX_IS_TYPE(ROUTER, v)) {
|
||||
w->cost = v->cost
|
||||
w = ospf6_vertex_create(lsa);
|
||||
w->area = oa;
|
||||
w->parent = v;
|
||||
if (VERTEX_IS_TYPE(ROUTER, v)) {
|
||||
w->cost = v->cost
|
||||
+ ROUTER_LSDESC_GET_METRIC(lsdesc);
|
||||
w->hops =
|
||||
v->hops
|
||||
+ (VERTEX_IS_TYPE(NETWORK, w) ?
|
||||
0 : 1);
|
||||
} else /* NETWORK */ {
|
||||
w->cost = v->cost;
|
||||
w->hops = v->hops + 1;
|
||||
}
|
||||
w->hops =
|
||||
v->hops
|
||||
+ (VERTEX_IS_TYPE(NETWORK, w) ? 0 : 1);
|
||||
} else {
|
||||
/* NETWORK */
|
||||
w->cost = v->cost;
|
||||
w->hops = v->hops + 1;
|
||||
}
|
||||
|
||||
/* nexthop calculation */
|
||||
if (w->hops == 0)
|
||||
ospf6_add_nexthop(w->nh_list,
|
||||
/* nexthop calculation */
|
||||
if (w->hops == 0)
|
||||
ospf6_add_nexthop(
|
||||
w->nh_list,
|
||||
ROUTER_LSDESC_GET_IFID(lsdesc), NULL);
|
||||
else if (w->hops == 1 && v->hops == 0)
|
||||
ospf6_nexthop_calc(w, v, lsdesc);
|
||||
else {
|
||||
ospf6_copy_nexthops(w->nh_list,
|
||||
v->nh_list);
|
||||
}
|
||||
else if (w->hops == 1 && v->hops == 0)
|
||||
ospf6_nexthop_calc(w, v, lsdesc);
|
||||
else
|
||||
ospf6_copy_nexthops(w->nh_list, v->nh_list);
|
||||
|
||||
/* add new candidate to the candidate_list */
|
||||
if (IS_OSPF6_DEBUG_SPF(PROCESS))
|
||||
zlog_debug(
|
||||
|
||||
/* add new candidate to the candidate_list */
|
||||
if (IS_OSPF6_DEBUG_SPF(PROCESS))
|
||||
zlog_debug(
|
||||
" New candidate: %s hops %d cost %d",
|
||||
w->name, w->hops, w->cost);
|
||||
pqueue_enqueue(w, candidate_list);
|
||||
}
|
||||
pqueue_enqueue(w, candidate_list);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pqueue_delete(candidate_list);
|
||||
|
||||
ospf6_remove_temp_router_lsa(oa);
|
||||
|
||||
oa->spf_calculation++;
|
||||
}
|
||||
|
||||
|
@ -1029,3 +950,153 @@ void ospf6_spf_init(void)
|
|||
install_element(OSPF6_NODE, &ospf6_timers_throttle_spf_cmd);
|
||||
install_element(OSPF6_NODE, &no_ospf6_timers_throttle_spf_cmd);
|
||||
}
|
||||
|
||||
/* Create Aggregated Large Router-LSA from multiple Link-State IDs
|
||||
* RFC 5340 A 4.3:
|
||||
* When more than one router-LSA is received from a single router,
|
||||
* the links are processed as if concatenated into a single LSA.*/
|
||||
struct ospf6_lsa *ospf6_create_single_router_lsa(struct ospf6_area *area,
|
||||
struct ospf6_lsdb *lsdb,
|
||||
uint32_t adv_router)
|
||||
{
|
||||
struct ospf6_lsa *lsa = NULL;
|
||||
struct ospf6_lsa *rtr_lsa = NULL;
|
||||
struct ospf6_lsa_header *lsa_header = NULL;
|
||||
uint8_t *new_header = NULL;
|
||||
const struct route_node *end = NULL;
|
||||
uint16_t lsa_length, total_lsa_length = 0, num_lsa = 0;
|
||||
u_int16_t type = 0;
|
||||
char ifbuf[16];
|
||||
uint32_t interface_id;
|
||||
caddr_t lsd;
|
||||
|
||||
lsa_length = sizeof(struct ospf6_lsa_header) +
|
||||
sizeof(struct ospf6_router_lsa);
|
||||
total_lsa_length = lsa_length;
|
||||
type = htons(OSPF6_LSTYPE_ROUTER);
|
||||
|
||||
/* First check Aggregated LSA formed earlier in Cache */
|
||||
lsa = ospf6_lsdb_lookup(type, htonl(0), adv_router,
|
||||
area->temp_router_lsa_lsdb);
|
||||
if (lsa)
|
||||
return lsa;
|
||||
|
||||
inet_ntop(AF_INET, &adv_router, ifbuf, sizeof(ifbuf));
|
||||
|
||||
/* Determine total LSA length from all link state ids */
|
||||
end = ospf6_lsdb_head(lsdb, 2, type, adv_router, &rtr_lsa);
|
||||
while (rtr_lsa) {
|
||||
lsa = rtr_lsa;
|
||||
if (OSPF6_LSA_IS_MAXAGE(rtr_lsa)) {
|
||||
rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
|
||||
continue;
|
||||
}
|
||||
lsa_header = (struct ospf6_lsa_header *) rtr_lsa->header;
|
||||
total_lsa_length += (ntohs(lsa_header->length)
|
||||
- lsa_length);
|
||||
num_lsa++;
|
||||
rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
|
||||
}
|
||||
if (IS_OSPF6_DEBUG_SPF(PROCESS))
|
||||
zlog_debug("%s: adv_router %s num_lsa %u to convert.",
|
||||
__PRETTY_FUNCTION__, ifbuf, num_lsa);
|
||||
if (num_lsa == 1)
|
||||
return lsa;
|
||||
|
||||
if (num_lsa == 0) {
|
||||
if (IS_OSPF6_DEBUG_SPF(PROCESS))
|
||||
zlog_debug("%s: adv_router %s not found in LSDB.",
|
||||
__PRETTY_FUNCTION__, ifbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate memory for this LSA */
|
||||
new_header = XMALLOC(MTYPE_OSPF6_LSA_HEADER, total_lsa_length);
|
||||
if (!new_header)
|
||||
return NULL;
|
||||
|
||||
/* LSA information structure */
|
||||
lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA,
|
||||
sizeof(struct ospf6_lsa));
|
||||
if (!lsa) {
|
||||
free(new_header);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lsa->header = (struct ospf6_lsa_header *)new_header;
|
||||
|
||||
lsa->lsdb = area->temp_router_lsa_lsdb;
|
||||
|
||||
/* Fill Larger LSA Payload */
|
||||
end = ospf6_lsdb_head(lsdb, 2, type, adv_router, &rtr_lsa);
|
||||
if (rtr_lsa) {
|
||||
if (!OSPF6_LSA_IS_MAXAGE(rtr_lsa)) {
|
||||
/* Append first Link State ID LSA */
|
||||
lsa_header = (struct ospf6_lsa_header *)rtr_lsa->header;
|
||||
memcpy(new_header, lsa_header,
|
||||
ntohs(lsa_header->length));
|
||||
/* Assign new lsa length as aggregated length. */
|
||||
((struct ospf6_lsa_header *)new_header)->length =
|
||||
htons(total_lsa_length);
|
||||
new_header += ntohs(lsa_header->length);
|
||||
num_lsa--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print LSA Name */
|
||||
ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
|
||||
|
||||
rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
|
||||
while (rtr_lsa) {
|
||||
if (OSPF6_LSA_IS_MAXAGE(rtr_lsa)) {
|
||||
rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IS_OSPF6_DEBUG_SPF(PROCESS)) {
|
||||
lsd = OSPF6_LSA_HEADER_END(rtr_lsa->header) + 4;
|
||||
interface_id = ROUTER_LSDESC_GET_IFID(lsd);
|
||||
inet_ntop(AF_INET, &interface_id, ifbuf, sizeof(ifbuf));
|
||||
zlog_debug("%s: Next Router LSA %s to aggreat with len %u interface_id %s",
|
||||
__PRETTY_FUNCTION__, rtr_lsa->name,
|
||||
ntohs(lsa_header->length), ifbuf);
|
||||
}
|
||||
|
||||
/* Append Next Link State ID LSA */
|
||||
lsa_header = (struct ospf6_lsa_header *) rtr_lsa->header;
|
||||
memcpy(new_header, (OSPF6_LSA_HEADER_END(rtr_lsa->header) + 4),
|
||||
(ntohs(lsa_header->length) - lsa_length));
|
||||
new_header += (ntohs(lsa_header->length) - lsa_length);
|
||||
num_lsa--;
|
||||
|
||||
rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
|
||||
}
|
||||
|
||||
/* Calculate birth of this lsa */
|
||||
ospf6_lsa_age_set(lsa);
|
||||
|
||||
/* Store Aggregated LSA into area temp lsdb */
|
||||
ospf6_lsdb_add(lsa, area->temp_router_lsa_lsdb);
|
||||
|
||||
if (IS_OSPF6_DEBUG_SPF(PROCESS))
|
||||
zlog_debug("%s: LSA %s id %u type 0%x len %u num_lsa %u",
|
||||
__PRETTY_FUNCTION__, lsa->name,
|
||||
ntohl(lsa->header->id), ntohs(lsa->header->type),
|
||||
ntohs(lsa->header->length), num_lsa);
|
||||
|
||||
return lsa;
|
||||
}
|
||||
|
||||
void ospf6_remove_temp_router_lsa(struct ospf6_area *area)
|
||||
{
|
||||
struct ospf6_lsa *lsa = NULL;
|
||||
|
||||
for (ALL_LSDB(area->temp_router_lsa_lsdb, lsa)) {
|
||||
if (IS_OSPF6_DEBUG_SPF(PROCESS))
|
||||
zlog_debug("%s Remove LSA %s lsa->lock %u lsdb count %u",
|
||||
__PRETTY_FUNCTION__,
|
||||
lsa->name, lsa->lock,
|
||||
area->temp_router_lsa_lsdb->count);
|
||||
ospf6_lsdb_remove(lsa, area->temp_router_lsa_lsdb);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,5 +149,9 @@ extern int config_write_ospf6_debug_spf(struct vty *vty);
|
|||
extern void install_element_ospf6_debug_spf(void);
|
||||
extern void ospf6_spf_init(void);
|
||||
extern void ospf6_spf_reason_string(unsigned int reason, char *buf, int size);
|
||||
extern struct ospf6_lsa *ospf6_create_single_router_lsa(struct ospf6_area *area,
|
||||
struct ospf6_lsdb *lsdb,
|
||||
uint32_t adv_router);
|
||||
extern void ospf6_remove_temp_router_lsa(struct ospf6_area *area);
|
||||
|
||||
#endif /* OSPF6_SPF_H */
|
||||
|
|
|
@ -360,6 +360,49 @@ DEFUN (show_ipv6_ospf6_database_router,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN_HIDDEN (show_ipv6_ospf6_database_aggr_router,
|
||||
show_ipv6_ospf6_database_aggr_router_cmd,
|
||||
"show ipv6 ospf6 database aggr adv-router A.B.C.D",
|
||||
SHOW_STR
|
||||
IPV6_STR
|
||||
OSPF6_STR
|
||||
"Display Link state database\n"
|
||||
"Aggregated Router LSA\n"
|
||||
"Search by Advertising Router\n"
|
||||
"Specify Advertising Router as IPv4 address notation\n")
|
||||
{
|
||||
int level = OSPF6_LSDB_SHOW_LEVEL_DETAIL;
|
||||
uint16_t type = htons(OSPF6_LSTYPE_ROUTER);
|
||||
int idx_ipv4 = 6;
|
||||
struct listnode *i;
|
||||
struct ospf6 *o = ospf6;
|
||||
struct ospf6_area *oa;
|
||||
struct ospf6_lsdb *lsdb;
|
||||
uint32_t adv_router = 0;
|
||||
|
||||
inet_pton(AF_INET, argv[idx_ipv4]->arg, &adv_router);
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa)) {
|
||||
if (adv_router == o->router_id)
|
||||
lsdb = oa->lsdb_self;
|
||||
else
|
||||
lsdb = oa->lsdb;
|
||||
if (ospf6_create_single_router_lsa(oa, lsdb,
|
||||
adv_router) == NULL) {
|
||||
vty_out(vty, "Adv router is not found in LSDB.");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
ospf6_lsdb_show(vty, level, &type, NULL, NULL,
|
||||
oa->temp_router_lsa_lsdb);
|
||||
/* Remove the temp cache */
|
||||
ospf6_remove_temp_router_lsa(oa);
|
||||
}
|
||||
|
||||
vty_out(vty, "\n");
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN (show_ipv6_ospf6_database_type_id,
|
||||
show_ipv6_ospf6_database_type_id_cmd,
|
||||
"show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> linkstate-id A.B.C.D [<detail|dump|internal>]",
|
||||
|
@ -1219,6 +1262,7 @@ void ospf6_init(void)
|
|||
install_element(
|
||||
VIEW_NODE,
|
||||
&show_ipv6_ospf6_database_type_self_originated_linkstate_id_cmd);
|
||||
install_element(VIEW_NODE, &show_ipv6_ospf6_database_aggr_router_cmd);
|
||||
|
||||
/* Make ospf protocol socket. */
|
||||
ospf6_serv_sock();
|
||||
|
|
Loading…
Reference in a new issue