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"
51 unsigned char conf_debug_ospf6_brouter
= 0;
52 uint32_t conf_debug_ospf6_brouter_specific_router_id
;
53 uint32_t conf_debug_ospf6_brouter_specific_area_id
;
55 #define MAX_LSA_PAYLOAD (1024 + 256)
56 /******************************/
57 /* RFC2740 3.4.3.1 Router-LSA */
58 /******************************/
60 static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa
*lsa
, char *buf
,
63 struct ospf6_router_lsa
*router_lsa
;
64 struct ospf6_router_lsdesc
*lsdesc
;
66 char buf1
[INET_ADDRSTRLEN
], buf2
[INET_ADDRSTRLEN
];
69 router_lsa
= (struct ospf6_router_lsa
70 *)((char *)lsa
->header
71 + sizeof(struct ospf6_lsa_header
));
72 start
= (char *)router_lsa
+ sizeof(struct ospf6_router_lsa
);
73 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
75 lsdesc
= (struct ospf6_router_lsdesc
77 + pos
* (sizeof(struct
78 ospf6_router_lsdesc
)));
79 if ((char *)lsdesc
+ sizeof(struct ospf6_router_lsdesc
)
81 if (buf
&& (buflen
> INET_ADDRSTRLEN
* 2)) {
83 &lsdesc
->neighbor_interface_id
, buf1
,
85 inet_ntop(AF_INET
, &lsdesc
->neighbor_router_id
,
87 snprintf(buf
, buflen
, "%s/%s", buf2
, buf1
);
97 static int ospf6_router_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
98 json_object
*json_obj
, bool use_json
)
100 char *start
, *end
, *current
;
101 char buf
[32], name
[32], bits
[16], options
[32];
102 struct ospf6_router_lsa
*router_lsa
;
103 struct ospf6_router_lsdesc
*lsdesc
;
104 json_object
*json_arr
;
105 json_object
*json_loop
;
108 (struct ospf6_router_lsa
*)((char *)lsa
->header
109 + sizeof(struct ospf6_lsa_header
));
111 ospf6_capability_printbuf(router_lsa
->bits
, bits
, sizeof(bits
));
112 ospf6_options_printbuf(router_lsa
->options
, options
, sizeof(options
));
114 json_object_string_add(json_obj
, "bits", bits
);
115 json_object_string_add(json_obj
, "options", options
);
116 json_arr
= json_object_new_array();
118 vty_out(vty
, " Bits: %s Options: %s\n", bits
, options
);
120 start
= (char *)router_lsa
+ sizeof(struct ospf6_router_lsa
);
121 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
122 for (current
= start
;
123 current
+ sizeof(struct ospf6_router_lsdesc
) <= end
;
124 current
+= sizeof(struct ospf6_router_lsdesc
)) {
125 lsdesc
= (struct ospf6_router_lsdesc
*)current
;
127 if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_POINTTOPOINT
)
128 snprintf(name
, sizeof(name
), "Point-To-Point");
129 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK
)
130 snprintf(name
, sizeof(name
), "Transit-Network");
131 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_STUB_NETWORK
)
132 snprintf(name
, sizeof(name
), "Stub-Network");
133 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_VIRTUAL_LINK
)
134 snprintf(name
, sizeof(name
), "Virtual-Link");
136 snprintf(name
, sizeof(name
), "Unknown (%#x)",
140 json_loop
= json_object_new_object();
141 json_object_string_add(json_loop
, "type", name
);
142 json_object_int_add(json_loop
, "metric",
143 ntohs(lsdesc
->metric
));
144 json_object_string_add(json_loop
, "interfaceId",
146 &lsdesc
->interface_id
,
148 json_object_string_add(
149 json_loop
, "neighborInterfaceId",
151 &lsdesc
->neighbor_interface_id
, buf
,
153 json_object_string_add(
154 json_loop
, "neighborRouterId",
155 inet_ntop(AF_INET
, &lsdesc
->neighbor_router_id
,
157 json_object_array_add(json_arr
, json_loop
);
159 vty_out(vty
, " Type: %s Metric: %d\n", name
,
160 ntohs(lsdesc
->metric
));
161 vty_out(vty
, " Interface ID: %s\n",
162 inet_ntop(AF_INET
, &lsdesc
->interface_id
, buf
,
164 vty_out(vty
, " Neighbor Interface ID: %s\n",
166 &lsdesc
->neighbor_interface_id
, buf
,
168 vty_out(vty
, " Neighbor Router ID: %s\n",
169 inet_ntop(AF_INET
, &lsdesc
->neighbor_router_id
,
174 json_object_object_add(json_obj
, "lsaDescription", json_arr
);
179 static void ospf6_router_lsa_options_set(struct ospf6_area
*oa
,
180 struct ospf6_router_lsa
*router_lsa
)
182 OSPF6_OPT_CLEAR_ALL(router_lsa
->options
);
183 memcpy(router_lsa
->options
, oa
->options
, 3);
185 if (ospf6_check_and_set_router_abr(oa
->ospf6
))
186 SET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_B
);
188 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_B
);
190 if (!IS_AREA_STUB(oa
) && ospf6_asbr_is_asbr(oa
->ospf6
)) {
191 SET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_E
);
193 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_E
);
196 /* If the router is ASBR and the area-type is NSSA set the
197 * translate bit in router LSA.
200 && (ospf6_asbr_is_asbr(oa
->ospf6
) || IS_OSPF6_ABR(oa
->ospf6
))) {
201 if (oa
->NSSATranslatorRole
== OSPF6_NSSA_ROLE_ALWAYS
)
202 SET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_NT
);
204 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_NT
);
207 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_V
);
208 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_W
);
211 int ospf6_router_is_stub_router(struct ospf6_lsa
*lsa
)
213 struct ospf6_router_lsa
*rtr_lsa
;
215 if (lsa
!= NULL
&& OSPF6_LSA_IS_TYPE(ROUTER
, lsa
)) {
216 rtr_lsa
= (struct ospf6_router_lsa
217 *)((caddr_t
)lsa
->header
218 + sizeof(struct ospf6_lsa_header
));
220 if (!OSPF6_OPT_ISSET(rtr_lsa
->options
, OSPF6_OPT_R
)) {
221 return OSPF6_IS_STUB_ROUTER
;
222 } else if (!OSPF6_OPT_ISSET(rtr_lsa
->options
, OSPF6_OPT_V6
)) {
223 return OSPF6_IS_STUB_ROUTER_V6
;
227 return OSPF6_NOT_STUB_ROUTER
;
230 int ospf6_router_lsa_originate(struct thread
*thread
)
232 struct ospf6_area
*oa
;
234 char buffer
[OSPF6_MAX_LSASIZE
];
235 struct ospf6_lsa_header
*lsa_header
;
236 struct ospf6_lsa
*lsa
;
238 uint32_t link_state_id
= 0;
239 struct listnode
*node
, *nnode
;
241 struct ospf6_interface
*oi
;
242 struct ospf6_neighbor
*on
, *drouter
= NULL
;
243 struct ospf6_router_lsa
*router_lsa
;
244 struct ospf6_router_lsdesc
*lsdesc
;
249 oa
= (struct ospf6_area
*)THREAD_ARG(thread
);
250 oa
->thread_router_lsa
= NULL
;
252 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER
))
253 zlog_debug("Originate Router-LSA for Area %s", oa
->name
);
255 memset(buffer
, 0, sizeof(buffer
));
256 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
258 (struct ospf6_router_lsa
*)((caddr_t
)lsa_header
259 + sizeof(struct ospf6_lsa_header
));
261 ospf6_router_lsa_options_set(oa
, router_lsa
);
263 /* describe links for each interfaces */
264 lsdesc
= (struct ospf6_router_lsdesc
265 *)((caddr_t
)router_lsa
266 + sizeof(struct ospf6_router_lsa
));
268 for (ALL_LIST_ELEMENTS(oa
->if_list
, node
, nnode
, oi
)) {
269 /* Interfaces in state Down or Loopback are not described */
270 if (oi
->state
== OSPF6_INTERFACE_DOWN
271 || oi
->state
== OSPF6_INTERFACE_LOOPBACK
)
274 /* Nor are interfaces without any full adjacencies described */
276 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
))
277 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
283 /* Multiple Router-LSA instance according to size limit setting
285 if ((oa
->router_lsa_size_limit
!= 0)
286 && ((size_t)((char *)lsdesc
- buffer
)
287 + sizeof(struct ospf6_router_lsdesc
)
288 > oa
->router_lsa_size_limit
)) {
290 == (caddr_t
)router_lsa
291 + sizeof(struct ospf6_router_lsa
)) {
293 "Size limit setting for Router-LSA too short");
297 /* Fill LSA Header */
299 lsa_header
->type
= htons(OSPF6_LSTYPE_ROUTER
);
300 lsa_header
->id
= htonl(link_state_id
);
301 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
302 lsa_header
->seqnum
= ospf6_new_ls_seqnum(
303 lsa_header
->type
, lsa_header
->id
,
304 lsa_header
->adv_router
, oa
->lsdb
);
306 htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
309 ospf6_lsa_checksum(lsa_header
);
312 lsa
= ospf6_lsa_create(lsa_header
);
315 ospf6_lsa_originate_area(lsa
, oa
);
317 /* Reset Buffer to fill next Router LSA */
318 memset(buffer
, 0, sizeof(buffer
));
319 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
321 (struct ospf6_router_lsa
322 *)((caddr_t
)lsa_header
323 + sizeof(struct ospf6_lsa_header
));
325 ospf6_router_lsa_options_set(oa
, router_lsa
);
327 /* describe links for each interfaces */
328 lsdesc
= (struct ospf6_router_lsdesc
329 *)((caddr_t
)router_lsa
330 + sizeof(struct ospf6_router_lsa
));
335 /* Point-to-Point interfaces */
336 if (oi
->type
== OSPF_IFTYPE_POINTOPOINT
) {
337 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
)) {
338 if (on
->state
!= OSPF6_NEIGHBOR_FULL
)
341 lsdesc
->type
= OSPF6_ROUTER_LSDESC_POINTTOPOINT
;
342 lsdesc
->metric
= htons(oi
->cost
);
343 lsdesc
->interface_id
=
344 htonl(oi
->interface
->ifindex
);
345 lsdesc
->neighbor_interface_id
=
347 lsdesc
->neighbor_router_id
= on
->router_id
;
353 /* Broadcast and NBMA interfaces */
354 else if (oi
->type
== OSPF_IFTYPE_BROADCAST
) {
355 /* If this router is not DR,
356 and If this router not fully adjacent with DR,
357 this interface is not transit yet: ignore. */
358 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
360 ospf6_neighbor_lookup(oi
->drouter
, oi
);
362 || drouter
->state
!= OSPF6_NEIGHBOR_FULL
)
366 lsdesc
->type
= OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK
;
367 lsdesc
->metric
= htons(oi
->cost
);
368 lsdesc
->interface_id
= htonl(oi
->interface
->ifindex
);
369 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
370 lsdesc
->neighbor_interface_id
=
371 htonl(drouter
->ifindex
);
372 lsdesc
->neighbor_router_id
= drouter
->router_id
;
374 lsdesc
->neighbor_interface_id
=
375 htonl(oi
->interface
->ifindex
);
376 lsdesc
->neighbor_router_id
=
377 oi
->area
->ospf6
->router_id
;
382 assert(0); /* Unknown interface type */
387 /* Point-to-Multipoint interfaces */
391 /* Fill LSA Header */
393 lsa_header
->type
= htons(OSPF6_LSTYPE_ROUTER
);
394 lsa_header
->id
= htonl(link_state_id
);
395 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
397 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
398 lsa_header
->adv_router
, oa
->lsdb
);
399 lsa_header
->length
= htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
402 ospf6_lsa_checksum(lsa_header
);
405 lsa
= ospf6_lsa_create(lsa_header
);
408 ospf6_lsa_originate_area(lsa
, oa
);
412 /* Do premature-aging of rest, undesired Router-LSAs */
413 type
= ntohs(OSPF6_LSTYPE_ROUTER
);
414 router
= oa
->ospf6
->router_id
;
416 for (ALL_LSDB_TYPED_ADVRTR(oa
->lsdb
, type
, router
, lsa
)) {
417 if (ntohl(lsa
->header
->id
) < link_state_id
)
419 ospf6_lsa_purge(lsa
);
424 * Waiting till the LSA is actually removed from the database to trigger
425 * SPF delays network convergence. Unlike IPv4, for an ABR, when all
426 * interfaces associated with an area are gone, triggering an SPF right
428 * helps convergence with inter-area routes.
430 if (count
&& !link_state_id
)
431 ospf6_spf_schedule(oa
->ospf6
,
432 OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED
);
437 /*******************************/
438 /* RFC2740 3.4.3.2 Network-LSA */
439 /*******************************/
441 static char *ospf6_network_lsa_get_ar_id(struct ospf6_lsa
*lsa
, char *buf
,
444 char *start
, *end
, *current
;
445 struct ospf6_network_lsa
*network_lsa
;
446 struct ospf6_network_lsdesc
*lsdesc
;
449 network_lsa
= (struct ospf6_network_lsa
450 *)((caddr_t
)lsa
->header
451 + sizeof(struct ospf6_lsa_header
));
453 start
= (char *)network_lsa
+ sizeof(struct ospf6_network_lsa
);
454 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
455 current
= start
+ pos
* (sizeof(struct ospf6_network_lsdesc
));
457 if ((current
+ sizeof(struct ospf6_network_lsdesc
)) <= end
) {
458 lsdesc
= (struct ospf6_network_lsdesc
*)current
;
460 inet_ntop(AF_INET
, &lsdesc
->router_id
, buf
,
470 static int ospf6_network_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
471 json_object
*json_obj
, bool use_json
)
473 char *start
, *end
, *current
;
474 struct ospf6_network_lsa
*network_lsa
;
475 struct ospf6_network_lsdesc
*lsdesc
;
476 char buf
[128], options
[32];
477 json_object
*json_arr
;
480 (struct ospf6_network_lsa
*)((caddr_t
)lsa
->header
481 + sizeof(struct ospf6_lsa_header
));
483 ospf6_options_printbuf(network_lsa
->options
, options
, sizeof(options
));
485 json_object_string_add(json_obj
, "options", options
);
487 vty_out(vty
, " Options: %s\n", options
);
489 start
= (char *)network_lsa
+ sizeof(struct ospf6_network_lsa
);
490 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
492 json_arr
= json_object_new_array();
494 for (current
= start
;
495 current
+ sizeof(struct ospf6_network_lsdesc
) <= end
;
496 current
+= sizeof(struct ospf6_network_lsdesc
)) {
497 lsdesc
= (struct ospf6_network_lsdesc
*)current
;
498 inet_ntop(AF_INET
, &lsdesc
->router_id
, buf
, sizeof(buf
));
500 json_object_array_add(json_arr
,
501 json_object_new_string(buf
));
503 vty_out(vty
, " Attached Router: %s\n", buf
);
506 json_object_object_add(json_obj
, "attachedRouter", json_arr
);
511 int ospf6_network_lsa_originate(struct thread
*thread
)
513 struct ospf6_interface
*oi
;
515 char buffer
[OSPF6_MAX_LSASIZE
];
516 struct ospf6_lsa_header
*lsa_header
;
519 struct ospf6_lsa
*old
, *lsa
;
520 struct ospf6_network_lsa
*network_lsa
;
521 struct ospf6_network_lsdesc
*lsdesc
;
522 struct ospf6_neighbor
*on
;
523 struct ospf6_link_lsa
*link_lsa
;
527 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
528 oi
->thread_network_lsa
= NULL
;
530 /* The interface must be enabled until here. A Network-LSA of a
531 disabled interface (but was once enabled) should be flushed
532 by ospf6_lsa_refresh (), and does not come here. */
535 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_NETWORK
),
536 htonl(oi
->interface
->ifindex
),
537 oi
->area
->ospf6
->router_id
, oi
->area
->lsdb
);
539 /* Do not originate Network-LSA if not DR */
540 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
542 ospf6_lsa_purge(old
);
544 * Waiting till the LSA is actually removed from the
546 * trigger SPF delays network convergence.
550 OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED
);
555 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK
))
556 zlog_debug("Originate Network-LSA for Interface %s",
557 oi
->interface
->name
);
559 /* If none of neighbor is adjacent to us */
562 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
))
563 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
567 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK
))
568 zlog_debug("Interface stub, ignore");
570 ospf6_lsa_purge(old
);
575 memset(buffer
, 0, sizeof(buffer
));
576 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
578 (struct ospf6_network_lsa
*)((caddr_t
)lsa_header
579 + sizeof(struct ospf6_lsa_header
));
581 /* Collect the interface's Link-LSAs to describe
582 network's optional capabilities */
583 type
= htons(OSPF6_LSTYPE_LINK
);
584 for (ALL_LSDB_TYPED(oi
->lsdb
, type
, lsa
)) {
585 link_lsa
= (struct ospf6_link_lsa
586 *)((caddr_t
)lsa
->header
587 + sizeof(struct ospf6_lsa_header
));
588 network_lsa
->options
[0] |= link_lsa
->options
[0];
589 network_lsa
->options
[1] |= link_lsa
->options
[1];
590 network_lsa
->options
[2] |= link_lsa
->options
[2];
593 lsdesc
= (struct ospf6_network_lsdesc
594 *)((caddr_t
)network_lsa
595 + sizeof(struct ospf6_network_lsa
));
597 /* set Link Description to the router itself */
598 lsdesc
->router_id
= oi
->area
->ospf6
->router_id
;
601 /* Walk through the neighbors */
602 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
)) {
603 if (on
->state
!= OSPF6_NEIGHBOR_FULL
)
606 /* set this neighbor's Router-ID to LSA */
607 lsdesc
->router_id
= on
->router_id
;
611 /* Fill LSA Header */
613 lsa_header
->type
= htons(OSPF6_LSTYPE_NETWORK
);
614 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
615 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
617 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
618 lsa_header
->adv_router
, oi
->area
->lsdb
);
619 lsa_header
->length
= htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
622 ospf6_lsa_checksum(lsa_header
);
625 lsa
= ospf6_lsa_create(lsa_header
);
628 ospf6_lsa_originate_area(lsa
, oi
->area
);
634 /****************************/
635 /* RFC2740 3.4.3.6 Link-LSA */
636 /****************************/
638 static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa
*lsa
, char *buf
,
641 char *start
, *end
, *current
;
642 struct ospf6_link_lsa
*link_lsa
;
644 struct ospf6_prefix
*prefix
;
645 int cnt
= 0, prefixnum
;
648 link_lsa
= (struct ospf6_link_lsa
649 *)((caddr_t
)lsa
->header
650 + sizeof(struct ospf6_lsa_header
));
653 inet_ntop(AF_INET6
, &link_lsa
->linklocal_addr
, buf
,
658 prefixnum
= ntohl(link_lsa
->prefix_num
);
662 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
663 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
666 while (current
+ sizeof(struct ospf6_prefix
) <= end
) {
667 prefix
= (struct ospf6_prefix
*)current
;
668 if (prefix
->prefix_length
== 0
669 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
) {
673 if (cnt
< (pos
- 1)) {
674 current
+= OSPF6_PREFIX_SIZE(prefix
);
677 memset(&in6
, 0, sizeof(in6
));
678 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
680 prefix
->prefix_length
));
681 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
689 static int ospf6_link_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
690 json_object
*json_obj
, bool use_json
)
692 char *start
, *end
, *current
;
693 struct ospf6_link_lsa
*link_lsa
;
695 char buf
[128], options
[32];
696 struct ospf6_prefix
*prefix
;
698 json_object
*json_loop
;
699 json_object
*json_arr
= NULL
;
700 char prefix_string
[133];
702 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsa
->header
703 + sizeof(struct ospf6_lsa_header
));
705 ospf6_options_printbuf(link_lsa
->options
, options
, sizeof(options
));
706 inet_ntop(AF_INET6
, &link_lsa
->linklocal_addr
, buf
, sizeof(buf
));
707 prefixnum
= ntohl(link_lsa
->prefix_num
);
710 json_arr
= json_object_new_array();
711 json_object_int_add(json_obj
, "priority", link_lsa
->priority
);
712 json_object_string_add(json_obj
, "options", options
);
713 json_object_string_add(json_obj
, "linkLocalAddress", buf
);
714 json_object_int_add(json_obj
, "numberOfPrefix", prefixnum
);
716 vty_out(vty
, " Priority: %d Options: %s\n",
717 link_lsa
->priority
, options
);
718 vty_out(vty
, " LinkLocal Address: %s\n", buf
);
719 vty_out(vty
, " Number of Prefix: %d\n", prefixnum
);
722 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
723 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
724 for (current
= start
; current
< end
;
725 current
+= OSPF6_PREFIX_SIZE(prefix
)) {
726 prefix
= (struct ospf6_prefix
*)current
;
727 if (prefix
->prefix_length
== 0
728 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
)
731 ospf6_prefix_options_printbuf(prefix
->prefix_options
, buf
,
734 json_loop
= json_object_new_object();
735 json_object_string_add(json_loop
, "prefixOption", buf
);
737 vty_out(vty
, " Prefix Options: %s\n", buf
);
739 memset(&in6
, 0, sizeof(in6
));
740 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
741 OSPF6_PREFIX_SPACE(prefix
->prefix_length
));
742 inet_ntop(AF_INET6
, &in6
, buf
, sizeof(buf
));
744 snprintf(prefix_string
, sizeof(prefix_string
), "%s/%d",
745 buf
, prefix
->prefix_length
);
746 json_object_string_add(json_loop
, "prefix",
748 json_object_array_add(json_arr
, json_loop
);
750 vty_out(vty
, " Prefix: %s/%d\n", buf
,
751 prefix
->prefix_length
);
754 json_object_object_add(json_obj
, "prefix", json_arr
);
759 int ospf6_link_lsa_originate(struct thread
*thread
)
761 struct ospf6_interface
*oi
;
763 char buffer
[OSPF6_MAX_LSASIZE
];
764 struct ospf6_lsa_header
*lsa_header
;
765 struct ospf6_lsa
*old
, *lsa
;
767 struct ospf6_link_lsa
*link_lsa
;
768 struct ospf6_route
*route
;
769 struct ospf6_prefix
*op
;
770 int count
, max_addr_count
;
772 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
773 oi
->thread_link_lsa
= NULL
;
777 /* find previous LSA */
778 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_LINK
),
779 htonl(oi
->interface
->ifindex
),
780 oi
->area
->ospf6
->router_id
, oi
->lsdb
);
782 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
784 ospf6_lsa_purge(old
);
788 if (IS_OSPF6_DEBUG_ORIGINATE(LINK
))
789 zlog_debug("Originate Link-LSA for Interface %s",
790 oi
->interface
->name
);
792 /* can't make Link-LSA if linklocal address not set */
793 if (oi
->linklocal_addr
== NULL
) {
794 if (IS_OSPF6_DEBUG_ORIGINATE(LINK
))
796 "No Linklocal address on %s, defer originating",
797 oi
->interface
->name
);
799 ospf6_lsa_purge(old
);
804 memset(buffer
, 0, sizeof(buffer
));
805 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
806 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsa_header
807 + sizeof(struct ospf6_lsa_header
));
810 link_lsa
->priority
= oi
->priority
;
811 memcpy(link_lsa
->options
, oi
->area
->options
, 3);
812 memcpy(&link_lsa
->linklocal_addr
, oi
->linklocal_addr
,
813 sizeof(struct in6_addr
));
815 op
= (struct ospf6_prefix
*)((caddr_t
)link_lsa
816 + sizeof(struct ospf6_link_lsa
));
818 /* connected prefix to advertise, number of interface addresses
819 * supported is based on MTU size of OSPFv3 packets
821 if (oi
->ifmtu
>= OSPF6_JUMBO_MTU
)
822 max_addr_count
= OSPF6_MAX_IF_ADDRS_JUMBO
;
824 max_addr_count
= OSPF6_MAX_IF_ADDRS
;
825 for (route
= ospf6_route_head(oi
->route_connected
), count
= 0;
826 route
&& count
< max_addr_count
;
827 route
= ospf6_route_next(route
), count
++) {
828 op
->prefix_length
= route
->prefix
.prefixlen
;
829 op
->prefix_options
= route
->path
.prefix_options
;
830 op
->prefix_metric
= htons(0);
831 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
832 OSPF6_PREFIX_SPACE(op
->prefix_length
));
833 op
= OSPF6_PREFIX_NEXT(op
);
836 link_lsa
->prefix_num
= htonl(count
);
838 /* Fill LSA Header */
840 lsa_header
->type
= htons(OSPF6_LSTYPE_LINK
);
841 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
842 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
844 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
845 lsa_header
->adv_router
, oi
->lsdb
);
846 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)buffer
);
849 ospf6_lsa_checksum(lsa_header
);
852 lsa
= ospf6_lsa_create(lsa_header
);
855 ospf6_lsa_originate_interface(lsa
, oi
);
861 /*****************************************/
862 /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
863 /*****************************************/
864 static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
865 char *buf
, int buflen
,
868 char *start
, *end
, *current
;
869 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
871 int prefixnum
, cnt
= 0;
872 struct ospf6_prefix
*prefix
;
877 (struct ospf6_intra_prefix_lsa
878 *)((caddr_t
)lsa
->header
879 + sizeof(struct ospf6_lsa_header
));
881 prefixnum
= ntohs(intra_prefix_lsa
->prefix_num
);
882 if ((pos
+ 1) > prefixnum
)
885 start
= (char *)intra_prefix_lsa
886 + sizeof(struct ospf6_intra_prefix_lsa
);
887 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
890 while (current
+ sizeof(struct ospf6_prefix
) <= end
) {
891 prefix
= (struct ospf6_prefix
*)current
;
892 if (prefix
->prefix_length
== 0
893 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
) {
898 current
+= OSPF6_PREFIX_SIZE(prefix
);
901 memset(&in6
, 0, sizeof(in6
));
902 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
904 prefix
->prefix_length
));
905 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
906 snprintf(tbuf
, sizeof(tbuf
), "/%d",
907 prefix
->prefix_length
);
908 strlcat(buf
, tbuf
, buflen
);
916 static int ospf6_intra_prefix_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
917 json_object
*json_obj
, bool use_json
)
919 char *start
, *end
, *current
;
920 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
923 struct ospf6_prefix
*prefix
;
924 char id
[16], adv_router
[16];
926 json_object
*json_loop
;
927 json_object
*json_arr
= NULL
;
928 char prefix_string
[133];
930 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
931 *)((caddr_t
)lsa
->header
932 + sizeof(struct ospf6_lsa_header
));
934 prefixnum
= ntohs(intra_prefix_lsa
->prefix_num
);
937 json_arr
= json_object_new_array();
938 json_object_int_add(json_obj
, "numberOfPrefix", prefixnum
);
940 vty_out(vty
, " Number of Prefix: %d\n", prefixnum
);
942 inet_ntop(AF_INET
, &intra_prefix_lsa
->ref_id
, id
, sizeof(id
));
943 inet_ntop(AF_INET
, &intra_prefix_lsa
->ref_adv_router
, adv_router
,
946 json_object_string_add(
947 json_obj
, "reference",
948 ospf6_lstype_name(intra_prefix_lsa
->ref_type
));
949 json_object_string_add(json_obj
, "referenceId", id
);
950 json_object_string_add(json_obj
, "referenceAdv", adv_router
);
952 vty_out(vty
, " Reference: %s Id: %s Adv: %s\n",
953 ospf6_lstype_name(intra_prefix_lsa
->ref_type
), id
,
956 start
= (char *)intra_prefix_lsa
957 + sizeof(struct ospf6_intra_prefix_lsa
);
958 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
959 for (current
= start
; current
< end
;
960 current
+= OSPF6_PREFIX_SIZE(prefix
)) {
961 prefix
= (struct ospf6_prefix
*)current
;
962 if (prefix
->prefix_length
== 0
963 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
)
966 ospf6_prefix_options_printbuf(prefix
->prefix_options
, buf
,
969 json_loop
= json_object_new_object();
970 json_object_string_add(json_loop
, "prefixOption", buf
);
972 vty_out(vty
, " Prefix Options: %s\n", buf
);
974 memset(&in6
, 0, sizeof(in6
));
975 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
976 OSPF6_PREFIX_SPACE(prefix
->prefix_length
));
977 inet_ntop(AF_INET6
, &in6
, buf
, sizeof(buf
));
979 snprintf(prefix_string
, sizeof(prefix_string
), "%s/%d",
980 buf
, prefix
->prefix_length
);
981 json_object_string_add(json_loop
, "prefix",
983 json_object_int_add(json_loop
, "metric",
984 ntohs(prefix
->prefix_metric
));
985 json_object_array_add(json_arr
, json_loop
);
987 vty_out(vty
, " Prefix: %s/%d\n", buf
,
988 prefix
->prefix_length
);
989 vty_out(vty
, " Metric: %d\n",
990 ntohs(prefix
->prefix_metric
));
994 json_object_object_add(json_obj
, "prefix", json_arr
);
999 int ospf6_intra_prefix_lsa_originate_stub(struct thread
*thread
)
1001 struct ospf6_area
*oa
;
1003 char buffer
[OSPF6_MAX_LSASIZE
];
1004 struct ospf6_lsa_header
*lsa_header
;
1005 struct ospf6_lsa
*old
, *lsa
, *old_next
= NULL
;
1007 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1008 struct ospf6_interface
*oi
;
1009 struct ospf6_neighbor
*on
;
1010 struct ospf6_route
*route
;
1011 struct ospf6_prefix
*op
;
1012 struct listnode
*i
, *j
;
1014 unsigned short prefix_num
= 0;
1015 struct ospf6_route_table
*route_advertise
;
1017 int count
, max_addr_count
;
1019 oa
= (struct ospf6_area
*)THREAD_ARG(thread
);
1020 oa
->thread_intra_prefix_lsa
= NULL
;
1022 /* find previous LSA */
1023 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX
), htonl(0),
1024 oa
->ospf6
->router_id
, oa
->lsdb
);
1026 if (!IS_AREA_ENABLED(oa
)) {
1028 ospf6_lsa_purge(old
);
1029 /* find previous LSA */
1030 old_next
= ospf6_lsdb_lookup(
1031 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1032 htonl(++ls_id
), oa
->ospf6
->router_id
, oa
->lsdb
);
1035 ospf6_lsa_purge(old_next
);
1036 old_next
= ospf6_lsdb_lookup(
1037 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1038 htonl(++ls_id
), oa
->ospf6
->router_id
,
1045 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1047 "Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
1050 /* prepare buffer */
1051 memset(buffer
, 0, sizeof(buffer
));
1052 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1053 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
1054 *)((caddr_t
)lsa_header
1055 + sizeof(struct ospf6_lsa_header
));
1057 /* Fill Intra-Area-Prefix-LSA */
1058 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_ROUTER
);
1059 intra_prefix_lsa
->ref_id
= htonl(0);
1060 intra_prefix_lsa
->ref_adv_router
= oa
->ospf6
->router_id
;
1062 route_advertise
= ospf6_route_table_create(0, 0);
1063 route_advertise
->hook_add
= NULL
;
1064 route_advertise
->hook_remove
= NULL
;
1066 for (ALL_LIST_ELEMENTS_RO(oa
->if_list
, i
, oi
)) {
1067 if (oi
->state
== OSPF6_INTERFACE_DOWN
) {
1068 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1069 zlog_debug(" Interface %s is down, ignore",
1070 oi
->interface
->name
);
1076 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
))
1077 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
1080 if (oi
->state
!= OSPF6_INTERFACE_LOOPBACK
1081 && oi
->state
!= OSPF6_INTERFACE_POINTTOPOINT
1082 && full_count
!= 0) {
1083 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1084 zlog_debug(" Interface %s is not stub, ignore",
1085 oi
->interface
->name
);
1089 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1090 zlog_debug(" Interface %s:", oi
->interface
->name
);
1092 /* connected prefix to advertise */
1093 if (oi
->ifmtu
>= OSPF6_JUMBO_MTU
)
1094 max_addr_count
= OSPF6_MAX_IF_ADDRS_JUMBO
;
1096 max_addr_count
= OSPF6_MAX_IF_ADDRS
;
1098 for (route
= ospf6_route_head(oi
->route_connected
), count
= 0;
1099 route
&& count
< max_addr_count
;
1100 route
= ospf6_route_best_next(route
), count
++) {
1101 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1102 zlog_debug(" include %pFX", &route
->prefix
);
1103 ospf6_route_add(ospf6_route_copy(route
),
1108 if (route_advertise
->count
== 0) {
1111 ospf6_lsa_purge(old
);
1112 /* find previous LSA */
1113 old_next
= ospf6_lsdb_lookup(
1114 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1115 htonl(++ls_id
), oa
->ospf6
->router_id
, oa
->lsdb
);
1118 ospf6_lsa_purge(old_next
);
1119 old_next
= ospf6_lsdb_lookup(
1120 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1121 htonl(++ls_id
), oa
->ospf6
->router_id
,
1125 ospf6_route_table_delete(route_advertise
);
1129 /* Neighbor change to FULL, if INTRA-AREA-PREFIX LSA
1130 * has not change, Flush old LSA and Re-Originate INP,
1131 * as ospf6_flood() checks if LSA is same as DB,
1132 * it won't be updated to neighbor's DB.
1134 if (oa
->intra_prefix_originate
) {
1135 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1137 "%s: Re-originate intra prefix LSA, Current full nbrs %u",
1138 __func__
, oa
->full_nbrs
);
1140 ospf6_lsa_purge_multi_ls_id(oa
, old
);
1141 oa
->intra_prefix_originate
= 0;
1144 /* put prefixes to advertise */
1146 op
= (struct ospf6_prefix
*)((caddr_t
)intra_prefix_lsa
1147 + sizeof(struct ospf6_intra_prefix_lsa
));
1148 for (route
= ospf6_route_head(route_advertise
); route
;
1149 route
= ospf6_route_best_next(route
)) {
1150 if (((caddr_t
)op
- (caddr_t
)lsa_header
) > MAX_LSA_PAYLOAD
) {
1152 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
1154 /* Fill LSA Header */
1155 lsa_header
->age
= 0;
1156 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1157 lsa_header
->id
= htonl(ls_id
++);
1158 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
1159 lsa_header
->seqnum
= ospf6_new_ls_seqnum(
1160 lsa_header
->type
, lsa_header
->id
,
1161 lsa_header
->adv_router
, oa
->lsdb
);
1162 lsa_header
->length
=
1163 htons((caddr_t
)op
- (caddr_t
)lsa_header
);
1166 ospf6_lsa_checksum(lsa_header
);
1169 lsa
= ospf6_lsa_create(lsa_header
);
1172 ospf6_lsa_originate_area(lsa
, oa
);
1174 /* Prepare next buffer */
1175 memset(buffer
, 0, sizeof(buffer
));
1176 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1178 (struct ospf6_intra_prefix_lsa
1179 *)((caddr_t
)lsa_header
1180 + sizeof(struct ospf6_lsa_header
));
1182 /* Fill Intra-Area-Prefix-LSA */
1183 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_ROUTER
);
1184 intra_prefix_lsa
->ref_id
= htonl(0);
1185 intra_prefix_lsa
->ref_adv_router
= oa
->ospf6
->router_id
;
1187 /* Put next set of prefixes to advertise */
1189 op
= (struct ospf6_prefix
1190 *)((caddr_t
)intra_prefix_lsa
1192 ospf6_intra_prefix_lsa
));
1195 op
->prefix_length
= route
->prefix
.prefixlen
;
1196 op
->prefix_options
= route
->path
.prefix_options
;
1197 op
->prefix_metric
= htons(route
->path
.cost
);
1198 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
1199 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1202 op
= OSPF6_PREFIX_NEXT(op
);
1205 ospf6_route_table_delete(route_advertise
);
1207 if (prefix_num
== 0) {
1208 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1210 "Quit to Advertise Intra-Prefix: no route to advertise");
1214 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
1216 /* Fill LSA Header */
1217 lsa_header
->age
= 0;
1218 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1219 lsa_header
->id
= htonl(ls_id
++);
1220 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
1221 lsa_header
->seqnum
=
1222 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
1223 lsa_header
->adv_router
, oa
->lsdb
);
1224 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)lsa_header
);
1227 ospf6_lsa_checksum(lsa_header
);
1230 lsa
= ospf6_lsa_create(lsa_header
);
1233 ospf6_lsa_originate_area(lsa
, oa
);
1239 int ospf6_intra_prefix_lsa_originate_transit(struct thread
*thread
)
1241 struct ospf6_interface
*oi
;
1243 char buffer
[OSPF6_MAX_LSASIZE
];
1244 struct ospf6_lsa_header
*lsa_header
;
1245 struct ospf6_lsa
*old
, *lsa
;
1247 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1248 struct ospf6_neighbor
*on
;
1249 struct ospf6_route
*route
;
1250 struct ospf6_prefix
*op
;
1253 unsigned short prefix_num
= 0;
1254 struct ospf6_route_table
*route_advertise
;
1255 struct ospf6_link_lsa
*link_lsa
;
1256 char *start
, *end
, *current
;
1259 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
1260 oi
->thread_intra_prefix_lsa
= NULL
;
1264 /* find previous LSA */
1265 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1266 htonl(oi
->interface
->ifindex
),
1267 oi
->area
->ospf6
->router_id
, oi
->area
->lsdb
);
1269 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1271 ospf6_lsa_purge(old
);
1275 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1277 "Originate Intra-Area-Prefix-LSA for interface %s's prefix",
1278 oi
->interface
->name
);
1280 /* prepare buffer */
1281 memset(buffer
, 0, sizeof(buffer
));
1282 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1283 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
1284 *)((caddr_t
)lsa_header
1285 + sizeof(struct ospf6_lsa_header
));
1287 /* Fill Intra-Area-Prefix-LSA */
1288 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_NETWORK
);
1289 intra_prefix_lsa
->ref_id
= htonl(oi
->interface
->ifindex
);
1290 intra_prefix_lsa
->ref_adv_router
= oi
->area
->ospf6
->router_id
;
1292 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
1293 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1294 zlog_debug(" Interface is not DR");
1296 ospf6_lsa_purge(old
);
1301 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
))
1302 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
1305 if (full_count
== 0) {
1306 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1307 zlog_debug(" Interface is stub");
1309 ospf6_lsa_purge(old
);
1313 /* connected prefix to advertise */
1314 route_advertise
= ospf6_route_table_create(0, 0);
1315 route_advertise
->hook_add
= NULL
;
1316 route_advertise
->hook_remove
= NULL
;
1318 type
= ntohs(OSPF6_LSTYPE_LINK
);
1319 for (ALL_LSDB_TYPED(oi
->lsdb
, type
, lsa
)) {
1320 if (OSPF6_LSA_IS_MAXAGE(lsa
))
1323 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1324 zlog_debug(" include prefix from %s", lsa
->name
);
1326 if (lsa
->header
->adv_router
!= oi
->area
->ospf6
->router_id
) {
1327 on
= ospf6_neighbor_lookup(lsa
->header
->adv_router
, oi
);
1328 if (on
== NULL
|| on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1329 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1331 " Neighbor not found or not Full, ignore");
1336 link_lsa
= (struct ospf6_link_lsa
1337 *)((caddr_t
)lsa
->header
1338 + sizeof(struct ospf6_lsa_header
));
1340 prefix_num
= (unsigned short)ntohl(link_lsa
->prefix_num
);
1341 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
1342 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
1343 for (current
= start
; current
< end
&& prefix_num
;
1344 current
+= OSPF6_PREFIX_SIZE(op
)) {
1345 op
= (struct ospf6_prefix
*)current
;
1346 if (op
->prefix_length
== 0
1347 || current
+ OSPF6_PREFIX_SIZE(op
) > end
)
1350 route
= ospf6_route_create();
1352 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
1353 route
->prefix
.family
= AF_INET6
;
1354 route
->prefix
.prefixlen
= op
->prefix_length
;
1355 memset(&route
->prefix
.u
.prefix6
, 0,
1356 sizeof(struct in6_addr
));
1357 memcpy(&route
->prefix
.u
.prefix6
, OSPF6_PREFIX_BODY(op
),
1358 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1360 route
->path
.origin
.type
= lsa
->header
->type
;
1361 route
->path
.origin
.id
= lsa
->header
->id
;
1362 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1363 route
->path
.options
[0] = link_lsa
->options
[0];
1364 route
->path
.options
[1] = link_lsa
->options
[1];
1365 route
->path
.options
[2] = link_lsa
->options
[2];
1366 route
->path
.prefix_options
= op
->prefix_options
;
1367 route
->path
.area_id
= oi
->area
->area_id
;
1368 route
->path
.type
= OSPF6_PATH_TYPE_INTRA
;
1370 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1371 zlog_debug(" include %pFX", &route
->prefix
);
1373 ospf6_route_add(route
, route_advertise
);
1376 if (current
!= end
&& IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1377 zlog_debug("Trailing garbage in %s", lsa
->name
);
1380 op
= (struct ospf6_prefix
*)((caddr_t
)intra_prefix_lsa
1381 + sizeof(struct ospf6_intra_prefix_lsa
));
1384 for (route
= ospf6_route_head(route_advertise
); route
;
1385 route
= ospf6_route_best_next(route
)) {
1386 op
->prefix_length
= route
->prefix
.prefixlen
;
1387 op
->prefix_options
= route
->path
.prefix_options
;
1388 op
->prefix_metric
= htons(0);
1389 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
1390 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1391 op
= OSPF6_PREFIX_NEXT(op
);
1395 ospf6_route_table_delete(route_advertise
);
1397 if (prefix_num
== 0) {
1398 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1400 "Quit to Advertise Intra-Prefix: no route to advertise");
1404 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
1406 /* Fill LSA Header */
1407 lsa_header
->age
= 0;
1408 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1409 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
1410 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
1411 lsa_header
->seqnum
=
1412 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
1413 lsa_header
->adv_router
, oi
->area
->lsdb
);
1414 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)lsa_header
);
1417 ospf6_lsa_checksum(lsa_header
);
1420 lsa
= ospf6_lsa_create(lsa_header
);
1423 ospf6_lsa_originate_area(lsa
, oi
->area
);
1428 static void ospf6_intra_prefix_update_route_origin(struct ospf6_route
*oa_route
,
1429 struct ospf6
*ospf6
)
1431 struct ospf6_path
*h_path
;
1432 struct ospf6_route
*g_route
, *nroute
;
1434 /* Update Global ospf6 route path */
1435 g_route
= ospf6_route_lookup(&oa_route
->prefix
, ospf6
->route_table
);
1439 for (ospf6_route_lock(g_route
); g_route
&&
1440 ospf6_route_is_prefix(&oa_route
->prefix
, g_route
);
1442 nroute
= ospf6_route_next(g_route
);
1443 if (g_route
->type
!= oa_route
->type
)
1445 if (g_route
->path
.area_id
!= oa_route
->path
.area_id
)
1447 if (g_route
->path
.type
!= OSPF6_PATH_TYPE_INTRA
)
1449 if (g_route
->path
.cost
!= oa_route
->path
.cost
)
1452 if (ospf6_route_is_same_origin(g_route
, oa_route
)) {
1453 h_path
= (struct ospf6_path
*)listgetdata(
1454 listhead(g_route
->paths
));
1455 g_route
->path
.origin
.type
= h_path
->origin
.type
;
1456 g_route
->path
.origin
.id
= h_path
->origin
.id
;
1457 g_route
->path
.origin
.adv_router
=
1458 h_path
->origin
.adv_router
;
1460 ospf6_route_unlock(nroute
);
1465 h_path
= (struct ospf6_path
*)listgetdata(
1466 listhead(oa_route
->paths
));
1467 oa_route
->path
.origin
.type
= h_path
->origin
.type
;
1468 oa_route
->path
.origin
.id
= h_path
->origin
.id
;
1469 oa_route
->path
.origin
.adv_router
= h_path
->origin
.adv_router
;
1472 void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area
*oa
,
1473 struct ospf6_route
*old
,
1474 struct ospf6_route
*route
)
1476 struct ospf6_route
*old_route
, *ls_entry
;
1477 struct ospf6_path
*ecmp_path
, *o_path
= NULL
;
1478 struct listnode
*anode
, *anext
;
1479 struct listnode
*nnode
, *rnode
, *rnext
;
1480 struct ospf6_nexthop
*nh
, *rnh
;
1481 char buf
[PREFIX2STR_BUFFER
];
1482 bool route_found
= false;
1483 struct interface
*ifp
= NULL
;
1484 struct ospf6_lsa
*lsa
;
1485 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1487 /* check for old entry match with new route origin,
1490 for (old_route
= old
; old_route
; old_route
= old_route
->next
) {
1491 bool route_updated
= false;
1493 if (!ospf6_route_is_same(old_route
, route
) ||
1494 (old_route
->path
.type
!= route
->path
.type
))
1497 /* Current and New route has same origin,
1500 for (ALL_LIST_ELEMENTS(old_route
->paths
, anode
, anext
,
1502 /* Check old route path and route has same
1505 if (o_path
->area_id
!= route
->path
.area_id
||
1506 (memcmp(&(o_path
)->origin
, &(route
)->path
.origin
,
1507 sizeof(struct ospf6_ls_origin
)) != 0))
1510 /* Cost is not same then delete current path */
1511 if (o_path
->cost
== route
->path
.cost
)
1514 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1516 "%s: route %pFX cost old %u new %u is not same, replace route",
1517 __func__
, &old_route
->prefix
, o_path
->cost
,
1521 /* Remove selected current path's nh from
1522 * effective nh list.
1524 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
, nnode
, nh
)) {
1525 for (ALL_LIST_ELEMENTS(old_route
->nh_list
,
1526 rnode
, rnext
, rnh
)) {
1527 if (!ospf6_nexthop_is_same(rnh
, nh
))
1529 listnode_delete(old_route
->nh_list
,
1531 ospf6_nexthop_delete(rnh
);
1532 route_updated
= true;
1536 listnode_delete(old_route
->paths
, o_path
);
1537 ospf6_path_free(o_path
);
1539 /* Current route's path (adv_router info) is similar
1540 * to route being added.
1541 * Replace current route's path with paths list head.
1542 * Update FIB with effective NHs.
1544 if (listcount(old_route
->paths
)) {
1545 if (route_updated
) {
1546 for (ALL_LIST_ELEMENTS(old_route
->paths
,
1547 anode
, anext
, o_path
)) {
1548 ospf6_merge_nexthops(
1552 /* Update ospf6 route table and
1553 * RIB/FIB with effective
1556 if (oa
->route_table
->hook_add
)
1557 (*oa
->route_table
->hook_add
)(
1560 if (old_route
->path
.origin
.id
==
1561 route
->path
.origin
.id
&&
1562 old_route
->path
.origin
.adv_router
==
1563 route
->path
.origin
.adv_router
) {
1564 ospf6_intra_prefix_update_route_origin(
1565 old_route
, oa
->ospf6
);
1570 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1572 "%s: route %pFX old cost %u new cost %u, delete old entry.",
1573 __func__
, &old_route
->prefix
,
1574 old_route
->path
.cost
,
1577 if (oa
->route_table
->hook_remove
)
1578 ospf6_route_remove(old_route
,
1581 SET_FLAG(old_route
->flag
,
1582 OSPF6_ROUTE_REMOVE
);
1590 for (old_route
= old
; old_route
; old_route
= old_route
->next
) {
1592 if (!ospf6_route_is_same(old_route
, route
) ||
1593 (old_route
->path
.type
!= route
->path
.type
))
1596 /* Old Route and New Route have Equal Cost, Merge NHs */
1597 if (old_route
->path
.cost
== route
->path
.cost
) {
1600 /* check if this path exists already in
1601 * route->paths list, if so, replace nh_list.
1603 for (ALL_LIST_ELEMENTS_RO(old_route
->paths
, anode
,
1605 if (o_path
->area_id
== route
->path
.area_id
&&
1606 (memcmp(&(o_path
)->origin
,
1607 &(route
)->path
.origin
,
1608 sizeof(struct ospf6_ls_origin
)) == 0))
1611 /* If path is not found in old_route paths's list,
1612 * add a new path to route paths list and merge
1613 * nexthops in route->path->nh_list.
1614 * Otherwise replace existing path's nh_list.
1616 if (o_path
== NULL
) {
1617 ecmp_path
= ospf6_path_dup(&route
->path
);
1619 /* Add a nh_list to new ecmp path */
1620 ospf6_copy_nexthops(ecmp_path
->nh_list
,
1622 /* Add the new path to route's path list */
1623 listnode_add_sort(old_route
->paths
, ecmp_path
);
1625 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1627 "%s: route %pFX %p another path added with nh %u, effective paths %u nh %u",
1628 __func__
, &route
->prefix
,
1630 listcount(ecmp_path
->nh_list
),
1631 old_route
->paths
? listcount(
1634 listcount(old_route
->nh_list
));
1637 list_delete_all_node(o_path
->nh_list
);
1638 ospf6_copy_nexthops(o_path
->nh_list
,
1643 list_delete_all_node(old_route
->nh_list
);
1645 for (ALL_LIST_ELEMENTS_RO(old_route
->paths
, anode
,
1647 ls_entry
= ospf6_route_lookup(
1650 if (ls_entry
== NULL
) {
1651 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1653 "%s: ls_prfix %s ls_entry not found.",
1657 lsa
= ospf6_lsdb_lookup(o_path
->origin
.type
,
1659 o_path
->origin
.adv_router
,
1662 if (IS_OSPF6_DEBUG_EXAMIN(
1664 struct prefix adv_prefix
;
1666 ospf6_linkstate_prefix(
1667 o_path
->origin
.adv_router
,
1668 o_path
->origin
.id
, &adv_prefix
);
1670 "%s: adv_router %pFX lsa not found",
1671 __func__
, &adv_prefix
);
1676 (struct ospf6_intra_prefix_lsa
*)
1677 OSPF6_LSA_HEADER_END(lsa
->header
);
1679 if (intra_prefix_lsa
->ref_adv_router
1680 == oa
->ospf6
->router_id
) {
1681 ifp
= if_lookup_prefix(
1687 /* Nexthop interface found */
1688 ospf6_route_add_nexthop(old_route
,
1692 /* The connected interfaces between
1693 * routers can be in different networks.
1694 * In this case the matching interface
1695 * is not found. Copy nexthops from the
1698 ospf6_route_merge_nexthops(old_route
,
1703 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1705 "%s: route %pFX %p with final effective paths %u nh %u",
1706 __func__
, &route
->prefix
,
1709 ? listcount(old_route
->paths
)
1711 listcount(old_route
->nh_list
));
1713 /* used in intra_route_calculation() to add to
1714 * global ospf6 route table.
1716 UNSET_FLAG(old_route
->flag
, OSPF6_ROUTE_REMOVE
);
1717 SET_FLAG(old_route
->flag
, OSPF6_ROUTE_ADD
);
1718 /* Update ospf6 route table and RIB/FIB */
1719 if (oa
->route_table
->hook_add
)
1720 (*oa
->route_table
->hook_add
)(old_route
);
1721 /* Delete the new route its info added to existing
1724 ospf6_route_delete(route
);
1731 /* Add new route to existing node in ospf6 route table. */
1732 ospf6_route_add(route
, oa
->route_table
);
1736 void ospf6_intra_prefix_lsa_add(struct ospf6_lsa
*lsa
)
1738 struct ospf6_area
*oa
;
1739 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1740 struct prefix ls_prefix
;
1741 struct ospf6_route
*route
, *ls_entry
, *old
;
1743 struct ospf6_prefix
*op
;
1744 char *start
, *current
, *end
;
1745 char buf
[PREFIX2STR_BUFFER
];
1746 struct interface
*ifp
= NULL
;
1747 int direct_connect
= 0;
1748 struct ospf6_path
*path
;
1750 if (OSPF6_LSA_IS_MAXAGE(lsa
))
1753 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1754 zlog_debug("%s: LSA %s found", __func__
, lsa
->name
);
1756 oa
= OSPF6_AREA(lsa
->lsdb
->data
);
1759 (struct ospf6_intra_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1761 if (intra_prefix_lsa
->ref_type
== htons(OSPF6_LSTYPE_ROUTER
))
1762 ospf6_linkstate_prefix(intra_prefix_lsa
->ref_adv_router
,
1763 intra_prefix_lsa
->ref_id
, &ls_prefix
);
1764 else if (intra_prefix_lsa
->ref_type
== htons(OSPF6_LSTYPE_NETWORK
))
1765 ospf6_linkstate_prefix(intra_prefix_lsa
->ref_adv_router
,
1766 intra_prefix_lsa
->ref_id
, &ls_prefix
);
1768 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1769 zlog_debug("Unknown reference LS-type: %#hx",
1770 ntohs(intra_prefix_lsa
->ref_type
));
1774 ls_entry
= ospf6_route_lookup(&ls_prefix
, oa
->spf_table
);
1775 if (ls_entry
== NULL
) {
1776 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1777 ospf6_linkstate_prefix2str(&ls_prefix
, buf
,
1779 zlog_debug("LS entry does not exist: %s", buf
);
1784 if (intra_prefix_lsa
->ref_adv_router
== oa
->ospf6
->router_id
) {
1785 /* the intra-prefix are directly connected */
1789 prefix_num
= ntohs(intra_prefix_lsa
->prefix_num
);
1790 start
= (caddr_t
)intra_prefix_lsa
1791 + sizeof(struct ospf6_intra_prefix_lsa
);
1792 end
= OSPF6_LSA_END(lsa
->header
);
1793 for (current
= start
; current
< end
; current
+= OSPF6_PREFIX_SIZE(op
)) {
1794 op
= (struct ospf6_prefix
*)current
;
1795 if (prefix_num
== 0)
1797 if (end
< current
+ OSPF6_PREFIX_SIZE(op
))
1800 /* Appendix A.4.1.1 */
1801 if (CHECK_FLAG(op
->prefix_options
, OSPF6_PREFIX_OPTION_NU
)) {
1802 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1803 ospf6_linkstate_prefix2str(
1804 (struct prefix
*)OSPF6_PREFIX_BODY(op
),
1807 "%s: Skipping Prefix %s has NU option set",
1813 route
= ospf6_route_create();
1815 memset(&route
->prefix
, 0, sizeof(struct prefix
));
1816 route
->prefix
.family
= AF_INET6
;
1817 route
->prefix
.prefixlen
= op
->prefix_length
;
1818 ospf6_prefix_in6_addr(&route
->prefix
.u
.prefix6
,
1819 intra_prefix_lsa
, op
);
1821 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
1822 route
->path
.origin
.type
= lsa
->header
->type
;
1823 route
->path
.origin
.id
= lsa
->header
->id
;
1824 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1825 route
->path
.prefix_options
= op
->prefix_options
;
1826 route
->path
.area_id
= oa
->area_id
;
1827 route
->path
.type
= OSPF6_PATH_TYPE_INTRA
;
1828 route
->path
.metric_type
= 1;
1830 ls_entry
->path
.cost
+ ntohs(op
->prefix_metric
);
1831 memcpy(&route
->path
.ls_prefix
, &ls_prefix
,
1832 sizeof(struct prefix
));
1833 if (direct_connect
) {
1834 ifp
= if_lookup_prefix(&route
->prefix
,
1839 /* Nexthop interface found */
1840 ospf6_route_add_nexthop(route
, ifp
->ifindex
, NULL
);
1842 /* The connected interfaces between routers can be in
1843 * different networks. In this case the matching
1844 * interface is not found. Copy nexthops from the
1847 ospf6_route_copy_nexthops(route
, ls_entry
);
1850 path
= ospf6_path_dup(&route
->path
);
1851 ospf6_copy_nexthops(path
->nh_list
, route
->path
.nh_list
);
1852 listnode_add_sort(route
->paths
, path
);
1854 old
= ospf6_route_lookup(&route
->prefix
, oa
->route_table
);
1856 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1857 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1859 "%s Update route: %s old cost %u new cost %u paths %u nh %u",
1860 __func__
, buf
, old
->path
.cost
,
1862 listcount(route
->paths
),
1863 listcount(route
->nh_list
));
1865 ospf6_intra_prefix_route_ecmp_path(oa
, old
, route
);
1867 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1868 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1870 "%s route %s add with cost %u paths %u nh %u",
1871 __func__
, buf
, route
->path
.cost
,
1872 listcount(route
->paths
),
1873 listcount(route
->nh_list
));
1875 ospf6_route_add(route
, oa
->route_table
);
1880 if (current
!= end
&& IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1881 zlog_debug("Trailing garbage ignored");
1884 static void ospf6_intra_prefix_lsa_remove_update_route(struct ospf6_lsa
*lsa
,
1885 struct ospf6_area
*oa
,
1886 struct ospf6_route
*route
)
1888 struct listnode
*anode
, *anext
;
1889 struct listnode
*nnode
, *rnode
, *rnext
;
1890 struct ospf6_nexthop
*nh
, *rnh
;
1891 struct ospf6_path
*o_path
;
1892 bool nh_updated
= false;
1893 char buf
[PREFIX2STR_BUFFER
];
1895 /* Iterate all paths of route to find maching
1896 * with LSA remove info.
1897 * If route->path is same, replace
1900 for (ALL_LIST_ELEMENTS(route
->paths
, anode
, anext
, o_path
)) {
1901 if ((o_path
->origin
.type
!= lsa
->header
->type
) ||
1902 (o_path
->origin
.adv_router
!= lsa
->header
->adv_router
) ||
1903 (o_path
->origin
.id
!= lsa
->header
->id
))
1906 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1907 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1909 "%s: route %s path found with cost %u nh %u to remove.",
1910 __func__
, buf
, o_path
->cost
,
1911 listcount(o_path
->nh_list
));
1914 /* Remove found path's nh_list from
1915 * the route's nh_list.
1917 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
, nnode
, nh
)) {
1918 for (ALL_LIST_ELEMENTS(route
->nh_list
, rnode
,
1920 if (!ospf6_nexthop_is_same(rnh
, nh
))
1922 listnode_delete(route
->nh_list
, rnh
);
1923 ospf6_nexthop_delete(rnh
);
1926 /* Delete the path from route's
1929 listnode_delete(route
->paths
, o_path
);
1930 ospf6_path_free(o_path
);
1936 /* Iterate all paths and merge nexthop,
1937 * unlesss any of the nexthop similar to
1938 * ones deleted as part of path deletion.
1940 for (ALL_LIST_ELEMENTS(route
->paths
, anode
, anext
, o_path
))
1941 ospf6_merge_nexthops(route
->nh_list
, o_path
->nh_list
);
1944 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1945 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1947 "%s: route %s update paths %u nh %u", __func__
,
1948 buf
, route
->paths
? listcount(route
->paths
) : 0,
1949 route
->nh_list
? listcount(route
->nh_list
) : 0);
1952 /* Update Global Route table and
1953 * RIB/FIB with effective
1956 if (oa
->route_table
->hook_add
)
1957 (*oa
->route_table
->hook_add
)(route
);
1959 /* route's primary path is similar
1960 * to LSA, replace route's primary
1961 * path with route's paths list
1964 if ((route
->path
.origin
.id
== lsa
->header
->id
) &&
1965 (route
->path
.origin
.adv_router
==
1966 lsa
->header
->adv_router
)) {
1967 ospf6_intra_prefix_update_route_origin(route
,
1974 void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa
*lsa
)
1976 struct ospf6_area
*oa
;
1977 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1978 struct prefix prefix
;
1979 struct ospf6_route
*route
, *nroute
;
1981 struct ospf6_prefix
*op
;
1982 char *start
, *current
, *end
;
1983 char buf
[PREFIX2STR_BUFFER
];
1985 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1986 zlog_debug("%s: %s disappearing", __func__
, lsa
->name
);
1988 oa
= OSPF6_AREA(lsa
->lsdb
->data
);
1991 (struct ospf6_intra_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1994 prefix_num
= ntohs(intra_prefix_lsa
->prefix_num
);
1995 start
= (caddr_t
)intra_prefix_lsa
1996 + sizeof(struct ospf6_intra_prefix_lsa
);
1997 end
= OSPF6_LSA_END(lsa
->header
);
1998 for (current
= start
; current
< end
; current
+= OSPF6_PREFIX_SIZE(op
)) {
1999 op
= (struct ospf6_prefix
*)current
;
2000 if (prefix_num
== 0)
2002 if (end
< current
+ OSPF6_PREFIX_SIZE(op
))
2006 memset(&prefix
, 0, sizeof(struct prefix
));
2007 prefix
.family
= AF_INET6
;
2008 prefix
.prefixlen
= op
->prefix_length
;
2009 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, intra_prefix_lsa
, op
);
2011 route
= ospf6_route_lookup(&prefix
, oa
->route_table
);
2015 for (ospf6_route_lock(route
);
2016 route
&& ospf6_route_is_prefix(&prefix
, route
);
2018 nroute
= ospf6_route_next(route
);
2019 if (route
->type
!= OSPF6_DEST_TYPE_NETWORK
)
2021 if (route
->path
.area_id
!= oa
->area_id
)
2023 if (route
->path
.type
!= OSPF6_PATH_TYPE_INTRA
)
2025 /* Route has multiple ECMP paths, remove matching
2026 * path. Update current route's effective nh list
2027 * after removal of one of the path.
2029 if (listcount(route
->paths
) > 1) {
2030 ospf6_intra_prefix_lsa_remove_update_route(
2034 if (route
->path
.origin
.type
!= lsa
->header
->type
2035 || route
->path
.origin
.id
!= lsa
->header
->id
2036 || route
->path
.origin
.adv_router
2037 != lsa
->header
->adv_router
)
2040 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
2041 prefix2str(&route
->prefix
, buf
,
2044 "%s: route remove %s with path type %u cost %u paths %u nh %u",
2045 __func__
, buf
, route
->path
.type
,
2047 listcount(route
->paths
),
2048 listcount(route
->nh_list
));
2050 ospf6_route_remove(route
, oa
->route_table
);
2054 ospf6_route_unlock(route
);
2057 if (current
!= end
&& IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
2058 zlog_debug("Trailing garbage ignored");
2061 void ospf6_intra_route_calculation(struct ospf6_area
*oa
)
2063 struct ospf6_route
*route
, *nroute
;
2065 struct ospf6_lsa
*lsa
;
2066 void (*hook_add
)(struct ospf6_route
*) = NULL
;
2067 void (*hook_remove
)(struct ospf6_route
*) = NULL
;
2068 char buf
[PREFIX2STR_BUFFER
];
2070 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
2071 zlog_debug("Re-examin intra-routes for area %s", oa
->name
);
2073 hook_add
= oa
->route_table
->hook_add
;
2074 hook_remove
= oa
->route_table
->hook_remove
;
2075 oa
->route_table
->hook_add
= NULL
;
2076 oa
->route_table
->hook_remove
= NULL
;
2078 for (route
= ospf6_route_head(oa
->route_table
); route
;
2079 route
= ospf6_route_next(route
))
2080 route
->flag
= OSPF6_ROUTE_REMOVE
;
2082 type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
2083 for (ALL_LSDB_TYPED(oa
->lsdb
, type
, lsa
))
2084 ospf6_intra_prefix_lsa_add(lsa
);
2086 oa
->route_table
->hook_add
= hook_add
;
2087 oa
->route_table
->hook_remove
= hook_remove
;
2089 for (route
= ospf6_route_head(oa
->route_table
); route
; route
= nroute
) {
2090 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
2091 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
2092 zlog_debug("%s: route %s, flag 0x%x", __func__
, buf
,
2096 nroute
= ospf6_route_next(route
);
2097 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
)
2098 && CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ADD
)) {
2099 UNSET_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
);
2100 UNSET_FLAG(route
->flag
, OSPF6_ROUTE_ADD
);
2103 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
))
2104 ospf6_route_remove(route
, oa
->route_table
);
2105 else if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ADD
)
2106 || CHECK_FLAG(route
->flag
, OSPF6_ROUTE_CHANGE
)) {
2111 /* Redo the summaries as things might have changed */
2112 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
2113 zlog_debug("%s: Originate summary for route %s",
2115 ospf6_abr_originate_summary(route
, oa
->ospf6
);
2120 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
2121 zlog_debug("Re-examin intra-routes for area %s: Done",
2125 static void ospf6_brouter_debug_print(struct ospf6_route
*brouter
)
2127 uint32_t brouter_id
;
2128 char brouter_name
[16];
2130 char destination
[64];
2131 char installed
[64], changed
[64];
2132 struct timeval now
, res
;
2133 char id
[16], adv_router
[16];
2134 char capa
[16], options
[16];
2136 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2137 inet_ntop(AF_INET
, &brouter_id
, brouter_name
, sizeof(brouter_name
));
2138 inet_ntop(AF_INET
, &brouter
->path
.area_id
, area_name
,
2140 ospf6_linkstate_prefix2str(&brouter
->prefix
, destination
,
2141 sizeof(destination
));
2144 timersub(&now
, &brouter
->installed
, &res
);
2145 timerstring(&res
, installed
, sizeof(installed
));
2148 timersub(&now
, &brouter
->changed
, &res
);
2149 timerstring(&res
, changed
, sizeof(changed
));
2151 inet_ntop(AF_INET
, &brouter
->path
.origin
.id
, id
, sizeof(id
));
2152 inet_ntop(AF_INET
, &brouter
->path
.origin
.adv_router
, adv_router
,
2153 sizeof(adv_router
));
2155 ospf6_options_printbuf(brouter
->path
.options
, options
, sizeof(options
));
2156 ospf6_capability_printbuf(brouter
->path
.router_bits
, capa
,
2159 zlog_info("Brouter: %s via area %s", brouter_name
, area_name
);
2160 zlog_info(" memory: prev: %p this: %p next: %p parent rnode: %p",
2161 (void *)brouter
->prev
, (void *)brouter
, (void *)brouter
->next
,
2162 (void *)brouter
->rnode
);
2163 zlog_info(" type: %d prefix: %s installed: %s changed: %s",
2164 brouter
->type
, destination
, installed
, changed
);
2165 zlog_info(" lock: %d flags: %s%s%s%s", brouter
->lock
,
2166 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_BEST
) ? "B" : "-"),
2167 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
) ? "A" : "-"),
2168 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
) ? "R" : "-"),
2169 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
) ? "C" : "-"));
2170 zlog_info(" path type: %s ls-origin %s id: %s adv-router %s",
2171 OSPF6_PATH_TYPE_NAME(brouter
->path
.type
),
2172 ospf6_lstype_name(brouter
->path
.origin
.type
), id
, adv_router
);
2173 zlog_info(" options: %s router-bits: %s metric-type: %d metric: %d/%d",
2174 options
, capa
, brouter
->path
.metric_type
, brouter
->path
.cost
,
2175 brouter
->path
.u
.cost_e2
);
2176 zlog_info(" paths %u nh %u", listcount(brouter
->paths
),
2177 listcount(brouter
->nh_list
));
2180 void ospf6_intra_brouter_calculation(struct ospf6_area
*oa
)
2182 struct ospf6_route
*brouter
, *nbrouter
, *copy
;
2183 void (*hook_add
)(struct ospf6_route
*) = NULL
;
2184 void (*hook_remove
)(struct ospf6_route
*) = NULL
;
2185 uint32_t brouter_id
;
2186 char brouter_name
[16];
2188 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa
->area_id
) ||
2189 IS_OSPF6_DEBUG_ROUTE(MEMORY
))
2190 zlog_debug("%s: border-router calculation for area %s",
2191 __func__
, oa
->name
);
2193 hook_add
= oa
->ospf6
->brouter_table
->hook_add
;
2194 hook_remove
= oa
->ospf6
->brouter_table
->hook_remove
;
2195 oa
->ospf6
->brouter_table
->hook_add
= NULL
;
2196 oa
->ospf6
->brouter_table
->hook_remove
= NULL
;
2198 /* withdraw the previous router entries for the area */
2199 for (brouter
= ospf6_route_head(oa
->ospf6
->brouter_table
); brouter
;
2200 brouter
= ospf6_route_next(brouter
)) {
2201 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2202 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
2203 sizeof(brouter_name
));
2205 if (brouter
->path
.area_id
!= oa
->area_id
)
2208 SET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
2210 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id
)
2211 || IS_OSPF6_DEBUG_ROUTE(MEMORY
)) {
2212 zlog_debug("%p: mark as removing: area %s brouter %s",
2213 (void *)brouter
, oa
->name
, brouter_name
);
2214 ospf6_brouter_debug_print(brouter
);
2218 for (brouter
= ospf6_route_head(oa
->spf_table
); brouter
;
2219 brouter
= ospf6_route_next(brouter
)) {
2220 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2221 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
2222 sizeof(brouter_name
));
2224 if (brouter
->type
!= OSPF6_DEST_TYPE_LINKSTATE
)
2227 if (ospf6_linkstate_prefix_id(&brouter
->prefix
) != htonl(0))
2230 if (!CHECK_FLAG(brouter
->path
.router_bits
, OSPF6_ROUTER_BIT_E
)
2231 && !CHECK_FLAG(brouter
->path
.router_bits
,
2232 OSPF6_ROUTER_BIT_B
))
2235 if (!OSPF6_OPT_ISSET(brouter
->path
.options
, OSPF6_OPT_V6
)
2236 || !OSPF6_OPT_ISSET(brouter
->path
.options
, OSPF6_OPT_R
))
2239 copy
= ospf6_route_copy(brouter
);
2240 copy
->type
= OSPF6_DEST_TYPE_ROUTER
;
2241 copy
->path
.area_id
= oa
->area_id
;
2242 ospf6_route_add(copy
, oa
->ospf6
->brouter_table
);
2244 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id
)
2245 || IS_OSPF6_DEBUG_ROUTE(MEMORY
)) {
2246 zlog_debug("%p: transfer: area %s brouter %s",
2247 (void *)brouter
, oa
->name
, brouter_name
);
2248 ospf6_brouter_debug_print(brouter
);
2252 oa
->ospf6
->brouter_table
->hook_add
= hook_add
;
2253 oa
->ospf6
->brouter_table
->hook_remove
= hook_remove
;
2255 for (brouter
= ospf6_route_head(oa
->ospf6
->brouter_table
); brouter
;
2256 brouter
= nbrouter
) {
2259 * brouter may have been "deleted" in the last loop iteration.
2260 * If this is the case there is still 1 final refcount lock
2261 * taken by ospf6_route_next, that will be released by the same
2262 * call and result in deletion. To avoid heap UAF we must then
2263 * skip processing the deleted route.
2265 if (brouter
->lock
== 1) {
2266 if (IS_OSPF6_DEBUG_ROUTE(MEMORY
))
2267 ospf6_brouter_debug_print(brouter
);
2268 nbrouter
= ospf6_route_next(brouter
);
2271 nbrouter
= ospf6_route_next(brouter
);
2274 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2275 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
2276 sizeof(brouter_name
));
2278 if (brouter
->path
.area_id
!= oa
->area_id
)
2281 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_WAS_REMOVED
))
2284 /* After iterating spf_table for all routers including
2285 * intra brouter, clear mark for remove flag for
2286 * inter border router if its adv router present in
2289 if (brouter
->path
.type
== OSPF6_PATH_TYPE_INTER
) {
2290 struct prefix adv_prefix
;
2292 ospf6_linkstate_prefix(brouter
->path
.origin
.adv_router
,
2293 htonl(0), &adv_prefix
);
2295 if (ospf6_route_lookup(&adv_prefix
, oa
->spf_table
)) {
2296 if (IS_OSPF6_DEBUG_BROUTER
) {
2298 "%s: keep inter brouter %s as adv router 0x%x found in spf",
2299 __func__
, brouter_name
,
2300 brouter
->path
.origin
2302 ospf6_brouter_debug_print(brouter
);
2304 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
2308 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
)
2309 && CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
)) {
2310 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
2311 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
);
2314 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
)) {
2315 if (IS_OSPF6_DEBUG_BROUTER
2316 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2318 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2321 "%s: brouter %s disappears via area %s",
2322 __func__
, brouter_name
, oa
->name
);
2323 /* This is used to protect nbrouter from removed from
2324 * the table. For an example, ospf6_abr_examin_summary,
2325 * removes brouters which are marked for remove.
2327 oa
->intra_brouter_calc
= 1;
2328 ospf6_route_remove(brouter
, oa
->ospf6
->brouter_table
);
2330 } else if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
)
2331 || CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
)) {
2332 if (IS_OSPF6_DEBUG_BROUTER
2333 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2335 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2337 zlog_info("%s: brouter %s appears via area %s",
2338 __func__
, brouter_name
, oa
->name
);
2342 (*hook_add
)(brouter
);
2344 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2346 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2349 "brouter %s still exists via area %s",
2350 brouter_name
, oa
->name
);
2351 /* But re-originate summaries */
2352 ospf6_abr_originate_summary(brouter
, oa
->ospf6
);
2356 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
);
2357 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
);
2359 /* Reset for nbrouter */
2360 oa
->intra_brouter_calc
= 0;
2363 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa
->area_id
) ||
2364 IS_OSPF6_DEBUG_ROUTE(MEMORY
))
2365 zlog_debug("%s: border-router calculation for area %s: done",
2366 __func__
, oa
->name
);
2369 static struct ospf6_lsa_handler router_handler
= {
2370 .lh_type
= OSPF6_LSTYPE_ROUTER
,
2371 .lh_name
= "Router",
2372 .lh_short_name
= "Rtr",
2373 .lh_show
= ospf6_router_lsa_show
,
2374 .lh_get_prefix_str
= ospf6_router_lsa_get_nbr_id
,
2377 static struct ospf6_lsa_handler network_handler
= {
2378 .lh_type
= OSPF6_LSTYPE_NETWORK
,
2379 .lh_name
= "Network",
2380 .lh_short_name
= "Net",
2381 .lh_show
= ospf6_network_lsa_show
,
2382 .lh_get_prefix_str
= ospf6_network_lsa_get_ar_id
,
2385 static struct ospf6_lsa_handler link_handler
= {
2386 .lh_type
= OSPF6_LSTYPE_LINK
,
2388 .lh_short_name
= "Lnk",
2389 .lh_show
= ospf6_link_lsa_show
,
2390 .lh_get_prefix_str
= ospf6_link_lsa_get_prefix_str
,
2393 static struct ospf6_lsa_handler intra_prefix_handler
= {
2394 .lh_type
= OSPF6_LSTYPE_INTRA_PREFIX
,
2395 .lh_name
= "Intra-Prefix",
2396 .lh_short_name
= "INP",
2397 .lh_show
= ospf6_intra_prefix_lsa_show
,
2398 .lh_get_prefix_str
= ospf6_intra_prefix_lsa_get_prefix_str
,
2401 void ospf6_intra_init(void)
2403 ospf6_install_lsa_handler(&router_handler
);
2404 ospf6_install_lsa_handler(&network_handler
);
2405 ospf6_install_lsa_handler(&link_handler
);
2406 ospf6_install_lsa_handler(&intra_prefix_handler
);
2409 DEFUN (debug_ospf6_brouter
,
2410 debug_ospf6_brouter_cmd
,
2411 "debug ospf6 border-routers",
2414 "Debug border router\n"
2417 OSPF6_DEBUG_BROUTER_ON();
2421 DEFUN (no_debug_ospf6_brouter
,
2422 no_debug_ospf6_brouter_cmd
,
2423 "no debug ospf6 border-routers",
2427 "Debug border router\n"
2430 OSPF6_DEBUG_BROUTER_OFF();
2434 DEFUN (debug_ospf6_brouter_router
,
2435 debug_ospf6_brouter_router_cmd
,
2436 "debug ospf6 border-routers router-id A.B.C.D",
2439 "Debug border router\n"
2440 "Debug specific border router\n"
2441 "Specify border-router's router-id\n"
2446 inet_pton(AF_INET
, argv
[idx_ipv4
]->arg
, &router_id
);
2447 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON(router_id
);
2451 DEFUN (no_debug_ospf6_brouter_router
,
2452 no_debug_ospf6_brouter_router_cmd
,
2453 "no debug ospf6 border-routers router-id",
2457 "Debug border router\n"
2458 "Debug specific border router\n"
2461 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF();
2465 DEFUN (debug_ospf6_brouter_area
,
2466 debug_ospf6_brouter_area_cmd
,
2467 "debug ospf6 border-routers area-id A.B.C.D",
2470 "Debug border router\n"
2471 "Debug border routers in specific Area\n"
2477 inet_pton(AF_INET
, argv
[idx_ipv4
]->arg
, &area_id
);
2478 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON(area_id
);
2482 DEFUN (no_debug_ospf6_brouter_area
,
2483 no_debug_ospf6_brouter_area_cmd
,
2484 "no debug ospf6 border-routers area-id",
2488 "Debug border router\n"
2489 "Debug border routers in specific Area\n"
2492 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF();
2496 int config_write_ospf6_debug_brouter(struct vty
*vty
)
2499 if (IS_OSPF6_DEBUG_BROUTER
)
2500 vty_out(vty
, "debug ospf6 border-routers\n");
2501 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER
) {
2502 inet_ntop(AF_INET
, &conf_debug_ospf6_brouter_specific_router_id
,
2504 vty_out(vty
, "debug ospf6 border-routers router-id %s\n", buf
);
2506 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA
) {
2507 inet_ntop(AF_INET
, &conf_debug_ospf6_brouter_specific_area_id
,
2509 vty_out(vty
, "debug ospf6 border-routers area-id %s\n", buf
);
2514 void install_element_ospf6_debug_brouter(void)
2516 install_element(ENABLE_NODE
, &debug_ospf6_brouter_cmd
);
2517 install_element(ENABLE_NODE
, &debug_ospf6_brouter_router_cmd
);
2518 install_element(ENABLE_NODE
, &debug_ospf6_brouter_area_cmd
);
2519 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_cmd
);
2520 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_router_cmd
);
2521 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_area_cmd
);
2522 install_element(CONFIG_NODE
, &debug_ospf6_brouter_cmd
);
2523 install_element(CONFIG_NODE
, &debug_ospf6_brouter_router_cmd
);
2524 install_element(CONFIG_NODE
, &debug_ospf6_brouter_area_cmd
);
2525 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_cmd
);
2526 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_router_cmd
);
2527 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_area_cmd
);