1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2003 Yasuhiro Ohara
19 #include "ospf6_proto.h"
20 #include "ospf6_message.h"
21 #include "ospf6_route.h"
22 #include "ospf6_lsa.h"
23 #include "ospf6_lsdb.h"
25 #include "ospf6_top.h"
26 #include "ospf6_area.h"
27 #include "ospf6_interface.h"
28 #include "ospf6_neighbor.h"
29 #include "ospf6_intra.h"
30 #include "ospf6_asbr.h"
31 #include "ospf6_abr.h"
32 #include "ospf6_flood.h"
34 #include "ospf6_spf.h"
37 unsigned char conf_debug_ospf6_brouter
= 0;
38 uint32_t conf_debug_ospf6_brouter_specific_router_id
;
39 uint32_t conf_debug_ospf6_brouter_specific_area_id
;
41 #define MAX_LSA_PAYLOAD (1024 + 256)
42 /******************************/
43 /* RFC2740 3.4.3.1 Router-LSA */
44 /******************************/
46 static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa
*lsa
, char *buf
,
49 struct ospf6_router_lsa
*router_lsa
;
50 struct ospf6_router_lsdesc
*lsdesc
;
52 char buf1
[INET_ADDRSTRLEN
], buf2
[INET_ADDRSTRLEN
];
55 router_lsa
= (struct ospf6_router_lsa
56 *)((char *)lsa
->header
57 + sizeof(struct ospf6_lsa_header
));
58 start
= (char *)router_lsa
+ sizeof(struct ospf6_router_lsa
);
59 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
61 lsdesc
= (struct ospf6_router_lsdesc
63 + pos
* (sizeof(struct
64 ospf6_router_lsdesc
)));
65 if ((char *)lsdesc
+ sizeof(struct ospf6_router_lsdesc
)
67 if (buf
&& (buflen
> INET_ADDRSTRLEN
* 2)) {
69 &lsdesc
->neighbor_interface_id
, buf1
,
71 inet_ntop(AF_INET
, &lsdesc
->neighbor_router_id
,
73 snprintf(buf
, buflen
, "%s/%s", buf2
, buf1
);
83 static int ospf6_router_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
84 json_object
*json_obj
, bool use_json
)
86 char *start
, *end
, *current
;
87 char buf
[32], name
[32], bits
[16], options
[32];
88 struct ospf6_router_lsa
*router_lsa
;
89 struct ospf6_router_lsdesc
*lsdesc
;
90 json_object
*json_arr
;
91 json_object
*json_loop
;
94 (struct ospf6_router_lsa
*)((char *)lsa
->header
95 + sizeof(struct ospf6_lsa_header
));
97 ospf6_capability_printbuf(router_lsa
->bits
, bits
, sizeof(bits
));
98 ospf6_options_printbuf(router_lsa
->options
, options
, sizeof(options
));
100 json_object_string_add(json_obj
, "bits", bits
);
101 json_object_string_add(json_obj
, "options", options
);
102 json_arr
= json_object_new_array();
104 vty_out(vty
, " Bits: %s Options: %s\n", bits
, options
);
106 start
= (char *)router_lsa
+ sizeof(struct ospf6_router_lsa
);
107 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
108 for (current
= start
;
109 current
+ sizeof(struct ospf6_router_lsdesc
) <= end
;
110 current
+= sizeof(struct ospf6_router_lsdesc
)) {
111 lsdesc
= (struct ospf6_router_lsdesc
*)current
;
113 if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_POINTTOPOINT
)
114 snprintf(name
, sizeof(name
), "Point-To-Point");
115 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK
)
116 snprintf(name
, sizeof(name
), "Transit-Network");
117 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_STUB_NETWORK
)
118 snprintf(name
, sizeof(name
), "Stub-Network");
119 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_VIRTUAL_LINK
)
120 snprintf(name
, sizeof(name
), "Virtual-Link");
122 snprintf(name
, sizeof(name
), "Unknown (%#x)",
126 json_loop
= json_object_new_object();
127 json_object_string_add(json_loop
, "type", name
);
128 json_object_int_add(json_loop
, "metric",
129 ntohs(lsdesc
->metric
));
130 json_object_string_addf(
131 json_loop
, "interfaceId", "%pI4",
132 (in_addr_t
*)&lsdesc
->interface_id
);
133 json_object_string_addf(
134 json_loop
, "neighborInterfaceId", "%pI4",
135 (in_addr_t
*)&lsdesc
->neighbor_interface_id
);
136 json_object_string_addf(json_loop
, "neighborRouterId",
138 &lsdesc
->neighbor_router_id
);
139 json_object_array_add(json_arr
, json_loop
);
141 vty_out(vty
, " Type: %s Metric: %d\n", name
,
142 ntohs(lsdesc
->metric
));
143 vty_out(vty
, " Interface ID: %s\n",
144 inet_ntop(AF_INET
, &lsdesc
->interface_id
, buf
,
146 vty_out(vty
, " Neighbor Interface ID: %s\n",
148 &lsdesc
->neighbor_interface_id
, buf
,
150 vty_out(vty
, " Neighbor Router ID: %s\n",
151 inet_ntop(AF_INET
, &lsdesc
->neighbor_router_id
,
156 json_object_object_add(json_obj
, "lsaDescription", json_arr
);
161 static void ospf6_router_lsa_options_set(struct ospf6_area
*oa
,
162 struct ospf6_router_lsa
*router_lsa
)
164 OSPF6_OPT_CLEAR_ALL(router_lsa
->options
);
165 memcpy(router_lsa
->options
, oa
->options
, 3);
167 if (ospf6_check_and_set_router_abr(oa
->ospf6
))
168 SET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_B
);
170 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_B
);
172 if (!IS_AREA_STUB(oa
) && ospf6_asbr_is_asbr(oa
->ospf6
)) {
173 SET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_E
);
175 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_E
);
178 /* If the router is ASBR and the area-type is NSSA set the
179 * translate bit in router LSA.
182 && (ospf6_asbr_is_asbr(oa
->ospf6
) || IS_OSPF6_ABR(oa
->ospf6
))) {
183 if (oa
->NSSATranslatorRole
== OSPF6_NSSA_ROLE_ALWAYS
)
184 SET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_NT
);
186 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_NT
);
189 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_V
);
190 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_W
);
193 int ospf6_router_is_stub_router(struct ospf6_lsa
*lsa
)
195 struct ospf6_router_lsa
*rtr_lsa
;
197 if (lsa
!= NULL
&& OSPF6_LSA_IS_TYPE(ROUTER
, lsa
)) {
198 rtr_lsa
= (struct ospf6_router_lsa
199 *)((caddr_t
)lsa
->header
200 + sizeof(struct ospf6_lsa_header
));
202 if (!OSPF6_OPT_ISSET(rtr_lsa
->options
, OSPF6_OPT_R
)) {
203 return OSPF6_IS_STUB_ROUTER
;
204 } else if (!OSPF6_OPT_ISSET(rtr_lsa
->options
, OSPF6_OPT_V6
)) {
205 return OSPF6_IS_STUB_ROUTER_V6
;
209 return OSPF6_NOT_STUB_ROUTER
;
212 void ospf6_router_lsa_originate(struct thread
*thread
)
214 struct ospf6_area
*oa
;
216 char buffer
[OSPF6_MAX_LSASIZE
];
217 struct ospf6_lsa_header
*lsa_header
;
218 struct ospf6_lsa
*lsa
;
220 uint32_t link_state_id
= 0;
221 struct listnode
*node
, *nnode
;
223 struct ospf6_interface
*oi
;
224 struct ospf6_neighbor
*on
, *drouter
= NULL
;
225 struct ospf6_router_lsa
*router_lsa
;
226 struct ospf6_router_lsdesc
*lsdesc
;
231 oa
= (struct ospf6_area
*)THREAD_ARG(thread
);
233 if (oa
->ospf6
->gr_info
.restart_in_progress
) {
234 if (IS_DEBUG_OSPF6_GR
)
236 "Graceful Restart in progress, don't originate LSA");
240 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER
))
241 zlog_debug("Originate Router-LSA for Area %s", oa
->name
);
243 memset(buffer
, 0, sizeof(buffer
));
244 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
246 (struct ospf6_router_lsa
*)((caddr_t
)lsa_header
247 + sizeof(struct ospf6_lsa_header
));
249 ospf6_router_lsa_options_set(oa
, router_lsa
);
251 /* describe links for each interfaces */
252 lsdesc
= (struct ospf6_router_lsdesc
253 *)((caddr_t
)router_lsa
254 + sizeof(struct ospf6_router_lsa
));
256 for (ALL_LIST_ELEMENTS(oa
->if_list
, node
, nnode
, oi
)) {
257 /* Interfaces in state Down or Loopback are not described */
258 if (oi
->state
== OSPF6_INTERFACE_DOWN
259 || oi
->state
== OSPF6_INTERFACE_LOOPBACK
)
262 /* Nor are interfaces without any full adjacencies described */
264 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
))
265 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
271 /* Multiple Router-LSA instance according to size limit setting
273 if ((oa
->router_lsa_size_limit
!= 0)
274 && ((size_t)((char *)lsdesc
- buffer
)
275 + sizeof(struct ospf6_router_lsdesc
)
276 > oa
->router_lsa_size_limit
)) {
278 == (caddr_t
)router_lsa
279 + sizeof(struct ospf6_router_lsa
)) {
281 "Size limit setting for Router-LSA too short");
285 /* Fill LSA Header */
287 lsa_header
->type
= htons(OSPF6_LSTYPE_ROUTER
);
288 lsa_header
->id
= htonl(link_state_id
);
289 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
290 lsa_header
->seqnum
= ospf6_new_ls_seqnum(
291 lsa_header
->type
, lsa_header
->id
,
292 lsa_header
->adv_router
, oa
->lsdb
);
294 htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
297 ospf6_lsa_checksum(lsa_header
);
300 lsa
= ospf6_lsa_create(lsa_header
);
303 ospf6_lsa_originate_area(lsa
, oa
);
305 /* Reset Buffer to fill next Router LSA */
306 memset(buffer
, 0, sizeof(buffer
));
307 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
309 (struct ospf6_router_lsa
310 *)((caddr_t
)lsa_header
311 + sizeof(struct ospf6_lsa_header
));
313 ospf6_router_lsa_options_set(oa
, router_lsa
);
315 /* describe links for each interfaces */
316 lsdesc
= (struct ospf6_router_lsdesc
317 *)((caddr_t
)router_lsa
318 + sizeof(struct ospf6_router_lsa
));
323 /* Point-to-Point interfaces */
324 if (oi
->type
== OSPF_IFTYPE_POINTOPOINT
) {
325 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
)) {
326 if (on
->state
!= OSPF6_NEIGHBOR_FULL
)
329 lsdesc
->type
= OSPF6_ROUTER_LSDESC_POINTTOPOINT
;
330 lsdesc
->metric
= htons(oi
->cost
);
331 lsdesc
->interface_id
=
332 htonl(oi
->interface
->ifindex
);
333 lsdesc
->neighbor_interface_id
=
335 lsdesc
->neighbor_router_id
= on
->router_id
;
341 /* Broadcast and NBMA interfaces */
342 else if (oi
->type
== OSPF_IFTYPE_BROADCAST
) {
343 /* If this router is not DR,
344 and If this router not fully adjacent with DR,
345 this interface is not transit yet: ignore. */
346 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
348 ospf6_neighbor_lookup(oi
->drouter
, oi
);
350 || drouter
->state
!= OSPF6_NEIGHBOR_FULL
)
354 lsdesc
->type
= OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK
;
355 lsdesc
->metric
= htons(oi
->cost
);
356 lsdesc
->interface_id
= htonl(oi
->interface
->ifindex
);
357 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
358 lsdesc
->neighbor_interface_id
=
359 htonl(drouter
->ifindex
);
360 lsdesc
->neighbor_router_id
= drouter
->router_id
;
362 lsdesc
->neighbor_interface_id
=
363 htonl(oi
->interface
->ifindex
);
364 lsdesc
->neighbor_router_id
=
365 oi
->area
->ospf6
->router_id
;
370 assert(0); /* Unknown interface type */
375 /* Point-to-Multipoint interfaces */
379 /* Fill LSA Header */
381 lsa_header
->type
= htons(OSPF6_LSTYPE_ROUTER
);
382 lsa_header
->id
= htonl(link_state_id
);
383 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
385 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
386 lsa_header
->adv_router
, oa
->lsdb
);
387 lsa_header
->length
= htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
390 ospf6_lsa_checksum(lsa_header
);
393 lsa
= ospf6_lsa_create(lsa_header
);
396 ospf6_lsa_originate_area(lsa
, oa
);
400 /* Do premature-aging of rest, undesired Router-LSAs */
401 type
= ntohs(OSPF6_LSTYPE_ROUTER
);
402 router
= oa
->ospf6
->router_id
;
404 for (ALL_LSDB_TYPED_ADVRTR(oa
->lsdb
, type
, router
, lsa
)) {
405 if (ntohl(lsa
->header
->id
) < link_state_id
)
407 ospf6_lsa_purge(lsa
);
412 * Waiting till the LSA is actually removed from the database to trigger
413 * SPF delays network convergence. Unlike IPv4, for an ABR, when all
414 * interfaces associated with an area are gone, triggering an SPF right
416 * helps convergence with inter-area routes.
418 if (count
&& !link_state_id
)
419 ospf6_spf_schedule(oa
->ospf6
,
420 OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED
);
423 /*******************************/
424 /* RFC2740 3.4.3.2 Network-LSA */
425 /*******************************/
427 static char *ospf6_network_lsa_get_ar_id(struct ospf6_lsa
*lsa
, char *buf
,
430 char *start
, *end
, *current
;
431 struct ospf6_network_lsa
*network_lsa
;
432 struct ospf6_network_lsdesc
*lsdesc
;
435 network_lsa
= (struct ospf6_network_lsa
436 *)((caddr_t
)lsa
->header
437 + sizeof(struct ospf6_lsa_header
));
439 start
= (char *)network_lsa
+ sizeof(struct ospf6_network_lsa
);
440 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
441 current
= start
+ pos
* (sizeof(struct ospf6_network_lsdesc
));
443 if ((current
+ sizeof(struct ospf6_network_lsdesc
)) <= end
) {
444 lsdesc
= (struct ospf6_network_lsdesc
*)current
;
446 inet_ntop(AF_INET
, &lsdesc
->router_id
, buf
,
456 static int ospf6_network_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
457 json_object
*json_obj
, bool use_json
)
459 char *start
, *end
, *current
;
460 struct ospf6_network_lsa
*network_lsa
;
461 struct ospf6_network_lsdesc
*lsdesc
;
462 char buf
[128], options
[32];
463 json_object
*json_arr
;
466 (struct ospf6_network_lsa
*)((caddr_t
)lsa
->header
467 + sizeof(struct ospf6_lsa_header
));
469 ospf6_options_printbuf(network_lsa
->options
, options
, sizeof(options
));
471 json_object_string_add(json_obj
, "options", options
);
473 vty_out(vty
, " Options: %s\n", options
);
475 start
= (char *)network_lsa
+ sizeof(struct ospf6_network_lsa
);
476 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
478 json_arr
= json_object_new_array();
480 for (current
= start
;
481 current
+ sizeof(struct ospf6_network_lsdesc
) <= end
;
482 current
+= sizeof(struct ospf6_network_lsdesc
)) {
483 lsdesc
= (struct ospf6_network_lsdesc
*)current
;
484 inet_ntop(AF_INET
, &lsdesc
->router_id
, buf
, sizeof(buf
));
486 json_object_array_add(json_arr
,
487 json_object_new_string(buf
));
489 vty_out(vty
, " Attached Router: %s\n", buf
);
492 json_object_object_add(json_obj
, "attachedRouter", json_arr
);
497 void ospf6_network_lsa_originate(struct thread
*thread
)
499 struct ospf6_interface
*oi
;
501 char buffer
[OSPF6_MAX_LSASIZE
];
502 struct ospf6_lsa_header
*lsa_header
;
505 struct ospf6_lsa
*old
, *lsa
;
506 struct ospf6_network_lsa
*network_lsa
;
507 struct ospf6_network_lsdesc
*lsdesc
;
508 struct ospf6_neighbor
*on
;
509 struct ospf6_link_lsa
*link_lsa
;
513 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
515 /* The interface must be enabled until here. A Network-LSA of a
516 disabled interface (but was once enabled) should be flushed
517 by ospf6_lsa_refresh (), and does not come here. */
520 if (oi
->area
->ospf6
->gr_info
.restart_in_progress
) {
521 if (IS_DEBUG_OSPF6_GR
)
523 "Graceful Restart in progress, don't originate LSA");
527 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_NETWORK
),
528 htonl(oi
->interface
->ifindex
),
529 oi
->area
->ospf6
->router_id
, oi
->area
->lsdb
);
531 /* Do not originate Network-LSA if not DR */
532 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
534 ospf6_lsa_purge(old
);
536 * Waiting till the LSA is actually removed from the
538 * trigger SPF delays network convergence.
542 OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED
);
547 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK
))
548 zlog_debug("Originate Network-LSA for Interface %s",
549 oi
->interface
->name
);
551 /* If none of neighbor is adjacent to us */
554 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
))
555 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
559 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK
))
560 zlog_debug("Interface stub, ignore");
562 ospf6_lsa_purge(old
);
567 memset(buffer
, 0, sizeof(buffer
));
568 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
570 (struct ospf6_network_lsa
*)((caddr_t
)lsa_header
571 + sizeof(struct ospf6_lsa_header
));
573 /* Collect the interface's Link-LSAs to describe
574 network's optional capabilities */
575 type
= htons(OSPF6_LSTYPE_LINK
);
576 for (ALL_LSDB_TYPED(oi
->lsdb
, type
, lsa
)) {
577 link_lsa
= (struct ospf6_link_lsa
578 *)((caddr_t
)lsa
->header
579 + sizeof(struct ospf6_lsa_header
));
580 network_lsa
->options
[0] |= link_lsa
->options
[0];
581 network_lsa
->options
[1] |= link_lsa
->options
[1];
582 network_lsa
->options
[2] |= link_lsa
->options
[2];
585 lsdesc
= (struct ospf6_network_lsdesc
586 *)((caddr_t
)network_lsa
587 + sizeof(struct ospf6_network_lsa
));
589 /* set Link Description to the router itself */
590 lsdesc
->router_id
= oi
->area
->ospf6
->router_id
;
593 /* Walk through the neighbors */
594 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
)) {
595 if (on
->state
!= OSPF6_NEIGHBOR_FULL
)
598 /* set this neighbor's Router-ID to LSA */
599 lsdesc
->router_id
= on
->router_id
;
603 /* Fill LSA Header */
605 lsa_header
->type
= htons(OSPF6_LSTYPE_NETWORK
);
606 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
607 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
609 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
610 lsa_header
->adv_router
, oi
->area
->lsdb
);
611 lsa_header
->length
= htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
614 ospf6_lsa_checksum(lsa_header
);
617 lsa
= ospf6_lsa_create(lsa_header
);
620 ospf6_lsa_originate_area(lsa
, oi
->area
);
624 /****************************/
625 /* RFC2740 3.4.3.6 Link-LSA */
626 /****************************/
628 static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa
*lsa
, char *buf
,
631 char *start
, *end
, *current
;
632 struct ospf6_link_lsa
*link_lsa
;
634 struct ospf6_prefix
*prefix
;
635 int cnt
= 0, prefixnum
;
638 link_lsa
= (struct ospf6_link_lsa
639 *)((caddr_t
)lsa
->header
640 + sizeof(struct ospf6_lsa_header
));
643 inet_ntop(AF_INET6
, &link_lsa
->linklocal_addr
, buf
,
648 prefixnum
= ntohl(link_lsa
->prefix_num
);
652 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
653 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
656 while (current
+ sizeof(struct ospf6_prefix
) <= end
) {
657 prefix
= (struct ospf6_prefix
*)current
;
658 if (prefix
->prefix_length
== 0
659 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
) {
663 if (cnt
< (pos
- 1)) {
664 current
+= OSPF6_PREFIX_SIZE(prefix
);
667 memset(&in6
, 0, sizeof(in6
));
668 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
670 prefix
->prefix_length
));
671 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
679 static int ospf6_link_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
680 json_object
*json_obj
, bool use_json
)
682 char *start
, *end
, *current
;
683 struct ospf6_link_lsa
*link_lsa
;
685 char buf
[128], options
[32];
686 struct ospf6_prefix
*prefix
;
688 json_object
*json_loop
;
689 json_object
*json_arr
= NULL
;
690 char prefix_string
[133];
692 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsa
->header
693 + sizeof(struct ospf6_lsa_header
));
695 ospf6_options_printbuf(link_lsa
->options
, options
, sizeof(options
));
696 inet_ntop(AF_INET6
, &link_lsa
->linklocal_addr
, buf
, sizeof(buf
));
697 prefixnum
= ntohl(link_lsa
->prefix_num
);
700 json_arr
= json_object_new_array();
701 json_object_int_add(json_obj
, "priority", link_lsa
->priority
);
702 json_object_string_add(json_obj
, "options", options
);
703 json_object_string_add(json_obj
, "linkLocalAddress", buf
);
704 json_object_int_add(json_obj
, "numberOfPrefix", prefixnum
);
706 vty_out(vty
, " Priority: %d Options: %s\n",
707 link_lsa
->priority
, options
);
708 vty_out(vty
, " LinkLocal Address: %s\n", buf
);
709 vty_out(vty
, " Number of Prefix: %d\n", prefixnum
);
712 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
713 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
714 for (current
= start
; current
< end
;
715 current
+= OSPF6_PREFIX_SIZE(prefix
)) {
716 prefix
= (struct ospf6_prefix
*)current
;
717 if (prefix
->prefix_length
== 0
718 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
)
721 ospf6_prefix_options_printbuf(prefix
->prefix_options
, buf
,
724 json_loop
= json_object_new_object();
725 json_object_string_add(json_loop
, "prefixOption", buf
);
727 vty_out(vty
, " Prefix Options: %s\n", buf
);
729 memset(&in6
, 0, sizeof(in6
));
730 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
731 OSPF6_PREFIX_SPACE(prefix
->prefix_length
));
732 inet_ntop(AF_INET6
, &in6
, buf
, sizeof(buf
));
734 snprintf(prefix_string
, sizeof(prefix_string
), "%s/%d",
735 buf
, prefix
->prefix_length
);
736 json_object_string_add(json_loop
, "prefix",
738 json_object_array_add(json_arr
, json_loop
);
740 vty_out(vty
, " Prefix: %s/%d\n", buf
,
741 prefix
->prefix_length
);
744 json_object_object_add(json_obj
, "prefix", json_arr
);
749 void ospf6_link_lsa_originate(struct thread
*thread
)
751 struct ospf6_interface
*oi
;
753 char buffer
[OSPF6_MAX_LSASIZE
];
754 struct ospf6_lsa_header
*lsa_header
;
755 struct ospf6_lsa
*old
, *lsa
;
757 struct ospf6_link_lsa
*link_lsa
;
758 struct ospf6_route
*route
;
759 struct ospf6_prefix
*op
;
761 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
765 if (oi
->area
->ospf6
->gr_info
.restart_in_progress
) {
766 if (IS_DEBUG_OSPF6_GR
)
768 "Graceful Restart in progress, don't originate LSA");
773 /* find previous LSA */
774 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_LINK
),
775 htonl(oi
->interface
->ifindex
),
776 oi
->area
->ospf6
->router_id
, oi
->lsdb
);
778 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
780 ospf6_lsa_purge(old
);
784 if (IS_OSPF6_DEBUG_ORIGINATE(LINK
))
785 zlog_debug("Originate Link-LSA for Interface %s",
786 oi
->interface
->name
);
788 /* can't make Link-LSA if linklocal address not set */
789 if (oi
->linklocal_addr
== NULL
) {
790 if (IS_OSPF6_DEBUG_ORIGINATE(LINK
))
792 "No Linklocal address on %s, defer originating",
793 oi
->interface
->name
);
795 ospf6_lsa_purge(old
);
800 memset(buffer
, 0, sizeof(buffer
));
801 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
802 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsa_header
803 + sizeof(struct ospf6_lsa_header
));
806 link_lsa
->priority
= oi
->priority
;
807 memcpy(link_lsa
->options
, oi
->area
->options
, 3);
808 memcpy(&link_lsa
->linklocal_addr
, oi
->linklocal_addr
,
809 sizeof(struct in6_addr
));
810 link_lsa
->prefix_num
= htonl(oi
->route_connected
->count
);
812 op
= (struct ospf6_prefix
*)((caddr_t
)link_lsa
813 + sizeof(struct ospf6_link_lsa
));
815 /* connected prefix to advertise */
816 for (route
= ospf6_route_head(oi
->route_connected
); route
;
817 route
= ospf6_route_next(route
)) {
818 op
->prefix_length
= route
->prefix
.prefixlen
;
819 op
->prefix_options
= route
->prefix_options
;
820 op
->prefix_metric
= htons(0);
821 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
822 OSPF6_PREFIX_SPACE(op
->prefix_length
));
823 op
= OSPF6_PREFIX_NEXT(op
);
826 /* Fill LSA Header */
828 lsa_header
->type
= htons(OSPF6_LSTYPE_LINK
);
829 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
830 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
832 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
833 lsa_header
->adv_router
, oi
->lsdb
);
834 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)buffer
);
837 ospf6_lsa_checksum(lsa_header
);
840 lsa
= ospf6_lsa_create(lsa_header
);
843 ospf6_lsa_originate_interface(lsa
, oi
);
847 /*****************************************/
848 /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
849 /*****************************************/
850 static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
851 char *buf
, int buflen
,
854 char *start
, *end
, *current
;
855 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
857 int prefixnum
, cnt
= 0;
858 struct ospf6_prefix
*prefix
;
863 (struct ospf6_intra_prefix_lsa
864 *)((caddr_t
)lsa
->header
865 + sizeof(struct ospf6_lsa_header
));
867 prefixnum
= ntohs(intra_prefix_lsa
->prefix_num
);
868 if ((pos
+ 1) > prefixnum
)
871 start
= (char *)intra_prefix_lsa
872 + sizeof(struct ospf6_intra_prefix_lsa
);
873 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
876 while (current
+ sizeof(struct ospf6_prefix
) <= end
) {
877 prefix
= (struct ospf6_prefix
*)current
;
878 if (prefix
->prefix_length
== 0
879 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
) {
884 current
+= OSPF6_PREFIX_SIZE(prefix
);
887 memset(&in6
, 0, sizeof(in6
));
888 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
890 prefix
->prefix_length
));
891 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
892 snprintf(tbuf
, sizeof(tbuf
), "/%d",
893 prefix
->prefix_length
);
894 strlcat(buf
, tbuf
, buflen
);
902 static int ospf6_intra_prefix_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
903 json_object
*json_obj
, bool use_json
)
905 char *start
, *end
, *current
;
906 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
909 struct ospf6_prefix
*prefix
;
910 char id
[16], adv_router
[16];
912 json_object
*json_loop
;
913 json_object
*json_arr
= NULL
;
914 char prefix_string
[133];
916 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
917 *)((caddr_t
)lsa
->header
918 + sizeof(struct ospf6_lsa_header
));
920 prefixnum
= ntohs(intra_prefix_lsa
->prefix_num
);
923 json_arr
= json_object_new_array();
924 json_object_int_add(json_obj
, "numberOfPrefix", prefixnum
);
926 vty_out(vty
, " Number of Prefix: %d\n", prefixnum
);
928 inet_ntop(AF_INET
, &intra_prefix_lsa
->ref_id
, id
, sizeof(id
));
929 inet_ntop(AF_INET
, &intra_prefix_lsa
->ref_adv_router
, adv_router
,
932 json_object_string_add(
933 json_obj
, "reference",
934 ospf6_lstype_name(intra_prefix_lsa
->ref_type
));
935 json_object_string_add(json_obj
, "referenceId", id
);
936 json_object_string_add(json_obj
, "referenceAdv", adv_router
);
938 vty_out(vty
, " Reference: %s Id: %s Adv: %s\n",
939 ospf6_lstype_name(intra_prefix_lsa
->ref_type
), id
,
942 start
= (char *)intra_prefix_lsa
943 + sizeof(struct ospf6_intra_prefix_lsa
);
944 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
945 for (current
= start
; current
< end
;
946 current
+= OSPF6_PREFIX_SIZE(prefix
)) {
947 prefix
= (struct ospf6_prefix
*)current
;
948 if (prefix
->prefix_length
== 0
949 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
)
952 ospf6_prefix_options_printbuf(prefix
->prefix_options
, buf
,
955 json_loop
= json_object_new_object();
956 json_object_string_add(json_loop
, "prefixOption", buf
);
958 vty_out(vty
, " Prefix Options: %s\n", buf
);
960 memset(&in6
, 0, sizeof(in6
));
961 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
962 OSPF6_PREFIX_SPACE(prefix
->prefix_length
));
963 inet_ntop(AF_INET6
, &in6
, buf
, sizeof(buf
));
965 snprintf(prefix_string
, sizeof(prefix_string
), "%s/%d",
966 buf
, prefix
->prefix_length
);
967 json_object_string_add(json_loop
, "prefix",
969 json_object_int_add(json_loop
, "metric",
970 ntohs(prefix
->prefix_metric
));
971 json_object_array_add(json_arr
, json_loop
);
973 vty_out(vty
, " Prefix: %s/%d\n", buf
,
974 prefix
->prefix_length
);
975 vty_out(vty
, " Metric: %d\n",
976 ntohs(prefix
->prefix_metric
));
980 json_object_object_add(json_obj
, "prefix", json_arr
);
985 void ospf6_intra_prefix_lsa_originate_stub(struct thread
*thread
)
987 struct ospf6_area
*oa
;
989 char buffer
[OSPF6_MAX_LSASIZE
];
990 struct ospf6_lsa_header
*lsa_header
;
991 struct ospf6_lsa
*old
, *lsa
, *old_next
= NULL
;
993 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
994 struct ospf6_interface
*oi
;
995 struct ospf6_neighbor
*on
;
996 struct ospf6_route
*route
;
997 struct ospf6_prefix
*op
;
998 struct listnode
*i
, *j
;
1000 unsigned short prefix_num
= 0;
1001 struct ospf6_route_table
*route_advertise
;
1004 oa
= (struct ospf6_area
*)THREAD_ARG(thread
);
1006 if (oa
->ospf6
->gr_info
.restart_in_progress
) {
1007 if (IS_DEBUG_OSPF6_GR
)
1009 "Graceful Restart in progress, don't originate LSA");
1013 /* find previous LSA */
1014 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX
), htonl(0),
1015 oa
->ospf6
->router_id
, oa
->lsdb
);
1017 if (!IS_AREA_ENABLED(oa
)) {
1019 ospf6_lsa_purge(old
);
1020 /* find previous LSA */
1021 old_next
= ospf6_lsdb_lookup(
1022 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1023 htonl(++ls_id
), oa
->ospf6
->router_id
, oa
->lsdb
);
1026 ospf6_lsa_purge(old_next
);
1027 old_next
= ospf6_lsdb_lookup(
1028 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1029 htonl(++ls_id
), oa
->ospf6
->router_id
,
1036 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1038 "Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
1041 /* prepare buffer */
1042 memset(buffer
, 0, sizeof(buffer
));
1043 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1044 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
1045 *)((caddr_t
)lsa_header
1046 + sizeof(struct ospf6_lsa_header
));
1048 /* Fill Intra-Area-Prefix-LSA */
1049 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_ROUTER
);
1050 intra_prefix_lsa
->ref_id
= htonl(0);
1051 intra_prefix_lsa
->ref_adv_router
= oa
->ospf6
->router_id
;
1053 route_advertise
= ospf6_route_table_create(0, 0);
1055 for (ALL_LIST_ELEMENTS_RO(oa
->if_list
, i
, oi
)) {
1056 if (oi
->state
== OSPF6_INTERFACE_DOWN
) {
1057 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1058 zlog_debug(" Interface %s is down, ignore",
1059 oi
->interface
->name
);
1065 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
))
1066 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
1069 if (oi
->state
!= OSPF6_INTERFACE_LOOPBACK
1070 && oi
->state
!= OSPF6_INTERFACE_POINTTOPOINT
1071 && full_count
!= 0) {
1072 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1073 zlog_debug(" Interface %s is not stub, ignore",
1074 oi
->interface
->name
);
1078 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1079 zlog_debug(" Interface %s:", oi
->interface
->name
);
1081 /* connected prefix to advertise */
1082 for (route
= ospf6_route_head(oi
->route_connected
); route
;
1083 route
= ospf6_route_best_next(route
)) {
1084 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1085 zlog_debug(" include %pFX", &route
->prefix
);
1086 ospf6_route_add(ospf6_route_copy(route
),
1091 if (route_advertise
->count
== 0) {
1094 ospf6_lsa_purge(old
);
1095 /* find previous LSA */
1096 old_next
= ospf6_lsdb_lookup(
1097 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1098 htonl(++ls_id
), oa
->ospf6
->router_id
, oa
->lsdb
);
1101 ospf6_lsa_purge(old_next
);
1102 old_next
= ospf6_lsdb_lookup(
1103 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1104 htonl(++ls_id
), oa
->ospf6
->router_id
,
1108 ospf6_route_table_delete(route_advertise
);
1112 /* Neighbor change to FULL, if INTRA-AREA-PREFIX LSA
1113 * has not change, Flush old LSA and Re-Originate INP,
1114 * as ospf6_flood() checks if LSA is same as DB,
1115 * it won't be updated to neighbor's DB.
1117 if (oa
->intra_prefix_originate
) {
1118 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1120 "%s: Re-originate intra prefix LSA, Current full nbrs %u",
1121 __func__
, oa
->full_nbrs
);
1123 ospf6_lsa_purge_multi_ls_id(oa
, old
);
1124 oa
->intra_prefix_originate
= 0;
1127 /* put prefixes to advertise */
1129 op
= (struct ospf6_prefix
*)((caddr_t
)intra_prefix_lsa
1130 + sizeof(struct ospf6_intra_prefix_lsa
));
1131 for (route
= ospf6_route_head(route_advertise
); route
;
1132 route
= ospf6_route_best_next(route
)) {
1133 if (((caddr_t
)op
- (caddr_t
)lsa_header
) > MAX_LSA_PAYLOAD
) {
1135 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
1137 /* Fill LSA Header */
1138 lsa_header
->age
= 0;
1139 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1140 lsa_header
->id
= htonl(ls_id
++);
1141 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
1142 lsa_header
->seqnum
= ospf6_new_ls_seqnum(
1143 lsa_header
->type
, lsa_header
->id
,
1144 lsa_header
->adv_router
, oa
->lsdb
);
1145 lsa_header
->length
=
1146 htons((caddr_t
)op
- (caddr_t
)lsa_header
);
1149 ospf6_lsa_checksum(lsa_header
);
1152 lsa
= ospf6_lsa_create(lsa_header
);
1155 ospf6_lsa_originate_area(lsa
, oa
);
1157 /* Prepare next buffer */
1158 memset(buffer
, 0, sizeof(buffer
));
1159 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1161 (struct ospf6_intra_prefix_lsa
1162 *)((caddr_t
)lsa_header
1163 + sizeof(struct ospf6_lsa_header
));
1165 /* Fill Intra-Area-Prefix-LSA */
1166 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_ROUTER
);
1167 intra_prefix_lsa
->ref_id
= htonl(0);
1168 intra_prefix_lsa
->ref_adv_router
= oa
->ospf6
->router_id
;
1170 /* Put next set of prefixes to advertise */
1172 op
= (struct ospf6_prefix
1173 *)((caddr_t
)intra_prefix_lsa
1175 ospf6_intra_prefix_lsa
));
1178 op
->prefix_length
= route
->prefix
.prefixlen
;
1179 op
->prefix_options
= route
->prefix_options
;
1180 op
->prefix_metric
= htons(route
->path
.cost
);
1181 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
1182 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1185 op
= OSPF6_PREFIX_NEXT(op
);
1188 ospf6_route_table_delete(route_advertise
);
1190 if (prefix_num
== 0) {
1191 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1193 "Quit to Advertise Intra-Prefix: no route to advertise");
1197 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
1199 /* Fill LSA Header */
1200 lsa_header
->age
= 0;
1201 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1202 lsa_header
->id
= htonl(ls_id
++);
1203 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
1204 lsa_header
->seqnum
=
1205 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
1206 lsa_header
->adv_router
, oa
->lsdb
);
1207 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)lsa_header
);
1210 ospf6_lsa_checksum(lsa_header
);
1213 lsa
= ospf6_lsa_create(lsa_header
);
1216 ospf6_lsa_originate_area(lsa
, oa
);
1220 void ospf6_intra_prefix_lsa_originate_transit(struct thread
*thread
)
1222 struct ospf6_interface
*oi
;
1224 char buffer
[OSPF6_MAX_LSASIZE
];
1225 struct ospf6_lsa_header
*lsa_header
;
1226 struct ospf6_lsa
*old
, *lsa
;
1228 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1229 struct ospf6_neighbor
*on
;
1230 struct ospf6_route
*route
;
1231 struct ospf6_prefix
*op
;
1234 unsigned short prefix_num
= 0;
1235 struct ospf6_route_table
*route_advertise
;
1236 struct ospf6_link_lsa
*link_lsa
;
1237 char *start
, *end
, *current
;
1240 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
1244 if (oi
->area
->ospf6
->gr_info
.restart_in_progress
) {
1245 if (IS_DEBUG_OSPF6_GR
)
1247 "Graceful Restart in progress, don't originate LSA");
1251 /* find previous LSA */
1252 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1253 htonl(oi
->interface
->ifindex
),
1254 oi
->area
->ospf6
->router_id
, oi
->area
->lsdb
);
1256 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1258 ospf6_lsa_purge(old
);
1262 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1264 "Originate Intra-Area-Prefix-LSA for interface %s's prefix",
1265 oi
->interface
->name
);
1267 /* prepare buffer */
1268 memset(buffer
, 0, sizeof(buffer
));
1269 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1270 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
1271 *)((caddr_t
)lsa_header
1272 + sizeof(struct ospf6_lsa_header
));
1274 /* Fill Intra-Area-Prefix-LSA */
1275 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_NETWORK
);
1276 intra_prefix_lsa
->ref_id
= htonl(oi
->interface
->ifindex
);
1277 intra_prefix_lsa
->ref_adv_router
= oi
->area
->ospf6
->router_id
;
1279 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
1280 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1281 zlog_debug(" Interface is not DR");
1283 ospf6_lsa_purge(old
);
1288 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
))
1289 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
1292 if (full_count
== 0) {
1293 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1294 zlog_debug(" Interface is stub");
1296 ospf6_lsa_purge(old
);
1300 /* connected prefix to advertise */
1301 route_advertise
= ospf6_route_table_create(0, 0);
1303 type
= ntohs(OSPF6_LSTYPE_LINK
);
1304 for (ALL_LSDB_TYPED(oi
->lsdb
, type
, lsa
)) {
1305 if (OSPF6_LSA_IS_MAXAGE(lsa
))
1308 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1309 zlog_debug(" include prefix from %s", lsa
->name
);
1311 if (lsa
->header
->adv_router
!= oi
->area
->ospf6
->router_id
) {
1312 on
= ospf6_neighbor_lookup(lsa
->header
->adv_router
, oi
);
1313 if (on
== NULL
|| on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1314 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1316 " Neighbor not found or not Full, ignore");
1321 link_lsa
= (struct ospf6_link_lsa
1322 *)((caddr_t
)lsa
->header
1323 + sizeof(struct ospf6_lsa_header
));
1325 prefix_num
= (unsigned short)ntohl(link_lsa
->prefix_num
);
1326 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
1327 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
1328 for (current
= start
; current
< end
&& prefix_num
;
1329 current
+= OSPF6_PREFIX_SIZE(op
)) {
1330 op
= (struct ospf6_prefix
*)current
;
1331 if (op
->prefix_length
== 0
1332 || current
+ OSPF6_PREFIX_SIZE(op
) > end
)
1335 route
= ospf6_route_create(oi
->area
->ospf6
);
1337 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
1338 route
->prefix
.family
= AF_INET6
;
1339 route
->prefix
.prefixlen
= op
->prefix_length
;
1340 memset(&route
->prefix
.u
.prefix6
, 0,
1341 sizeof(struct in6_addr
));
1342 memcpy(&route
->prefix
.u
.prefix6
, OSPF6_PREFIX_BODY(op
),
1343 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1344 route
->prefix_options
= op
->prefix_options
;
1346 route
->path
.origin
.type
= lsa
->header
->type
;
1347 route
->path
.origin
.id
= lsa
->header
->id
;
1348 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1349 route
->path
.options
[0] = link_lsa
->options
[0];
1350 route
->path
.options
[1] = link_lsa
->options
[1];
1351 route
->path
.options
[2] = link_lsa
->options
[2];
1352 route
->path
.area_id
= oi
->area
->area_id
;
1353 route
->path
.type
= OSPF6_PATH_TYPE_INTRA
;
1355 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1356 zlog_debug(" include %pFX", &route
->prefix
);
1358 ospf6_route_add(route
, route_advertise
);
1361 if (current
!= end
&& IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1362 zlog_debug("Trailing garbage in %s", lsa
->name
);
1365 op
= (struct ospf6_prefix
*)((caddr_t
)intra_prefix_lsa
1366 + sizeof(struct ospf6_intra_prefix_lsa
));
1369 for (route
= ospf6_route_head(route_advertise
); route
;
1370 route
= ospf6_route_best_next(route
)) {
1371 op
->prefix_length
= route
->prefix
.prefixlen
;
1372 op
->prefix_options
= route
->prefix_options
;
1373 op
->prefix_metric
= htons(0);
1374 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
1375 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1376 op
= OSPF6_PREFIX_NEXT(op
);
1380 ospf6_route_table_delete(route_advertise
);
1382 if (prefix_num
== 0) {
1383 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1385 "Quit to Advertise Intra-Prefix: no route to advertise");
1389 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
1391 /* Fill LSA Header */
1392 lsa_header
->age
= 0;
1393 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1394 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
1395 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
1396 lsa_header
->seqnum
=
1397 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
1398 lsa_header
->adv_router
, oi
->area
->lsdb
);
1399 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)lsa_header
);
1402 ospf6_lsa_checksum(lsa_header
);
1405 lsa
= ospf6_lsa_create(lsa_header
);
1408 ospf6_lsa_originate_area(lsa
, oi
->area
);
1411 static void ospf6_intra_prefix_update_route_origin(struct ospf6_route
*oa_route
,
1412 struct ospf6
*ospf6
)
1414 struct ospf6_path
*h_path
;
1415 struct ospf6_route
*g_route
, *nroute
;
1417 /* Update Global ospf6 route path */
1418 g_route
= ospf6_route_lookup(&oa_route
->prefix
, ospf6
->route_table
);
1422 for (ospf6_route_lock(g_route
); g_route
&&
1423 ospf6_route_is_prefix(&oa_route
->prefix
, g_route
);
1425 nroute
= ospf6_route_next(g_route
);
1426 if (g_route
->type
!= oa_route
->type
)
1428 if (g_route
->path
.area_id
!= oa_route
->path
.area_id
)
1430 if (g_route
->path
.type
!= OSPF6_PATH_TYPE_INTRA
)
1432 if (g_route
->path
.cost
!= oa_route
->path
.cost
)
1435 if (ospf6_route_is_same_origin(g_route
, oa_route
)) {
1436 h_path
= (struct ospf6_path
*)listgetdata(
1437 listhead(g_route
->paths
));
1438 g_route
->path
.origin
.type
= h_path
->origin
.type
;
1439 g_route
->path
.origin
.id
= h_path
->origin
.id
;
1440 g_route
->path
.origin
.adv_router
=
1441 h_path
->origin
.adv_router
;
1443 ospf6_route_unlock(nroute
);
1448 h_path
= (struct ospf6_path
*)listgetdata(
1449 listhead(oa_route
->paths
));
1450 oa_route
->path
.origin
.type
= h_path
->origin
.type
;
1451 oa_route
->path
.origin
.id
= h_path
->origin
.id
;
1452 oa_route
->path
.origin
.adv_router
= h_path
->origin
.adv_router
;
1455 void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area
*oa
,
1456 struct ospf6_route
*old
,
1457 struct ospf6_route
*route
)
1459 struct ospf6_route
*old_route
, *ls_entry
;
1460 struct ospf6_path
*ecmp_path
, *o_path
= NULL
;
1461 struct listnode
*anode
, *anext
;
1462 struct listnode
*nnode
, *rnode
, *rnext
;
1463 struct ospf6_nexthop
*nh
, *rnh
;
1464 bool route_found
= false;
1465 struct interface
*ifp
= NULL
;
1466 struct ospf6_lsa
*lsa
;
1467 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1469 /* check for old entry match with new route origin,
1472 for (old_route
= old
; old_route
; old_route
= old_route
->next
) {
1473 bool route_updated
= false;
1475 /* The route linked-list is grouped in batches of prefix.
1476 * If the new prefix is not the same as the one of interest
1477 * then we have walked over the end of the batch and so we
1478 * should break rather than continuing unnecessarily.
1480 if (!ospf6_route_is_same(old_route
, route
))
1482 if (old_route
->path
.type
!= route
->path
.type
)
1485 /* Current and New route has same origin,
1488 for (ALL_LIST_ELEMENTS(old_route
->paths
, anode
, anext
,
1490 /* Check old route path and route has same
1493 if (o_path
->area_id
!= route
->path
.area_id
1494 || !ospf6_ls_origin_same(o_path
, &route
->path
))
1497 /* Cost is not same then delete current path */
1498 if (o_path
->cost
== route
->path
.cost
)
1501 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1503 "%s: route %pFX cost old %u new %u is not same, replace route",
1504 __func__
, &old_route
->prefix
, o_path
->cost
,
1508 /* Remove selected current path's nh from
1509 * effective nh list.
1511 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
, nnode
, nh
)) {
1512 for (ALL_LIST_ELEMENTS(old_route
->nh_list
,
1513 rnode
, rnext
, rnh
)) {
1514 if (!ospf6_nexthop_is_same(rnh
, nh
))
1516 listnode_delete(old_route
->nh_list
,
1518 ospf6_nexthop_delete(rnh
);
1519 route_updated
= true;
1523 listnode_delete(old_route
->paths
, o_path
);
1524 ospf6_path_free(o_path
);
1526 /* Current route's path (adv_router info) is similar
1527 * to route being added.
1528 * Replace current route's path with paths list head.
1529 * Update FIB with effective NHs.
1531 if (listcount(old_route
->paths
)) {
1532 if (route_updated
) {
1533 for (ALL_LIST_ELEMENTS(old_route
->paths
,
1534 anode
, anext
, o_path
)) {
1535 ospf6_merge_nexthops(
1539 /* Update ospf6 route table and
1540 * RIB/FIB with effective
1543 if (oa
->route_table
->hook_add
)
1544 (*oa
->route_table
->hook_add
)(
1547 if (old_route
->path
.origin
.id
==
1548 route
->path
.origin
.id
&&
1549 old_route
->path
.origin
.adv_router
==
1550 route
->path
.origin
.adv_router
) {
1551 ospf6_intra_prefix_update_route_origin(
1552 old_route
, oa
->ospf6
);
1557 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1559 "%s: route %pFX old cost %u new cost %u, delete old entry.",
1560 __func__
, &old_route
->prefix
,
1561 old_route
->path
.cost
,
1564 if (oa
->route_table
->hook_remove
)
1565 ospf6_route_remove(old_route
,
1568 SET_FLAG(old_route
->flag
,
1569 OSPF6_ROUTE_REMOVE
);
1577 for (old_route
= old
; old_route
; old_route
= old_route
->next
) {
1579 /* The route linked-list is grouped in batches of prefix.
1580 * If the new prefix is not the same as the one of interest
1581 * then we have walked over the end of the batch and so we
1582 * should break rather than continuing unnecessarily.
1584 if (!ospf6_route_is_same(old_route
, route
))
1586 if (old_route
->path
.type
!= route
->path
.type
)
1589 /* Old Route and New Route have Equal Cost, Merge NHs */
1590 if (old_route
->path
.cost
== route
->path
.cost
) {
1593 /* check if this path exists already in
1594 * route->paths list, if so, replace nh_list.
1596 for (ALL_LIST_ELEMENTS_RO(old_route
->paths
, anode
,
1598 if (o_path
->area_id
== route
->path
.area_id
1599 && ospf6_ls_origin_same(o_path
, &route
->path
))
1602 /* If path is not found in old_route paths's list,
1603 * add a new path to route paths list and merge
1604 * nexthops in route->path->nh_list.
1605 * Otherwise replace existing path's nh_list.
1607 if (o_path
== NULL
) {
1608 ecmp_path
= ospf6_path_dup(&route
->path
);
1610 /* Add a nh_list to new ecmp path */
1611 ospf6_copy_nexthops(ecmp_path
->nh_list
,
1613 /* Add the new path to route's path list */
1614 listnode_add_sort(old_route
->paths
, ecmp_path
);
1616 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1618 "%s: route %pFX %p another path added with nh %u, effective paths %u nh %u",
1619 __func__
, &route
->prefix
,
1621 listcount(ecmp_path
->nh_list
),
1622 old_route
->paths
? listcount(
1625 listcount(old_route
->nh_list
));
1628 list_delete_all_node(o_path
->nh_list
);
1629 ospf6_copy_nexthops(o_path
->nh_list
,
1634 list_delete_all_node(old_route
->nh_list
);
1636 for (ALL_LIST_ELEMENTS_RO(old_route
->paths
, anode
,
1638 ls_entry
= ospf6_route_lookup(
1641 if (ls_entry
== NULL
) {
1642 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1644 "%s: ls_prfix %pFX ls_entry not found.",
1646 &o_path
->ls_prefix
);
1649 lsa
= ospf6_lsdb_lookup(o_path
->origin
.type
,
1651 o_path
->origin
.adv_router
,
1654 if (IS_OSPF6_DEBUG_EXAMIN(
1656 struct prefix adv_prefix
;
1658 ospf6_linkstate_prefix(
1659 o_path
->origin
.adv_router
,
1660 o_path
->origin
.id
, &adv_prefix
);
1662 "%s: adv_router %pFX lsa not found",
1663 __func__
, &adv_prefix
);
1668 (struct ospf6_intra_prefix_lsa
*)
1669 OSPF6_LSA_HEADER_END(lsa
->header
);
1671 if (intra_prefix_lsa
->ref_adv_router
1672 == oa
->ospf6
->router_id
) {
1673 ifp
= if_lookup_prefix(
1679 /* Nexthop interface found */
1680 ospf6_route_add_nexthop(old_route
,
1684 /* The connected interfaces between
1685 * routers can be in different networks.
1686 * In this case the matching interface
1687 * is not found. Copy nexthops from the
1690 ospf6_route_merge_nexthops(old_route
,
1695 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1697 "%s: route %pFX %p with final effective paths %u nh %u",
1698 __func__
, &route
->prefix
,
1701 ? listcount(old_route
->paths
)
1703 listcount(old_route
->nh_list
));
1705 /* used in intra_route_calculation() to add to
1706 * global ospf6 route table.
1708 UNSET_FLAG(old_route
->flag
, OSPF6_ROUTE_REMOVE
);
1709 SET_FLAG(old_route
->flag
, OSPF6_ROUTE_ADD
);
1710 /* Update ospf6 route table and RIB/FIB */
1711 if (oa
->route_table
->hook_add
)
1712 (*oa
->route_table
->hook_add
)(old_route
);
1713 /* Delete the new route its info added to existing
1716 ospf6_route_delete(route
);
1723 /* Add new route to existing node in ospf6 route table. */
1724 ospf6_route_add(route
, oa
->route_table
);
1728 void ospf6_intra_prefix_lsa_add(struct ospf6_lsa
*lsa
)
1730 struct ospf6_area
*oa
;
1731 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1732 struct prefix ls_prefix
;
1733 struct ospf6_route
*route
, *ls_entry
, *old
;
1735 struct ospf6_prefix
*op
;
1736 char *start
, *current
, *end
;
1737 char buf
[PREFIX2STR_BUFFER
];
1738 struct interface
*ifp
= NULL
;
1739 int direct_connect
= 0;
1740 struct ospf6_path
*path
;
1742 if (OSPF6_LSA_IS_MAXAGE(lsa
))
1745 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1746 zlog_debug("%s: LSA %s found", __func__
, lsa
->name
);
1748 oa
= OSPF6_AREA(lsa
->lsdb
->data
);
1751 (struct ospf6_intra_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1753 if (intra_prefix_lsa
->ref_type
== htons(OSPF6_LSTYPE_ROUTER
) ||
1754 intra_prefix_lsa
->ref_type
== htons(OSPF6_LSTYPE_NETWORK
))
1755 ospf6_linkstate_prefix(intra_prefix_lsa
->ref_adv_router
,
1756 intra_prefix_lsa
->ref_id
, &ls_prefix
);
1758 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1759 zlog_debug("Unknown reference LS-type: %#hx",
1760 ntohs(intra_prefix_lsa
->ref_type
));
1764 ls_entry
= ospf6_route_lookup(&ls_prefix
, oa
->spf_table
);
1765 if (ls_entry
== NULL
) {
1766 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1767 ospf6_linkstate_prefix2str(&ls_prefix
, buf
,
1769 zlog_debug("LS entry does not exist: %s", buf
);
1774 if (intra_prefix_lsa
->ref_adv_router
== oa
->ospf6
->router_id
) {
1775 /* the intra-prefix are directly connected */
1779 prefix_num
= ntohs(intra_prefix_lsa
->prefix_num
);
1780 start
= (caddr_t
)intra_prefix_lsa
1781 + sizeof(struct ospf6_intra_prefix_lsa
);
1782 end
= OSPF6_LSA_END(lsa
->header
);
1783 for (current
= start
; current
< end
; current
+= OSPF6_PREFIX_SIZE(op
)) {
1784 op
= (struct ospf6_prefix
*)current
;
1785 if (prefix_num
== 0)
1787 if (end
< current
+ OSPF6_PREFIX_SIZE(op
))
1790 /* Appendix A.4.1.1 */
1791 if (CHECK_FLAG(op
->prefix_options
, OSPF6_PREFIX_OPTION_NU
)) {
1792 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1793 ospf6_linkstate_prefix2str(
1794 (struct prefix
*)OSPF6_PREFIX_BODY(op
),
1797 "%s: Skipping Prefix %s has NU option set",
1803 route
= ospf6_route_create(oa
->ospf6
);
1805 memset(&route
->prefix
, 0, sizeof(struct prefix
));
1806 route
->prefix
.family
= AF_INET6
;
1807 route
->prefix
.prefixlen
= op
->prefix_length
;
1808 ospf6_prefix_in6_addr(&route
->prefix
.u
.prefix6
,
1809 intra_prefix_lsa
, op
);
1810 route
->prefix_options
= op
->prefix_options
;
1812 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
1813 route
->path
.origin
.type
= lsa
->header
->type
;
1814 route
->path
.origin
.id
= lsa
->header
->id
;
1815 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1816 route
->path
.area_id
= oa
->area_id
;
1817 route
->path
.type
= OSPF6_PATH_TYPE_INTRA
;
1818 route
->path
.metric_type
= 1;
1820 ls_entry
->path
.cost
+ ntohs(op
->prefix_metric
);
1821 memcpy(&route
->path
.ls_prefix
, &ls_prefix
,
1822 sizeof(struct prefix
));
1823 if (direct_connect
) {
1824 ifp
= if_lookup_prefix(&route
->prefix
,
1829 /* Nexthop interface found */
1830 ospf6_route_add_nexthop(route
, ifp
->ifindex
, NULL
);
1832 /* The connected interfaces between routers can be in
1833 * different networks. In this case the matching
1834 * interface is not found. Copy nexthops from the
1837 ospf6_route_copy_nexthops(route
, ls_entry
);
1840 path
= ospf6_path_dup(&route
->path
);
1841 ospf6_copy_nexthops(path
->nh_list
, route
->path
.nh_list
);
1842 listnode_add_sort(route
->paths
, path
);
1844 old
= ospf6_route_lookup(&route
->prefix
, oa
->route_table
);
1846 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1847 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1849 "%s Update route: %s old cost %u new cost %u paths %u nh %u",
1850 __func__
, buf
, old
->path
.cost
,
1852 listcount(route
->paths
),
1853 listcount(route
->nh_list
));
1855 ospf6_intra_prefix_route_ecmp_path(oa
, old
, route
);
1857 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1858 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1860 "%s route %s add with cost %u paths %u nh %u",
1861 __func__
, buf
, route
->path
.cost
,
1862 listcount(route
->paths
),
1863 listcount(route
->nh_list
));
1865 ospf6_route_add(route
, oa
->route_table
);
1870 if (current
!= end
&& IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1871 zlog_debug("Trailing garbage ignored");
1874 static void ospf6_intra_prefix_lsa_remove_update_route(struct ospf6_lsa
*lsa
,
1875 struct ospf6_area
*oa
,
1876 struct ospf6_route
*route
)
1878 struct listnode
*anode
, *anext
;
1879 struct listnode
*nnode
, *rnode
, *rnext
;
1880 struct ospf6_nexthop
*nh
, *rnh
;
1881 struct ospf6_path
*o_path
;
1882 bool nh_updated
= false;
1883 char buf
[PREFIX2STR_BUFFER
];
1885 /* Iterate all paths of route to find maching
1886 * with LSA remove info.
1887 * If route->path is same, replace
1890 for (ALL_LIST_ELEMENTS(route
->paths
, anode
, anext
, o_path
)) {
1891 if ((o_path
->origin
.type
!= lsa
->header
->type
) ||
1892 (o_path
->origin
.adv_router
!= lsa
->header
->adv_router
) ||
1893 (o_path
->origin
.id
!= lsa
->header
->id
))
1896 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1897 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1899 "%s: route %s path found with cost %u nh %u to remove.",
1900 __func__
, buf
, o_path
->cost
,
1901 listcount(o_path
->nh_list
));
1904 /* Remove found path's nh_list from
1905 * the route's nh_list.
1907 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
, nnode
, nh
)) {
1908 for (ALL_LIST_ELEMENTS(route
->nh_list
, rnode
,
1910 if (!ospf6_nexthop_is_same(rnh
, nh
))
1912 listnode_delete(route
->nh_list
, rnh
);
1913 ospf6_nexthop_delete(rnh
);
1916 /* Delete the path from route's
1919 listnode_delete(route
->paths
, o_path
);
1920 ospf6_path_free(o_path
);
1926 /* Iterate all paths and merge nexthop,
1927 * unlesss any of the nexthop similar to
1928 * ones deleted as part of path deletion.
1930 for (ALL_LIST_ELEMENTS(route
->paths
, anode
, anext
, o_path
))
1931 ospf6_merge_nexthops(route
->nh_list
, o_path
->nh_list
);
1934 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1935 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1937 "%s: route %s update paths %u nh %u", __func__
,
1938 buf
, route
->paths
? listcount(route
->paths
) : 0,
1939 route
->nh_list
? listcount(route
->nh_list
) : 0);
1942 /* Update Global Route table and
1943 * RIB/FIB with effective
1946 if (oa
->route_table
->hook_add
)
1947 (*oa
->route_table
->hook_add
)(route
);
1949 /* route's primary path is similar
1950 * to LSA, replace route's primary
1951 * path with route's paths list
1954 if ((route
->path
.origin
.id
== lsa
->header
->id
) &&
1955 (route
->path
.origin
.adv_router
==
1956 lsa
->header
->adv_router
)) {
1957 ospf6_intra_prefix_update_route_origin(route
,
1964 void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa
*lsa
)
1966 struct ospf6_area
*oa
;
1967 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1968 struct prefix prefix
;
1969 struct ospf6_route
*route
, *nroute
;
1971 struct ospf6_prefix
*op
;
1972 char *start
, *current
, *end
;
1973 char buf
[PREFIX2STR_BUFFER
];
1975 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1976 zlog_debug("%s: %s disappearing", __func__
, lsa
->name
);
1978 oa
= OSPF6_AREA(lsa
->lsdb
->data
);
1981 (struct ospf6_intra_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1984 prefix_num
= ntohs(intra_prefix_lsa
->prefix_num
);
1985 start
= (caddr_t
)intra_prefix_lsa
1986 + sizeof(struct ospf6_intra_prefix_lsa
);
1987 end
= OSPF6_LSA_END(lsa
->header
);
1988 for (current
= start
; current
< end
; current
+= OSPF6_PREFIX_SIZE(op
)) {
1989 op
= (struct ospf6_prefix
*)current
;
1990 if (prefix_num
== 0)
1992 if (end
< current
+ OSPF6_PREFIX_SIZE(op
))
1996 memset(&prefix
, 0, sizeof(prefix
));
1997 prefix
.family
= AF_INET6
;
1998 prefix
.prefixlen
= op
->prefix_length
;
1999 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, intra_prefix_lsa
, op
);
2001 route
= ospf6_route_lookup(&prefix
, oa
->route_table
);
2005 for (ospf6_route_lock(route
);
2006 route
&& ospf6_route_is_prefix(&prefix
, route
);
2008 nroute
= ospf6_route_next(route
);
2009 if (route
->type
!= OSPF6_DEST_TYPE_NETWORK
)
2011 if (route
->path
.area_id
!= oa
->area_id
)
2013 if (route
->path
.type
!= OSPF6_PATH_TYPE_INTRA
)
2015 /* Route has multiple ECMP paths, remove matching
2016 * path. Update current route's effective nh list
2017 * after removal of one of the path.
2019 if (listcount(route
->paths
) > 1) {
2020 ospf6_intra_prefix_lsa_remove_update_route(
2024 if (route
->path
.origin
.type
!= lsa
->header
->type
2025 || route
->path
.origin
.id
!= lsa
->header
->id
2026 || route
->path
.origin
.adv_router
2027 != lsa
->header
->adv_router
)
2030 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
2031 prefix2str(&route
->prefix
, buf
,
2034 "%s: route remove %s with path type %u cost %u paths %u nh %u",
2035 __func__
, buf
, route
->path
.type
,
2037 listcount(route
->paths
),
2038 listcount(route
->nh_list
));
2040 ospf6_route_remove(route
, oa
->route_table
);
2044 ospf6_route_unlock(route
);
2047 if (current
!= end
&& IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
2048 zlog_debug("Trailing garbage ignored");
2051 void ospf6_intra_route_calculation(struct ospf6_area
*oa
)
2053 struct ospf6_route
*route
, *nroute
;
2055 struct ospf6_lsa
*lsa
;
2056 void (*hook_add
)(struct ospf6_route
*) = NULL
;
2057 void (*hook_remove
)(struct ospf6_route
*) = NULL
;
2058 char buf
[PREFIX2STR_BUFFER
];
2060 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
2061 zlog_debug("Re-examin intra-routes for area %s", oa
->name
);
2063 hook_add
= oa
->route_table
->hook_add
;
2064 hook_remove
= oa
->route_table
->hook_remove
;
2065 oa
->route_table
->hook_add
= NULL
;
2066 oa
->route_table
->hook_remove
= NULL
;
2068 for (route
= ospf6_route_head(oa
->route_table
); route
;
2069 route
= ospf6_route_next(route
))
2070 route
->flag
= OSPF6_ROUTE_REMOVE
;
2072 type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
2073 for (ALL_LSDB_TYPED(oa
->lsdb
, type
, lsa
))
2074 ospf6_intra_prefix_lsa_add(lsa
);
2076 oa
->route_table
->hook_add
= hook_add
;
2077 oa
->route_table
->hook_remove
= hook_remove
;
2079 for (route
= ospf6_route_head(oa
->route_table
); route
; route
= nroute
) {
2080 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
2081 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
2082 zlog_debug("%s: route %s, flag 0x%x", __func__
, buf
,
2086 nroute
= ospf6_route_next(route
);
2087 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
)
2088 && CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ADD
)) {
2089 UNSET_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
);
2090 UNSET_FLAG(route
->flag
, OSPF6_ROUTE_ADD
);
2093 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
))
2094 ospf6_route_remove(route
, oa
->route_table
);
2095 else if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ADD
)
2096 || CHECK_FLAG(route
->flag
, OSPF6_ROUTE_CHANGE
)) {
2101 /* Redo the summaries as things might have changed */
2102 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
2103 zlog_debug("%s: Originate summary for route %s",
2105 ospf6_abr_originate_summary(route
, oa
->ospf6
);
2110 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
2111 zlog_debug("Re-examin intra-routes for area %s: Done",
2115 static void ospf6_brouter_debug_print(struct ospf6_route
*brouter
)
2117 uint32_t brouter_id
;
2118 char brouter_name
[16];
2120 char destination
[64];
2121 char installed
[64], changed
[64];
2122 struct timeval now
, res
;
2123 char id
[16], adv_router
[16];
2124 char capa
[16], options
[32];
2126 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2127 inet_ntop(AF_INET
, &brouter_id
, brouter_name
, sizeof(brouter_name
));
2128 inet_ntop(AF_INET
, &brouter
->path
.area_id
, area_name
,
2130 ospf6_linkstate_prefix2str(&brouter
->prefix
, destination
,
2131 sizeof(destination
));
2134 timersub(&now
, &brouter
->installed
, &res
);
2135 timerstring(&res
, installed
, sizeof(installed
));
2138 timersub(&now
, &brouter
->changed
, &res
);
2139 timerstring(&res
, changed
, sizeof(changed
));
2141 inet_ntop(AF_INET
, &brouter
->path
.origin
.id
, id
, sizeof(id
));
2142 inet_ntop(AF_INET
, &brouter
->path
.origin
.adv_router
, adv_router
,
2143 sizeof(adv_router
));
2145 ospf6_options_printbuf(brouter
->path
.options
, options
, sizeof(options
));
2146 ospf6_capability_printbuf(brouter
->path
.router_bits
, capa
,
2149 zlog_info("Brouter: %s via area %s", brouter_name
, area_name
);
2150 zlog_info(" memory: prev: %p this: %p next: %p parent rnode: %p",
2151 (void *)brouter
->prev
, (void *)brouter
, (void *)brouter
->next
,
2152 (void *)brouter
->rnode
);
2153 zlog_info(" type: %d prefix: %s installed: %s changed: %s",
2154 brouter
->type
, destination
, installed
, changed
);
2155 zlog_info(" lock: %d flags: %s%s%s%s", brouter
->lock
,
2156 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_BEST
) ? "B" : "-"),
2157 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
) ? "A" : "-"),
2158 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
) ? "R" : "-"),
2159 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
) ? "C" : "-"));
2160 zlog_info(" path type: %s ls-origin %s id: %s adv-router %s",
2161 OSPF6_PATH_TYPE_NAME(brouter
->path
.type
),
2162 ospf6_lstype_name(brouter
->path
.origin
.type
), id
, adv_router
);
2163 zlog_info(" options: %s router-bits: %s metric-type: %d metric: %d/%d",
2164 options
, capa
, brouter
->path
.metric_type
, brouter
->path
.cost
,
2165 brouter
->path
.u
.cost_e2
);
2166 zlog_info(" paths %u nh %u", listcount(brouter
->paths
),
2167 listcount(brouter
->nh_list
));
2170 void ospf6_intra_brouter_calculation(struct ospf6_area
*oa
)
2172 struct ospf6_route
*brouter
, *nbrouter
, *copy
;
2173 void (*hook_add
)(struct ospf6_route
*) = NULL
;
2174 void (*hook_remove
)(struct ospf6_route
*) = NULL
;
2175 uint32_t brouter_id
;
2176 char brouter_name
[16];
2178 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa
->area_id
) ||
2179 IS_OSPF6_DEBUG_ROUTE(MEMORY
))
2180 zlog_debug("%s: border-router calculation for area %s",
2181 __func__
, oa
->name
);
2183 hook_add
= oa
->ospf6
->brouter_table
->hook_add
;
2184 hook_remove
= oa
->ospf6
->brouter_table
->hook_remove
;
2185 oa
->ospf6
->brouter_table
->hook_add
= NULL
;
2186 oa
->ospf6
->brouter_table
->hook_remove
= NULL
;
2188 /* withdraw the previous router entries for the area */
2189 for (brouter
= ospf6_route_head(oa
->ospf6
->brouter_table
); brouter
;
2190 brouter
= ospf6_route_next(brouter
)) {
2191 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2192 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
2193 sizeof(brouter_name
));
2195 if (brouter
->path
.area_id
!= oa
->area_id
)
2198 SET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
2200 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id
)
2201 || IS_OSPF6_DEBUG_ROUTE(MEMORY
)) {
2202 zlog_debug("%p: mark as removing: area %s brouter %s",
2203 (void *)brouter
, oa
->name
, brouter_name
);
2204 ospf6_brouter_debug_print(brouter
);
2208 for (brouter
= ospf6_route_head(oa
->spf_table
); brouter
;
2209 brouter
= ospf6_route_next(brouter
)) {
2210 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2211 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
2212 sizeof(brouter_name
));
2214 if (brouter
->type
!= OSPF6_DEST_TYPE_LINKSTATE
)
2217 if (ospf6_linkstate_prefix_id(&brouter
->prefix
) != htonl(0))
2220 if (!CHECK_FLAG(brouter
->path
.router_bits
, OSPF6_ROUTER_BIT_E
)
2221 && !CHECK_FLAG(brouter
->path
.router_bits
,
2222 OSPF6_ROUTER_BIT_B
))
2225 if (!OSPF6_OPT_ISSET(brouter
->path
.options
, OSPF6_OPT_V6
)
2226 || !OSPF6_OPT_ISSET(brouter
->path
.options
, OSPF6_OPT_R
))
2229 copy
= ospf6_route_copy(brouter
);
2230 copy
->type
= OSPF6_DEST_TYPE_ROUTER
;
2231 copy
->path
.area_id
= oa
->area_id
;
2232 ospf6_route_add(copy
, oa
->ospf6
->brouter_table
);
2234 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id
)
2235 || IS_OSPF6_DEBUG_ROUTE(MEMORY
)) {
2236 zlog_debug("%p: transfer: area %s brouter %s",
2237 (void *)brouter
, oa
->name
, brouter_name
);
2238 ospf6_brouter_debug_print(brouter
);
2242 oa
->ospf6
->brouter_table
->hook_add
= hook_add
;
2243 oa
->ospf6
->brouter_table
->hook_remove
= hook_remove
;
2245 for (brouter
= ospf6_route_head(oa
->ospf6
->brouter_table
); brouter
;
2246 brouter
= nbrouter
) {
2249 * brouter may have been "deleted" in the last loop iteration.
2250 * If this is the case there is still 1 final refcount lock
2251 * taken by ospf6_route_next, that will be released by the same
2252 * call and result in deletion. To avoid heap UAF we must then
2253 * skip processing the deleted route.
2255 if (brouter
->lock
== 1) {
2256 if (IS_OSPF6_DEBUG_ROUTE(MEMORY
))
2257 ospf6_brouter_debug_print(brouter
);
2258 nbrouter
= ospf6_route_next(brouter
);
2261 nbrouter
= ospf6_route_next(brouter
);
2264 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2265 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
2266 sizeof(brouter_name
));
2268 if (brouter
->path
.area_id
!= oa
->area_id
)
2271 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_WAS_REMOVED
))
2274 /* After iterating spf_table for all routers including
2275 * intra brouter, clear mark for remove flag for
2276 * inter border router if its adv router present in
2279 if (brouter
->path
.type
== OSPF6_PATH_TYPE_INTER
) {
2280 struct prefix adv_prefix
;
2282 ospf6_linkstate_prefix(brouter
->path
.origin
.adv_router
,
2283 htonl(0), &adv_prefix
);
2285 if (ospf6_route_lookup(&adv_prefix
, oa
->spf_table
)) {
2286 if (IS_OSPF6_DEBUG_BROUTER
) {
2288 "%s: keep inter brouter %s as adv router 0x%x found in spf",
2289 __func__
, brouter_name
,
2290 brouter
->path
.origin
2292 ospf6_brouter_debug_print(brouter
);
2294 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
2298 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
)
2299 && CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
)) {
2300 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
2301 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
);
2304 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
)) {
2305 if (IS_OSPF6_DEBUG_BROUTER
2306 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2308 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2311 "%s: brouter %s disappears via area %s",
2312 __func__
, brouter_name
, oa
->name
);
2313 /* This is used to protect nbrouter from removed from
2314 * the table. For an example, ospf6_abr_examin_summary,
2315 * removes brouters which are marked for remove.
2317 oa
->intra_brouter_calc
= true;
2318 ospf6_route_remove(brouter
, oa
->ospf6
->brouter_table
);
2320 } else if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
)
2321 || CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
)) {
2322 if (IS_OSPF6_DEBUG_BROUTER
2323 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2325 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2327 zlog_info("%s: brouter %s appears via area %s",
2328 __func__
, brouter_name
, oa
->name
);
2332 (*hook_add
)(brouter
);
2334 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2336 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2339 "brouter %s still exists via area %s",
2340 brouter_name
, oa
->name
);
2341 /* But re-originate summaries */
2342 ospf6_abr_originate_summary(brouter
, oa
->ospf6
);
2346 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
);
2347 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
);
2349 /* Reset for nbrouter */
2350 oa
->intra_brouter_calc
= false;
2353 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa
->area_id
) ||
2354 IS_OSPF6_DEBUG_ROUTE(MEMORY
))
2355 zlog_debug("%s: border-router calculation for area %s: done",
2356 __func__
, oa
->name
);
2359 static struct ospf6_lsa_handler router_handler
= {
2360 .lh_type
= OSPF6_LSTYPE_ROUTER
,
2361 .lh_name
= "Router",
2362 .lh_short_name
= "Rtr",
2363 .lh_show
= ospf6_router_lsa_show
,
2364 .lh_get_prefix_str
= ospf6_router_lsa_get_nbr_id
,
2367 static struct ospf6_lsa_handler network_handler
= {
2368 .lh_type
= OSPF6_LSTYPE_NETWORK
,
2369 .lh_name
= "Network",
2370 .lh_short_name
= "Net",
2371 .lh_show
= ospf6_network_lsa_show
,
2372 .lh_get_prefix_str
= ospf6_network_lsa_get_ar_id
,
2375 static struct ospf6_lsa_handler link_handler
= {
2376 .lh_type
= OSPF6_LSTYPE_LINK
,
2378 .lh_short_name
= "Lnk",
2379 .lh_show
= ospf6_link_lsa_show
,
2380 .lh_get_prefix_str
= ospf6_link_lsa_get_prefix_str
,
2383 static struct ospf6_lsa_handler intra_prefix_handler
= {
2384 .lh_type
= OSPF6_LSTYPE_INTRA_PREFIX
,
2385 .lh_name
= "Intra-Prefix",
2386 .lh_short_name
= "INP",
2387 .lh_show
= ospf6_intra_prefix_lsa_show
,
2388 .lh_get_prefix_str
= ospf6_intra_prefix_lsa_get_prefix_str
,
2391 void ospf6_intra_init(void)
2393 ospf6_install_lsa_handler(&router_handler
);
2394 ospf6_install_lsa_handler(&network_handler
);
2395 ospf6_install_lsa_handler(&link_handler
);
2396 ospf6_install_lsa_handler(&intra_prefix_handler
);
2399 DEFUN (debug_ospf6_brouter
,
2400 debug_ospf6_brouter_cmd
,
2401 "debug ospf6 border-routers",
2404 "Debug border router\n"
2407 OSPF6_DEBUG_BROUTER_ON();
2411 DEFUN (no_debug_ospf6_brouter
,
2412 no_debug_ospf6_brouter_cmd
,
2413 "no debug ospf6 border-routers",
2417 "Debug border router\n"
2420 OSPF6_DEBUG_BROUTER_OFF();
2424 DEFUN (debug_ospf6_brouter_router
,
2425 debug_ospf6_brouter_router_cmd
,
2426 "debug ospf6 border-routers router-id A.B.C.D",
2429 "Debug border router\n"
2430 "Debug specific border router\n"
2431 "Specify border-router's router-id\n"
2436 inet_pton(AF_INET
, argv
[idx_ipv4
]->arg
, &router_id
);
2437 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON(router_id
);
2441 DEFUN (no_debug_ospf6_brouter_router
,
2442 no_debug_ospf6_brouter_router_cmd
,
2443 "no debug ospf6 border-routers router-id [A.B.C.D]",
2447 "Debug border router\n"
2448 "Debug specific border router\n"
2449 "Specify border-router's router-id\n"
2452 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF();
2456 DEFUN (debug_ospf6_brouter_area
,
2457 debug_ospf6_brouter_area_cmd
,
2458 "debug ospf6 border-routers area-id A.B.C.D",
2461 "Debug border router\n"
2462 "Debug border routers in specific Area\n"
2468 inet_pton(AF_INET
, argv
[idx_ipv4
]->arg
, &area_id
);
2469 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON(area_id
);
2473 DEFUN (no_debug_ospf6_brouter_area
,
2474 no_debug_ospf6_brouter_area_cmd
,
2475 "no debug ospf6 border-routers area-id [A.B.C.D]",
2479 "Debug border router\n"
2480 "Debug border routers in specific Area\n"
2484 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF();
2488 int config_write_ospf6_debug_brouter(struct vty
*vty
)
2491 if (IS_OSPF6_DEBUG_BROUTER
)
2492 vty_out(vty
, "debug ospf6 border-routers\n");
2493 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER
) {
2494 inet_ntop(AF_INET
, &conf_debug_ospf6_brouter_specific_router_id
,
2496 vty_out(vty
, "debug ospf6 border-routers router-id %s\n", buf
);
2498 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA
) {
2499 inet_ntop(AF_INET
, &conf_debug_ospf6_brouter_specific_area_id
,
2501 vty_out(vty
, "debug ospf6 border-routers area-id %s\n", buf
);
2506 void install_element_ospf6_debug_brouter(void)
2508 install_element(ENABLE_NODE
, &debug_ospf6_brouter_cmd
);
2509 install_element(ENABLE_NODE
, &debug_ospf6_brouter_router_cmd
);
2510 install_element(ENABLE_NODE
, &debug_ospf6_brouter_area_cmd
);
2511 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_cmd
);
2512 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_router_cmd
);
2513 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_area_cmd
);
2514 install_element(CONFIG_NODE
, &debug_ospf6_brouter_cmd
);
2515 install_element(CONFIG_NODE
, &debug_ospf6_brouter_router_cmd
);
2516 install_element(CONFIG_NODE
, &debug_ospf6_brouter_area_cmd
);
2517 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_cmd
);
2518 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_router_cmd
);
2519 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_area_cmd
);