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
< end
) {
80 if (buf
&& (buflen
> INET_ADDRSTRLEN
* 2)) {
82 &lsdesc
->neighbor_interface_id
, buf1
,
84 inet_ntop(AF_INET
, &lsdesc
->neighbor_router_id
,
86 sprintf(buf
, "%s/%s", buf2
, buf1
);
95 static int ospf6_router_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
)
97 char *start
, *end
, *current
;
98 char buf
[32], name
[32], bits
[16], options
[32];
99 struct ospf6_router_lsa
*router_lsa
;
100 struct ospf6_router_lsdesc
*lsdesc
;
103 (struct ospf6_router_lsa
*)((char *)lsa
->header
104 + sizeof(struct ospf6_lsa_header
));
106 ospf6_capability_printbuf(router_lsa
->bits
, bits
, sizeof(bits
));
107 ospf6_options_printbuf(router_lsa
->options
, options
, sizeof(options
));
108 vty_out(vty
, " Bits: %s Options: %s\n", bits
, options
);
110 start
= (char *)router_lsa
+ sizeof(struct ospf6_router_lsa
);
111 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
112 for (current
= start
;
113 current
+ sizeof(struct ospf6_router_lsdesc
) <= end
;
114 current
+= sizeof(struct ospf6_router_lsdesc
)) {
115 lsdesc
= (struct ospf6_router_lsdesc
*)current
;
117 if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_POINTTOPOINT
)
118 snprintf(name
, sizeof(name
), "Point-To-Point");
119 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK
)
120 snprintf(name
, sizeof(name
), "Transit-Network");
121 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_STUB_NETWORK
)
122 snprintf(name
, sizeof(name
), "Stub-Network");
123 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_VIRTUAL_LINK
)
124 snprintf(name
, sizeof(name
), "Virtual-Link");
126 snprintf(name
, sizeof(name
), "Unknown (%#x)",
129 vty_out(vty
, " Type: %s Metric: %d\n", name
,
130 ntohs(lsdesc
->metric
));
131 vty_out(vty
, " Interface ID: %s\n",
132 inet_ntop(AF_INET
, &lsdesc
->interface_id
, buf
,
134 vty_out(vty
, " Neighbor Interface ID: %s\n",
135 inet_ntop(AF_INET
, &lsdesc
->neighbor_interface_id
, buf
,
137 vty_out(vty
, " Neighbor Router ID: %s\n",
138 inet_ntop(AF_INET
, &lsdesc
->neighbor_router_id
, buf
,
144 static void ospf6_router_lsa_options_set(struct ospf6_area
*oa
,
145 struct ospf6_router_lsa
*router_lsa
)
147 OSPF6_OPT_CLEAR_ALL(router_lsa
->options
);
148 memcpy(router_lsa
->options
, oa
->options
, 3);
150 if (ospf6_is_router_abr(oa
->ospf6
))
151 SET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_B
);
153 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_B
);
155 if (!IS_AREA_STUB(oa
) && ospf6_asbr_is_asbr(oa
->ospf6
)) {
156 SET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_E
);
158 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_E
);
161 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_V
);
162 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_W
);
165 int ospf6_router_is_stub_router(struct ospf6_lsa
*lsa
)
167 struct ospf6_router_lsa
*rtr_lsa
;
169 if (lsa
!= NULL
&& OSPF6_LSA_IS_TYPE(ROUTER
, lsa
)) {
170 rtr_lsa
= (struct ospf6_router_lsa
171 *)((caddr_t
)lsa
->header
172 + sizeof(struct ospf6_lsa_header
));
174 if (!OSPF6_OPT_ISSET(rtr_lsa
->options
, OSPF6_OPT_R
)) {
175 return OSPF6_IS_STUB_ROUTER
;
176 } else if (!OSPF6_OPT_ISSET(rtr_lsa
->options
, OSPF6_OPT_V6
)) {
177 return OSPF6_IS_STUB_ROUTER_V6
;
181 return OSPF6_NOT_STUB_ROUTER
;
184 int ospf6_router_lsa_originate(struct thread
*thread
)
186 struct ospf6_area
*oa
;
188 char buffer
[OSPF6_MAX_LSASIZE
];
189 struct ospf6_lsa_header
*lsa_header
;
190 struct ospf6_lsa
*lsa
;
192 uint32_t link_state_id
= 0;
193 struct listnode
*node
, *nnode
;
195 struct ospf6_interface
*oi
;
196 struct ospf6_neighbor
*on
, *drouter
= NULL
;
197 struct ospf6_router_lsa
*router_lsa
;
198 struct ospf6_router_lsdesc
*lsdesc
;
203 oa
= (struct ospf6_area
*)THREAD_ARG(thread
);
204 oa
->thread_router_lsa
= NULL
;
206 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER
))
207 zlog_debug("Originate Router-LSA for Area %s", oa
->name
);
209 memset(buffer
, 0, sizeof(buffer
));
210 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
212 (struct ospf6_router_lsa
*)((caddr_t
)lsa_header
213 + sizeof(struct ospf6_lsa_header
));
215 ospf6_router_lsa_options_set(oa
, router_lsa
);
217 /* describe links for each interfaces */
218 lsdesc
= (struct ospf6_router_lsdesc
219 *)((caddr_t
)router_lsa
220 + sizeof(struct ospf6_router_lsa
));
222 for (ALL_LIST_ELEMENTS(oa
->if_list
, node
, nnode
, oi
)) {
223 /* Interfaces in state Down or Loopback are not described */
224 if (oi
->state
== OSPF6_INTERFACE_DOWN
225 || oi
->state
== OSPF6_INTERFACE_LOOPBACK
)
228 /* Nor are interfaces without any full adjacencies described */
230 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
))
231 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
237 /* Multiple Router-LSA instance according to size limit setting
239 if ((oa
->router_lsa_size_limit
!= 0)
240 && ((size_t)((char *)lsdesc
- buffer
)
241 + sizeof(struct ospf6_router_lsdesc
)
242 > oa
->router_lsa_size_limit
)) {
244 == (caddr_t
)router_lsa
245 + sizeof(struct ospf6_router_lsa
)) {
246 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER
))
248 "Size limit setting for Router-LSA too short");
252 /* Fill LSA Header */
254 lsa_header
->type
= htons(OSPF6_LSTYPE_ROUTER
);
255 lsa_header
->id
= htonl(link_state_id
);
256 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
257 lsa_header
->seqnum
= ospf6_new_ls_seqnum(
258 lsa_header
->type
, lsa_header
->id
,
259 lsa_header
->adv_router
, oa
->lsdb
);
261 htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
264 ospf6_lsa_checksum(lsa_header
);
267 lsa
= ospf6_lsa_create(lsa_header
);
270 ospf6_lsa_originate_area(lsa
, oa
);
272 /* Reset Buffer to fill next Router LSA */
273 memset(buffer
, 0, sizeof(buffer
));
274 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
276 (struct ospf6_router_lsa
277 *)((caddr_t
)lsa_header
278 + sizeof(struct ospf6_lsa_header
));
280 ospf6_router_lsa_options_set(oa
, router_lsa
);
282 /* describe links for each interfaces */
283 lsdesc
= (struct ospf6_router_lsdesc
284 *)((caddr_t
)router_lsa
285 + sizeof(struct ospf6_router_lsa
));
290 /* Point-to-Point interfaces */
291 if (oi
->type
== OSPF_IFTYPE_POINTOPOINT
) {
292 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
)) {
293 if (on
->state
!= OSPF6_NEIGHBOR_FULL
)
296 lsdesc
->type
= OSPF6_ROUTER_LSDESC_POINTTOPOINT
;
297 lsdesc
->metric
= htons(oi
->cost
);
298 lsdesc
->interface_id
=
299 htonl(oi
->interface
->ifindex
);
300 lsdesc
->neighbor_interface_id
=
302 lsdesc
->neighbor_router_id
= on
->router_id
;
308 /* Broadcast and NBMA interfaces */
309 else if (oi
->type
== OSPF_IFTYPE_BROADCAST
) {
310 /* If this router is not DR,
311 and If this router not fully adjacent with DR,
312 this interface is not transit yet: ignore. */
313 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
315 ospf6_neighbor_lookup(oi
->drouter
, oi
);
317 || drouter
->state
!= OSPF6_NEIGHBOR_FULL
)
321 lsdesc
->type
= OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK
;
322 lsdesc
->metric
= htons(oi
->cost
);
323 lsdesc
->interface_id
= htonl(oi
->interface
->ifindex
);
324 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
325 lsdesc
->neighbor_interface_id
=
326 htonl(drouter
->ifindex
);
327 lsdesc
->neighbor_router_id
= drouter
->router_id
;
329 lsdesc
->neighbor_interface_id
=
330 htonl(oi
->interface
->ifindex
);
331 lsdesc
->neighbor_router_id
=
332 oi
->area
->ospf6
->router_id
;
337 assert(0); /* Unknown interface type */
342 /* Point-to-Multipoint interfaces */
346 /* Fill LSA Header */
348 lsa_header
->type
= htons(OSPF6_LSTYPE_ROUTER
);
349 lsa_header
->id
= htonl(link_state_id
);
350 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
352 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
353 lsa_header
->adv_router
, oa
->lsdb
);
354 lsa_header
->length
= htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
357 ospf6_lsa_checksum(lsa_header
);
360 lsa
= ospf6_lsa_create(lsa_header
);
363 ospf6_lsa_originate_area(lsa
, oa
);
367 /* Do premature-aging of rest, undesired Router-LSAs */
368 type
= ntohs(OSPF6_LSTYPE_ROUTER
);
369 router
= oa
->ospf6
->router_id
;
371 for (ALL_LSDB_TYPED_ADVRTR(oa
->lsdb
, type
, router
, lsa
)) {
372 if (ntohl(lsa
->header
->id
) < link_state_id
)
374 ospf6_lsa_purge(lsa
);
379 * Waiting till the LSA is actually removed from the database to trigger
380 * SPF delays network convergence. Unlike IPv4, for an ABR, when all
381 * interfaces associated with an area are gone, triggering an SPF right
383 * helps convergence with inter-area routes.
385 if (count
&& !link_state_id
)
386 ospf6_spf_schedule(oa
->ospf6
,
387 OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED
);
392 /*******************************/
393 /* RFC2740 3.4.3.2 Network-LSA */
394 /*******************************/
396 static char *ospf6_network_lsa_get_ar_id(struct ospf6_lsa
*lsa
, char *buf
,
399 char *start
, *end
, *current
;
400 struct ospf6_network_lsa
*network_lsa
;
401 struct ospf6_network_lsdesc
*lsdesc
;
404 network_lsa
= (struct ospf6_network_lsa
405 *)((caddr_t
)lsa
->header
406 + sizeof(struct ospf6_lsa_header
));
408 start
= (char *)network_lsa
+ sizeof(struct ospf6_network_lsa
);
409 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
410 current
= start
+ pos
* (sizeof(struct ospf6_network_lsdesc
));
412 if ((current
+ sizeof(struct ospf6_network_lsdesc
)) <= end
) {
413 lsdesc
= (struct ospf6_network_lsdesc
*)current
;
415 inet_ntop(AF_INET
, &lsdesc
->router_id
, buf
,
424 static int ospf6_network_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
)
426 char *start
, *end
, *current
;
427 struct ospf6_network_lsa
*network_lsa
;
428 struct ospf6_network_lsdesc
*lsdesc
;
429 char buf
[128], options
[32];
432 (struct ospf6_network_lsa
*)((caddr_t
)lsa
->header
433 + sizeof(struct ospf6_lsa_header
));
435 ospf6_options_printbuf(network_lsa
->options
, options
, sizeof(options
));
436 vty_out(vty
, " Options: %s\n", options
);
438 start
= (char *)network_lsa
+ sizeof(struct ospf6_network_lsa
);
439 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
440 for (current
= start
;
441 current
+ sizeof(struct ospf6_network_lsdesc
) <= end
;
442 current
+= sizeof(struct ospf6_network_lsdesc
)) {
443 lsdesc
= (struct ospf6_network_lsdesc
*)current
;
444 inet_ntop(AF_INET
, &lsdesc
->router_id
, buf
, sizeof(buf
));
445 vty_out(vty
, " Attached Router: %s\n", buf
);
450 int ospf6_network_lsa_originate(struct thread
*thread
)
452 struct ospf6_interface
*oi
;
454 char buffer
[OSPF6_MAX_LSASIZE
];
455 struct ospf6_lsa_header
*lsa_header
;
458 struct ospf6_lsa
*old
, *lsa
;
459 struct ospf6_network_lsa
*network_lsa
;
460 struct ospf6_network_lsdesc
*lsdesc
;
461 struct ospf6_neighbor
*on
;
462 struct ospf6_link_lsa
*link_lsa
;
466 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
467 oi
->thread_network_lsa
= NULL
;
469 /* The interface must be enabled until here. A Network-LSA of a
470 disabled interface (but was once enabled) should be flushed
471 by ospf6_lsa_refresh (), and does not come here. */
474 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_NETWORK
),
475 htonl(oi
->interface
->ifindex
),
476 oi
->area
->ospf6
->router_id
, oi
->area
->lsdb
);
478 /* Do not originate Network-LSA if not DR */
479 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
481 ospf6_lsa_purge(old
);
483 * Waiting till the LSA is actually removed from the
485 * trigger SPF delays network convergence.
489 OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED
);
494 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK
))
495 zlog_debug("Originate Network-LSA for Interface %s",
496 oi
->interface
->name
);
498 /* If none of neighbor is adjacent to us */
501 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
))
502 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
506 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK
))
507 zlog_debug("Interface stub, ignore");
509 ospf6_lsa_purge(old
);
514 memset(buffer
, 0, sizeof(buffer
));
515 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
517 (struct ospf6_network_lsa
*)((caddr_t
)lsa_header
518 + sizeof(struct ospf6_lsa_header
));
520 /* Collect the interface's Link-LSAs to describe
521 network's optional capabilities */
522 type
= htons(OSPF6_LSTYPE_LINK
);
523 for (ALL_LSDB_TYPED(oi
->lsdb
, type
, lsa
)) {
524 link_lsa
= (struct ospf6_link_lsa
525 *)((caddr_t
)lsa
->header
526 + sizeof(struct ospf6_lsa_header
));
527 network_lsa
->options
[0] |= link_lsa
->options
[0];
528 network_lsa
->options
[1] |= link_lsa
->options
[1];
529 network_lsa
->options
[2] |= link_lsa
->options
[2];
532 lsdesc
= (struct ospf6_network_lsdesc
533 *)((caddr_t
)network_lsa
534 + sizeof(struct ospf6_network_lsa
));
536 /* set Link Description to the router itself */
537 lsdesc
->router_id
= oi
->area
->ospf6
->router_id
;
540 /* Walk through the neighbors */
541 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
)) {
542 if (on
->state
!= OSPF6_NEIGHBOR_FULL
)
545 /* set this neighbor's Router-ID to LSA */
546 lsdesc
->router_id
= on
->router_id
;
550 /* Fill LSA Header */
552 lsa_header
->type
= htons(OSPF6_LSTYPE_NETWORK
);
553 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
554 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
556 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
557 lsa_header
->adv_router
, oi
->area
->lsdb
);
558 lsa_header
->length
= htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
561 ospf6_lsa_checksum(lsa_header
);
564 lsa
= ospf6_lsa_create(lsa_header
);
567 ospf6_lsa_originate_area(lsa
, oi
->area
);
573 /****************************/
574 /* RFC2740 3.4.3.6 Link-LSA */
575 /****************************/
577 static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa
*lsa
, char *buf
,
580 char *start
, *end
, *current
;
581 struct ospf6_link_lsa
*link_lsa
;
583 struct ospf6_prefix
*prefix
;
584 int cnt
= 0, prefixnum
;
587 link_lsa
= (struct ospf6_link_lsa
588 *)((caddr_t
)lsa
->header
589 + sizeof(struct ospf6_lsa_header
));
592 inet_ntop(AF_INET6
, &link_lsa
->linklocal_addr
, buf
,
597 prefixnum
= ntohl(link_lsa
->prefix_num
);
601 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
602 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
606 prefix
= (struct ospf6_prefix
*)current
;
607 if (prefix
->prefix_length
== 0
608 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
) {
614 start
+ pos
* OSPF6_PREFIX_SIZE(prefix
);
617 memset(&in6
, 0, sizeof(in6
));
618 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
620 prefix
->prefix_length
));
621 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
624 } while (current
<= end
);
629 static int ospf6_link_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
)
631 char *start
, *end
, *current
;
632 struct ospf6_link_lsa
*link_lsa
;
634 char buf
[128], options
[32];
635 struct ospf6_prefix
*prefix
;
636 const char *p
, *mc
, *la
, *nu
;
639 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsa
->header
640 + sizeof(struct ospf6_lsa_header
));
642 ospf6_options_printbuf(link_lsa
->options
, options
, sizeof(options
));
643 inet_ntop(AF_INET6
, &link_lsa
->linklocal_addr
, buf
, sizeof(buf
));
644 prefixnum
= ntohl(link_lsa
->prefix_num
);
646 vty_out(vty
, " Priority: %d Options: %s\n", link_lsa
->priority
,
648 vty_out(vty
, " LinkLocal Address: %s\n", buf
);
649 vty_out(vty
, " Number of Prefix: %d\n", prefixnum
);
651 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
652 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
653 for (current
= start
; current
< end
;
654 current
+= OSPF6_PREFIX_SIZE(prefix
)) {
655 prefix
= (struct ospf6_prefix
*)current
;
656 if (prefix
->prefix_length
== 0
657 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
)
660 p
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_P
)
663 mc
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_MC
)
666 la
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_LA
)
669 nu
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_NU
)
672 vty_out(vty
, " Prefix Options: %s|%s|%s|%s\n", p
, mc
, la
,
675 memset(&in6
, 0, sizeof(in6
));
676 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
677 OSPF6_PREFIX_SPACE(prefix
->prefix_length
));
678 inet_ntop(AF_INET6
, &in6
, buf
, sizeof(buf
));
679 vty_out(vty
, " Prefix: %s/%d\n", buf
,
680 prefix
->prefix_length
);
686 int ospf6_link_lsa_originate(struct thread
*thread
)
688 struct ospf6_interface
*oi
;
690 char buffer
[OSPF6_MAX_LSASIZE
];
691 struct ospf6_lsa_header
*lsa_header
;
692 struct ospf6_lsa
*old
, *lsa
;
694 struct ospf6_link_lsa
*link_lsa
;
695 struct ospf6_route
*route
;
696 struct ospf6_prefix
*op
;
698 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
699 oi
->thread_link_lsa
= NULL
;
703 /* find previous LSA */
704 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_LINK
),
705 htonl(oi
->interface
->ifindex
),
706 oi
->area
->ospf6
->router_id
, oi
->lsdb
);
708 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
710 ospf6_lsa_purge(old
);
714 if (IS_OSPF6_DEBUG_ORIGINATE(LINK
))
715 zlog_debug("Originate Link-LSA for Interface %s",
716 oi
->interface
->name
);
718 /* can't make Link-LSA if linklocal address not set */
719 if (oi
->linklocal_addr
== NULL
) {
720 if (IS_OSPF6_DEBUG_ORIGINATE(LINK
))
722 "No Linklocal address on %s, defer originating",
723 oi
->interface
->name
);
725 ospf6_lsa_purge(old
);
730 memset(buffer
, 0, sizeof(buffer
));
731 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
732 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsa_header
733 + sizeof(struct ospf6_lsa_header
));
736 link_lsa
->priority
= oi
->priority
;
737 memcpy(link_lsa
->options
, oi
->area
->options
, 3);
738 memcpy(&link_lsa
->linklocal_addr
, oi
->linklocal_addr
,
739 sizeof(struct in6_addr
));
740 link_lsa
->prefix_num
= htonl(oi
->route_connected
->count
);
742 op
= (struct ospf6_prefix
*)((caddr_t
)link_lsa
743 + sizeof(struct ospf6_link_lsa
));
745 /* connected prefix to advertise */
746 for (route
= ospf6_route_head(oi
->route_connected
); route
;
747 route
= ospf6_route_next(route
)) {
748 op
->prefix_length
= route
->prefix
.prefixlen
;
749 op
->prefix_options
= route
->path
.prefix_options
;
750 op
->prefix_metric
= htons(0);
751 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
752 OSPF6_PREFIX_SPACE(op
->prefix_length
));
753 op
= OSPF6_PREFIX_NEXT(op
);
756 /* Fill LSA Header */
758 lsa_header
->type
= htons(OSPF6_LSTYPE_LINK
);
759 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
760 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
762 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
763 lsa_header
->adv_router
, oi
->lsdb
);
764 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)buffer
);
767 ospf6_lsa_checksum(lsa_header
);
770 lsa
= ospf6_lsa_create(lsa_header
);
773 ospf6_lsa_originate_interface(lsa
, oi
);
779 /*****************************************/
780 /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
781 /*****************************************/
782 static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
783 char *buf
, int buflen
,
786 char *start
, *end
, *current
;
787 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
789 int prefixnum
, cnt
= 0;
790 struct ospf6_prefix
*prefix
;
794 (struct ospf6_intra_prefix_lsa
795 *)((caddr_t
)lsa
->header
796 + sizeof(struct ospf6_lsa_header
));
798 prefixnum
= ntohs(intra_prefix_lsa
->prefix_num
);
802 start
= (char *)intra_prefix_lsa
803 + sizeof(struct ospf6_intra_prefix_lsa
);
804 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
808 prefix
= (struct ospf6_prefix
*)current
;
809 if (prefix
->prefix_length
== 0
810 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
) {
816 start
+ pos
* OSPF6_PREFIX_SIZE(prefix
);
819 memset(&in6
, 0, sizeof(in6
));
820 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
822 prefix
->prefix_length
));
823 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
824 sprintf(&buf
[strlen(buf
)], "/%d",
825 prefix
->prefix_length
);
828 } while (current
<= end
);
833 static int ospf6_intra_prefix_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
)
835 char *start
, *end
, *current
;
836 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
839 struct ospf6_prefix
*prefix
;
840 char id
[16], adv_router
[16];
841 const char *p
, *mc
, *la
, *nu
;
844 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
845 *)((caddr_t
)lsa
->header
846 + sizeof(struct ospf6_lsa_header
));
848 prefixnum
= ntohs(intra_prefix_lsa
->prefix_num
);
850 vty_out(vty
, " Number of Prefix: %d\n", prefixnum
);
852 inet_ntop(AF_INET
, &intra_prefix_lsa
->ref_id
, id
, sizeof(id
));
853 inet_ntop(AF_INET
, &intra_prefix_lsa
->ref_adv_router
, adv_router
,
855 vty_out(vty
, " Reference: %s Id: %s Adv: %s\n",
856 ospf6_lstype_name(intra_prefix_lsa
->ref_type
), id
, adv_router
);
858 start
= (char *)intra_prefix_lsa
859 + sizeof(struct ospf6_intra_prefix_lsa
);
860 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
861 for (current
= start
; current
< end
;
862 current
+= OSPF6_PREFIX_SIZE(prefix
)) {
863 prefix
= (struct ospf6_prefix
*)current
;
864 if (prefix
->prefix_length
== 0
865 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
)
868 p
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_P
)
871 mc
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_MC
)
874 la
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_LA
)
877 nu
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_NU
)
880 vty_out(vty
, " Prefix Options: %s|%s|%s|%s\n", p
, mc
, la
,
883 memset(&in6
, 0, sizeof(in6
));
884 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
885 OSPF6_PREFIX_SPACE(prefix
->prefix_length
));
886 inet_ntop(AF_INET6
, &in6
, buf
, sizeof(buf
));
887 vty_out(vty
, " Prefix: %s/%d\n", buf
,
888 prefix
->prefix_length
);
894 int ospf6_intra_prefix_lsa_originate_stub(struct thread
*thread
)
896 struct ospf6_area
*oa
;
898 char buffer
[OSPF6_MAX_LSASIZE
];
899 struct ospf6_lsa_header
*lsa_header
;
900 struct ospf6_lsa
*old
, *lsa
, *old_next
= NULL
;
902 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
903 struct ospf6_interface
*oi
;
904 struct ospf6_neighbor
*on
;
905 struct ospf6_route
*route
;
906 struct ospf6_prefix
*op
;
907 struct listnode
*i
, *j
;
909 unsigned short prefix_num
= 0;
910 struct ospf6_route_table
*route_advertise
;
913 oa
= (struct ospf6_area
*)THREAD_ARG(thread
);
914 oa
->thread_intra_prefix_lsa
= NULL
;
916 /* find previous LSA */
917 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX
), htonl(0),
918 oa
->ospf6
->router_id
, oa
->lsdb
);
920 if (!IS_AREA_ENABLED(oa
)) {
922 ospf6_lsa_purge(old
);
923 /* find previous LSA */
924 old_next
= ospf6_lsdb_lookup(
925 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
926 htonl(++ls_id
), oa
->ospf6
->router_id
, oa
->lsdb
);
929 ospf6_lsa_purge(old_next
);
930 old_next
= ospf6_lsdb_lookup(
931 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
932 htonl(++ls_id
), oa
->ospf6
->router_id
,
939 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
941 "Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
945 memset(buffer
, 0, sizeof(buffer
));
946 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
947 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
948 *)((caddr_t
)lsa_header
949 + sizeof(struct ospf6_lsa_header
));
951 /* Fill Intra-Area-Prefix-LSA */
952 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_ROUTER
);
953 intra_prefix_lsa
->ref_id
= htonl(0);
954 intra_prefix_lsa
->ref_adv_router
= oa
->ospf6
->router_id
;
956 route_advertise
= ospf6_route_table_create(0, 0);
958 for (ALL_LIST_ELEMENTS_RO(oa
->if_list
, i
, oi
)) {
959 if (oi
->state
== OSPF6_INTERFACE_DOWN
) {
960 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
961 zlog_debug(" Interface %s is down, ignore",
962 oi
->interface
->name
);
968 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
))
969 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
972 if (oi
->state
!= OSPF6_INTERFACE_LOOPBACK
973 && oi
->state
!= OSPF6_INTERFACE_POINTTOPOINT
974 && full_count
!= 0) {
975 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
976 zlog_debug(" Interface %s is not stub, ignore",
977 oi
->interface
->name
);
981 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
982 zlog_debug(" Interface %s:", oi
->interface
->name
);
984 /* connected prefix to advertise */
985 for (route
= ospf6_route_head(oi
->route_connected
); route
;
986 route
= ospf6_route_best_next(route
)) {
987 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
988 zlog_debug(" include %pFX", &route
->prefix
);
989 ospf6_route_add(ospf6_route_copy(route
),
990 route_advertise
, oa
->ospf6
);
994 if (route_advertise
->count
== 0) {
997 ospf6_lsa_purge(old
);
998 /* find previous LSA */
999 old_next
= ospf6_lsdb_lookup(
1000 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1001 htonl(++ls_id
), oa
->ospf6
->router_id
, oa
->lsdb
);
1004 ospf6_lsa_purge(old_next
);
1005 old_next
= ospf6_lsdb_lookup(
1006 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1007 htonl(++ls_id
), oa
->ospf6
->router_id
,
1011 ospf6_route_table_delete(route_advertise
, oa
->ospf6
);
1015 /* Neighbor change to FULL, if INTRA-AREA-PREFIX LSA
1016 * has not change, Flush old LSA and Re-Originate INP,
1017 * as ospf6_flood() checks if LSA is same as DB,
1018 * it won't be updated to neighbor's DB.
1020 if (oa
->intra_prefix_originate
) {
1021 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1023 "%s: Re-originate intra prefix LSA, Current full nbrs %u",
1024 __func__
, oa
->full_nbrs
);
1026 ospf6_lsa_purge_multi_ls_id(oa
, old
);
1027 oa
->intra_prefix_originate
= 0;
1030 /* put prefixes to advertise */
1032 op
= (struct ospf6_prefix
*)((caddr_t
)intra_prefix_lsa
1033 + sizeof(struct ospf6_intra_prefix_lsa
));
1034 for (route
= ospf6_route_head(route_advertise
); route
;
1035 route
= ospf6_route_best_next(route
)) {
1036 if (((caddr_t
)op
- (caddr_t
)lsa_header
) > MAX_LSA_PAYLOAD
) {
1038 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
1040 /* Fill LSA Header */
1041 lsa_header
->age
= 0;
1042 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1043 lsa_header
->id
= htonl(ls_id
++);
1044 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
1045 lsa_header
->seqnum
= ospf6_new_ls_seqnum(
1046 lsa_header
->type
, lsa_header
->id
,
1047 lsa_header
->adv_router
, oa
->lsdb
);
1048 lsa_header
->length
=
1049 htons((caddr_t
)op
- (caddr_t
)lsa_header
);
1052 ospf6_lsa_checksum(lsa_header
);
1055 lsa
= ospf6_lsa_create(lsa_header
);
1058 ospf6_lsa_originate_area(lsa
, oa
);
1060 /* Prepare next buffer */
1061 memset(buffer
, 0, sizeof(buffer
));
1062 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1064 (struct ospf6_intra_prefix_lsa
1065 *)((caddr_t
)lsa_header
1066 + sizeof(struct ospf6_lsa_header
));
1068 /* Fill Intra-Area-Prefix-LSA */
1069 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_ROUTER
);
1070 intra_prefix_lsa
->ref_id
= htonl(0);
1071 intra_prefix_lsa
->ref_adv_router
= oa
->ospf6
->router_id
;
1073 /* Put next set of prefixes to advertise */
1075 op
= (struct ospf6_prefix
1076 *)((caddr_t
)intra_prefix_lsa
1078 ospf6_intra_prefix_lsa
));
1081 op
->prefix_length
= route
->prefix
.prefixlen
;
1082 op
->prefix_options
= route
->path
.prefix_options
;
1083 op
->prefix_metric
= htons(route
->path
.cost
);
1084 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
1085 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1088 op
= OSPF6_PREFIX_NEXT(op
);
1091 ospf6_route_table_delete(route_advertise
, oa
->ospf6
);
1093 if (prefix_num
== 0) {
1094 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1096 "Quit to Advertise Intra-Prefix: no route to advertise");
1100 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
1102 /* Fill LSA Header */
1103 lsa_header
->age
= 0;
1104 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1105 lsa_header
->id
= htonl(ls_id
++);
1106 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
1107 lsa_header
->seqnum
=
1108 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
1109 lsa_header
->adv_router
, oa
->lsdb
);
1110 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)lsa_header
);
1113 ospf6_lsa_checksum(lsa_header
);
1116 lsa
= ospf6_lsa_create(lsa_header
);
1119 ospf6_lsa_originate_area(lsa
, oa
);
1125 int ospf6_intra_prefix_lsa_originate_transit(struct thread
*thread
)
1127 struct ospf6_interface
*oi
;
1129 char buffer
[OSPF6_MAX_LSASIZE
];
1130 struct ospf6_lsa_header
*lsa_header
;
1131 struct ospf6_lsa
*old
, *lsa
;
1133 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1134 struct ospf6_neighbor
*on
;
1135 struct ospf6_route
*route
;
1136 struct ospf6_prefix
*op
;
1139 unsigned short prefix_num
= 0;
1140 struct ospf6_route_table
*route_advertise
;
1141 struct ospf6_link_lsa
*link_lsa
;
1142 char *start
, *end
, *current
;
1145 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
1146 oi
->thread_intra_prefix_lsa
= NULL
;
1150 /* find previous LSA */
1151 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1152 htonl(oi
->interface
->ifindex
),
1153 oi
->area
->ospf6
->router_id
, oi
->area
->lsdb
);
1155 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1157 ospf6_lsa_purge(old
);
1161 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1163 "Originate Intra-Area-Prefix-LSA for interface %s's prefix",
1164 oi
->interface
->name
);
1166 /* prepare buffer */
1167 memset(buffer
, 0, sizeof(buffer
));
1168 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1169 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
1170 *)((caddr_t
)lsa_header
1171 + sizeof(struct ospf6_lsa_header
));
1173 /* Fill Intra-Area-Prefix-LSA */
1174 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_NETWORK
);
1175 intra_prefix_lsa
->ref_id
= htonl(oi
->interface
->ifindex
);
1176 intra_prefix_lsa
->ref_adv_router
= oi
->area
->ospf6
->router_id
;
1178 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
1179 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1180 zlog_debug(" Interface is not DR");
1182 ospf6_lsa_purge(old
);
1187 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
))
1188 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
1191 if (full_count
== 0) {
1192 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1193 zlog_debug(" Interface is stub");
1195 ospf6_lsa_purge(old
);
1199 /* connected prefix to advertise */
1200 route_advertise
= ospf6_route_table_create(0, 0);
1202 type
= ntohs(OSPF6_LSTYPE_LINK
);
1203 for (ALL_LSDB_TYPED(oi
->lsdb
, type
, lsa
)) {
1204 if (OSPF6_LSA_IS_MAXAGE(lsa
))
1207 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1208 zlog_debug(" include prefix from %s", lsa
->name
);
1210 if (lsa
->header
->adv_router
!= oi
->area
->ospf6
->router_id
) {
1211 on
= ospf6_neighbor_lookup(lsa
->header
->adv_router
, oi
);
1212 if (on
== NULL
|| on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1213 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1215 " Neighbor not found or not Full, ignore");
1220 link_lsa
= (struct ospf6_link_lsa
1221 *)((caddr_t
)lsa
->header
1222 + sizeof(struct ospf6_lsa_header
));
1224 prefix_num
= (unsigned short)ntohl(link_lsa
->prefix_num
);
1225 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
1226 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
1227 for (current
= start
; current
< end
&& prefix_num
;
1228 current
+= OSPF6_PREFIX_SIZE(op
)) {
1229 op
= (struct ospf6_prefix
*)current
;
1230 if (op
->prefix_length
== 0
1231 || current
+ OSPF6_PREFIX_SIZE(op
) > end
)
1234 route
= ospf6_route_create();
1236 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
1237 route
->prefix
.family
= AF_INET6
;
1238 route
->prefix
.prefixlen
= op
->prefix_length
;
1239 memset(&route
->prefix
.u
.prefix6
, 0,
1240 sizeof(struct in6_addr
));
1241 memcpy(&route
->prefix
.u
.prefix6
, OSPF6_PREFIX_BODY(op
),
1242 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1244 route
->path
.origin
.type
= lsa
->header
->type
;
1245 route
->path
.origin
.id
= lsa
->header
->id
;
1246 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1247 route
->path
.options
[0] = link_lsa
->options
[0];
1248 route
->path
.options
[1] = link_lsa
->options
[1];
1249 route
->path
.options
[2] = link_lsa
->options
[2];
1250 route
->path
.prefix_options
= op
->prefix_options
;
1251 route
->path
.area_id
= oi
->area
->area_id
;
1252 route
->path
.type
= OSPF6_PATH_TYPE_INTRA
;
1254 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1255 zlog_debug(" include %pFX", &route
->prefix
);
1257 ospf6_route_add(route
, route_advertise
,
1261 if (current
!= end
&& IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1262 zlog_debug("Trailing garbage in %s", lsa
->name
);
1265 op
= (struct ospf6_prefix
*)((caddr_t
)intra_prefix_lsa
1266 + sizeof(struct ospf6_intra_prefix_lsa
));
1269 for (route
= ospf6_route_head(route_advertise
); route
;
1270 route
= ospf6_route_best_next(route
)) {
1271 op
->prefix_length
= route
->prefix
.prefixlen
;
1272 op
->prefix_options
= route
->path
.prefix_options
;
1273 op
->prefix_metric
= htons(0);
1274 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
1275 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1276 op
= OSPF6_PREFIX_NEXT(op
);
1280 ospf6_route_table_delete(route_advertise
, oi
->area
->ospf6
);
1282 if (prefix_num
== 0) {
1283 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1285 "Quit to Advertise Intra-Prefix: no route to advertise");
1289 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
1291 /* Fill LSA Header */
1292 lsa_header
->age
= 0;
1293 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1294 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
1295 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
1296 lsa_header
->seqnum
=
1297 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
1298 lsa_header
->adv_router
, oi
->area
->lsdb
);
1299 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)lsa_header
);
1302 ospf6_lsa_checksum(lsa_header
);
1305 lsa
= ospf6_lsa_create(lsa_header
);
1308 ospf6_lsa_originate_area(lsa
, oi
->area
);
1313 static void ospf6_intra_prefix_update_route_origin(struct ospf6_route
*oa_route
,
1314 struct ospf6
*ospf6
)
1316 struct ospf6_path
*h_path
;
1317 struct ospf6_route
*g_route
, *nroute
;
1319 /* Update Global ospf6 route path */
1320 g_route
= ospf6_route_lookup(&oa_route
->prefix
, ospf6
->route_table
);
1324 for (ospf6_route_lock(g_route
); g_route
&&
1325 ospf6_route_is_prefix(&oa_route
->prefix
, g_route
);
1327 nroute
= ospf6_route_next(g_route
);
1328 if (g_route
->type
!= oa_route
->type
)
1330 if (g_route
->path
.area_id
!= oa_route
->path
.area_id
)
1332 if (g_route
->path
.type
!= OSPF6_PATH_TYPE_INTRA
)
1334 if (g_route
->path
.cost
!= oa_route
->path
.cost
)
1337 if (ospf6_route_is_same_origin(g_route
, oa_route
)) {
1338 h_path
= (struct ospf6_path
*)listgetdata(
1339 listhead(g_route
->paths
));
1340 g_route
->path
.origin
.type
= h_path
->origin
.type
;
1341 g_route
->path
.origin
.id
= h_path
->origin
.id
;
1342 g_route
->path
.origin
.adv_router
=
1343 h_path
->origin
.adv_router
;
1348 h_path
= (struct ospf6_path
*)listgetdata(
1349 listhead(oa_route
->paths
));
1350 oa_route
->path
.origin
.type
= h_path
->origin
.type
;
1351 oa_route
->path
.origin
.id
= h_path
->origin
.id
;
1352 oa_route
->path
.origin
.adv_router
= h_path
->origin
.adv_router
;
1355 void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area
*oa
,
1356 struct ospf6_route
*old
,
1357 struct ospf6_route
*route
)
1359 struct ospf6_route
*old_route
, *ls_entry
;
1360 struct ospf6_path
*ecmp_path
, *o_path
= NULL
;
1361 struct listnode
*anode
, *anext
;
1362 struct listnode
*nnode
, *rnode
, *rnext
;
1363 struct ospf6_nexthop
*nh
, *rnh
;
1364 char buf
[PREFIX2STR_BUFFER
];
1365 bool route_found
= false;
1366 struct interface
*ifp
= NULL
;
1367 struct ospf6_lsa
*lsa
;
1368 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1370 /* check for old entry match with new route origin,
1373 for (old_route
= old
; old_route
; old_route
= old_route
->next
) {
1374 bool route_updated
= false;
1376 if (!ospf6_route_is_same(old_route
, route
) ||
1377 (old_route
->path
.type
!= route
->path
.type
))
1380 /* Current and New route has same origin,
1383 for (ALL_LIST_ELEMENTS(old_route
->paths
, anode
, anext
,
1385 /* Check old route path and route has same
1388 if (o_path
->area_id
!= route
->path
.area_id
||
1389 (memcmp(&(o_path
)->origin
, &(route
)->path
.origin
,
1390 sizeof(struct ospf6_ls_origin
)) != 0))
1393 /* Cost is not same then delete current path */
1394 if (o_path
->cost
== route
->path
.cost
)
1397 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1399 "%s: route %pFX cost old %u new %u is not same, replace route",
1400 __func__
, &old_route
->prefix
, o_path
->cost
,
1404 /* Remove selected current path's nh from
1405 * effective nh list.
1407 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
, nnode
, nh
)) {
1408 for (ALL_LIST_ELEMENTS(old_route
->nh_list
,
1409 rnode
, rnext
, rnh
)) {
1410 if (!ospf6_nexthop_is_same(rnh
, nh
))
1412 listnode_delete(old_route
->nh_list
,
1414 ospf6_nexthop_delete(rnh
);
1415 route_updated
= true;
1419 listnode_delete(old_route
->paths
, o_path
);
1420 ospf6_path_free(o_path
);
1422 /* Current route's path (adv_router info) is similar
1423 * to route being added.
1424 * Replace current route's path with paths list head.
1425 * Update FIB with effective NHs.
1427 if (listcount(old_route
->paths
)) {
1428 if (route_updated
) {
1429 for (ALL_LIST_ELEMENTS(old_route
->paths
,
1430 anode
, anext
, o_path
)) {
1431 ospf6_merge_nexthops(
1435 /* Update ospf6 route table and
1436 * RIB/FIB with effective
1439 if (oa
->route_table
->hook_add
)
1440 (*oa
->route_table
->hook_add
)(
1441 old_route
, oa
->ospf6
);
1443 if (old_route
->path
.origin
.id
==
1444 route
->path
.origin
.id
&&
1445 old_route
->path
.origin
.adv_router
==
1446 route
->path
.origin
.adv_router
) {
1447 ospf6_intra_prefix_update_route_origin(
1448 old_route
, oa
->ospf6
);
1453 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1455 "%s: route %pFX old cost %u new cost %u, delete old entry.",
1456 __func__
, &old_route
->prefix
,
1457 old_route
->path
.cost
,
1460 if (oa
->route_table
->hook_remove
)
1461 ospf6_route_remove(old_route
,
1465 SET_FLAG(old_route
->flag
,
1466 OSPF6_ROUTE_REMOVE
);
1474 for (old_route
= old
; old_route
; old_route
= old_route
->next
) {
1476 if (!ospf6_route_is_same(old_route
, route
) ||
1477 (old_route
->path
.type
!= route
->path
.type
))
1480 /* Old Route and New Route have Equal Cost, Merge NHs */
1481 if (old_route
->path
.cost
== route
->path
.cost
) {
1484 /* check if this path exists already in
1485 * route->paths list, if so, replace nh_list.
1487 for (ALL_LIST_ELEMENTS_RO(old_route
->paths
, anode
,
1489 if (o_path
->area_id
== route
->path
.area_id
&&
1490 (memcmp(&(o_path
)->origin
,
1491 &(route
)->path
.origin
,
1492 sizeof(struct ospf6_ls_origin
)) == 0))
1495 /* If path is not found in old_route paths's list,
1496 * add a new path to route paths list and merge
1497 * nexthops in route->path->nh_list.
1498 * Otherwise replace existing path's nh_list.
1500 if (o_path
== NULL
) {
1501 ecmp_path
= ospf6_path_dup(&route
->path
);
1503 /* Add a nh_list to new ecmp path */
1504 ospf6_copy_nexthops(ecmp_path
->nh_list
,
1506 /* Add the new path to route's path list */
1507 listnode_add_sort(old_route
->paths
, ecmp_path
);
1509 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1511 "%s: route %pFX %p another path added with nh %u, effective paths %u nh %u",
1512 __func__
, &route
->prefix
,
1514 listcount(ecmp_path
->nh_list
),
1515 old_route
->paths
? listcount(
1518 listcount(old_route
->nh_list
));
1521 list_delete_all_node(o_path
->nh_list
);
1522 ospf6_copy_nexthops(o_path
->nh_list
,
1527 list_delete_all_node(old_route
->nh_list
);
1529 for (ALL_LIST_ELEMENTS_RO(old_route
->paths
, anode
,
1531 ls_entry
= ospf6_route_lookup(
1534 if (ls_entry
== NULL
) {
1535 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1537 "%s: ls_prfix %s ls_entry not found.",
1541 lsa
= ospf6_lsdb_lookup(o_path
->origin
.type
,
1543 o_path
->origin
.adv_router
,
1546 if (IS_OSPF6_DEBUG_EXAMIN(
1548 struct prefix adv_prefix
;
1550 ospf6_linkstate_prefix(
1551 o_path
->origin
.adv_router
,
1552 o_path
->origin
.id
, &adv_prefix
);
1554 "%s: adv_router %pFX lsa not found",
1555 __func__
, &adv_prefix
);
1560 (struct ospf6_intra_prefix_lsa
*)
1561 OSPF6_LSA_HEADER_END(lsa
->header
);
1563 if (intra_prefix_lsa
->ref_adv_router
1564 == oa
->ospf6
->router_id
) {
1565 ifp
= if_lookup_prefix(
1571 /* Nexthop interface found */
1572 ospf6_route_add_nexthop(old_route
,
1576 /* The connected interfaces between
1577 * routers can be in different networks.
1578 * In this case the matching interface
1579 * is not found. Copy nexthops from the
1582 ospf6_route_merge_nexthops(old_route
,
1587 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1589 "%s: route %pFX %p with final effective paths %u nh%u",
1590 __func__
, &route
->prefix
,
1593 ? listcount(old_route
->paths
)
1595 listcount(old_route
->nh_list
));
1597 /* used in intra_route_calculation() to add to
1598 * global ospf6 route table.
1600 UNSET_FLAG(old_route
->flag
, OSPF6_ROUTE_REMOVE
);
1601 SET_FLAG(old_route
->flag
, OSPF6_ROUTE_ADD
);
1602 /* Update ospf6 route table and RIB/FIB */
1603 if (oa
->route_table
->hook_add
)
1604 (*oa
->route_table
->hook_add
)(old_route
,
1606 /* Delete the new route its info added to existing
1609 ospf6_route_delete(route
);
1616 /* Add new route to existing node in ospf6 route table. */
1617 ospf6_route_add(route
, oa
->route_table
, oa
->ospf6
);
1621 void ospf6_intra_prefix_lsa_add(struct ospf6_lsa
*lsa
)
1623 struct ospf6_area
*oa
;
1624 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1625 struct prefix ls_prefix
;
1626 struct ospf6_route
*route
, *ls_entry
, *old
;
1628 struct ospf6_prefix
*op
;
1629 char *start
, *current
, *end
;
1630 char buf
[PREFIX2STR_BUFFER
];
1631 struct interface
*ifp
= NULL
;
1632 int direct_connect
= 0;
1633 struct ospf6_path
*path
;
1635 if (OSPF6_LSA_IS_MAXAGE(lsa
))
1638 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1639 zlog_debug("%s: LSA %s found", __func__
, lsa
->name
);
1641 oa
= OSPF6_AREA(lsa
->lsdb
->data
);
1644 (struct ospf6_intra_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1646 if (intra_prefix_lsa
->ref_type
== htons(OSPF6_LSTYPE_ROUTER
))
1647 ospf6_linkstate_prefix(intra_prefix_lsa
->ref_adv_router
,
1648 intra_prefix_lsa
->ref_id
, &ls_prefix
);
1649 else if (intra_prefix_lsa
->ref_type
== htons(OSPF6_LSTYPE_NETWORK
))
1650 ospf6_linkstate_prefix(intra_prefix_lsa
->ref_adv_router
,
1651 intra_prefix_lsa
->ref_id
, &ls_prefix
);
1653 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1654 zlog_debug("Unknown reference LS-type: %#hx",
1655 ntohs(intra_prefix_lsa
->ref_type
));
1659 ls_entry
= ospf6_route_lookup(&ls_prefix
, oa
->spf_table
);
1660 if (ls_entry
== NULL
) {
1661 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1662 ospf6_linkstate_prefix2str(&ls_prefix
, buf
,
1664 zlog_debug("LS entry does not exist: %s", buf
);
1669 if (intra_prefix_lsa
->ref_adv_router
== oa
->ospf6
->router_id
) {
1670 /* the intra-prefix are directly connected */
1674 prefix_num
= ntohs(intra_prefix_lsa
->prefix_num
);
1675 start
= (caddr_t
)intra_prefix_lsa
1676 + sizeof(struct ospf6_intra_prefix_lsa
);
1677 end
= OSPF6_LSA_END(lsa
->header
);
1678 for (current
= start
; current
< end
; current
+= OSPF6_PREFIX_SIZE(op
)) {
1679 op
= (struct ospf6_prefix
*)current
;
1680 if (prefix_num
== 0)
1682 if (end
< current
+ OSPF6_PREFIX_SIZE(op
))
1685 /* Appendix A.4.1.1 */
1686 if (CHECK_FLAG(op
->prefix_options
, OSPF6_PREFIX_OPTION_NU
)) {
1687 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1688 ospf6_linkstate_prefix2str(
1689 (struct prefix
*)OSPF6_PREFIX_BODY(op
),
1692 "%s: Skipping Prefix %s has NU option set",
1698 route
= ospf6_route_create();
1700 memset(&route
->prefix
, 0, sizeof(struct prefix
));
1701 route
->prefix
.family
= AF_INET6
;
1702 route
->prefix
.prefixlen
= op
->prefix_length
;
1703 ospf6_prefix_in6_addr(&route
->prefix
.u
.prefix6
,
1704 intra_prefix_lsa
, op
);
1706 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
1707 route
->path
.origin
.type
= lsa
->header
->type
;
1708 route
->path
.origin
.id
= lsa
->header
->id
;
1709 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1710 route
->path
.prefix_options
= op
->prefix_options
;
1711 route
->path
.area_id
= oa
->area_id
;
1712 route
->path
.type
= OSPF6_PATH_TYPE_INTRA
;
1713 route
->path
.metric_type
= 1;
1715 ls_entry
->path
.cost
+ ntohs(op
->prefix_metric
);
1716 memcpy(&route
->path
.ls_prefix
, &ls_prefix
,
1717 sizeof(struct prefix
));
1718 if (direct_connect
) {
1719 ifp
= if_lookup_prefix(&route
->prefix
,
1724 /* Nexthop interface found */
1725 ospf6_route_add_nexthop(route
, ifp
->ifindex
, NULL
);
1727 /* The connected interfaces between routers can be in
1728 * different networks. In this case the matching
1729 * interface is not found. Copy nexthops from the
1732 ospf6_route_copy_nexthops(route
, ls_entry
);
1735 path
= ospf6_path_dup(&route
->path
);
1736 ospf6_copy_nexthops(path
->nh_list
, route
->path
.nh_list
);
1737 listnode_add_sort(route
->paths
, path
);
1739 old
= ospf6_route_lookup(&route
->prefix
, oa
->route_table
);
1741 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1742 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1744 "%s Update route: %s old cost %u new cost %u paths %u nh %u",
1745 __func__
, buf
, old
->path
.cost
,
1747 listcount(route
->paths
),
1748 listcount(route
->nh_list
));
1750 ospf6_intra_prefix_route_ecmp_path(oa
, old
, route
);
1752 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1753 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1755 "%s route %s add with cost %u paths %u nh %u",
1756 __func__
, buf
, route
->path
.cost
,
1757 listcount(route
->paths
),
1758 listcount(route
->nh_list
));
1760 ospf6_route_add(route
, oa
->route_table
, oa
->ospf6
);
1765 if (current
!= end
&& IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1766 zlog_debug("Trailing garbage ignored");
1769 static void ospf6_intra_prefix_lsa_remove_update_route(struct ospf6_lsa
*lsa
,
1770 struct ospf6_area
*oa
,
1771 struct ospf6_route
*route
)
1773 struct listnode
*anode
, *anext
;
1774 struct listnode
*nnode
, *rnode
, *rnext
;
1775 struct ospf6_nexthop
*nh
, *rnh
;
1776 struct ospf6_path
*o_path
;
1777 bool nh_updated
= false;
1778 char buf
[PREFIX2STR_BUFFER
];
1780 /* Iterate all paths of route to find maching
1781 * with LSA remove info.
1782 * If route->path is same, replace
1785 for (ALL_LIST_ELEMENTS(route
->paths
, anode
, anext
, o_path
)) {
1786 if ((o_path
->origin
.type
!= lsa
->header
->type
) ||
1787 (o_path
->origin
.adv_router
!= lsa
->header
->adv_router
) ||
1788 (o_path
->origin
.id
!= lsa
->header
->id
))
1791 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1792 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1794 "%s: route %s path found with cost %u nh %u to remove.",
1795 __func__
, buf
, o_path
->cost
,
1796 listcount(o_path
->nh_list
));
1799 /* Remove found path's nh_list from
1800 * the route's nh_list.
1802 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
, nnode
, nh
)) {
1803 for (ALL_LIST_ELEMENTS(route
->nh_list
, rnode
,
1805 if (!ospf6_nexthop_is_same(rnh
, nh
))
1807 listnode_delete(route
->nh_list
, rnh
);
1808 ospf6_nexthop_delete(rnh
);
1811 /* Delete the path from route's
1814 listnode_delete(route
->paths
, o_path
);
1815 ospf6_path_free(o_path
);
1821 /* Iterate all paths and merge nexthop,
1822 * unlesss any of the nexthop similar to
1823 * ones deleted as part of path deletion.
1825 for (ALL_LIST_ELEMENTS(route
->paths
, anode
, anext
, o_path
))
1826 ospf6_merge_nexthops(route
->nh_list
, o_path
->nh_list
);
1829 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1830 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1832 "%s: route %s update paths %u nh %u", __func__
,
1833 buf
, route
->paths
? listcount(route
->paths
) : 0,
1834 route
->nh_list
? listcount(route
->nh_list
) : 0);
1837 /* Update Global Route table and
1838 * RIB/FIB with effective
1841 if (oa
->route_table
->hook_add
)
1842 (*oa
->route_table
->hook_add
)(route
, oa
->ospf6
);
1844 /* route's primary path is similar
1845 * to LSA, replace route's primary
1846 * path with route's paths list
1849 if ((route
->path
.origin
.id
== lsa
->header
->id
) &&
1850 (route
->path
.origin
.adv_router
==
1851 lsa
->header
->adv_router
)) {
1852 ospf6_intra_prefix_update_route_origin(route
,
1859 void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa
*lsa
)
1861 struct ospf6_area
*oa
;
1862 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1863 struct prefix prefix
;
1864 struct ospf6_route
*route
, *nroute
;
1866 struct ospf6_prefix
*op
;
1867 char *start
, *current
, *end
;
1868 char buf
[PREFIX2STR_BUFFER
];
1870 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1871 zlog_debug("%s: %s disappearing", __func__
, lsa
->name
);
1873 oa
= OSPF6_AREA(lsa
->lsdb
->data
);
1876 (struct ospf6_intra_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1879 prefix_num
= ntohs(intra_prefix_lsa
->prefix_num
);
1880 start
= (caddr_t
)intra_prefix_lsa
1881 + sizeof(struct ospf6_intra_prefix_lsa
);
1882 end
= OSPF6_LSA_END(lsa
->header
);
1883 for (current
= start
; current
< end
; current
+= OSPF6_PREFIX_SIZE(op
)) {
1884 op
= (struct ospf6_prefix
*)current
;
1885 if (prefix_num
== 0)
1887 if (end
< current
+ OSPF6_PREFIX_SIZE(op
))
1891 memset(&prefix
, 0, sizeof(struct prefix
));
1892 prefix
.family
= AF_INET6
;
1893 prefix
.prefixlen
= op
->prefix_length
;
1894 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, intra_prefix_lsa
, op
);
1896 route
= ospf6_route_lookup(&prefix
, oa
->route_table
);
1900 for (ospf6_route_lock(route
);
1901 route
&& ospf6_route_is_prefix(&prefix
, route
);
1903 nroute
= ospf6_route_next(route
);
1904 if (route
->type
!= OSPF6_DEST_TYPE_NETWORK
)
1906 if (route
->path
.area_id
!= oa
->area_id
)
1908 if (route
->path
.type
!= OSPF6_PATH_TYPE_INTRA
)
1910 /* Route has multiple ECMP paths, remove matching
1911 * path. Update current route's effective nh list
1912 * after removal of one of the path.
1914 if (listcount(route
->paths
) > 1) {
1915 ospf6_intra_prefix_lsa_remove_update_route(
1919 if (route
->path
.origin
.type
!= lsa
->header
->type
1920 || route
->path
.origin
.id
!= lsa
->header
->id
1921 || route
->path
.origin
.adv_router
1922 != lsa
->header
->adv_router
)
1925 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1926 prefix2str(&route
->prefix
, buf
,
1929 "%s: route remove %s with path type %u cost %u paths %u nh %u",
1930 __func__
, buf
, route
->path
.type
,
1932 listcount(route
->paths
),
1933 listcount(route
->nh_list
));
1935 ospf6_route_remove(route
, oa
->route_table
,
1940 ospf6_route_unlock(route
);
1943 if (current
!= end
&& IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1944 zlog_debug("Trailing garbage ignored");
1947 void ospf6_intra_route_calculation(struct ospf6_area
*oa
)
1949 struct ospf6_route
*route
, *nroute
;
1951 struct ospf6_lsa
*lsa
;
1952 void (*hook_add
)(struct ospf6_route
*, struct ospf6
*) = NULL
;
1953 void (*hook_remove
)(struct ospf6_route
*, struct ospf6
*) = NULL
;
1955 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1956 zlog_debug("Re-examin intra-routes for area %s", oa
->name
);
1958 hook_add
= oa
->route_table
->hook_add
;
1959 hook_remove
= oa
->route_table
->hook_remove
;
1960 oa
->route_table
->hook_add
= NULL
;
1961 oa
->route_table
->hook_remove
= NULL
;
1963 for (route
= ospf6_route_head(oa
->route_table
); route
;
1964 route
= ospf6_route_next(route
))
1965 route
->flag
= OSPF6_ROUTE_REMOVE
;
1967 type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1968 for (ALL_LSDB_TYPED(oa
->lsdb
, type
, lsa
))
1969 ospf6_intra_prefix_lsa_add(lsa
);
1971 oa
->route_table
->hook_add
= hook_add
;
1972 oa
->route_table
->hook_remove
= hook_remove
;
1974 for (route
= ospf6_route_head(oa
->route_table
); route
; route
= nroute
) {
1975 nroute
= ospf6_route_next(route
);
1976 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
)
1977 && CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ADD
)) {
1978 UNSET_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
);
1979 UNSET_FLAG(route
->flag
, OSPF6_ROUTE_ADD
);
1982 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
))
1983 ospf6_route_remove(route
, oa
->route_table
, oa
->ospf6
);
1984 else if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ADD
)
1985 || CHECK_FLAG(route
->flag
, OSPF6_ROUTE_CHANGE
)) {
1987 (*hook_add
)(route
, oa
->ospf6
);
1990 /* Redo the summaries as things might have changed */
1991 ospf6_abr_originate_summary(route
, oa
->ospf6
);
1996 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1997 zlog_debug("Re-examin intra-routes for area %s: Done",
2001 static void ospf6_brouter_debug_print(struct ospf6_route
*brouter
)
2003 uint32_t brouter_id
;
2004 char brouter_name
[16];
2006 char destination
[64];
2007 char installed
[64], changed
[64];
2008 struct timeval now
, res
;
2009 char id
[16], adv_router
[16];
2010 char capa
[16], options
[16];
2012 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2013 inet_ntop(AF_INET
, &brouter_id
, brouter_name
, sizeof(brouter_name
));
2014 inet_ntop(AF_INET
, &brouter
->path
.area_id
, area_name
,
2016 ospf6_linkstate_prefix2str(&brouter
->prefix
, destination
,
2017 sizeof(destination
));
2020 timersub(&now
, &brouter
->installed
, &res
);
2021 timerstring(&res
, installed
, sizeof(installed
));
2024 timersub(&now
, &brouter
->changed
, &res
);
2025 timerstring(&res
, changed
, sizeof(changed
));
2027 inet_ntop(AF_INET
, &brouter
->path
.origin
.id
, id
, sizeof(id
));
2028 inet_ntop(AF_INET
, &brouter
->path
.origin
.adv_router
, adv_router
,
2029 sizeof(adv_router
));
2031 ospf6_options_printbuf(brouter
->path
.options
, options
, sizeof(options
));
2032 ospf6_capability_printbuf(brouter
->path
.router_bits
, capa
,
2035 zlog_info("Brouter: %s via area %s", brouter_name
, area_name
);
2036 zlog_info(" memory: prev: %p this: %p next: %p parent rnode: %p",
2037 (void *)brouter
->prev
, (void *)brouter
, (void *)brouter
->next
,
2038 (void *)brouter
->rnode
);
2039 zlog_info(" type: %d prefix: %s installed: %s changed: %s",
2040 brouter
->type
, destination
, installed
, changed
);
2041 zlog_info(" lock: %d flags: %s%s%s%s", brouter
->lock
,
2042 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_BEST
) ? "B" : "-"),
2043 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
) ? "A" : "-"),
2044 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
) ? "R" : "-"),
2045 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
) ? "C" : "-"));
2046 zlog_info(" path type: %s ls-origin %s id: %s adv-router %s",
2047 OSPF6_PATH_TYPE_NAME(brouter
->path
.type
),
2048 ospf6_lstype_name(brouter
->path
.origin
.type
), id
, adv_router
);
2049 zlog_info(" options: %s router-bits: %s metric-type: %d metric: %d/%d",
2050 options
, capa
, brouter
->path
.metric_type
, brouter
->path
.cost
,
2051 brouter
->path
.u
.cost_e2
);
2052 zlog_info(" paths %u nh %u", listcount(brouter
->paths
),
2053 listcount(brouter
->nh_list
));
2056 void ospf6_intra_brouter_calculation(struct ospf6_area
*oa
)
2058 struct ospf6_route
*brouter
, *nbrouter
, *copy
;
2059 void (*hook_add
)(struct ospf6_route
*, struct ospf6
*) = NULL
;
2060 void (*hook_remove
)(struct ospf6_route
*, struct ospf6
*) = NULL
;
2061 uint32_t brouter_id
;
2062 char brouter_name
[16];
2064 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa
->area_id
) ||
2065 IS_OSPF6_DEBUG_ROUTE(MEMORY
))
2066 zlog_info("%s: border-router calculation for area %s", __func__
,
2069 hook_add
= oa
->ospf6
->brouter_table
->hook_add
;
2070 hook_remove
= oa
->ospf6
->brouter_table
->hook_remove
;
2071 oa
->ospf6
->brouter_table
->hook_add
= NULL
;
2072 oa
->ospf6
->brouter_table
->hook_remove
= NULL
;
2074 /* withdraw the previous router entries for the area */
2075 for (brouter
= ospf6_route_head(oa
->ospf6
->brouter_table
); brouter
;
2076 brouter
= ospf6_route_next(brouter
)) {
2077 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2078 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
2079 sizeof(brouter_name
));
2081 if (brouter
->path
.area_id
!= oa
->area_id
)
2084 SET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
2086 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id
)
2087 || IS_OSPF6_DEBUG_ROUTE(MEMORY
)) {
2088 zlog_info("%p: mark as removing: area %s brouter %s",
2089 (void *)brouter
, oa
->name
, brouter_name
);
2090 ospf6_brouter_debug_print(brouter
);
2094 for (brouter
= ospf6_route_head(oa
->spf_table
); brouter
;
2095 brouter
= ospf6_route_next(brouter
)) {
2096 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2097 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
2098 sizeof(brouter_name
));
2100 if (brouter
->type
!= OSPF6_DEST_TYPE_LINKSTATE
)
2103 if (ospf6_linkstate_prefix_id(&brouter
->prefix
) != htonl(0))
2106 if (!CHECK_FLAG(brouter
->path
.router_bits
, OSPF6_ROUTER_BIT_E
)
2107 && !CHECK_FLAG(brouter
->path
.router_bits
,
2108 OSPF6_ROUTER_BIT_B
))
2111 if (!OSPF6_OPT_ISSET(brouter
->path
.options
, OSPF6_OPT_V6
)
2112 || !OSPF6_OPT_ISSET(brouter
->path
.options
, OSPF6_OPT_R
))
2115 copy
= ospf6_route_copy(brouter
);
2116 copy
->type
= OSPF6_DEST_TYPE_ROUTER
;
2117 copy
->path
.area_id
= oa
->area_id
;
2118 ospf6_route_add(copy
, oa
->ospf6
->brouter_table
, oa
->ospf6
);
2120 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id
)
2121 || IS_OSPF6_DEBUG_ROUTE(MEMORY
)) {
2122 zlog_info("%p: transfer: area %s brouter %s",
2123 (void *)brouter
, oa
->name
, brouter_name
);
2124 ospf6_brouter_debug_print(brouter
);
2128 oa
->ospf6
->brouter_table
->hook_add
= hook_add
;
2129 oa
->ospf6
->brouter_table
->hook_remove
= hook_remove
;
2131 for (brouter
= ospf6_route_head(oa
->ospf6
->brouter_table
); brouter
;
2132 brouter
= nbrouter
) {
2135 * brouter may have been "deleted" in the last loop iteration.
2136 * If this is the case there is still 1 final refcount lock
2137 * taken by ospf6_route_next, that will be released by the same
2138 * call and result in deletion. To avoid heap UAF we must then
2139 * skip processing the deleted route.
2141 if (brouter
->lock
== 1) {
2142 if (IS_OSPF6_DEBUG_ROUTE(MEMORY
))
2143 ospf6_brouter_debug_print(brouter
);
2144 nbrouter
= ospf6_route_next(brouter
);
2147 nbrouter
= ospf6_route_next(brouter
);
2150 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2151 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
2152 sizeof(brouter_name
));
2154 if (brouter
->path
.area_id
!= oa
->area_id
)
2157 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_WAS_REMOVED
))
2160 /* After iterating spf_table for all routers including
2161 * intra brouter, clear mark for remove flag for
2162 * inter border router if its adv router present in
2165 if (brouter
->path
.type
== OSPF6_PATH_TYPE_INTER
) {
2166 struct prefix adv_prefix
;
2168 ospf6_linkstate_prefix(brouter
->path
.origin
.adv_router
,
2169 htonl(0), &adv_prefix
);
2171 if (ospf6_route_lookup(&adv_prefix
, oa
->spf_table
)) {
2172 if (IS_OSPF6_DEBUG_BROUTER
) {
2174 "%s: keep inter brouter %s as adv router 0x%x found in spf",
2175 __func__
, brouter_name
,
2176 brouter
->path
.origin
2178 ospf6_brouter_debug_print(brouter
);
2180 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
2184 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
)
2185 && CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
)) {
2186 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
2187 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
);
2190 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
)) {
2191 if (IS_OSPF6_DEBUG_BROUTER
2192 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2194 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2197 "%s: brouter %s disappears via area %s",
2198 __func__
, brouter_name
, oa
->name
);
2199 /* This is used to protect nbrouter from removed from
2200 * the table. For an example, ospf6_abr_examin_summary,
2201 * removes brouters which are marked for remove.
2203 oa
->intra_brouter_calc
= 1;
2204 ospf6_route_remove(brouter
, oa
->ospf6
->brouter_table
,
2207 } else if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
)
2208 || CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
)) {
2209 if (IS_OSPF6_DEBUG_BROUTER
2210 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2212 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2214 zlog_info("%s: brouter %s appears via area %s",
2215 __func__
, brouter_name
, oa
->name
);
2219 (*hook_add
)(brouter
, oa
->ospf6
);
2221 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2223 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2225 zlog_info("brouter %s still exists via area %s",
2226 brouter_name
, oa
->name
);
2227 /* But re-originate summaries */
2228 ospf6_abr_originate_summary(brouter
, oa
->ospf6
);
2232 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
);
2233 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
);
2235 /* Reset for nbrouter */
2236 oa
->intra_brouter_calc
= 0;
2239 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa
->area_id
) ||
2240 IS_OSPF6_DEBUG_ROUTE(MEMORY
))
2241 zlog_info("%s: border-router calculation for area %s: done",
2242 __func__
, oa
->name
);
2245 static struct ospf6_lsa_handler router_handler
= {
2246 .lh_type
= OSPF6_LSTYPE_ROUTER
,
2247 .lh_name
= "Router",
2248 .lh_short_name
= "Rtr",
2249 .lh_show
= ospf6_router_lsa_show
,
2250 .lh_get_prefix_str
= ospf6_router_lsa_get_nbr_id
,
2253 static struct ospf6_lsa_handler network_handler
= {
2254 .lh_type
= OSPF6_LSTYPE_NETWORK
,
2255 .lh_name
= "Network",
2256 .lh_short_name
= "Net",
2257 .lh_show
= ospf6_network_lsa_show
,
2258 .lh_get_prefix_str
= ospf6_network_lsa_get_ar_id
,
2261 static struct ospf6_lsa_handler link_handler
= {
2262 .lh_type
= OSPF6_LSTYPE_LINK
,
2264 .lh_short_name
= "Lnk",
2265 .lh_show
= ospf6_link_lsa_show
,
2266 .lh_get_prefix_str
= ospf6_link_lsa_get_prefix_str
,
2269 static struct ospf6_lsa_handler intra_prefix_handler
= {
2270 .lh_type
= OSPF6_LSTYPE_INTRA_PREFIX
,
2271 .lh_name
= "Intra-Prefix",
2272 .lh_short_name
= "INP",
2273 .lh_show
= ospf6_intra_prefix_lsa_show
,
2274 .lh_get_prefix_str
= ospf6_intra_prefix_lsa_get_prefix_str
,
2277 void ospf6_intra_init(void)
2279 ospf6_install_lsa_handler(&router_handler
);
2280 ospf6_install_lsa_handler(&network_handler
);
2281 ospf6_install_lsa_handler(&link_handler
);
2282 ospf6_install_lsa_handler(&intra_prefix_handler
);
2285 DEFUN (debug_ospf6_brouter
,
2286 debug_ospf6_brouter_cmd
,
2287 "debug ospf6 border-routers",
2290 "Debug border router\n"
2293 OSPF6_DEBUG_BROUTER_ON();
2297 DEFUN (no_debug_ospf6_brouter
,
2298 no_debug_ospf6_brouter_cmd
,
2299 "no debug ospf6 border-routers",
2303 "Debug border router\n"
2306 OSPF6_DEBUG_BROUTER_OFF();
2310 DEFUN (debug_ospf6_brouter_router
,
2311 debug_ospf6_brouter_router_cmd
,
2312 "debug ospf6 border-routers router-id A.B.C.D",
2315 "Debug border router\n"
2316 "Debug specific border router\n"
2317 "Specify border-router's router-id\n"
2322 inet_pton(AF_INET
, argv
[idx_ipv4
]->arg
, &router_id
);
2323 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON(router_id
);
2327 DEFUN (no_debug_ospf6_brouter_router
,
2328 no_debug_ospf6_brouter_router_cmd
,
2329 "no debug ospf6 border-routers router-id",
2333 "Debug border router\n"
2334 "Debug specific border router\n"
2337 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF();
2341 DEFUN (debug_ospf6_brouter_area
,
2342 debug_ospf6_brouter_area_cmd
,
2343 "debug ospf6 border-routers area-id A.B.C.D",
2346 "Debug border router\n"
2347 "Debug border routers in specific Area\n"
2353 inet_pton(AF_INET
, argv
[idx_ipv4
]->arg
, &area_id
);
2354 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON(area_id
);
2358 DEFUN (no_debug_ospf6_brouter_area
,
2359 no_debug_ospf6_brouter_area_cmd
,
2360 "no debug ospf6 border-routers area-id",
2364 "Debug border router\n"
2365 "Debug border routers in specific Area\n"
2368 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF();
2372 int config_write_ospf6_debug_brouter(struct vty
*vty
)
2375 if (IS_OSPF6_DEBUG_BROUTER
)
2376 vty_out(vty
, "debug ospf6 border-routers\n");
2377 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER
) {
2378 inet_ntop(AF_INET
, &conf_debug_ospf6_brouter_specific_router_id
,
2380 vty_out(vty
, "debug ospf6 border-routers router-id %s\n", buf
);
2382 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA
) {
2383 inet_ntop(AF_INET
, &conf_debug_ospf6_brouter_specific_area_id
,
2385 vty_out(vty
, "debug ospf6 border-routers area-id %s\n", buf
);
2390 void install_element_ospf6_debug_brouter(void)
2392 install_element(ENABLE_NODE
, &debug_ospf6_brouter_cmd
);
2393 install_element(ENABLE_NODE
, &debug_ospf6_brouter_router_cmd
);
2394 install_element(ENABLE_NODE
, &debug_ospf6_brouter_area_cmd
);
2395 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_cmd
);
2396 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_router_cmd
);
2397 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_area_cmd
);
2398 install_element(CONFIG_NODE
, &debug_ospf6_brouter_cmd
);
2399 install_element(CONFIG_NODE
, &debug_ospf6_brouter_router_cmd
);
2400 install_element(CONFIG_NODE
, &debug_ospf6_brouter_area_cmd
);
2401 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_cmd
);
2402 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_router_cmd
);
2403 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_area_cmd
);