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_add = ospf6_area_lsdb_hook_add;
|
||||||
oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove;
|
oa->lsdb->hook_remove = ospf6_area_lsdb_hook_remove;
|
||||||
oa->lsdb_self = ospf6_lsdb_create(oa);
|
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 = OSPF6_ROUTE_TABLE_CREATE(AREA, SPF_RESULTS);
|
||||||
oa->spf_table->scope = oa;
|
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);
|
||||||
ospf6_lsdb_delete(oa->lsdb_self);
|
ospf6_lsdb_delete(oa->lsdb_self);
|
||||||
|
ospf6_lsdb_delete(oa->temp_router_lsa_lsdb);
|
||||||
|
|
||||||
ospf6_spf_table_finish(oa->spf_table);
|
ospf6_spf_table_finish(oa->spf_table);
|
||||||
ospf6_route_table_delete(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;
|
||||||
struct ospf6_lsdb *lsdb_self;
|
struct ospf6_lsdb *lsdb_self;
|
||||||
|
struct ospf6_lsdb *temp_router_lsa_lsdb;
|
||||||
|
|
||||||
struct ospf6_route_table *spf_table;
|
struct ospf6_route_table *spf_table;
|
||||||
struct ospf6_route_table *route_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 */
|
/* ospf6 age functions */
|
||||||
/* calculate birth */
|
/* calculate birth */
|
||||||
static void ospf6_lsa_age_set(struct ospf6_lsa *lsa)
|
void ospf6_lsa_age_set(struct ospf6_lsa *lsa)
|
||||||
{
|
{
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
|
|
||||||
|
|
|
@ -252,5 +252,6 @@ extern void ospf6_lsa_terminate(void);
|
||||||
|
|
||||||
extern int config_write_ospf6_debug_lsa(struct vty *vty);
|
extern int config_write_ospf6_debug_lsa(struct vty *vty);
|
||||||
extern void install_element_ospf6_debug_lsa(void);
|
extern void install_element_ospf6_debug_lsa(void);
|
||||||
|
extern void ospf6_lsa_age_set(struct ospf6_lsa *lsa);
|
||||||
|
|
||||||
#endif /* OSPF6_LSA_H */
|
#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,
|
static struct ospf6_lsa *ospf6_lsdesc_lsa(caddr_t lsdesc,
|
||||||
struct ospf6_vertex *v,
|
struct ospf6_vertex *v)
|
||||||
uint32_t link_id)
|
|
||||||
{
|
{
|
||||||
struct ospf6_lsa *lsa;
|
struct ospf6_lsa *lsa = NULL;
|
||||||
u_int16_t type = 0;
|
u_int16_t type = 0;
|
||||||
u_int32_t id = 0, adv_router = 0;
|
u_int32_t id = 0, adv_router = 0;
|
||||||
|
|
||||||
if (VERTEX_IS_TYPE(NETWORK, v)) {
|
if (VERTEX_IS_TYPE(NETWORK, v)) {
|
||||||
type = htons(OSPF6_LSTYPE_ROUTER);
|
type = htons(OSPF6_LSTYPE_ROUTER);
|
||||||
id = link_id;
|
id = htonl(0);
|
||||||
adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID(lsdesc);
|
adv_router = NETWORK_LSDESC_GET_NBR_ROUTERID(lsdesc);
|
||||||
} else {
|
} else {
|
||||||
if (ROUTER_LSDESC_IS_TYPE(POINTTOPOINT, lsdesc)) {
|
if (ROUTER_LSDESC_IS_TYPE(POINTTOPOINT, lsdesc)) {
|
||||||
type = htons(OSPF6_LSTYPE_ROUTER);
|
type = htons(OSPF6_LSTYPE_ROUTER);
|
||||||
id = link_id;
|
id = htonl(0);
|
||||||
adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID(lsdesc);
|
adv_router = ROUTER_LSDESC_GET_NBR_ROUTERID(lsdesc);
|
||||||
} else if (ROUTER_LSDESC_IS_TYPE(TRANSIT_NETWORK, lsdesc)) {
|
} else if (ROUTER_LSDESC_IS_TYPE(TRANSIT_NETWORK, lsdesc)) {
|
||||||
type = htons(OSPF6_LSTYPE_NETWORK);
|
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)) {
|
if (IS_OSPF6_DEBUG_SPF(PROCESS)) {
|
||||||
char ibuf[16], abuf[16];
|
char ibuf[16], abuf[16];
|
||||||
inet_ntop(AF_INET, &id, ibuf, sizeof(ibuf));
|
inet_ntop(AF_INET, &id, ibuf, sizeof(ibuf));
|
||||||
inet_ntop(AF_INET, &adv_router, abuf, sizeof(abuf));
|
inet_ntop(AF_INET, &adv_router, abuf, sizeof(abuf));
|
||||||
if (lsa)
|
if (lsa)
|
||||||
zlog_debug(" Link to: %s , V %s id %u", lsa->name,
|
zlog_debug(" Link to: %s len %u, V %s", lsa->name,
|
||||||
v->name, link_id);
|
ntohs(lsa->header->length), v->name);
|
||||||
else
|
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,
|
ospf6_lstype_name(type), ibuf, abuf,
|
||||||
v->name, link_id);
|
v->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return lsa;
|
return lsa;
|
||||||
|
@ -461,17 +463,14 @@ void ospf6_spf_calculation(u_int32_t router_id,
|
||||||
struct ospf6_vertex *root, *v, *w;
|
struct ospf6_vertex *root, *v, *w;
|
||||||
int size;
|
int size;
|
||||||
caddr_t lsdesc;
|
caddr_t lsdesc;
|
||||||
struct ospf6_lsa *lsa, *self_rtr_lsa = NULL, *rtr_lsa = NULL;
|
struct ospf6_lsa *lsa;
|
||||||
const struct route_node *end = NULL;
|
|
||||||
struct in6_addr address;
|
struct in6_addr address;
|
||||||
struct ospf6_lsdb *lsdb = NULL;
|
|
||||||
|
|
||||||
ospf6_spf_table_finish(result_table);
|
ospf6_spf_table_finish(result_table);
|
||||||
|
|
||||||
/* Install the calculating router itself as the root of the SPF tree */
|
/* Install the calculating router itself as the root of the SPF tree */
|
||||||
/* construct root vertex */
|
/* construct root vertex */
|
||||||
lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_ROUTER), htonl(0), router_id,
|
lsa = ospf6_create_single_router_lsa(oa, oa->lsdb_self, router_id);
|
||||||
oa->lsdb_self);
|
|
||||||
if (lsa == NULL) {
|
if (lsa == NULL) {
|
||||||
if (IS_OSPF6_DEBUG_SPF(PROCESS))
|
if (IS_OSPF6_DEBUG_SPF(PROCESS))
|
||||||
zlog_debug("%s: No router LSA for area %s\n", __func__,
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self_rtr_lsa = lsa;
|
|
||||||
|
|
||||||
/* initialize */
|
/* initialize */
|
||||||
candidate_list = pqueue_create();
|
candidate_list = pqueue_create();
|
||||||
candidate_list->cmp = ospf6_vertex_cmp;
|
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)))
|
&& ospf6_router_is_stub_router(v->lsa)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (VERTEX_IS_TYPE(ROUTER, v)) {
|
/* For each LS description in the just-added vertex V's LSA */
|
||||||
/* First fetch root Router LSAs from lsdb_self */
|
size = (VERTEX_IS_TYPE(ROUTER, v)
|
||||||
if (v->lsa == self_rtr_lsa)
|
? sizeof(struct ospf6_router_lsdesc)
|
||||||
lsdb = oa->lsdb_self;
|
: sizeof(struct ospf6_network_lsdesc));
|
||||||
else
|
for (lsdesc = OSPF6_LSA_HEADER_END(v->lsa->header) + 4;
|
||||||
lsdb = v->area->lsdb;
|
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
|
if (OSPF6_LSA_IS_MAXAGE(lsa))
|
||||||
* with different Link State ID */
|
continue;
|
||||||
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))
|
if (!ospf6_lsdesc_backlink(lsa, lsdesc, v))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!ospf6_lsdesc_backlink(lsa,
|
w = ospf6_vertex_create(lsa);
|
||||||
lsdesc, v))
|
w->area = oa;
|
||||||
continue;
|
w->parent = v;
|
||||||
|
if (VERTEX_IS_TYPE(ROUTER, v)) {
|
||||||
w = ospf6_vertex_create(lsa);
|
w->cost = v->cost
|
||||||
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
|
|
||||||
+ ROUTER_LSDESC_GET_METRIC(lsdesc);
|
+ ROUTER_LSDESC_GET_METRIC(lsdesc);
|
||||||
w->hops =
|
w->hops =
|
||||||
v->hops
|
v->hops
|
||||||
+ (VERTEX_IS_TYPE(NETWORK, w) ?
|
+ (VERTEX_IS_TYPE(NETWORK, w) ? 0 : 1);
|
||||||
0 : 1);
|
} else {
|
||||||
} else /* NETWORK */ {
|
/* NETWORK */
|
||||||
w->cost = v->cost;
|
w->cost = v->cost;
|
||||||
w->hops = v->hops + 1;
|
w->hops = v->hops + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* nexthop calculation */
|
/* nexthop calculation */
|
||||||
if (w->hops == 0)
|
if (w->hops == 0)
|
||||||
ospf6_add_nexthop(w->nh_list,
|
ospf6_add_nexthop(
|
||||||
|
w->nh_list,
|
||||||
ROUTER_LSDESC_GET_IFID(lsdesc), NULL);
|
ROUTER_LSDESC_GET_IFID(lsdesc), NULL);
|
||||||
else if (w->hops == 1 && v->hops == 0)
|
else if (w->hops == 1 && v->hops == 0)
|
||||||
ospf6_nexthop_calc(w, v, lsdesc);
|
ospf6_nexthop_calc(w, v, lsdesc);
|
||||||
else {
|
else
|
||||||
ospf6_copy_nexthops(w->nh_list,
|
ospf6_copy_nexthops(w->nh_list, v->nh_list);
|
||||||
v->nh_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add new candidate to the candidate_list */
|
|
||||||
if (IS_OSPF6_DEBUG_SPF(PROCESS))
|
/* add new candidate to the candidate_list */
|
||||||
zlog_debug(
|
if (IS_OSPF6_DEBUG_SPF(PROCESS))
|
||||||
|
zlog_debug(
|
||||||
" New candidate: %s hops %d cost %d",
|
" New candidate: %s hops %d cost %d",
|
||||||
w->name, w->hops, w->cost);
|
w->name, w->hops, w->cost);
|
||||||
pqueue_enqueue(w, candidate_list);
|
pqueue_enqueue(w, candidate_list);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pqueue_delete(candidate_list);
|
pqueue_delete(candidate_list);
|
||||||
|
|
||||||
|
ospf6_remove_temp_router_lsa(oa);
|
||||||
|
|
||||||
oa->spf_calculation++;
|
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, &ospf6_timers_throttle_spf_cmd);
|
||||||
install_element(OSPF6_NODE, &no_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 install_element_ospf6_debug_spf(void);
|
||||||
extern void ospf6_spf_init(void);
|
extern void ospf6_spf_init(void);
|
||||||
extern void ospf6_spf_reason_string(unsigned int reason, char *buf, int size);
|
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 */
|
#endif /* OSPF6_SPF_H */
|
||||||
|
|
|
@ -360,6 +360,49 @@ DEFUN (show_ipv6_ospf6_database_router,
|
||||||
return CMD_SUCCESS;
|
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,
|
DEFUN (show_ipv6_ospf6_database_type_id,
|
||||||
show_ipv6_ospf6_database_type_id_cmd,
|
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>]",
|
"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(
|
install_element(
|
||||||
VIEW_NODE,
|
VIEW_NODE,
|
||||||
&show_ipv6_ospf6_database_type_self_originated_linkstate_id_cmd);
|
&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. */
|
/* Make ospf protocol socket. */
|
||||||
ospf6_serv_sock();
|
ospf6_serv_sock();
|
||||||
|
|
Loading…
Reference in a new issue