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 u_int32_t conf_debug_ospf6_brouter_specific_router_id
;
53 u_int32_t conf_debug_ospf6_brouter_specific_area_id
;
55 /******************************/
56 /* RFC2740 3.4.3.1 Router-LSA */
57 /******************************/
59 static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa
*lsa
, char *buf
,
62 struct ospf6_router_lsa
*router_lsa
;
63 struct ospf6_router_lsdesc
*lsdesc
;
65 char buf1
[INET_ADDRSTRLEN
], buf2
[INET_ADDRSTRLEN
];
68 router_lsa
= (struct ospf6_router_lsa
69 *)((char *)lsa
->header
70 + sizeof(struct ospf6_lsa_header
));
71 start
= (char *)router_lsa
+ sizeof(struct ospf6_router_lsa
);
72 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
74 lsdesc
= (struct ospf6_router_lsdesc
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(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 u_int32_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");
255 /* Point-to-Point interfaces */
256 if (oi
->type
== OSPF_IFTYPE_POINTOPOINT
) {
257 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
)) {
258 if (on
->state
!= OSPF6_NEIGHBOR_FULL
)
261 lsdesc
->type
= OSPF6_ROUTER_LSDESC_POINTTOPOINT
;
262 lsdesc
->metric
= htons(oi
->cost
);
263 lsdesc
->interface_id
=
264 htonl(oi
->interface
->ifindex
);
265 lsdesc
->neighbor_interface_id
=
267 lsdesc
->neighbor_router_id
= on
->router_id
;
273 /* Broadcast and NBMA interfaces */
274 else if (oi
->type
== OSPF_IFTYPE_BROADCAST
) {
275 /* If this router is not DR,
276 and If this router not fully adjacent with DR,
277 this interface is not transit yet: ignore. */
278 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
280 ospf6_neighbor_lookup(oi
->drouter
, oi
);
282 || drouter
->state
!= OSPF6_NEIGHBOR_FULL
)
286 lsdesc
->type
= OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK
;
287 lsdesc
->metric
= htons(oi
->cost
);
288 lsdesc
->interface_id
= htonl(oi
->interface
->ifindex
);
289 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
290 lsdesc
->neighbor_interface_id
=
291 htonl(drouter
->ifindex
);
292 lsdesc
->neighbor_router_id
= drouter
->router_id
;
294 lsdesc
->neighbor_interface_id
=
295 htonl(oi
->interface
->ifindex
);
296 lsdesc
->neighbor_router_id
=
297 oi
->area
->ospf6
->router_id
;
302 assert(0); /* Unknown interface type */
307 /* Point-to-Multipoint interfaces */
311 /* Fill LSA Header */
313 lsa_header
->type
= htons(OSPF6_LSTYPE_ROUTER
);
314 lsa_header
->id
= htonl(link_state_id
);
315 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
317 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
318 lsa_header
->adv_router
, oa
->lsdb
);
319 lsa_header
->length
= htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
322 ospf6_lsa_checksum(lsa_header
);
325 lsa
= ospf6_lsa_create(lsa_header
);
328 ospf6_lsa_originate_area(lsa
, oa
);
332 /* Do premature-aging of rest, undesired Router-LSAs */
333 type
= ntohs(OSPF6_LSTYPE_ROUTER
);
334 router
= oa
->ospf6
->router_id
;
336 for (ALL_LSDB_TYPED_ADVRTR(oa
->lsdb
, type
, router
, lsa
)) {
337 if (ntohl(lsa
->header
->id
) < link_state_id
)
339 ospf6_lsa_purge(lsa
);
344 * Waiting till the LSA is actually removed from the database to trigger
345 * SPF delays network convergence. Unlike IPv4, for an ABR, when all
346 * interfaces associated with an area are gone, triggering an SPF right
348 * helps convergence with inter-area routes.
350 if (count
&& !link_state_id
)
351 ospf6_spf_schedule(oa
->ospf6
,
352 OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED
);
357 /*******************************/
358 /* RFC2740 3.4.3.2 Network-LSA */
359 /*******************************/
361 static char *ospf6_network_lsa_get_ar_id(struct ospf6_lsa
*lsa
, char *buf
,
364 char *start
, *end
, *current
;
365 struct ospf6_network_lsa
*network_lsa
;
366 struct ospf6_network_lsdesc
*lsdesc
;
369 network_lsa
= (struct ospf6_network_lsa
370 *)((caddr_t
)lsa
->header
371 + sizeof(struct ospf6_lsa_header
));
373 start
= (char *)network_lsa
+ sizeof(struct ospf6_network_lsa
);
374 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
375 current
= start
+ pos
* (sizeof(struct ospf6_network_lsdesc
));
377 if ((current
+ sizeof(struct ospf6_network_lsdesc
)) <= end
) {
378 lsdesc
= (struct ospf6_network_lsdesc
*)current
;
380 inet_ntop(AF_INET
, &lsdesc
->router_id
, buf
,
389 static int ospf6_network_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
)
391 char *start
, *end
, *current
;
392 struct ospf6_network_lsa
*network_lsa
;
393 struct ospf6_network_lsdesc
*lsdesc
;
394 char buf
[128], options
[32];
397 (struct ospf6_network_lsa
*)((caddr_t
)lsa
->header
398 + sizeof(struct ospf6_lsa_header
));
400 ospf6_options_printbuf(network_lsa
->options
, options
, sizeof(options
));
401 vty_out(vty
, " Options: %s\n", options
);
403 start
= (char *)network_lsa
+ sizeof(struct ospf6_network_lsa
);
404 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
405 for (current
= start
;
406 current
+ sizeof(struct ospf6_network_lsdesc
) <= end
;
407 current
+= sizeof(struct ospf6_network_lsdesc
)) {
408 lsdesc
= (struct ospf6_network_lsdesc
*)current
;
409 inet_ntop(AF_INET
, &lsdesc
->router_id
, buf
, sizeof(buf
));
410 vty_out(vty
, " Attached Router: %s\n", buf
);
415 int ospf6_network_lsa_originate(struct thread
*thread
)
417 struct ospf6_interface
*oi
;
419 char buffer
[OSPF6_MAX_LSASIZE
];
420 struct ospf6_lsa_header
*lsa_header
;
423 struct ospf6_lsa
*old
, *lsa
;
424 struct ospf6_network_lsa
*network_lsa
;
425 struct ospf6_network_lsdesc
*lsdesc
;
426 struct ospf6_neighbor
*on
;
427 struct ospf6_link_lsa
*link_lsa
;
431 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
432 oi
->thread_network_lsa
= NULL
;
434 /* The interface must be enabled until here. A Network-LSA of a
435 disabled interface (but was once enabled) should be flushed
436 by ospf6_lsa_refresh (), and does not come here. */
439 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_NETWORK
),
440 htonl(oi
->interface
->ifindex
),
441 oi
->area
->ospf6
->router_id
, oi
->area
->lsdb
);
443 /* Do not originate Network-LSA if not DR */
444 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
446 ospf6_lsa_purge(old
);
448 * Waiting till the LSA is actually removed from the
450 * trigger SPF delays network convergence.
454 OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED
);
459 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK
))
460 zlog_debug("Originate Network-LSA for Interface %s",
461 oi
->interface
->name
);
463 /* If none of neighbor is adjacent to us */
466 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
))
467 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
471 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK
))
472 zlog_debug("Interface stub, ignore");
474 ospf6_lsa_purge(old
);
479 memset(buffer
, 0, sizeof(buffer
));
480 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
482 (struct ospf6_network_lsa
*)((caddr_t
)lsa_header
483 + sizeof(struct ospf6_lsa_header
));
485 /* Collect the interface's Link-LSAs to describe
486 network's optional capabilities */
487 type
= htons(OSPF6_LSTYPE_LINK
);
488 for (ALL_LSDB_TYPED(oi
->lsdb
, type
, lsa
)) {
489 link_lsa
= (struct ospf6_link_lsa
490 *)((caddr_t
)lsa
->header
491 + sizeof(struct ospf6_lsa_header
));
492 network_lsa
->options
[0] |= link_lsa
->options
[0];
493 network_lsa
->options
[1] |= link_lsa
->options
[1];
494 network_lsa
->options
[2] |= link_lsa
->options
[2];
497 lsdesc
= (struct ospf6_network_lsdesc
498 *)((caddr_t
)network_lsa
499 + sizeof(struct ospf6_network_lsa
));
501 /* set Link Description to the router itself */
502 lsdesc
->router_id
= oi
->area
->ospf6
->router_id
;
505 /* Walk through the neighbors */
506 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
)) {
507 if (on
->state
!= OSPF6_NEIGHBOR_FULL
)
510 /* set this neighbor's Router-ID to LSA */
511 lsdesc
->router_id
= on
->router_id
;
515 /* Fill LSA Header */
517 lsa_header
->type
= htons(OSPF6_LSTYPE_NETWORK
);
518 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
519 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
521 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
522 lsa_header
->adv_router
, oi
->area
->lsdb
);
523 lsa_header
->length
= htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
526 ospf6_lsa_checksum(lsa_header
);
529 lsa
= ospf6_lsa_create(lsa_header
);
532 ospf6_lsa_originate_area(lsa
, oi
->area
);
538 /****************************/
539 /* RFC2740 3.4.3.6 Link-LSA */
540 /****************************/
542 static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa
*lsa
, char *buf
,
545 char *start
, *end
, *current
;
546 struct ospf6_link_lsa
*link_lsa
;
548 struct ospf6_prefix
*prefix
;
549 int cnt
= 0, prefixnum
;
552 link_lsa
= (struct ospf6_link_lsa
553 *)((caddr_t
)lsa
->header
554 + sizeof(struct ospf6_lsa_header
));
557 inet_ntop(AF_INET6
, &link_lsa
->linklocal_addr
, buf
,
562 prefixnum
= ntohl(link_lsa
->prefix_num
);
566 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
567 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
571 prefix
= (struct ospf6_prefix
*)current
;
572 if (prefix
->prefix_length
== 0
573 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
) {
579 start
+ pos
* OSPF6_PREFIX_SIZE(prefix
);
582 memset(&in6
, 0, sizeof(in6
));
583 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
585 prefix
->prefix_length
));
586 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
589 } while (current
<= end
);
594 static int ospf6_link_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
)
596 char *start
, *end
, *current
;
597 struct ospf6_link_lsa
*link_lsa
;
599 char buf
[128], options
[32];
600 struct ospf6_prefix
*prefix
;
601 const char *p
, *mc
, *la
, *nu
;
604 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsa
->header
605 + sizeof(struct ospf6_lsa_header
));
607 ospf6_options_printbuf(link_lsa
->options
, options
, sizeof(options
));
608 inet_ntop(AF_INET6
, &link_lsa
->linklocal_addr
, buf
, sizeof(buf
));
609 prefixnum
= ntohl(link_lsa
->prefix_num
);
611 vty_out(vty
, " Priority: %d Options: %s\n", link_lsa
->priority
,
613 vty_out(vty
, " LinkLocal Address: %s\n", buf
);
614 vty_out(vty
, " Number of Prefix: %d\n", prefixnum
);
616 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
617 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
618 for (current
= start
; current
< end
;
619 current
+= OSPF6_PREFIX_SIZE(prefix
)) {
620 prefix
= (struct ospf6_prefix
*)current
;
621 if (prefix
->prefix_length
== 0
622 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
)
625 p
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_P
)
628 mc
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_MC
)
631 la
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_LA
)
634 nu
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_NU
)
637 vty_out(vty
, " Prefix Options: %s|%s|%s|%s\n", p
, mc
, la
,
640 memset(&in6
, 0, sizeof(in6
));
641 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
642 OSPF6_PREFIX_SPACE(prefix
->prefix_length
));
643 inet_ntop(AF_INET6
, &in6
, buf
, sizeof(buf
));
644 vty_out(vty
, " Prefix: %s/%d\n", buf
,
645 prefix
->prefix_length
);
651 int ospf6_link_lsa_originate(struct thread
*thread
)
653 struct ospf6_interface
*oi
;
655 char buffer
[OSPF6_MAX_LSASIZE
];
656 struct ospf6_lsa_header
*lsa_header
;
657 struct ospf6_lsa
*old
, *lsa
;
659 struct ospf6_link_lsa
*link_lsa
;
660 struct ospf6_route
*route
;
661 struct ospf6_prefix
*op
;
663 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
664 oi
->thread_link_lsa
= NULL
;
668 /* find previous LSA */
669 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_LINK
),
670 htonl(oi
->interface
->ifindex
),
671 oi
->area
->ospf6
->router_id
, oi
->lsdb
);
673 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
675 ospf6_lsa_purge(old
);
679 if (IS_OSPF6_DEBUG_ORIGINATE(LINK
))
680 zlog_debug("Originate Link-LSA for Interface %s",
681 oi
->interface
->name
);
683 /* can't make Link-LSA if linklocal address not set */
684 if (oi
->linklocal_addr
== NULL
) {
685 if (IS_OSPF6_DEBUG_ORIGINATE(LINK
))
687 "No Linklocal address on %s, defer originating",
688 oi
->interface
->name
);
690 ospf6_lsa_purge(old
);
695 memset(buffer
, 0, sizeof(buffer
));
696 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
697 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsa_header
698 + sizeof(struct ospf6_lsa_header
));
701 link_lsa
->priority
= oi
->priority
;
702 memcpy(link_lsa
->options
, oi
->area
->options
, 3);
703 memcpy(&link_lsa
->linklocal_addr
, oi
->linklocal_addr
,
704 sizeof(struct in6_addr
));
705 link_lsa
->prefix_num
= htonl(oi
->route_connected
->count
);
707 op
= (struct ospf6_prefix
*)((caddr_t
)link_lsa
708 + sizeof(struct ospf6_link_lsa
));
710 /* connected prefix to advertise */
711 for (route
= ospf6_route_head(oi
->route_connected
); route
;
712 route
= ospf6_route_next(route
)) {
713 op
->prefix_length
= route
->prefix
.prefixlen
;
714 op
->prefix_options
= route
->path
.prefix_options
;
715 op
->prefix_metric
= htons(0);
716 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
717 OSPF6_PREFIX_SPACE(op
->prefix_length
));
718 op
= OSPF6_PREFIX_NEXT(op
);
721 /* Fill LSA Header */
723 lsa_header
->type
= htons(OSPF6_LSTYPE_LINK
);
724 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
725 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
727 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
728 lsa_header
->adv_router
, oi
->lsdb
);
729 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)buffer
);
732 ospf6_lsa_checksum(lsa_header
);
735 lsa
= ospf6_lsa_create(lsa_header
);
738 ospf6_lsa_originate_interface(lsa
, oi
);
744 /*****************************************/
745 /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
746 /*****************************************/
747 static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
748 char *buf
, int buflen
,
751 char *start
, *end
, *current
;
752 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
754 int prefixnum
, cnt
= 0;
755 struct ospf6_prefix
*prefix
;
759 (struct ospf6_intra_prefix_lsa
760 *)((caddr_t
)lsa
->header
761 + sizeof(struct ospf6_lsa_header
));
763 prefixnum
= ntohs(intra_prefix_lsa
->prefix_num
);
767 start
= (char *)intra_prefix_lsa
768 + sizeof(struct ospf6_intra_prefix_lsa
);
769 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
773 prefix
= (struct ospf6_prefix
*)current
;
774 if (prefix
->prefix_length
== 0
775 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
) {
781 start
+ pos
* OSPF6_PREFIX_SIZE(prefix
);
784 memset(&in6
, 0, sizeof(in6
));
785 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
787 prefix
->prefix_length
));
788 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
789 sprintf(&buf
[strlen(buf
)], "/%d",
790 prefix
->prefix_length
);
793 } while (current
<= end
);
798 static int ospf6_intra_prefix_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
)
800 char *start
, *end
, *current
;
801 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
804 struct ospf6_prefix
*prefix
;
805 char id
[16], adv_router
[16];
806 const char *p
, *mc
, *la
, *nu
;
809 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
810 *)((caddr_t
)lsa
->header
811 + sizeof(struct ospf6_lsa_header
));
813 prefixnum
= ntohs(intra_prefix_lsa
->prefix_num
);
815 vty_out(vty
, " Number of Prefix: %d\n", prefixnum
);
817 inet_ntop(AF_INET
, &intra_prefix_lsa
->ref_id
, id
, sizeof(id
));
818 inet_ntop(AF_INET
, &intra_prefix_lsa
->ref_adv_router
, adv_router
,
820 vty_out(vty
, " Reference: %s Id: %s Adv: %s\n",
821 ospf6_lstype_name(intra_prefix_lsa
->ref_type
), id
, adv_router
);
823 start
= (char *)intra_prefix_lsa
824 + sizeof(struct ospf6_intra_prefix_lsa
);
825 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
826 for (current
= start
; current
< end
;
827 current
+= OSPF6_PREFIX_SIZE(prefix
)) {
828 prefix
= (struct ospf6_prefix
*)current
;
829 if (prefix
->prefix_length
== 0
830 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
)
833 p
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_P
)
836 mc
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_MC
)
839 la
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_LA
)
842 nu
= (CHECK_FLAG(prefix
->prefix_options
, OSPF6_PREFIX_OPTION_NU
)
845 vty_out(vty
, " Prefix Options: %s|%s|%s|%s\n", p
, mc
, la
,
848 memset(&in6
, 0, sizeof(in6
));
849 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
850 OSPF6_PREFIX_SPACE(prefix
->prefix_length
));
851 inet_ntop(AF_INET6
, &in6
, buf
, sizeof(buf
));
852 vty_out(vty
, " Prefix: %s/%d\n", buf
,
853 prefix
->prefix_length
);
859 int ospf6_intra_prefix_lsa_originate_stub(struct thread
*thread
)
861 struct ospf6_area
*oa
;
863 char buffer
[OSPF6_MAX_LSASIZE
];
864 struct ospf6_lsa_header
*lsa_header
;
865 struct ospf6_lsa
*old
, *lsa
;
867 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
868 struct ospf6_interface
*oi
;
869 struct ospf6_neighbor
*on
;
870 struct ospf6_route
*route
;
871 struct ospf6_prefix
*op
;
872 struct listnode
*i
, *j
;
874 unsigned short prefix_num
= 0;
875 char buf
[PREFIX2STR_BUFFER
];
876 struct ospf6_route_table
*route_advertise
;
878 oa
= (struct ospf6_area
*)THREAD_ARG(thread
);
879 oa
->thread_intra_prefix_lsa
= NULL
;
881 /* find previous LSA */
882 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX
), htonl(0),
883 oa
->ospf6
->router_id
, oa
->lsdb
);
885 if (!IS_AREA_ENABLED(oa
)) {
887 ospf6_lsa_purge(old
);
891 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
893 "Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
897 memset(buffer
, 0, sizeof(buffer
));
898 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
899 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
900 *)((caddr_t
)lsa_header
901 + sizeof(struct ospf6_lsa_header
));
903 /* Fill Intra-Area-Prefix-LSA */
904 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_ROUTER
);
905 intra_prefix_lsa
->ref_id
= htonl(0);
906 intra_prefix_lsa
->ref_adv_router
= oa
->ospf6
->router_id
;
908 route_advertise
= ospf6_route_table_create(0, 0);
910 for (ALL_LIST_ELEMENTS_RO(oa
->if_list
, i
, oi
)) {
911 if (oi
->state
== OSPF6_INTERFACE_DOWN
) {
912 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
913 zlog_debug(" Interface %s is down, ignore",
914 oi
->interface
->name
);
920 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
))
921 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
924 if (oi
->state
!= OSPF6_INTERFACE_LOOPBACK
925 && oi
->state
!= OSPF6_INTERFACE_POINTTOPOINT
926 && full_count
!= 0) {
927 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
928 zlog_debug(" Interface %s is not stub, ignore",
929 oi
->interface
->name
);
933 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
934 zlog_debug(" Interface %s:", oi
->interface
->name
);
936 /* connected prefix to advertise */
937 for (route
= ospf6_route_head(oi
->route_connected
); route
;
938 route
= ospf6_route_best_next(route
)) {
939 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
)) {
940 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
941 zlog_debug(" include %s", buf
);
943 ospf6_route_add(ospf6_route_copy(route
),
948 if (route_advertise
->count
== 0) {
950 ospf6_lsa_purge(old
);
951 ospf6_route_table_delete(route_advertise
);
955 /* put prefixes to advertise */
957 op
= (struct ospf6_prefix
*)((caddr_t
)intra_prefix_lsa
958 + sizeof(struct ospf6_intra_prefix_lsa
));
959 for (route
= ospf6_route_head(route_advertise
); route
;
960 route
= ospf6_route_best_next(route
)) {
961 op
->prefix_length
= route
->prefix
.prefixlen
;
962 op
->prefix_options
= route
->path
.prefix_options
;
963 op
->prefix_metric
= htons(route
->path
.cost
);
964 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
965 OSPF6_PREFIX_SPACE(op
->prefix_length
));
966 op
= OSPF6_PREFIX_NEXT(op
);
970 ospf6_route_table_delete(route_advertise
);
972 if (prefix_num
== 0) {
973 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
975 "Quit to Advertise Intra-Prefix: no route to advertise");
979 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
981 /* Fill LSA Header */
983 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
984 lsa_header
->id
= htonl(0);
985 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
987 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
988 lsa_header
->adv_router
, oa
->lsdb
);
989 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)lsa_header
);
992 ospf6_lsa_checksum(lsa_header
);
995 lsa
= ospf6_lsa_create(lsa_header
);
998 ospf6_lsa_originate_area(lsa
, oa
);
1004 int ospf6_intra_prefix_lsa_originate_transit(struct thread
*thread
)
1006 struct ospf6_interface
*oi
;
1008 char buffer
[OSPF6_MAX_LSASIZE
];
1009 struct ospf6_lsa_header
*lsa_header
;
1010 struct ospf6_lsa
*old
, *lsa
;
1012 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1013 struct ospf6_neighbor
*on
;
1014 struct ospf6_route
*route
;
1015 struct ospf6_prefix
*op
;
1018 unsigned short prefix_num
= 0;
1019 struct ospf6_route_table
*route_advertise
;
1020 struct ospf6_link_lsa
*link_lsa
;
1021 char *start
, *end
, *current
;
1023 char buf
[PREFIX2STR_BUFFER
];
1025 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
1026 oi
->thread_intra_prefix_lsa
= NULL
;
1030 /* find previous LSA */
1031 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1032 htonl(oi
->interface
->ifindex
),
1033 oi
->area
->ospf6
->router_id
, oi
->area
->lsdb
);
1035 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1037 ospf6_lsa_purge(old
);
1041 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1043 "Originate Intra-Area-Prefix-LSA for interface %s's prefix",
1044 oi
->interface
->name
);
1046 /* prepare buffer */
1047 memset(buffer
, 0, sizeof(buffer
));
1048 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1049 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
1050 *)((caddr_t
)lsa_header
1051 + sizeof(struct ospf6_lsa_header
));
1053 /* Fill Intra-Area-Prefix-LSA */
1054 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_NETWORK
);
1055 intra_prefix_lsa
->ref_id
= htonl(oi
->interface
->ifindex
);
1056 intra_prefix_lsa
->ref_adv_router
= oi
->area
->ospf6
->router_id
;
1058 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
1059 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1060 zlog_debug(" Interface is not DR");
1062 ospf6_lsa_purge(old
);
1067 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
))
1068 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
1071 if (full_count
== 0) {
1072 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1073 zlog_debug(" Interface is stub");
1075 ospf6_lsa_purge(old
);
1079 /* connected prefix to advertise */
1080 route_advertise
= ospf6_route_table_create(0, 0);
1082 type
= ntohs(OSPF6_LSTYPE_LINK
);
1083 for (ALL_LSDB_TYPED(oi
->lsdb
, type
, lsa
)) {
1084 if (OSPF6_LSA_IS_MAXAGE(lsa
))
1087 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1088 zlog_debug(" include prefix from %s", lsa
->name
);
1090 if (lsa
->header
->adv_router
!= oi
->area
->ospf6
->router_id
) {
1091 on
= ospf6_neighbor_lookup(lsa
->header
->adv_router
, oi
);
1092 if (on
== NULL
|| on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1093 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1095 " Neighbor not found or not Full, ignore");
1100 link_lsa
= (struct ospf6_link_lsa
1101 *)((caddr_t
)lsa
->header
1102 + sizeof(struct ospf6_lsa_header
));
1104 prefix_num
= (unsigned short)ntohl(link_lsa
->prefix_num
);
1105 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
1106 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
1107 for (current
= start
; current
< end
&& prefix_num
;
1108 current
+= OSPF6_PREFIX_SIZE(op
)) {
1109 op
= (struct ospf6_prefix
*)current
;
1110 if (op
->prefix_length
== 0
1111 || current
+ OSPF6_PREFIX_SIZE(op
) > end
)
1114 route
= ospf6_route_create();
1116 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
1117 route
->prefix
.family
= AF_INET6
;
1118 route
->prefix
.prefixlen
= op
->prefix_length
;
1119 memset(&route
->prefix
.u
.prefix6
, 0,
1120 sizeof(struct in6_addr
));
1121 memcpy(&route
->prefix
.u
.prefix6
, OSPF6_PREFIX_BODY(op
),
1122 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1124 route
->path
.origin
.type
= lsa
->header
->type
;
1125 route
->path
.origin
.id
= lsa
->header
->id
;
1126 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1127 route
->path
.options
[0] = link_lsa
->options
[0];
1128 route
->path
.options
[1] = link_lsa
->options
[1];
1129 route
->path
.options
[2] = link_lsa
->options
[2];
1130 route
->path
.prefix_options
= op
->prefix_options
;
1131 route
->path
.area_id
= oi
->area
->area_id
;
1132 route
->path
.type
= OSPF6_PATH_TYPE_INTRA
;
1134 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
)) {
1135 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1136 zlog_debug(" include %s", buf
);
1139 ospf6_route_add(route
, route_advertise
);
1142 if (current
!= end
&& IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1143 zlog_debug("Trailing garbage in %s", lsa
->name
);
1146 op
= (struct ospf6_prefix
*)((caddr_t
)intra_prefix_lsa
1147 + sizeof(struct ospf6_intra_prefix_lsa
));
1150 for (route
= ospf6_route_head(route_advertise
); route
;
1151 route
= ospf6_route_best_next(route
)) {
1152 op
->prefix_length
= route
->prefix
.prefixlen
;
1153 op
->prefix_options
= route
->path
.prefix_options
;
1154 op
->prefix_metric
= htons(0);
1155 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
1156 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1157 op
= OSPF6_PREFIX_NEXT(op
);
1161 ospf6_route_table_delete(route_advertise
);
1163 if (prefix_num
== 0) {
1164 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1166 "Quit to Advertise Intra-Prefix: no route to advertise");
1170 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
1172 /* Fill LSA Header */
1173 lsa_header
->age
= 0;
1174 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1175 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
1176 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
1177 lsa_header
->seqnum
=
1178 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
1179 lsa_header
->adv_router
, oi
->area
->lsdb
);
1180 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)lsa_header
);
1183 ospf6_lsa_checksum(lsa_header
);
1186 lsa
= ospf6_lsa_create(lsa_header
);
1189 ospf6_lsa_originate_area(lsa
, oi
->area
);
1194 void ospf6_intra_prefix_lsa_add(struct ospf6_lsa
*lsa
)
1196 struct ospf6_area
*oa
;
1197 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1198 struct prefix ls_prefix
;
1199 struct ospf6_route
*route
, *ls_entry
;
1201 struct ospf6_prefix
*op
;
1202 char *start
, *current
, *end
;
1203 char buf
[PREFIX2STR_BUFFER
];
1204 struct interface
*ifp
;
1205 int direct_connect
= 0;
1207 if (OSPF6_LSA_IS_MAXAGE(lsa
))
1210 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1211 zlog_debug("%s found", lsa
->name
);
1213 oa
= OSPF6_AREA(lsa
->lsdb
->data
);
1216 (struct ospf6_intra_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1218 if (intra_prefix_lsa
->ref_type
== htons(OSPF6_LSTYPE_ROUTER
))
1219 ospf6_linkstate_prefix(intra_prefix_lsa
->ref_adv_router
,
1220 htonl(0), &ls_prefix
);
1221 else if (intra_prefix_lsa
->ref_type
== htons(OSPF6_LSTYPE_NETWORK
))
1222 ospf6_linkstate_prefix(intra_prefix_lsa
->ref_adv_router
,
1223 intra_prefix_lsa
->ref_id
, &ls_prefix
);
1225 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1226 zlog_debug("Unknown reference LS-type: %#hx",
1227 ntohs(intra_prefix_lsa
->ref_type
));
1231 ls_entry
= ospf6_route_lookup(&ls_prefix
, oa
->spf_table
);
1232 if (ls_entry
== NULL
) {
1233 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1234 ospf6_linkstate_prefix2str(&ls_prefix
, buf
,
1236 zlog_debug("LS entry does not exist: %s", buf
);
1241 if (intra_prefix_lsa
->ref_adv_router
== oa
->ospf6
->router_id
) {
1242 /* the intra-prefix are directly connected */
1246 prefix_num
= ntohs(intra_prefix_lsa
->prefix_num
);
1247 start
= (caddr_t
)intra_prefix_lsa
1248 + sizeof(struct ospf6_intra_prefix_lsa
);
1249 end
= OSPF6_LSA_END(lsa
->header
);
1250 for (current
= start
; current
< end
; current
+= OSPF6_PREFIX_SIZE(op
)) {
1251 op
= (struct ospf6_prefix
*)current
;
1252 if (prefix_num
== 0)
1254 if (end
< current
+ OSPF6_PREFIX_SIZE(op
))
1257 /* Appendix A.4.1.1 */
1258 if (CHECK_FLAG(op
->prefix_options
, OSPF6_PREFIX_OPTION_NU
)) {
1259 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1260 ospf6_linkstate_prefix2str(
1261 (struct prefix
*)OSPF6_PREFIX_BODY(op
),
1264 "%s: Skipping Prefix %s has NU option set",
1270 route
= ospf6_route_create();
1272 memset(&route
->prefix
, 0, sizeof(struct prefix
));
1273 route
->prefix
.family
= AF_INET6
;
1274 route
->prefix
.prefixlen
= op
->prefix_length
;
1275 ospf6_prefix_in6_addr(&route
->prefix
.u
.prefix6
, op
);
1277 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
1278 route
->path
.origin
.type
= lsa
->header
->type
;
1279 route
->path
.origin
.id
= lsa
->header
->id
;
1280 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1281 route
->path
.prefix_options
= op
->prefix_options
;
1282 route
->path
.area_id
= oa
->area_id
;
1283 route
->path
.type
= OSPF6_PATH_TYPE_INTRA
;
1284 route
->path
.metric_type
= 1;
1286 ls_entry
->path
.cost
+ ntohs(op
->prefix_metric
);
1288 if (direct_connect
) {
1289 ifp
= if_lookup_prefix(&route
->prefix
, VRF_DEFAULT
);
1291 ospf6_route_add_nexthop(route
, ifp
->ifindex
,
1294 ospf6_route_copy_nexthops(route
, ls_entry
);
1297 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1298 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1299 zlog_debug(" add %s", buf
);
1302 ospf6_route_add(route
, oa
->route_table
);
1306 if (current
!= end
&& IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1307 zlog_debug("Trailing garbage ignored");
1310 void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa
*lsa
)
1312 struct ospf6_area
*oa
;
1313 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1314 struct prefix prefix
;
1315 struct ospf6_route
*route
, *nroute
;
1317 struct ospf6_prefix
*op
;
1318 char *start
, *current
, *end
;
1319 char buf
[PREFIX2STR_BUFFER
];
1321 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1322 zlog_debug("%s disappearing", lsa
->name
);
1324 oa
= OSPF6_AREA(lsa
->lsdb
->data
);
1327 (struct ospf6_intra_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1330 prefix_num
= ntohs(intra_prefix_lsa
->prefix_num
);
1331 start
= (caddr_t
)intra_prefix_lsa
1332 + sizeof(struct ospf6_intra_prefix_lsa
);
1333 end
= OSPF6_LSA_END(lsa
->header
);
1334 for (current
= start
; current
< end
; current
+= OSPF6_PREFIX_SIZE(op
)) {
1335 op
= (struct ospf6_prefix
*)current
;
1336 if (prefix_num
== 0)
1338 if (end
< current
+ OSPF6_PREFIX_SIZE(op
))
1342 memset(&prefix
, 0, sizeof(struct prefix
));
1343 prefix
.family
= AF_INET6
;
1344 prefix
.prefixlen
= op
->prefix_length
;
1345 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, op
);
1347 route
= ospf6_route_lookup(&prefix
, oa
->route_table
);
1351 for (ospf6_route_lock(route
);
1352 route
&& ospf6_route_is_prefix(&prefix
, route
);
1354 nroute
= ospf6_route_next(route
);
1355 if (route
->type
!= OSPF6_DEST_TYPE_NETWORK
)
1357 if (route
->path
.area_id
!= oa
->area_id
)
1359 if (route
->path
.type
!= OSPF6_PATH_TYPE_INTRA
)
1361 if (route
->path
.origin
.type
!= lsa
->header
->type
1362 || route
->path
.origin
.id
!= lsa
->header
->id
1363 || route
->path
.origin
.adv_router
1364 != lsa
->header
->adv_router
)
1367 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1368 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1369 zlog_debug("remove %s", buf
);
1371 ospf6_route_remove(route
, oa
->route_table
);
1374 ospf6_route_unlock(route
);
1377 if (current
!= end
&& IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1378 zlog_debug("Trailing garbage ignored");
1381 void ospf6_intra_route_calculation(struct ospf6_area
*oa
)
1383 struct ospf6_route
*route
, *nroute
;
1385 struct ospf6_lsa
*lsa
;
1386 void (*hook_add
)(struct ospf6_route
*) = NULL
;
1387 void (*hook_remove
)(struct ospf6_route
*) = NULL
;
1389 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1390 zlog_debug("Re-examin intra-routes for area %s", oa
->name
);
1392 hook_add
= oa
->route_table
->hook_add
;
1393 hook_remove
= oa
->route_table
->hook_remove
;
1394 oa
->route_table
->hook_add
= NULL
;
1395 oa
->route_table
->hook_remove
= NULL
;
1397 for (route
= ospf6_route_head(oa
->route_table
); route
;
1398 route
= ospf6_route_next(route
))
1399 route
->flag
= OSPF6_ROUTE_REMOVE
;
1401 type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1402 for (ALL_LSDB_TYPED(oa
->lsdb
, type
, lsa
))
1403 ospf6_intra_prefix_lsa_add(lsa
);
1405 oa
->route_table
->hook_add
= hook_add
;
1406 oa
->route_table
->hook_remove
= hook_remove
;
1408 for (route
= ospf6_route_head(oa
->route_table
); route
; route
= nroute
) {
1409 nroute
= ospf6_route_next(route
);
1410 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
)
1411 && CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ADD
)) {
1412 UNSET_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
);
1413 UNSET_FLAG(route
->flag
, OSPF6_ROUTE_ADD
);
1416 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
))
1417 ospf6_route_remove(route
, oa
->route_table
);
1418 else if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ADD
)
1419 || CHECK_FLAG(route
->flag
, OSPF6_ROUTE_CHANGE
)) {
1424 /* Redo the summaries as things might have changed */
1425 ospf6_abr_originate_summary(route
);
1430 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1431 zlog_debug("Re-examin intra-routes for area %s: Done",
1435 static void ospf6_brouter_debug_print(struct ospf6_route
*brouter
)
1437 u_int32_t brouter_id
;
1438 char brouter_name
[16];
1440 char destination
[64];
1441 char installed
[16], changed
[16];
1442 struct timeval now
, res
;
1443 char id
[16], adv_router
[16];
1444 char capa
[16], options
[16];
1446 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
1447 inet_ntop(AF_INET
, &brouter_id
, brouter_name
, sizeof(brouter_name
));
1448 inet_ntop(AF_INET
, &brouter
->path
.area_id
, area_name
,
1450 ospf6_linkstate_prefix2str(&brouter
->prefix
, destination
,
1451 sizeof(destination
));
1454 timersub(&now
, &brouter
->installed
, &res
);
1455 timerstring(&res
, installed
, sizeof(installed
));
1458 timersub(&now
, &brouter
->changed
, &res
);
1459 timerstring(&res
, changed
, sizeof(changed
));
1461 inet_ntop(AF_INET
, &brouter
->path
.origin
.id
, id
, sizeof(id
));
1462 inet_ntop(AF_INET
, &brouter
->path
.origin
.adv_router
, adv_router
,
1463 sizeof(adv_router
));
1465 ospf6_options_printbuf(brouter
->path
.options
, options
, sizeof(options
));
1466 ospf6_capability_printbuf(brouter
->path
.router_bits
, capa
,
1469 zlog_info("Brouter: %s via area %s", brouter_name
, area_name
);
1470 zlog_info(" memory: prev: %p this: %p next: %p parent rnode: %p",
1471 (void *)brouter
->prev
, (void *)brouter
, (void *)brouter
->next
,
1472 (void *)brouter
->rnode
);
1473 zlog_info(" type: %d prefix: %s installed: %s changed: %s",
1474 brouter
->type
, destination
, installed
, changed
);
1475 zlog_info(" lock: %d flags: %s%s%s%s", brouter
->lock
,
1476 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_BEST
) ? "B" : "-"),
1477 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
) ? "A" : "-"),
1478 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
) ? "R" : "-"),
1479 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
) ? "C" : "-"));
1480 zlog_info(" path type: %s ls-origin %s id: %s adv-router %s",
1481 OSPF6_PATH_TYPE_NAME(brouter
->path
.type
),
1482 ospf6_lstype_name(brouter
->path
.origin
.type
), id
, adv_router
);
1483 zlog_info(" options: %s router-bits: %s metric-type: %d metric: %d/%d",
1484 options
, capa
, brouter
->path
.metric_type
, brouter
->path
.cost
,
1485 brouter
->path
.u
.cost_e2
);
1488 void ospf6_intra_brouter_calculation(struct ospf6_area
*oa
)
1490 struct ospf6_route
*brouter
, *nbrouter
, *copy
;
1491 void (*hook_add
)(struct ospf6_route
*) = NULL
;
1492 void (*hook_remove
)(struct ospf6_route
*) = NULL
;
1493 u_int32_t brouter_id
;
1494 char brouter_name
[16];
1496 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa
->area_id
))
1497 zlog_info("border-router calculation for area %s", oa
->name
);
1499 hook_add
= oa
->ospf6
->brouter_table
->hook_add
;
1500 hook_remove
= oa
->ospf6
->brouter_table
->hook_remove
;
1501 oa
->ospf6
->brouter_table
->hook_add
= NULL
;
1502 oa
->ospf6
->brouter_table
->hook_remove
= NULL
;
1504 /* withdraw the previous router entries for the area */
1505 for (brouter
= ospf6_route_head(oa
->ospf6
->brouter_table
); brouter
;
1506 brouter
= ospf6_route_next(brouter
)) {
1507 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
1508 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
1509 sizeof(brouter_name
));
1510 if (brouter
->path
.area_id
!= oa
->area_id
)
1512 SET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
1514 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id
)
1515 || IS_OSPF6_DEBUG_ROUTE(MEMORY
)) {
1516 zlog_info("%p: mark as removing: area %s brouter %s",
1517 (void *)brouter
, oa
->name
, brouter_name
);
1518 ospf6_brouter_debug_print(brouter
);
1522 for (brouter
= ospf6_route_head(oa
->spf_table
); brouter
;
1523 brouter
= ospf6_route_next(brouter
)) {
1524 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
1525 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
1526 sizeof(brouter_name
));
1528 if (brouter
->type
!= OSPF6_DEST_TYPE_LINKSTATE
)
1530 if (ospf6_linkstate_prefix_id(&brouter
->prefix
) != htonl(0))
1532 if (!CHECK_FLAG(brouter
->path
.router_bits
, OSPF6_ROUTER_BIT_E
)
1533 && !CHECK_FLAG(brouter
->path
.router_bits
,
1534 OSPF6_ROUTER_BIT_B
))
1537 if (!OSPF6_OPT_ISSET(brouter
->path
.options
, OSPF6_OPT_V6
)
1538 || !OSPF6_OPT_ISSET(brouter
->path
.options
, OSPF6_OPT_R
))
1541 copy
= ospf6_route_copy(brouter
);
1542 copy
->type
= OSPF6_DEST_TYPE_ROUTER
;
1543 copy
->path
.area_id
= oa
->area_id
;
1544 ospf6_route_add(copy
, oa
->ospf6
->brouter_table
);
1546 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id
)
1547 || IS_OSPF6_DEBUG_ROUTE(MEMORY
)) {
1548 zlog_info("%p: transfer: area %s brouter %s",
1549 (void *)brouter
, oa
->name
, brouter_name
);
1550 ospf6_brouter_debug_print(brouter
);
1554 oa
->ospf6
->brouter_table
->hook_add
= hook_add
;
1555 oa
->ospf6
->brouter_table
->hook_remove
= hook_remove
;
1557 for (brouter
= ospf6_route_head(oa
->ospf6
->brouter_table
); brouter
;
1558 brouter
= nbrouter
) {
1559 nbrouter
= ospf6_route_next(brouter
);
1560 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
1561 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
1562 sizeof(brouter_name
));
1564 if (brouter
->path
.area_id
!= oa
->area_id
)
1567 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_WAS_REMOVED
))
1570 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
)
1571 && CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
)) {
1572 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
1573 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
);
1576 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
)) {
1577 if (IS_OSPF6_DEBUG_BROUTER
1578 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
1580 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
1582 zlog_info("brouter %s disappears via area %s",
1583 brouter_name
, oa
->name
);
1584 ospf6_route_remove(brouter
, oa
->ospf6
->brouter_table
);
1586 } else if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
)
1587 || CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
)) {
1588 if (IS_OSPF6_DEBUG_BROUTER
1589 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
1591 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
1593 zlog_info("brouter %s appears via area %s",
1594 brouter_name
, oa
->name
);
1598 (*hook_add
)(brouter
);
1600 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
1602 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
1604 zlog_info("brouter %s still exists via area %s",
1605 brouter_name
, oa
->name
);
1606 /* But re-originate summaries */
1607 ospf6_abr_originate_summary(brouter
);
1611 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
);
1612 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
);
1616 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa
->area_id
))
1617 zlog_info("border-router calculation for area %s: done",
1621 struct ospf6_lsa_handler router_handler
= {OSPF6_LSTYPE_ROUTER
, "Router", "Rtr",
1622 ospf6_router_lsa_show
,
1623 ospf6_router_lsa_get_nbr_id
};
1625 struct ospf6_lsa_handler network_handler
= {OSPF6_LSTYPE_NETWORK
, "Network",
1626 "Net", ospf6_network_lsa_show
,
1627 ospf6_network_lsa_get_ar_id
};
1629 struct ospf6_lsa_handler link_handler
= {OSPF6_LSTYPE_LINK
, "Link", "Lnk",
1630 ospf6_link_lsa_show
,
1631 ospf6_link_lsa_get_prefix_str
};
1633 struct ospf6_lsa_handler intra_prefix_handler
= {
1634 OSPF6_LSTYPE_INTRA_PREFIX
, "Intra-Prefix", "INP",
1635 ospf6_intra_prefix_lsa_show
, ospf6_intra_prefix_lsa_get_prefix_str
};
1637 void ospf6_intra_init(void)
1639 ospf6_install_lsa_handler(&router_handler
);
1640 ospf6_install_lsa_handler(&network_handler
);
1641 ospf6_install_lsa_handler(&link_handler
);
1642 ospf6_install_lsa_handler(&intra_prefix_handler
);
1645 DEFUN (debug_ospf6_brouter
,
1646 debug_ospf6_brouter_cmd
,
1647 "debug ospf6 border-routers",
1650 "Debug border router\n"
1653 OSPF6_DEBUG_BROUTER_ON();
1657 DEFUN (no_debug_ospf6_brouter
,
1658 no_debug_ospf6_brouter_cmd
,
1659 "no debug ospf6 border-routers",
1663 "Debug border router\n"
1666 OSPF6_DEBUG_BROUTER_OFF();
1670 DEFUN (debug_ospf6_brouter_router
,
1671 debug_ospf6_brouter_router_cmd
,
1672 "debug ospf6 border-routers router-id A.B.C.D",
1675 "Debug border router\n"
1676 "Debug specific border router\n"
1677 "Specify border-router's router-id\n"
1681 u_int32_t router_id
;
1682 inet_pton(AF_INET
, argv
[idx_ipv4
]->arg
, &router_id
);
1683 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON(router_id
);
1687 DEFUN (no_debug_ospf6_brouter_router
,
1688 no_debug_ospf6_brouter_router_cmd
,
1689 "no debug ospf6 border-routers router-id",
1693 "Debug border router\n"
1694 "Debug specific border router\n"
1697 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF();
1701 DEFUN (debug_ospf6_brouter_area
,
1702 debug_ospf6_brouter_area_cmd
,
1703 "debug ospf6 border-routers area-id A.B.C.D",
1706 "Debug border router\n"
1707 "Debug border routers in specific Area\n"
1713 inet_pton(AF_INET
, argv
[idx_ipv4
]->arg
, &area_id
);
1714 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON(area_id
);
1718 DEFUN (no_debug_ospf6_brouter_area
,
1719 no_debug_ospf6_brouter_area_cmd
,
1720 "no debug ospf6 border-routers area-id",
1724 "Debug border router\n"
1725 "Debug border routers in specific Area\n"
1728 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF();
1732 int config_write_ospf6_debug_brouter(struct vty
*vty
)
1735 if (IS_OSPF6_DEBUG_BROUTER
)
1736 vty_out(vty
, "debug ospf6 border-routers\n");
1737 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER
) {
1738 inet_ntop(AF_INET
, &conf_debug_ospf6_brouter_specific_router_id
,
1740 vty_out(vty
, "debug ospf6 border-routers router-id %s\n", buf
);
1742 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA
) {
1743 inet_ntop(AF_INET
, &conf_debug_ospf6_brouter_specific_area_id
,
1745 vty_out(vty
, "debug ospf6 border-routers area-id %s\n", buf
);
1750 void install_element_ospf6_debug_brouter(void)
1752 install_element(ENABLE_NODE
, &debug_ospf6_brouter_cmd
);
1753 install_element(ENABLE_NODE
, &debug_ospf6_brouter_router_cmd
);
1754 install_element(ENABLE_NODE
, &debug_ospf6_brouter_area_cmd
);
1755 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_cmd
);
1756 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_router_cmd
);
1757 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_area_cmd
);
1758 install_element(CONFIG_NODE
, &debug_ospf6_brouter_cmd
);
1759 install_element(CONFIG_NODE
, &debug_ospf6_brouter_router_cmd
);
1760 install_element(CONFIG_NODE
, &debug_ospf6_brouter_area_cmd
);
1761 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_cmd
);
1762 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_router_cmd
);
1763 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_area_cmd
);