2 * Copyright (C) 2003 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "ospf6_proto.h"
35 #include "ospf6_message.h"
36 #include "ospf6_route.h"
37 #include "ospf6_lsa.h"
38 #include "ospf6_lsdb.h"
40 #include "ospf6_top.h"
41 #include "ospf6_area.h"
42 #include "ospf6_interface.h"
43 #include "ospf6_neighbor.h"
44 #include "ospf6_intra.h"
45 #include "ospf6_asbr.h"
46 #include "ospf6_abr.h"
47 #include "ospf6_flood.h"
49 #include "ospf6_spf.h"
52 unsigned char conf_debug_ospf6_brouter
= 0;
53 uint32_t conf_debug_ospf6_brouter_specific_router_id
;
54 uint32_t conf_debug_ospf6_brouter_specific_area_id
;
56 #define MAX_LSA_PAYLOAD (1024 + 256)
57 /******************************/
58 /* RFC2740 3.4.3.1 Router-LSA */
59 /******************************/
61 static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa
*lsa
, char *buf
,
64 struct ospf6_router_lsa
*router_lsa
;
65 struct ospf6_router_lsdesc
*lsdesc
;
67 char buf1
[INET_ADDRSTRLEN
], buf2
[INET_ADDRSTRLEN
];
70 router_lsa
= (struct ospf6_router_lsa
71 *)((char *)lsa
->header
72 + sizeof(struct ospf6_lsa_header
));
73 start
= (char *)router_lsa
+ sizeof(struct ospf6_router_lsa
);
74 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
76 lsdesc
= (struct ospf6_router_lsdesc
78 + pos
* (sizeof(struct
79 ospf6_router_lsdesc
)));
80 if ((char *)lsdesc
+ sizeof(struct ospf6_router_lsdesc
)
82 if (buf
&& (buflen
> INET_ADDRSTRLEN
* 2)) {
84 &lsdesc
->neighbor_interface_id
, buf1
,
86 inet_ntop(AF_INET
, &lsdesc
->neighbor_router_id
,
88 snprintf(buf
, buflen
, "%s/%s", buf2
, buf1
);
98 static int ospf6_router_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
99 json_object
*json_obj
, bool use_json
)
101 char *start
, *end
, *current
;
102 char buf
[32], name
[32], bits
[16], options
[32];
103 struct ospf6_router_lsa
*router_lsa
;
104 struct ospf6_router_lsdesc
*lsdesc
;
105 json_object
*json_arr
;
106 json_object
*json_loop
;
109 (struct ospf6_router_lsa
*)((char *)lsa
->header
110 + sizeof(struct ospf6_lsa_header
));
112 ospf6_capability_printbuf(router_lsa
->bits
, bits
, sizeof(bits
));
113 ospf6_options_printbuf(router_lsa
->options
, options
, sizeof(options
));
115 json_object_string_add(json_obj
, "bits", bits
);
116 json_object_string_add(json_obj
, "options", options
);
117 json_arr
= json_object_new_array();
119 vty_out(vty
, " Bits: %s Options: %s\n", bits
, options
);
121 start
= (char *)router_lsa
+ sizeof(struct ospf6_router_lsa
);
122 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
123 for (current
= start
;
124 current
+ sizeof(struct ospf6_router_lsdesc
) <= end
;
125 current
+= sizeof(struct ospf6_router_lsdesc
)) {
126 lsdesc
= (struct ospf6_router_lsdesc
*)current
;
128 if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_POINTTOPOINT
)
129 snprintf(name
, sizeof(name
), "Point-To-Point");
130 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK
)
131 snprintf(name
, sizeof(name
), "Transit-Network");
132 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_STUB_NETWORK
)
133 snprintf(name
, sizeof(name
), "Stub-Network");
134 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_VIRTUAL_LINK
)
135 snprintf(name
, sizeof(name
), "Virtual-Link");
137 snprintf(name
, sizeof(name
), "Unknown (%#x)",
141 json_loop
= json_object_new_object();
142 json_object_string_add(json_loop
, "type", name
);
143 json_object_int_add(json_loop
, "metric",
144 ntohs(lsdesc
->metric
));
145 json_object_string_addf(
146 json_loop
, "interfaceId", "%pI4",
147 (in_addr_t
*)&lsdesc
->interface_id
);
148 json_object_string_addf(
149 json_loop
, "neighborInterfaceId", "%pI4",
150 (in_addr_t
*)&lsdesc
->neighbor_interface_id
);
151 json_object_string_addf(json_loop
, "neighborRouterId",
153 &lsdesc
->neighbor_router_id
);
154 json_object_array_add(json_arr
, json_loop
);
156 vty_out(vty
, " Type: %s Metric: %d\n", name
,
157 ntohs(lsdesc
->metric
));
158 vty_out(vty
, " Interface ID: %s\n",
159 inet_ntop(AF_INET
, &lsdesc
->interface_id
, buf
,
161 vty_out(vty
, " Neighbor Interface ID: %s\n",
163 &lsdesc
->neighbor_interface_id
, buf
,
165 vty_out(vty
, " Neighbor Router ID: %s\n",
166 inet_ntop(AF_INET
, &lsdesc
->neighbor_router_id
,
171 json_object_object_add(json_obj
, "lsaDescription", json_arr
);
176 static void ospf6_router_lsa_options_set(struct ospf6_area
*oa
,
177 struct ospf6_router_lsa
*router_lsa
)
179 OSPF6_OPT_CLEAR_ALL(router_lsa
->options
);
180 memcpy(router_lsa
->options
, oa
->options
, 3);
182 if (ospf6_check_and_set_router_abr(oa
->ospf6
))
183 SET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_B
);
185 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_B
);
187 if (!IS_AREA_STUB(oa
) && ospf6_asbr_is_asbr(oa
->ospf6
)) {
188 SET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_E
);
190 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_E
);
193 /* If the router is ASBR and the area-type is NSSA set the
194 * translate bit in router LSA.
197 && (ospf6_asbr_is_asbr(oa
->ospf6
) || IS_OSPF6_ABR(oa
->ospf6
))) {
198 if (oa
->NSSATranslatorRole
== OSPF6_NSSA_ROLE_ALWAYS
)
199 SET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_NT
);
201 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_NT
);
204 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_V
);
205 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_W
);
208 int ospf6_router_is_stub_router(struct ospf6_lsa
*lsa
)
210 struct ospf6_router_lsa
*rtr_lsa
;
212 if (lsa
!= NULL
&& OSPF6_LSA_IS_TYPE(ROUTER
, lsa
)) {
213 rtr_lsa
= (struct ospf6_router_lsa
214 *)((caddr_t
)lsa
->header
215 + sizeof(struct ospf6_lsa_header
));
217 if (!OSPF6_OPT_ISSET(rtr_lsa
->options
, OSPF6_OPT_R
)) {
218 return OSPF6_IS_STUB_ROUTER
;
219 } else if (!OSPF6_OPT_ISSET(rtr_lsa
->options
, OSPF6_OPT_V6
)) {
220 return OSPF6_IS_STUB_ROUTER_V6
;
224 return OSPF6_NOT_STUB_ROUTER
;
227 int ospf6_router_lsa_originate(struct thread
*thread
)
229 struct ospf6_area
*oa
;
231 char buffer
[OSPF6_MAX_LSASIZE
];
232 struct ospf6_lsa_header
*lsa_header
;
233 struct ospf6_lsa
*lsa
;
235 uint32_t link_state_id
= 0;
236 struct listnode
*node
, *nnode
;
238 struct ospf6_interface
*oi
;
239 struct ospf6_neighbor
*on
, *drouter
= NULL
;
240 struct ospf6_router_lsa
*router_lsa
;
241 struct ospf6_router_lsdesc
*lsdesc
;
246 oa
= (struct ospf6_area
*)THREAD_ARG(thread
);
248 if (oa
->ospf6
->gr_info
.restart_in_progress
) {
249 if (IS_DEBUG_OSPF6_GR
)
251 "Graceful Restart in progress, don't originate LSA");
255 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER
))
256 zlog_debug("Originate Router-LSA for Area %s", oa
->name
);
258 memset(buffer
, 0, sizeof(buffer
));
259 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
261 (struct ospf6_router_lsa
*)((caddr_t
)lsa_header
262 + sizeof(struct ospf6_lsa_header
));
264 ospf6_router_lsa_options_set(oa
, router_lsa
);
266 /* describe links for each interfaces */
267 lsdesc
= (struct ospf6_router_lsdesc
268 *)((caddr_t
)router_lsa
269 + sizeof(struct ospf6_router_lsa
));
271 for (ALL_LIST_ELEMENTS(oa
->if_list
, node
, nnode
, oi
)) {
272 /* Interfaces in state Down or Loopback are not described */
273 if (oi
->state
== OSPF6_INTERFACE_DOWN
274 || oi
->state
== OSPF6_INTERFACE_LOOPBACK
)
277 /* Nor are interfaces without any full adjacencies described */
279 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
))
280 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
286 /* Multiple Router-LSA instance according to size limit setting
288 if ((oa
->router_lsa_size_limit
!= 0)
289 && ((size_t)((char *)lsdesc
- buffer
)
290 + sizeof(struct ospf6_router_lsdesc
)
291 > oa
->router_lsa_size_limit
)) {
293 == (caddr_t
)router_lsa
294 + sizeof(struct ospf6_router_lsa
)) {
296 "Size limit setting for Router-LSA too short");
300 /* Fill LSA Header */
302 lsa_header
->type
= htons(OSPF6_LSTYPE_ROUTER
);
303 lsa_header
->id
= htonl(link_state_id
);
304 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
305 lsa_header
->seqnum
= ospf6_new_ls_seqnum(
306 lsa_header
->type
, lsa_header
->id
,
307 lsa_header
->adv_router
, oa
->lsdb
);
309 htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
312 ospf6_lsa_checksum(lsa_header
);
315 lsa
= ospf6_lsa_create(lsa_header
);
318 ospf6_lsa_originate_area(lsa
, oa
);
320 /* Reset Buffer to fill next Router LSA */
321 memset(buffer
, 0, sizeof(buffer
));
322 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
324 (struct ospf6_router_lsa
325 *)((caddr_t
)lsa_header
326 + sizeof(struct ospf6_lsa_header
));
328 ospf6_router_lsa_options_set(oa
, router_lsa
);
330 /* describe links for each interfaces */
331 lsdesc
= (struct ospf6_router_lsdesc
332 *)((caddr_t
)router_lsa
333 + sizeof(struct ospf6_router_lsa
));
338 /* Point-to-Point interfaces */
339 if (oi
->type
== OSPF_IFTYPE_POINTOPOINT
) {
340 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
)) {
341 if (on
->state
!= OSPF6_NEIGHBOR_FULL
)
344 lsdesc
->type
= OSPF6_ROUTER_LSDESC_POINTTOPOINT
;
345 lsdesc
->metric
= htons(oi
->cost
);
346 lsdesc
->interface_id
=
347 htonl(oi
->interface
->ifindex
);
348 lsdesc
->neighbor_interface_id
=
350 lsdesc
->neighbor_router_id
= on
->router_id
;
356 /* Broadcast and NBMA interfaces */
357 else if (oi
->type
== OSPF_IFTYPE_BROADCAST
) {
358 /* If this router is not DR,
359 and If this router not fully adjacent with DR,
360 this interface is not transit yet: ignore. */
361 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
363 ospf6_neighbor_lookup(oi
->drouter
, oi
);
365 || drouter
->state
!= OSPF6_NEIGHBOR_FULL
)
369 lsdesc
->type
= OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK
;
370 lsdesc
->metric
= htons(oi
->cost
);
371 lsdesc
->interface_id
= htonl(oi
->interface
->ifindex
);
372 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
373 lsdesc
->neighbor_interface_id
=
374 htonl(drouter
->ifindex
);
375 lsdesc
->neighbor_router_id
= drouter
->router_id
;
377 lsdesc
->neighbor_interface_id
=
378 htonl(oi
->interface
->ifindex
);
379 lsdesc
->neighbor_router_id
=
380 oi
->area
->ospf6
->router_id
;
385 assert(0); /* Unknown interface type */
390 /* Point-to-Multipoint interfaces */
394 /* Fill LSA Header */
396 lsa_header
->type
= htons(OSPF6_LSTYPE_ROUTER
);
397 lsa_header
->id
= htonl(link_state_id
);
398 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
400 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
401 lsa_header
->adv_router
, oa
->lsdb
);
402 lsa_header
->length
= htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
405 ospf6_lsa_checksum(lsa_header
);
408 lsa
= ospf6_lsa_create(lsa_header
);
411 ospf6_lsa_originate_area(lsa
, oa
);
415 /* Do premature-aging of rest, undesired Router-LSAs */
416 type
= ntohs(OSPF6_LSTYPE_ROUTER
);
417 router
= oa
->ospf6
->router_id
;
419 for (ALL_LSDB_TYPED_ADVRTR(oa
->lsdb
, type
, router
, lsa
)) {
420 if (ntohl(lsa
->header
->id
) < link_state_id
)
422 ospf6_lsa_purge(lsa
);
427 * Waiting till the LSA is actually removed from the database to trigger
428 * SPF delays network convergence. Unlike IPv4, for an ABR, when all
429 * interfaces associated with an area are gone, triggering an SPF right
431 * helps convergence with inter-area routes.
433 if (count
&& !link_state_id
)
434 ospf6_spf_schedule(oa
->ospf6
,
435 OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED
);
440 /*******************************/
441 /* RFC2740 3.4.3.2 Network-LSA */
442 /*******************************/
444 static char *ospf6_network_lsa_get_ar_id(struct ospf6_lsa
*lsa
, char *buf
,
447 char *start
, *end
, *current
;
448 struct ospf6_network_lsa
*network_lsa
;
449 struct ospf6_network_lsdesc
*lsdesc
;
452 network_lsa
= (struct ospf6_network_lsa
453 *)((caddr_t
)lsa
->header
454 + sizeof(struct ospf6_lsa_header
));
456 start
= (char *)network_lsa
+ sizeof(struct ospf6_network_lsa
);
457 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
458 current
= start
+ pos
* (sizeof(struct ospf6_network_lsdesc
));
460 if ((current
+ sizeof(struct ospf6_network_lsdesc
)) <= end
) {
461 lsdesc
= (struct ospf6_network_lsdesc
*)current
;
463 inet_ntop(AF_INET
, &lsdesc
->router_id
, buf
,
473 static int ospf6_network_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
474 json_object
*json_obj
, bool use_json
)
476 char *start
, *end
, *current
;
477 struct ospf6_network_lsa
*network_lsa
;
478 struct ospf6_network_lsdesc
*lsdesc
;
479 char buf
[128], options
[32];
480 json_object
*json_arr
;
483 (struct ospf6_network_lsa
*)((caddr_t
)lsa
->header
484 + sizeof(struct ospf6_lsa_header
));
486 ospf6_options_printbuf(network_lsa
->options
, options
, sizeof(options
));
488 json_object_string_add(json_obj
, "options", options
);
490 vty_out(vty
, " Options: %s\n", options
);
492 start
= (char *)network_lsa
+ sizeof(struct ospf6_network_lsa
);
493 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
495 json_arr
= json_object_new_array();
497 for (current
= start
;
498 current
+ sizeof(struct ospf6_network_lsdesc
) <= end
;
499 current
+= sizeof(struct ospf6_network_lsdesc
)) {
500 lsdesc
= (struct ospf6_network_lsdesc
*)current
;
501 inet_ntop(AF_INET
, &lsdesc
->router_id
, buf
, sizeof(buf
));
503 json_object_array_add(json_arr
,
504 json_object_new_string(buf
));
506 vty_out(vty
, " Attached Router: %s\n", buf
);
509 json_object_object_add(json_obj
, "attachedRouter", json_arr
);
514 int ospf6_network_lsa_originate(struct thread
*thread
)
516 struct ospf6_interface
*oi
;
518 char buffer
[OSPF6_MAX_LSASIZE
];
519 struct ospf6_lsa_header
*lsa_header
;
522 struct ospf6_lsa
*old
, *lsa
;
523 struct ospf6_network_lsa
*network_lsa
;
524 struct ospf6_network_lsdesc
*lsdesc
;
525 struct ospf6_neighbor
*on
;
526 struct ospf6_link_lsa
*link_lsa
;
530 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
532 /* The interface must be enabled until here. A Network-LSA of a
533 disabled interface (but was once enabled) should be flushed
534 by ospf6_lsa_refresh (), and does not come here. */
537 if (oi
->area
->ospf6
->gr_info
.restart_in_progress
) {
538 if (IS_DEBUG_OSPF6_GR
)
540 "Graceful Restart in progress, don't originate LSA");
544 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_NETWORK
),
545 htonl(oi
->interface
->ifindex
),
546 oi
->area
->ospf6
->router_id
, oi
->area
->lsdb
);
548 /* Do not originate Network-LSA if not DR */
549 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
551 ospf6_lsa_purge(old
);
553 * Waiting till the LSA is actually removed from the
555 * trigger SPF delays network convergence.
559 OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED
);
564 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK
))
565 zlog_debug("Originate Network-LSA for Interface %s",
566 oi
->interface
->name
);
568 /* If none of neighbor is adjacent to us */
571 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
))
572 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
576 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK
))
577 zlog_debug("Interface stub, ignore");
579 ospf6_lsa_purge(old
);
584 memset(buffer
, 0, sizeof(buffer
));
585 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
587 (struct ospf6_network_lsa
*)((caddr_t
)lsa_header
588 + sizeof(struct ospf6_lsa_header
));
590 /* Collect the interface's Link-LSAs to describe
591 network's optional capabilities */
592 type
= htons(OSPF6_LSTYPE_LINK
);
593 for (ALL_LSDB_TYPED(oi
->lsdb
, type
, lsa
)) {
594 link_lsa
= (struct ospf6_link_lsa
595 *)((caddr_t
)lsa
->header
596 + sizeof(struct ospf6_lsa_header
));
597 network_lsa
->options
[0] |= link_lsa
->options
[0];
598 network_lsa
->options
[1] |= link_lsa
->options
[1];
599 network_lsa
->options
[2] |= link_lsa
->options
[2];
602 lsdesc
= (struct ospf6_network_lsdesc
603 *)((caddr_t
)network_lsa
604 + sizeof(struct ospf6_network_lsa
));
606 /* set Link Description to the router itself */
607 lsdesc
->router_id
= oi
->area
->ospf6
->router_id
;
610 /* Walk through the neighbors */
611 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
)) {
612 if (on
->state
!= OSPF6_NEIGHBOR_FULL
)
615 /* set this neighbor's Router-ID to LSA */
616 lsdesc
->router_id
= on
->router_id
;
620 /* Fill LSA Header */
622 lsa_header
->type
= htons(OSPF6_LSTYPE_NETWORK
);
623 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
624 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
626 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
627 lsa_header
->adv_router
, oi
->area
->lsdb
);
628 lsa_header
->length
= htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
631 ospf6_lsa_checksum(lsa_header
);
634 lsa
= ospf6_lsa_create(lsa_header
);
637 ospf6_lsa_originate_area(lsa
, oi
->area
);
643 /****************************/
644 /* RFC2740 3.4.3.6 Link-LSA */
645 /****************************/
647 static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa
*lsa
, char *buf
,
650 char *start
, *end
, *current
;
651 struct ospf6_link_lsa
*link_lsa
;
653 struct ospf6_prefix
*prefix
;
654 int cnt
= 0, prefixnum
;
657 link_lsa
= (struct ospf6_link_lsa
658 *)((caddr_t
)lsa
->header
659 + sizeof(struct ospf6_lsa_header
));
662 inet_ntop(AF_INET6
, &link_lsa
->linklocal_addr
, buf
,
667 prefixnum
= ntohl(link_lsa
->prefix_num
);
671 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
672 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
675 while (current
+ sizeof(struct ospf6_prefix
) <= end
) {
676 prefix
= (struct ospf6_prefix
*)current
;
677 if (prefix
->prefix_length
== 0
678 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
) {
682 if (cnt
< (pos
- 1)) {
683 current
+= OSPF6_PREFIX_SIZE(prefix
);
686 memset(&in6
, 0, sizeof(in6
));
687 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
689 prefix
->prefix_length
));
690 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
698 static int ospf6_link_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
699 json_object
*json_obj
, bool use_json
)
701 char *start
, *end
, *current
;
702 struct ospf6_link_lsa
*link_lsa
;
704 char buf
[128], options
[32];
705 struct ospf6_prefix
*prefix
;
707 json_object
*json_loop
;
708 json_object
*json_arr
= NULL
;
709 char prefix_string
[133];
711 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsa
->header
712 + sizeof(struct ospf6_lsa_header
));
714 ospf6_options_printbuf(link_lsa
->options
, options
, sizeof(options
));
715 inet_ntop(AF_INET6
, &link_lsa
->linklocal_addr
, buf
, sizeof(buf
));
716 prefixnum
= ntohl(link_lsa
->prefix_num
);
719 json_arr
= json_object_new_array();
720 json_object_int_add(json_obj
, "priority", link_lsa
->priority
);
721 json_object_string_add(json_obj
, "options", options
);
722 json_object_string_add(json_obj
, "linkLocalAddress", buf
);
723 json_object_int_add(json_obj
, "numberOfPrefix", prefixnum
);
725 vty_out(vty
, " Priority: %d Options: %s\n",
726 link_lsa
->priority
, options
);
727 vty_out(vty
, " LinkLocal Address: %s\n", buf
);
728 vty_out(vty
, " Number of Prefix: %d\n", prefixnum
);
731 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
732 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
733 for (current
= start
; current
< end
;
734 current
+= OSPF6_PREFIX_SIZE(prefix
)) {
735 prefix
= (struct ospf6_prefix
*)current
;
736 if (prefix
->prefix_length
== 0
737 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
)
740 ospf6_prefix_options_printbuf(prefix
->prefix_options
, buf
,
743 json_loop
= json_object_new_object();
744 json_object_string_add(json_loop
, "prefixOption", buf
);
746 vty_out(vty
, " Prefix Options: %s\n", buf
);
748 memset(&in6
, 0, sizeof(in6
));
749 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
750 OSPF6_PREFIX_SPACE(prefix
->prefix_length
));
751 inet_ntop(AF_INET6
, &in6
, buf
, sizeof(buf
));
753 snprintf(prefix_string
, sizeof(prefix_string
), "%s/%d",
754 buf
, prefix
->prefix_length
);
755 json_object_string_add(json_loop
, "prefix",
757 json_object_array_add(json_arr
, json_loop
);
759 vty_out(vty
, " Prefix: %s/%d\n", buf
,
760 prefix
->prefix_length
);
763 json_object_object_add(json_obj
, "prefix", json_arr
);
768 int ospf6_link_lsa_originate(struct thread
*thread
)
770 struct ospf6_interface
*oi
;
772 char buffer
[OSPF6_MAX_LSASIZE
];
773 struct ospf6_lsa_header
*lsa_header
;
774 struct ospf6_lsa
*old
, *lsa
;
776 struct ospf6_link_lsa
*link_lsa
;
777 struct ospf6_route
*route
;
778 struct ospf6_prefix
*op
;
780 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
784 if (oi
->area
->ospf6
->gr_info
.restart_in_progress
) {
785 if (IS_DEBUG_OSPF6_GR
)
787 "Graceful Restart in progress, don't originate LSA");
792 /* find previous LSA */
793 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_LINK
),
794 htonl(oi
->interface
->ifindex
),
795 oi
->area
->ospf6
->router_id
, oi
->lsdb
);
797 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
799 ospf6_lsa_purge(old
);
803 if (IS_OSPF6_DEBUG_ORIGINATE(LINK
))
804 zlog_debug("Originate Link-LSA for Interface %s",
805 oi
->interface
->name
);
807 /* can't make Link-LSA if linklocal address not set */
808 if (oi
->linklocal_addr
== NULL
) {
809 if (IS_OSPF6_DEBUG_ORIGINATE(LINK
))
811 "No Linklocal address on %s, defer originating",
812 oi
->interface
->name
);
814 ospf6_lsa_purge(old
);
819 memset(buffer
, 0, sizeof(buffer
));
820 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
821 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsa_header
822 + sizeof(struct ospf6_lsa_header
));
825 link_lsa
->priority
= oi
->priority
;
826 memcpy(link_lsa
->options
, oi
->area
->options
, 3);
827 memcpy(&link_lsa
->linklocal_addr
, oi
->linklocal_addr
,
828 sizeof(struct in6_addr
));
829 link_lsa
->prefix_num
= htonl(oi
->route_connected
->count
);
831 op
= (struct ospf6_prefix
*)((caddr_t
)link_lsa
832 + sizeof(struct ospf6_link_lsa
));
834 /* connected prefix to advertise */
835 for (route
= ospf6_route_head(oi
->route_connected
); route
;
836 route
= ospf6_route_next(route
)) {
837 op
->prefix_length
= route
->prefix
.prefixlen
;
838 op
->prefix_options
= route
->prefix_options
;
839 op
->prefix_metric
= htons(0);
840 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
841 OSPF6_PREFIX_SPACE(op
->prefix_length
));
842 op
= OSPF6_PREFIX_NEXT(op
);
845 /* Fill LSA Header */
847 lsa_header
->type
= htons(OSPF6_LSTYPE_LINK
);
848 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
849 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
851 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
852 lsa_header
->adv_router
, oi
->lsdb
);
853 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)buffer
);
856 ospf6_lsa_checksum(lsa_header
);
859 lsa
= ospf6_lsa_create(lsa_header
);
862 ospf6_lsa_originate_interface(lsa
, oi
);
868 /*****************************************/
869 /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
870 /*****************************************/
871 static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
872 char *buf
, int buflen
,
875 char *start
, *end
, *current
;
876 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
878 int prefixnum
, cnt
= 0;
879 struct ospf6_prefix
*prefix
;
884 (struct ospf6_intra_prefix_lsa
885 *)((caddr_t
)lsa
->header
886 + sizeof(struct ospf6_lsa_header
));
888 prefixnum
= ntohs(intra_prefix_lsa
->prefix_num
);
889 if ((pos
+ 1) > prefixnum
)
892 start
= (char *)intra_prefix_lsa
893 + sizeof(struct ospf6_intra_prefix_lsa
);
894 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
897 while (current
+ sizeof(struct ospf6_prefix
) <= end
) {
898 prefix
= (struct ospf6_prefix
*)current
;
899 if (prefix
->prefix_length
== 0
900 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
) {
905 current
+= OSPF6_PREFIX_SIZE(prefix
);
908 memset(&in6
, 0, sizeof(in6
));
909 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
911 prefix
->prefix_length
));
912 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
913 snprintf(tbuf
, sizeof(tbuf
), "/%d",
914 prefix
->prefix_length
);
915 strlcat(buf
, tbuf
, buflen
);
923 static int ospf6_intra_prefix_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
924 json_object
*json_obj
, bool use_json
)
926 char *start
, *end
, *current
;
927 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
930 struct ospf6_prefix
*prefix
;
931 char id
[16], adv_router
[16];
933 json_object
*json_loop
;
934 json_object
*json_arr
= NULL
;
935 char prefix_string
[133];
937 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
938 *)((caddr_t
)lsa
->header
939 + sizeof(struct ospf6_lsa_header
));
941 prefixnum
= ntohs(intra_prefix_lsa
->prefix_num
);
944 json_arr
= json_object_new_array();
945 json_object_int_add(json_obj
, "numberOfPrefix", prefixnum
);
947 vty_out(vty
, " Number of Prefix: %d\n", prefixnum
);
949 inet_ntop(AF_INET
, &intra_prefix_lsa
->ref_id
, id
, sizeof(id
));
950 inet_ntop(AF_INET
, &intra_prefix_lsa
->ref_adv_router
, adv_router
,
953 json_object_string_add(
954 json_obj
, "reference",
955 ospf6_lstype_name(intra_prefix_lsa
->ref_type
));
956 json_object_string_add(json_obj
, "referenceId", id
);
957 json_object_string_add(json_obj
, "referenceAdv", adv_router
);
959 vty_out(vty
, " Reference: %s Id: %s Adv: %s\n",
960 ospf6_lstype_name(intra_prefix_lsa
->ref_type
), id
,
963 start
= (char *)intra_prefix_lsa
964 + sizeof(struct ospf6_intra_prefix_lsa
);
965 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
966 for (current
= start
; current
< end
;
967 current
+= OSPF6_PREFIX_SIZE(prefix
)) {
968 prefix
= (struct ospf6_prefix
*)current
;
969 if (prefix
->prefix_length
== 0
970 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
)
973 ospf6_prefix_options_printbuf(prefix
->prefix_options
, buf
,
976 json_loop
= json_object_new_object();
977 json_object_string_add(json_loop
, "prefixOption", buf
);
979 vty_out(vty
, " Prefix Options: %s\n", buf
);
981 memset(&in6
, 0, sizeof(in6
));
982 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
983 OSPF6_PREFIX_SPACE(prefix
->prefix_length
));
984 inet_ntop(AF_INET6
, &in6
, buf
, sizeof(buf
));
986 snprintf(prefix_string
, sizeof(prefix_string
), "%s/%d",
987 buf
, prefix
->prefix_length
);
988 json_object_string_add(json_loop
, "prefix",
990 json_object_int_add(json_loop
, "metric",
991 ntohs(prefix
->prefix_metric
));
992 json_object_array_add(json_arr
, json_loop
);
994 vty_out(vty
, " Prefix: %s/%d\n", buf
,
995 prefix
->prefix_length
);
996 vty_out(vty
, " Metric: %d\n",
997 ntohs(prefix
->prefix_metric
));
1001 json_object_object_add(json_obj
, "prefix", json_arr
);
1006 int ospf6_intra_prefix_lsa_originate_stub(struct thread
*thread
)
1008 struct ospf6_area
*oa
;
1010 char buffer
[OSPF6_MAX_LSASIZE
];
1011 struct ospf6_lsa_header
*lsa_header
;
1012 struct ospf6_lsa
*old
, *lsa
, *old_next
= NULL
;
1014 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1015 struct ospf6_interface
*oi
;
1016 struct ospf6_neighbor
*on
;
1017 struct ospf6_route
*route
;
1018 struct ospf6_prefix
*op
;
1019 struct listnode
*i
, *j
;
1021 unsigned short prefix_num
= 0;
1022 struct ospf6_route_table
*route_advertise
;
1025 oa
= (struct ospf6_area
*)THREAD_ARG(thread
);
1027 if (oa
->ospf6
->gr_info
.restart_in_progress
) {
1028 if (IS_DEBUG_OSPF6_GR
)
1030 "Graceful Restart in progress, don't originate LSA");
1034 /* find previous LSA */
1035 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX
), htonl(0),
1036 oa
->ospf6
->router_id
, oa
->lsdb
);
1038 if (!IS_AREA_ENABLED(oa
)) {
1040 ospf6_lsa_purge(old
);
1041 /* find previous LSA */
1042 old_next
= ospf6_lsdb_lookup(
1043 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1044 htonl(++ls_id
), oa
->ospf6
->router_id
, oa
->lsdb
);
1047 ospf6_lsa_purge(old_next
);
1048 old_next
= ospf6_lsdb_lookup(
1049 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1050 htonl(++ls_id
), oa
->ospf6
->router_id
,
1057 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1059 "Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
1062 /* prepare buffer */
1063 memset(buffer
, 0, sizeof(buffer
));
1064 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1065 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
1066 *)((caddr_t
)lsa_header
1067 + sizeof(struct ospf6_lsa_header
));
1069 /* Fill Intra-Area-Prefix-LSA */
1070 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_ROUTER
);
1071 intra_prefix_lsa
->ref_id
= htonl(0);
1072 intra_prefix_lsa
->ref_adv_router
= oa
->ospf6
->router_id
;
1074 route_advertise
= ospf6_route_table_create(0, 0);
1076 for (ALL_LIST_ELEMENTS_RO(oa
->if_list
, i
, oi
)) {
1077 if (oi
->state
== OSPF6_INTERFACE_DOWN
) {
1078 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1079 zlog_debug(" Interface %s is down, ignore",
1080 oi
->interface
->name
);
1086 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
))
1087 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
1090 if (oi
->state
!= OSPF6_INTERFACE_LOOPBACK
1091 && oi
->state
!= OSPF6_INTERFACE_POINTTOPOINT
1092 && full_count
!= 0) {
1093 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1094 zlog_debug(" Interface %s is not stub, ignore",
1095 oi
->interface
->name
);
1099 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1100 zlog_debug(" Interface %s:", oi
->interface
->name
);
1102 /* connected prefix to advertise */
1103 for (route
= ospf6_route_head(oi
->route_connected
); route
;
1104 route
= ospf6_route_best_next(route
)) {
1105 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1106 zlog_debug(" include %pFX", &route
->prefix
);
1107 ospf6_route_add(ospf6_route_copy(route
),
1112 if (route_advertise
->count
== 0) {
1115 ospf6_lsa_purge(old
);
1116 /* find previous LSA */
1117 old_next
= ospf6_lsdb_lookup(
1118 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1119 htonl(++ls_id
), oa
->ospf6
->router_id
, oa
->lsdb
);
1122 ospf6_lsa_purge(old_next
);
1123 old_next
= ospf6_lsdb_lookup(
1124 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1125 htonl(++ls_id
), oa
->ospf6
->router_id
,
1129 ospf6_route_table_delete(route_advertise
);
1133 /* Neighbor change to FULL, if INTRA-AREA-PREFIX LSA
1134 * has not change, Flush old LSA and Re-Originate INP,
1135 * as ospf6_flood() checks if LSA is same as DB,
1136 * it won't be updated to neighbor's DB.
1138 if (oa
->intra_prefix_originate
) {
1139 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1141 "%s: Re-originate intra prefix LSA, Current full nbrs %u",
1142 __func__
, oa
->full_nbrs
);
1144 ospf6_lsa_purge_multi_ls_id(oa
, old
);
1145 oa
->intra_prefix_originate
= 0;
1148 /* put prefixes to advertise */
1150 op
= (struct ospf6_prefix
*)((caddr_t
)intra_prefix_lsa
1151 + sizeof(struct ospf6_intra_prefix_lsa
));
1152 for (route
= ospf6_route_head(route_advertise
); route
;
1153 route
= ospf6_route_best_next(route
)) {
1154 if (((caddr_t
)op
- (caddr_t
)lsa_header
) > MAX_LSA_PAYLOAD
) {
1156 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
1158 /* Fill LSA Header */
1159 lsa_header
->age
= 0;
1160 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1161 lsa_header
->id
= htonl(ls_id
++);
1162 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
1163 lsa_header
->seqnum
= ospf6_new_ls_seqnum(
1164 lsa_header
->type
, lsa_header
->id
,
1165 lsa_header
->adv_router
, oa
->lsdb
);
1166 lsa_header
->length
=
1167 htons((caddr_t
)op
- (caddr_t
)lsa_header
);
1170 ospf6_lsa_checksum(lsa_header
);
1173 lsa
= ospf6_lsa_create(lsa_header
);
1176 ospf6_lsa_originate_area(lsa
, oa
);
1178 /* Prepare next buffer */
1179 memset(buffer
, 0, sizeof(buffer
));
1180 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1182 (struct ospf6_intra_prefix_lsa
1183 *)((caddr_t
)lsa_header
1184 + sizeof(struct ospf6_lsa_header
));
1186 /* Fill Intra-Area-Prefix-LSA */
1187 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_ROUTER
);
1188 intra_prefix_lsa
->ref_id
= htonl(0);
1189 intra_prefix_lsa
->ref_adv_router
= oa
->ospf6
->router_id
;
1191 /* Put next set of prefixes to advertise */
1193 op
= (struct ospf6_prefix
1194 *)((caddr_t
)intra_prefix_lsa
1196 ospf6_intra_prefix_lsa
));
1199 op
->prefix_length
= route
->prefix
.prefixlen
;
1200 op
->prefix_options
= route
->prefix_options
;
1201 op
->prefix_metric
= htons(route
->path
.cost
);
1202 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
1203 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1206 op
= OSPF6_PREFIX_NEXT(op
);
1209 ospf6_route_table_delete(route_advertise
);
1211 if (prefix_num
== 0) {
1212 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1214 "Quit to Advertise Intra-Prefix: no route to advertise");
1218 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
1220 /* Fill LSA Header */
1221 lsa_header
->age
= 0;
1222 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1223 lsa_header
->id
= htonl(ls_id
++);
1224 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
1225 lsa_header
->seqnum
=
1226 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
1227 lsa_header
->adv_router
, oa
->lsdb
);
1228 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)lsa_header
);
1231 ospf6_lsa_checksum(lsa_header
);
1234 lsa
= ospf6_lsa_create(lsa_header
);
1237 ospf6_lsa_originate_area(lsa
, oa
);
1243 int ospf6_intra_prefix_lsa_originate_transit(struct thread
*thread
)
1245 struct ospf6_interface
*oi
;
1247 char buffer
[OSPF6_MAX_LSASIZE
];
1248 struct ospf6_lsa_header
*lsa_header
;
1249 struct ospf6_lsa
*old
, *lsa
;
1251 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1252 struct ospf6_neighbor
*on
;
1253 struct ospf6_route
*route
;
1254 struct ospf6_prefix
*op
;
1257 unsigned short prefix_num
= 0;
1258 struct ospf6_route_table
*route_advertise
;
1259 struct ospf6_link_lsa
*link_lsa
;
1260 char *start
, *end
, *current
;
1263 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
1267 if (oi
->area
->ospf6
->gr_info
.restart_in_progress
) {
1268 if (IS_DEBUG_OSPF6_GR
)
1270 "Graceful Restart in progress, don't originate LSA");
1274 /* find previous LSA */
1275 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1276 htonl(oi
->interface
->ifindex
),
1277 oi
->area
->ospf6
->router_id
, oi
->area
->lsdb
);
1279 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1281 ospf6_lsa_purge(old
);
1285 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1287 "Originate Intra-Area-Prefix-LSA for interface %s's prefix",
1288 oi
->interface
->name
);
1290 /* prepare buffer */
1291 memset(buffer
, 0, sizeof(buffer
));
1292 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1293 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
1294 *)((caddr_t
)lsa_header
1295 + sizeof(struct ospf6_lsa_header
));
1297 /* Fill Intra-Area-Prefix-LSA */
1298 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_NETWORK
);
1299 intra_prefix_lsa
->ref_id
= htonl(oi
->interface
->ifindex
);
1300 intra_prefix_lsa
->ref_adv_router
= oi
->area
->ospf6
->router_id
;
1302 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
1303 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1304 zlog_debug(" Interface is not DR");
1306 ospf6_lsa_purge(old
);
1311 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
))
1312 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
1315 if (full_count
== 0) {
1316 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1317 zlog_debug(" Interface is stub");
1319 ospf6_lsa_purge(old
);
1323 /* connected prefix to advertise */
1324 route_advertise
= ospf6_route_table_create(0, 0);
1326 type
= ntohs(OSPF6_LSTYPE_LINK
);
1327 for (ALL_LSDB_TYPED(oi
->lsdb
, type
, lsa
)) {
1328 if (OSPF6_LSA_IS_MAXAGE(lsa
))
1331 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1332 zlog_debug(" include prefix from %s", lsa
->name
);
1334 if (lsa
->header
->adv_router
!= oi
->area
->ospf6
->router_id
) {
1335 on
= ospf6_neighbor_lookup(lsa
->header
->adv_router
, oi
);
1336 if (on
== NULL
|| on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1337 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1339 " Neighbor not found or not Full, ignore");
1344 link_lsa
= (struct ospf6_link_lsa
1345 *)((caddr_t
)lsa
->header
1346 + sizeof(struct ospf6_lsa_header
));
1348 prefix_num
= (unsigned short)ntohl(link_lsa
->prefix_num
);
1349 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
1350 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
1351 for (current
= start
; current
< end
&& prefix_num
;
1352 current
+= OSPF6_PREFIX_SIZE(op
)) {
1353 op
= (struct ospf6_prefix
*)current
;
1354 if (op
->prefix_length
== 0
1355 || current
+ OSPF6_PREFIX_SIZE(op
) > end
)
1358 route
= ospf6_route_create(oi
->area
->ospf6
);
1360 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
1361 route
->prefix
.family
= AF_INET6
;
1362 route
->prefix
.prefixlen
= op
->prefix_length
;
1363 memset(&route
->prefix
.u
.prefix6
, 0,
1364 sizeof(struct in6_addr
));
1365 memcpy(&route
->prefix
.u
.prefix6
, OSPF6_PREFIX_BODY(op
),
1366 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1367 route
->prefix_options
= op
->prefix_options
;
1369 route
->path
.origin
.type
= lsa
->header
->type
;
1370 route
->path
.origin
.id
= lsa
->header
->id
;
1371 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1372 route
->path
.options
[0] = link_lsa
->options
[0];
1373 route
->path
.options
[1] = link_lsa
->options
[1];
1374 route
->path
.options
[2] = link_lsa
->options
[2];
1375 route
->path
.area_id
= oi
->area
->area_id
;
1376 route
->path
.type
= OSPF6_PATH_TYPE_INTRA
;
1378 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1379 zlog_debug(" include %pFX", &route
->prefix
);
1381 ospf6_route_add(route
, route_advertise
);
1384 if (current
!= end
&& IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1385 zlog_debug("Trailing garbage in %s", lsa
->name
);
1388 op
= (struct ospf6_prefix
*)((caddr_t
)intra_prefix_lsa
1389 + sizeof(struct ospf6_intra_prefix_lsa
));
1392 for (route
= ospf6_route_head(route_advertise
); route
;
1393 route
= ospf6_route_best_next(route
)) {
1394 op
->prefix_length
= route
->prefix
.prefixlen
;
1395 op
->prefix_options
= route
->prefix_options
;
1396 op
->prefix_metric
= htons(0);
1397 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
1398 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1399 op
= OSPF6_PREFIX_NEXT(op
);
1403 ospf6_route_table_delete(route_advertise
);
1405 if (prefix_num
== 0) {
1406 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1408 "Quit to Advertise Intra-Prefix: no route to advertise");
1412 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
1414 /* Fill LSA Header */
1415 lsa_header
->age
= 0;
1416 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1417 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
1418 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
1419 lsa_header
->seqnum
=
1420 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
1421 lsa_header
->adv_router
, oi
->area
->lsdb
);
1422 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)lsa_header
);
1425 ospf6_lsa_checksum(lsa_header
);
1428 lsa
= ospf6_lsa_create(lsa_header
);
1431 ospf6_lsa_originate_area(lsa
, oi
->area
);
1436 static void ospf6_intra_prefix_update_route_origin(struct ospf6_route
*oa_route
,
1437 struct ospf6
*ospf6
)
1439 struct ospf6_path
*h_path
;
1440 struct ospf6_route
*g_route
, *nroute
;
1442 /* Update Global ospf6 route path */
1443 g_route
= ospf6_route_lookup(&oa_route
->prefix
, ospf6
->route_table
);
1447 for (ospf6_route_lock(g_route
); g_route
&&
1448 ospf6_route_is_prefix(&oa_route
->prefix
, g_route
);
1450 nroute
= ospf6_route_next(g_route
);
1451 if (g_route
->type
!= oa_route
->type
)
1453 if (g_route
->path
.area_id
!= oa_route
->path
.area_id
)
1455 if (g_route
->path
.type
!= OSPF6_PATH_TYPE_INTRA
)
1457 if (g_route
->path
.cost
!= oa_route
->path
.cost
)
1460 if (ospf6_route_is_same_origin(g_route
, oa_route
)) {
1461 h_path
= (struct ospf6_path
*)listgetdata(
1462 listhead(g_route
->paths
));
1463 g_route
->path
.origin
.type
= h_path
->origin
.type
;
1464 g_route
->path
.origin
.id
= h_path
->origin
.id
;
1465 g_route
->path
.origin
.adv_router
=
1466 h_path
->origin
.adv_router
;
1468 ospf6_route_unlock(nroute
);
1473 h_path
= (struct ospf6_path
*)listgetdata(
1474 listhead(oa_route
->paths
));
1475 oa_route
->path
.origin
.type
= h_path
->origin
.type
;
1476 oa_route
->path
.origin
.id
= h_path
->origin
.id
;
1477 oa_route
->path
.origin
.adv_router
= h_path
->origin
.adv_router
;
1480 void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area
*oa
,
1481 struct ospf6_route
*old
,
1482 struct ospf6_route
*route
)
1484 struct ospf6_route
*old_route
, *ls_entry
;
1485 struct ospf6_path
*ecmp_path
, *o_path
= NULL
;
1486 struct listnode
*anode
, *anext
;
1487 struct listnode
*nnode
, *rnode
, *rnext
;
1488 struct ospf6_nexthop
*nh
, *rnh
;
1489 bool route_found
= false;
1490 struct interface
*ifp
= NULL
;
1491 struct ospf6_lsa
*lsa
;
1492 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1494 /* check for old entry match with new route origin,
1497 for (old_route
= old
; old_route
; old_route
= old_route
->next
) {
1498 bool route_updated
= false;
1500 /* The route linked-list is grouped in batches of prefix.
1501 * If the new prefix is not the same as the one of interest
1502 * then we have walked over the end of the batch and so we
1503 * should break rather than continuing unnecessarily.
1505 if (!ospf6_route_is_same(old_route
, route
))
1507 if (old_route
->path
.type
!= route
->path
.type
)
1510 /* Current and New route has same origin,
1513 for (ALL_LIST_ELEMENTS(old_route
->paths
, anode
, anext
,
1515 /* Check old route path and route has same
1518 if (o_path
->area_id
!= route
->path
.area_id
1519 || !ospf6_ls_origin_same(o_path
, &route
->path
))
1522 /* Cost is not same then delete current path */
1523 if (o_path
->cost
== route
->path
.cost
)
1526 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1528 "%s: route %pFX cost old %u new %u is not same, replace route",
1529 __func__
, &old_route
->prefix
, o_path
->cost
,
1533 /* Remove selected current path's nh from
1534 * effective nh list.
1536 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
, nnode
, nh
)) {
1537 for (ALL_LIST_ELEMENTS(old_route
->nh_list
,
1538 rnode
, rnext
, rnh
)) {
1539 if (!ospf6_nexthop_is_same(rnh
, nh
))
1541 listnode_delete(old_route
->nh_list
,
1543 ospf6_nexthop_delete(rnh
);
1544 route_updated
= true;
1548 listnode_delete(old_route
->paths
, o_path
);
1549 ospf6_path_free(o_path
);
1551 /* Current route's path (adv_router info) is similar
1552 * to route being added.
1553 * Replace current route's path with paths list head.
1554 * Update FIB with effective NHs.
1556 if (listcount(old_route
->paths
)) {
1557 if (route_updated
) {
1558 for (ALL_LIST_ELEMENTS(old_route
->paths
,
1559 anode
, anext
, o_path
)) {
1560 ospf6_merge_nexthops(
1564 /* Update ospf6 route table and
1565 * RIB/FIB with effective
1568 if (oa
->route_table
->hook_add
)
1569 (*oa
->route_table
->hook_add
)(
1572 if (old_route
->path
.origin
.id
==
1573 route
->path
.origin
.id
&&
1574 old_route
->path
.origin
.adv_router
==
1575 route
->path
.origin
.adv_router
) {
1576 ospf6_intra_prefix_update_route_origin(
1577 old_route
, oa
->ospf6
);
1582 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1584 "%s: route %pFX old cost %u new cost %u, delete old entry.",
1585 __func__
, &old_route
->prefix
,
1586 old_route
->path
.cost
,
1589 if (oa
->route_table
->hook_remove
)
1590 ospf6_route_remove(old_route
,
1593 SET_FLAG(old_route
->flag
,
1594 OSPF6_ROUTE_REMOVE
);
1602 for (old_route
= old
; old_route
; old_route
= old_route
->next
) {
1604 /* The route linked-list is grouped in batches of prefix.
1605 * If the new prefix is not the same as the one of interest
1606 * then we have walked over the end of the batch and so we
1607 * should break rather than continuing unnecessarily.
1609 if (!ospf6_route_is_same(old_route
, route
))
1611 if (old_route
->path
.type
!= route
->path
.type
)
1614 /* Old Route and New Route have Equal Cost, Merge NHs */
1615 if (old_route
->path
.cost
== route
->path
.cost
) {
1618 /* check if this path exists already in
1619 * route->paths list, if so, replace nh_list.
1621 for (ALL_LIST_ELEMENTS_RO(old_route
->paths
, anode
,
1623 if (o_path
->area_id
== route
->path
.area_id
1624 && ospf6_ls_origin_same(o_path
, &route
->path
))
1627 /* If path is not found in old_route paths's list,
1628 * add a new path to route paths list and merge
1629 * nexthops in route->path->nh_list.
1630 * Otherwise replace existing path's nh_list.
1632 if (o_path
== NULL
) {
1633 ecmp_path
= ospf6_path_dup(&route
->path
);
1635 /* Add a nh_list to new ecmp path */
1636 ospf6_copy_nexthops(ecmp_path
->nh_list
,
1638 /* Add the new path to route's path list */
1639 listnode_add_sort(old_route
->paths
, ecmp_path
);
1641 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1643 "%s: route %pFX %p another path added with nh %u, effective paths %u nh %u",
1644 __func__
, &route
->prefix
,
1646 listcount(ecmp_path
->nh_list
),
1647 old_route
->paths
? listcount(
1650 listcount(old_route
->nh_list
));
1653 list_delete_all_node(o_path
->nh_list
);
1654 ospf6_copy_nexthops(o_path
->nh_list
,
1659 list_delete_all_node(old_route
->nh_list
);
1661 for (ALL_LIST_ELEMENTS_RO(old_route
->paths
, anode
,
1663 ls_entry
= ospf6_route_lookup(
1666 if (ls_entry
== NULL
) {
1667 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1669 "%s: ls_prfix %pFX ls_entry not found.",
1671 &o_path
->ls_prefix
);
1674 lsa
= ospf6_lsdb_lookup(o_path
->origin
.type
,
1676 o_path
->origin
.adv_router
,
1679 if (IS_OSPF6_DEBUG_EXAMIN(
1681 struct prefix adv_prefix
;
1683 ospf6_linkstate_prefix(
1684 o_path
->origin
.adv_router
,
1685 o_path
->origin
.id
, &adv_prefix
);
1687 "%s: adv_router %pFX lsa not found",
1688 __func__
, &adv_prefix
);
1693 (struct ospf6_intra_prefix_lsa
*)
1694 OSPF6_LSA_HEADER_END(lsa
->header
);
1696 if (intra_prefix_lsa
->ref_adv_router
1697 == oa
->ospf6
->router_id
) {
1698 ifp
= if_lookup_prefix(
1704 /* Nexthop interface found */
1705 ospf6_route_add_nexthop(old_route
,
1709 /* The connected interfaces between
1710 * routers can be in different networks.
1711 * In this case the matching interface
1712 * is not found. Copy nexthops from the
1715 ospf6_route_merge_nexthops(old_route
,
1720 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1722 "%s: route %pFX %p with final effective paths %u nh %u",
1723 __func__
, &route
->prefix
,
1726 ? listcount(old_route
->paths
)
1728 listcount(old_route
->nh_list
));
1730 /* used in intra_route_calculation() to add to
1731 * global ospf6 route table.
1733 UNSET_FLAG(old_route
->flag
, OSPF6_ROUTE_REMOVE
);
1734 SET_FLAG(old_route
->flag
, OSPF6_ROUTE_ADD
);
1735 /* Update ospf6 route table and RIB/FIB */
1736 if (oa
->route_table
->hook_add
)
1737 (*oa
->route_table
->hook_add
)(old_route
);
1738 /* Delete the new route its info added to existing
1741 ospf6_route_delete(route
);
1748 /* Add new route to existing node in ospf6 route table. */
1749 ospf6_route_add(route
, oa
->route_table
);
1753 void ospf6_intra_prefix_lsa_add(struct ospf6_lsa
*lsa
)
1755 struct ospf6_area
*oa
;
1756 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1757 struct prefix ls_prefix
;
1758 struct ospf6_route
*route
, *ls_entry
, *old
;
1760 struct ospf6_prefix
*op
;
1761 char *start
, *current
, *end
;
1762 char buf
[PREFIX2STR_BUFFER
];
1763 struct interface
*ifp
= NULL
;
1764 int direct_connect
= 0;
1765 struct ospf6_path
*path
;
1767 if (OSPF6_LSA_IS_MAXAGE(lsa
))
1770 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1771 zlog_debug("%s: LSA %s found", __func__
, lsa
->name
);
1773 oa
= OSPF6_AREA(lsa
->lsdb
->data
);
1776 (struct ospf6_intra_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1778 if (intra_prefix_lsa
->ref_type
== htons(OSPF6_LSTYPE_ROUTER
))
1779 ospf6_linkstate_prefix(intra_prefix_lsa
->ref_adv_router
,
1780 intra_prefix_lsa
->ref_id
, &ls_prefix
);
1781 else if (intra_prefix_lsa
->ref_type
== htons(OSPF6_LSTYPE_NETWORK
))
1782 ospf6_linkstate_prefix(intra_prefix_lsa
->ref_adv_router
,
1783 intra_prefix_lsa
->ref_id
, &ls_prefix
);
1785 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1786 zlog_debug("Unknown reference LS-type: %#hx",
1787 ntohs(intra_prefix_lsa
->ref_type
));
1791 ls_entry
= ospf6_route_lookup(&ls_prefix
, oa
->spf_table
);
1792 if (ls_entry
== NULL
) {
1793 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1794 ospf6_linkstate_prefix2str(&ls_prefix
, buf
,
1796 zlog_debug("LS entry does not exist: %s", buf
);
1801 if (intra_prefix_lsa
->ref_adv_router
== oa
->ospf6
->router_id
) {
1802 /* the intra-prefix are directly connected */
1806 prefix_num
= ntohs(intra_prefix_lsa
->prefix_num
);
1807 start
= (caddr_t
)intra_prefix_lsa
1808 + sizeof(struct ospf6_intra_prefix_lsa
);
1809 end
= OSPF6_LSA_END(lsa
->header
);
1810 for (current
= start
; current
< end
; current
+= OSPF6_PREFIX_SIZE(op
)) {
1811 op
= (struct ospf6_prefix
*)current
;
1812 if (prefix_num
== 0)
1814 if (end
< current
+ OSPF6_PREFIX_SIZE(op
))
1817 /* Appendix A.4.1.1 */
1818 if (CHECK_FLAG(op
->prefix_options
, OSPF6_PREFIX_OPTION_NU
)) {
1819 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1820 ospf6_linkstate_prefix2str(
1821 (struct prefix
*)OSPF6_PREFIX_BODY(op
),
1824 "%s: Skipping Prefix %s has NU option set",
1830 route
= ospf6_route_create(oa
->ospf6
);
1832 memset(&route
->prefix
, 0, sizeof(struct prefix
));
1833 route
->prefix
.family
= AF_INET6
;
1834 route
->prefix
.prefixlen
= op
->prefix_length
;
1835 ospf6_prefix_in6_addr(&route
->prefix
.u
.prefix6
,
1836 intra_prefix_lsa
, op
);
1837 route
->prefix_options
= op
->prefix_options
;
1839 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
1840 route
->path
.origin
.type
= lsa
->header
->type
;
1841 route
->path
.origin
.id
= lsa
->header
->id
;
1842 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1843 route
->path
.area_id
= oa
->area_id
;
1844 route
->path
.type
= OSPF6_PATH_TYPE_INTRA
;
1845 route
->path
.metric_type
= 1;
1847 ls_entry
->path
.cost
+ ntohs(op
->prefix_metric
);
1848 memcpy(&route
->path
.ls_prefix
, &ls_prefix
,
1849 sizeof(struct prefix
));
1850 if (direct_connect
) {
1851 ifp
= if_lookup_prefix(&route
->prefix
,
1856 /* Nexthop interface found */
1857 ospf6_route_add_nexthop(route
, ifp
->ifindex
, NULL
);
1859 /* The connected interfaces between routers can be in
1860 * different networks. In this case the matching
1861 * interface is not found. Copy nexthops from the
1864 ospf6_route_copy_nexthops(route
, ls_entry
);
1867 path
= ospf6_path_dup(&route
->path
);
1868 ospf6_copy_nexthops(path
->nh_list
, route
->path
.nh_list
);
1869 listnode_add_sort(route
->paths
, path
);
1871 old
= ospf6_route_lookup(&route
->prefix
, oa
->route_table
);
1873 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1874 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1876 "%s Update route: %s old cost %u new cost %u paths %u nh %u",
1877 __func__
, buf
, old
->path
.cost
,
1879 listcount(route
->paths
),
1880 listcount(route
->nh_list
));
1882 ospf6_intra_prefix_route_ecmp_path(oa
, old
, route
);
1884 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1885 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1887 "%s route %s add with cost %u paths %u nh %u",
1888 __func__
, buf
, route
->path
.cost
,
1889 listcount(route
->paths
),
1890 listcount(route
->nh_list
));
1892 ospf6_route_add(route
, oa
->route_table
);
1897 if (current
!= end
&& IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1898 zlog_debug("Trailing garbage ignored");
1901 static void ospf6_intra_prefix_lsa_remove_update_route(struct ospf6_lsa
*lsa
,
1902 struct ospf6_area
*oa
,
1903 struct ospf6_route
*route
)
1905 struct listnode
*anode
, *anext
;
1906 struct listnode
*nnode
, *rnode
, *rnext
;
1907 struct ospf6_nexthop
*nh
, *rnh
;
1908 struct ospf6_path
*o_path
;
1909 bool nh_updated
= false;
1910 char buf
[PREFIX2STR_BUFFER
];
1912 /* Iterate all paths of route to find maching
1913 * with LSA remove info.
1914 * If route->path is same, replace
1917 for (ALL_LIST_ELEMENTS(route
->paths
, anode
, anext
, o_path
)) {
1918 if ((o_path
->origin
.type
!= lsa
->header
->type
) ||
1919 (o_path
->origin
.adv_router
!= lsa
->header
->adv_router
) ||
1920 (o_path
->origin
.id
!= lsa
->header
->id
))
1923 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1924 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1926 "%s: route %s path found with cost %u nh %u to remove.",
1927 __func__
, buf
, o_path
->cost
,
1928 listcount(o_path
->nh_list
));
1931 /* Remove found path's nh_list from
1932 * the route's nh_list.
1934 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
, nnode
, nh
)) {
1935 for (ALL_LIST_ELEMENTS(route
->nh_list
, rnode
,
1937 if (!ospf6_nexthop_is_same(rnh
, nh
))
1939 listnode_delete(route
->nh_list
, rnh
);
1940 ospf6_nexthop_delete(rnh
);
1943 /* Delete the path from route's
1946 listnode_delete(route
->paths
, o_path
);
1947 ospf6_path_free(o_path
);
1953 /* Iterate all paths and merge nexthop,
1954 * unlesss any of the nexthop similar to
1955 * ones deleted as part of path deletion.
1957 for (ALL_LIST_ELEMENTS(route
->paths
, anode
, anext
, o_path
))
1958 ospf6_merge_nexthops(route
->nh_list
, o_path
->nh_list
);
1961 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1962 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1964 "%s: route %s update paths %u nh %u", __func__
,
1965 buf
, route
->paths
? listcount(route
->paths
) : 0,
1966 route
->nh_list
? listcount(route
->nh_list
) : 0);
1969 /* Update Global Route table and
1970 * RIB/FIB with effective
1973 if (oa
->route_table
->hook_add
)
1974 (*oa
->route_table
->hook_add
)(route
);
1976 /* route's primary path is similar
1977 * to LSA, replace route's primary
1978 * path with route's paths list
1981 if ((route
->path
.origin
.id
== lsa
->header
->id
) &&
1982 (route
->path
.origin
.adv_router
==
1983 lsa
->header
->adv_router
)) {
1984 ospf6_intra_prefix_update_route_origin(route
,
1991 void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa
*lsa
)
1993 struct ospf6_area
*oa
;
1994 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1995 struct prefix prefix
;
1996 struct ospf6_route
*route
, *nroute
;
1998 struct ospf6_prefix
*op
;
1999 char *start
, *current
, *end
;
2000 char buf
[PREFIX2STR_BUFFER
];
2002 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
2003 zlog_debug("%s: %s disappearing", __func__
, lsa
->name
);
2005 oa
= OSPF6_AREA(lsa
->lsdb
->data
);
2008 (struct ospf6_intra_prefix_lsa
*)OSPF6_LSA_HEADER_END(
2011 prefix_num
= ntohs(intra_prefix_lsa
->prefix_num
);
2012 start
= (caddr_t
)intra_prefix_lsa
2013 + sizeof(struct ospf6_intra_prefix_lsa
);
2014 end
= OSPF6_LSA_END(lsa
->header
);
2015 for (current
= start
; current
< end
; current
+= OSPF6_PREFIX_SIZE(op
)) {
2016 op
= (struct ospf6_prefix
*)current
;
2017 if (prefix_num
== 0)
2019 if (end
< current
+ OSPF6_PREFIX_SIZE(op
))
2023 memset(&prefix
, 0, sizeof(struct prefix
));
2024 prefix
.family
= AF_INET6
;
2025 prefix
.prefixlen
= op
->prefix_length
;
2026 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, intra_prefix_lsa
, op
);
2028 route
= ospf6_route_lookup(&prefix
, oa
->route_table
);
2032 for (ospf6_route_lock(route
);
2033 route
&& ospf6_route_is_prefix(&prefix
, route
);
2035 nroute
= ospf6_route_next(route
);
2036 if (route
->type
!= OSPF6_DEST_TYPE_NETWORK
)
2038 if (route
->path
.area_id
!= oa
->area_id
)
2040 if (route
->path
.type
!= OSPF6_PATH_TYPE_INTRA
)
2042 /* Route has multiple ECMP paths, remove matching
2043 * path. Update current route's effective nh list
2044 * after removal of one of the path.
2046 if (listcount(route
->paths
) > 1) {
2047 ospf6_intra_prefix_lsa_remove_update_route(
2051 if (route
->path
.origin
.type
!= lsa
->header
->type
2052 || route
->path
.origin
.id
!= lsa
->header
->id
2053 || route
->path
.origin
.adv_router
2054 != lsa
->header
->adv_router
)
2057 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
2058 prefix2str(&route
->prefix
, buf
,
2061 "%s: route remove %s with path type %u cost %u paths %u nh %u",
2062 __func__
, buf
, route
->path
.type
,
2064 listcount(route
->paths
),
2065 listcount(route
->nh_list
));
2067 ospf6_route_remove(route
, oa
->route_table
);
2071 ospf6_route_unlock(route
);
2074 if (current
!= end
&& IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
2075 zlog_debug("Trailing garbage ignored");
2078 void ospf6_intra_route_calculation(struct ospf6_area
*oa
)
2080 struct ospf6_route
*route
, *nroute
;
2082 struct ospf6_lsa
*lsa
;
2083 void (*hook_add
)(struct ospf6_route
*) = NULL
;
2084 void (*hook_remove
)(struct ospf6_route
*) = NULL
;
2085 char buf
[PREFIX2STR_BUFFER
];
2087 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
2088 zlog_debug("Re-examin intra-routes for area %s", oa
->name
);
2090 hook_add
= oa
->route_table
->hook_add
;
2091 hook_remove
= oa
->route_table
->hook_remove
;
2092 oa
->route_table
->hook_add
= NULL
;
2093 oa
->route_table
->hook_remove
= NULL
;
2095 for (route
= ospf6_route_head(oa
->route_table
); route
;
2096 route
= ospf6_route_next(route
))
2097 route
->flag
= OSPF6_ROUTE_REMOVE
;
2099 type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
2100 for (ALL_LSDB_TYPED(oa
->lsdb
, type
, lsa
))
2101 ospf6_intra_prefix_lsa_add(lsa
);
2103 oa
->route_table
->hook_add
= hook_add
;
2104 oa
->route_table
->hook_remove
= hook_remove
;
2106 for (route
= ospf6_route_head(oa
->route_table
); route
; route
= nroute
) {
2107 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
2108 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
2109 zlog_debug("%s: route %s, flag 0x%x", __func__
, buf
,
2113 nroute
= ospf6_route_next(route
);
2114 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
)
2115 && CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ADD
)) {
2116 UNSET_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
);
2117 UNSET_FLAG(route
->flag
, OSPF6_ROUTE_ADD
);
2120 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
))
2121 ospf6_route_remove(route
, oa
->route_table
);
2122 else if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ADD
)
2123 || CHECK_FLAG(route
->flag
, OSPF6_ROUTE_CHANGE
)) {
2128 /* Redo the summaries as things might have changed */
2129 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
2130 zlog_debug("%s: Originate summary for route %s",
2132 ospf6_abr_originate_summary(route
, oa
->ospf6
);
2137 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
2138 zlog_debug("Re-examin intra-routes for area %s: Done",
2142 static void ospf6_brouter_debug_print(struct ospf6_route
*brouter
)
2144 uint32_t brouter_id
;
2145 char brouter_name
[16];
2147 char destination
[64];
2148 char installed
[64], changed
[64];
2149 struct timeval now
, res
;
2150 char id
[16], adv_router
[16];
2151 char capa
[16], options
[16];
2153 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2154 inet_ntop(AF_INET
, &brouter_id
, brouter_name
, sizeof(brouter_name
));
2155 inet_ntop(AF_INET
, &brouter
->path
.area_id
, area_name
,
2157 ospf6_linkstate_prefix2str(&brouter
->prefix
, destination
,
2158 sizeof(destination
));
2161 timersub(&now
, &brouter
->installed
, &res
);
2162 timerstring(&res
, installed
, sizeof(installed
));
2165 timersub(&now
, &brouter
->changed
, &res
);
2166 timerstring(&res
, changed
, sizeof(changed
));
2168 inet_ntop(AF_INET
, &brouter
->path
.origin
.id
, id
, sizeof(id
));
2169 inet_ntop(AF_INET
, &brouter
->path
.origin
.adv_router
, adv_router
,
2170 sizeof(adv_router
));
2172 ospf6_options_printbuf(brouter
->path
.options
, options
, sizeof(options
));
2173 ospf6_capability_printbuf(brouter
->path
.router_bits
, capa
,
2176 zlog_info("Brouter: %s via area %s", brouter_name
, area_name
);
2177 zlog_info(" memory: prev: %p this: %p next: %p parent rnode: %p",
2178 (void *)brouter
->prev
, (void *)brouter
, (void *)brouter
->next
,
2179 (void *)brouter
->rnode
);
2180 zlog_info(" type: %d prefix: %s installed: %s changed: %s",
2181 brouter
->type
, destination
, installed
, changed
);
2182 zlog_info(" lock: %d flags: %s%s%s%s", brouter
->lock
,
2183 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_BEST
) ? "B" : "-"),
2184 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
) ? "A" : "-"),
2185 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
) ? "R" : "-"),
2186 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
) ? "C" : "-"));
2187 zlog_info(" path type: %s ls-origin %s id: %s adv-router %s",
2188 OSPF6_PATH_TYPE_NAME(brouter
->path
.type
),
2189 ospf6_lstype_name(brouter
->path
.origin
.type
), id
, adv_router
);
2190 zlog_info(" options: %s router-bits: %s metric-type: %d metric: %d/%d",
2191 options
, capa
, brouter
->path
.metric_type
, brouter
->path
.cost
,
2192 brouter
->path
.u
.cost_e2
);
2193 zlog_info(" paths %u nh %u", listcount(brouter
->paths
),
2194 listcount(brouter
->nh_list
));
2197 void ospf6_intra_brouter_calculation(struct ospf6_area
*oa
)
2199 struct ospf6_route
*brouter
, *nbrouter
, *copy
;
2200 void (*hook_add
)(struct ospf6_route
*) = NULL
;
2201 void (*hook_remove
)(struct ospf6_route
*) = NULL
;
2202 uint32_t brouter_id
;
2203 char brouter_name
[16];
2205 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa
->area_id
) ||
2206 IS_OSPF6_DEBUG_ROUTE(MEMORY
))
2207 zlog_debug("%s: border-router calculation for area %s",
2208 __func__
, oa
->name
);
2210 hook_add
= oa
->ospf6
->brouter_table
->hook_add
;
2211 hook_remove
= oa
->ospf6
->brouter_table
->hook_remove
;
2212 oa
->ospf6
->brouter_table
->hook_add
= NULL
;
2213 oa
->ospf6
->brouter_table
->hook_remove
= NULL
;
2215 /* withdraw the previous router entries for the area */
2216 for (brouter
= ospf6_route_head(oa
->ospf6
->brouter_table
); brouter
;
2217 brouter
= ospf6_route_next(brouter
)) {
2218 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2219 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
2220 sizeof(brouter_name
));
2222 if (brouter
->path
.area_id
!= oa
->area_id
)
2225 SET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
2227 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id
)
2228 || IS_OSPF6_DEBUG_ROUTE(MEMORY
)) {
2229 zlog_debug("%p: mark as removing: area %s brouter %s",
2230 (void *)brouter
, oa
->name
, brouter_name
);
2231 ospf6_brouter_debug_print(brouter
);
2235 for (brouter
= ospf6_route_head(oa
->spf_table
); brouter
;
2236 brouter
= ospf6_route_next(brouter
)) {
2237 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2238 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
2239 sizeof(brouter_name
));
2241 if (brouter
->type
!= OSPF6_DEST_TYPE_LINKSTATE
)
2244 if (ospf6_linkstate_prefix_id(&brouter
->prefix
) != htonl(0))
2247 if (!CHECK_FLAG(brouter
->path
.router_bits
, OSPF6_ROUTER_BIT_E
)
2248 && !CHECK_FLAG(brouter
->path
.router_bits
,
2249 OSPF6_ROUTER_BIT_B
))
2252 if (!OSPF6_OPT_ISSET(brouter
->path
.options
, OSPF6_OPT_V6
)
2253 || !OSPF6_OPT_ISSET(brouter
->path
.options
, OSPF6_OPT_R
))
2256 copy
= ospf6_route_copy(brouter
);
2257 copy
->type
= OSPF6_DEST_TYPE_ROUTER
;
2258 copy
->path
.area_id
= oa
->area_id
;
2259 ospf6_route_add(copy
, oa
->ospf6
->brouter_table
);
2261 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id
)
2262 || IS_OSPF6_DEBUG_ROUTE(MEMORY
)) {
2263 zlog_debug("%p: transfer: area %s brouter %s",
2264 (void *)brouter
, oa
->name
, brouter_name
);
2265 ospf6_brouter_debug_print(brouter
);
2269 oa
->ospf6
->brouter_table
->hook_add
= hook_add
;
2270 oa
->ospf6
->brouter_table
->hook_remove
= hook_remove
;
2272 for (brouter
= ospf6_route_head(oa
->ospf6
->brouter_table
); brouter
;
2273 brouter
= nbrouter
) {
2276 * brouter may have been "deleted" in the last loop iteration.
2277 * If this is the case there is still 1 final refcount lock
2278 * taken by ospf6_route_next, that will be released by the same
2279 * call and result in deletion. To avoid heap UAF we must then
2280 * skip processing the deleted route.
2282 if (brouter
->lock
== 1) {
2283 if (IS_OSPF6_DEBUG_ROUTE(MEMORY
))
2284 ospf6_brouter_debug_print(brouter
);
2285 nbrouter
= ospf6_route_next(brouter
);
2288 nbrouter
= ospf6_route_next(brouter
);
2291 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2292 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
2293 sizeof(brouter_name
));
2295 if (brouter
->path
.area_id
!= oa
->area_id
)
2298 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_WAS_REMOVED
))
2301 /* After iterating spf_table for all routers including
2302 * intra brouter, clear mark for remove flag for
2303 * inter border router if its adv router present in
2306 if (brouter
->path
.type
== OSPF6_PATH_TYPE_INTER
) {
2307 struct prefix adv_prefix
;
2309 ospf6_linkstate_prefix(brouter
->path
.origin
.adv_router
,
2310 htonl(0), &adv_prefix
);
2312 if (ospf6_route_lookup(&adv_prefix
, oa
->spf_table
)) {
2313 if (IS_OSPF6_DEBUG_BROUTER
) {
2315 "%s: keep inter brouter %s as adv router 0x%x found in spf",
2316 __func__
, brouter_name
,
2317 brouter
->path
.origin
2319 ospf6_brouter_debug_print(brouter
);
2321 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
2325 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
)
2326 && CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
)) {
2327 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
2328 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
);
2331 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
)) {
2332 if (IS_OSPF6_DEBUG_BROUTER
2333 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2335 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2338 "%s: brouter %s disappears via area %s",
2339 __func__
, brouter_name
, oa
->name
);
2340 /* This is used to protect nbrouter from removed from
2341 * the table. For an example, ospf6_abr_examin_summary,
2342 * removes brouters which are marked for remove.
2344 oa
->intra_brouter_calc
= true;
2345 ospf6_route_remove(brouter
, oa
->ospf6
->brouter_table
);
2347 } else if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
)
2348 || CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
)) {
2349 if (IS_OSPF6_DEBUG_BROUTER
2350 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2352 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2354 zlog_info("%s: brouter %s appears via area %s",
2355 __func__
, brouter_name
, oa
->name
);
2359 (*hook_add
)(brouter
);
2361 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2363 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2366 "brouter %s still exists via area %s",
2367 brouter_name
, oa
->name
);
2368 /* But re-originate summaries */
2369 ospf6_abr_originate_summary(brouter
, oa
->ospf6
);
2373 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
);
2374 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
);
2376 /* Reset for nbrouter */
2377 oa
->intra_brouter_calc
= false;
2380 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa
->area_id
) ||
2381 IS_OSPF6_DEBUG_ROUTE(MEMORY
))
2382 zlog_debug("%s: border-router calculation for area %s: done",
2383 __func__
, oa
->name
);
2386 static struct ospf6_lsa_handler router_handler
= {
2387 .lh_type
= OSPF6_LSTYPE_ROUTER
,
2388 .lh_name
= "Router",
2389 .lh_short_name
= "Rtr",
2390 .lh_show
= ospf6_router_lsa_show
,
2391 .lh_get_prefix_str
= ospf6_router_lsa_get_nbr_id
,
2394 static struct ospf6_lsa_handler network_handler
= {
2395 .lh_type
= OSPF6_LSTYPE_NETWORK
,
2396 .lh_name
= "Network",
2397 .lh_short_name
= "Net",
2398 .lh_show
= ospf6_network_lsa_show
,
2399 .lh_get_prefix_str
= ospf6_network_lsa_get_ar_id
,
2402 static struct ospf6_lsa_handler link_handler
= {
2403 .lh_type
= OSPF6_LSTYPE_LINK
,
2405 .lh_short_name
= "Lnk",
2406 .lh_show
= ospf6_link_lsa_show
,
2407 .lh_get_prefix_str
= ospf6_link_lsa_get_prefix_str
,
2410 static struct ospf6_lsa_handler intra_prefix_handler
= {
2411 .lh_type
= OSPF6_LSTYPE_INTRA_PREFIX
,
2412 .lh_name
= "Intra-Prefix",
2413 .lh_short_name
= "INP",
2414 .lh_show
= ospf6_intra_prefix_lsa_show
,
2415 .lh_get_prefix_str
= ospf6_intra_prefix_lsa_get_prefix_str
,
2418 void ospf6_intra_init(void)
2420 ospf6_install_lsa_handler(&router_handler
);
2421 ospf6_install_lsa_handler(&network_handler
);
2422 ospf6_install_lsa_handler(&link_handler
);
2423 ospf6_install_lsa_handler(&intra_prefix_handler
);
2426 DEFUN (debug_ospf6_brouter
,
2427 debug_ospf6_brouter_cmd
,
2428 "debug ospf6 border-routers",
2431 "Debug border router\n"
2434 OSPF6_DEBUG_BROUTER_ON();
2438 DEFUN (no_debug_ospf6_brouter
,
2439 no_debug_ospf6_brouter_cmd
,
2440 "no debug ospf6 border-routers",
2444 "Debug border router\n"
2447 OSPF6_DEBUG_BROUTER_OFF();
2451 DEFUN (debug_ospf6_brouter_router
,
2452 debug_ospf6_brouter_router_cmd
,
2453 "debug ospf6 border-routers router-id A.B.C.D",
2456 "Debug border router\n"
2457 "Debug specific border router\n"
2458 "Specify border-router's router-id\n"
2463 inet_pton(AF_INET
, argv
[idx_ipv4
]->arg
, &router_id
);
2464 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON(router_id
);
2468 DEFUN (no_debug_ospf6_brouter_router
,
2469 no_debug_ospf6_brouter_router_cmd
,
2470 "no debug ospf6 border-routers router-id [A.B.C.D]",
2474 "Debug border router\n"
2475 "Debug specific border router\n"
2476 "Specify border-router's router-id\n"
2479 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF();
2483 DEFUN (debug_ospf6_brouter_area
,
2484 debug_ospf6_brouter_area_cmd
,
2485 "debug ospf6 border-routers area-id A.B.C.D",
2488 "Debug border router\n"
2489 "Debug border routers in specific Area\n"
2495 inet_pton(AF_INET
, argv
[idx_ipv4
]->arg
, &area_id
);
2496 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON(area_id
);
2500 DEFUN (no_debug_ospf6_brouter_area
,
2501 no_debug_ospf6_brouter_area_cmd
,
2502 "no debug ospf6 border-routers area-id [A.B.C.D]",
2506 "Debug border router\n"
2507 "Debug border routers in specific Area\n"
2511 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF();
2515 int config_write_ospf6_debug_brouter(struct vty
*vty
)
2518 if (IS_OSPF6_DEBUG_BROUTER
)
2519 vty_out(vty
, "debug ospf6 border-routers\n");
2520 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER
) {
2521 inet_ntop(AF_INET
, &conf_debug_ospf6_brouter_specific_router_id
,
2523 vty_out(vty
, "debug ospf6 border-routers router-id %s\n", buf
);
2525 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA
) {
2526 inet_ntop(AF_INET
, &conf_debug_ospf6_brouter_specific_area_id
,
2528 vty_out(vty
, "debug ospf6 border-routers area-id %s\n", buf
);
2533 void install_element_ospf6_debug_brouter(void)
2535 install_element(ENABLE_NODE
, &debug_ospf6_brouter_cmd
);
2536 install_element(ENABLE_NODE
, &debug_ospf6_brouter_router_cmd
);
2537 install_element(ENABLE_NODE
, &debug_ospf6_brouter_area_cmd
);
2538 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_cmd
);
2539 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_router_cmd
);
2540 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_area_cmd
);
2541 install_element(CONFIG_NODE
, &debug_ospf6_brouter_cmd
);
2542 install_element(CONFIG_NODE
, &debug_ospf6_brouter_router_cmd
);
2543 install_element(CONFIG_NODE
, &debug_ospf6_brouter_area_cmd
);
2544 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_cmd
);
2545 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_router_cmd
);
2546 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_area_cmd
);