2 * Copyright (C) 2003 Yasuhiro Ohara
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "ospf6_proto.h"
35 #include "ospf6_message.h"
36 #include "ospf6_route.h"
37 #include "ospf6_lsa.h"
38 #include "ospf6_lsdb.h"
40 #include "ospf6_top.h"
41 #include "ospf6_area.h"
42 #include "ospf6_interface.h"
43 #include "ospf6_neighbor.h"
44 #include "ospf6_intra.h"
45 #include "ospf6_asbr.h"
46 #include "ospf6_abr.h"
47 #include "ospf6_flood.h"
49 #include "ospf6_spf.h"
51 unsigned char conf_debug_ospf6_brouter
= 0;
52 uint32_t conf_debug_ospf6_brouter_specific_router_id
;
53 uint32_t conf_debug_ospf6_brouter_specific_area_id
;
55 #define MAX_LSA_PAYLOAD (1024 + 256)
56 /******************************/
57 /* RFC2740 3.4.3.1 Router-LSA */
58 /******************************/
60 static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa
*lsa
, char *buf
,
63 struct ospf6_router_lsa
*router_lsa
;
64 struct ospf6_router_lsdesc
*lsdesc
;
66 char buf1
[INET_ADDRSTRLEN
], buf2
[INET_ADDRSTRLEN
];
69 router_lsa
= (struct ospf6_router_lsa
70 *)((char *)lsa
->header
71 + sizeof(struct ospf6_lsa_header
));
72 start
= (char *)router_lsa
+ sizeof(struct ospf6_router_lsa
);
73 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
75 lsdesc
= (struct ospf6_router_lsdesc
77 + pos
* (sizeof(struct
78 ospf6_router_lsdesc
)));
79 if ((char *)lsdesc
+ sizeof(struct ospf6_router_lsdesc
)
81 if (buf
&& (buflen
> INET_ADDRSTRLEN
* 2)) {
83 &lsdesc
->neighbor_interface_id
, buf1
,
85 inet_ntop(AF_INET
, &lsdesc
->neighbor_router_id
,
87 snprintf(buf
, buflen
, "%s/%s", buf2
, buf1
);
97 static int ospf6_router_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
98 json_object
*json_obj
, bool use_json
)
100 char *start
, *end
, *current
;
101 char buf
[32], name
[32], bits
[16], options
[32];
102 struct ospf6_router_lsa
*router_lsa
;
103 struct ospf6_router_lsdesc
*lsdesc
;
104 json_object
*json_arr
;
105 json_object
*json_loop
;
108 (struct ospf6_router_lsa
*)((char *)lsa
->header
109 + sizeof(struct ospf6_lsa_header
));
111 ospf6_capability_printbuf(router_lsa
->bits
, bits
, sizeof(bits
));
112 ospf6_options_printbuf(router_lsa
->options
, options
, sizeof(options
));
114 json_object_string_add(json_obj
, "bits", bits
);
115 json_object_string_add(json_obj
, "options", options
);
116 json_arr
= json_object_new_array();
118 vty_out(vty
, " Bits: %s Options: %s\n", bits
, options
);
120 start
= (char *)router_lsa
+ sizeof(struct ospf6_router_lsa
);
121 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
122 for (current
= start
;
123 current
+ sizeof(struct ospf6_router_lsdesc
) <= end
;
124 current
+= sizeof(struct ospf6_router_lsdesc
)) {
125 lsdesc
= (struct ospf6_router_lsdesc
*)current
;
127 if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_POINTTOPOINT
)
128 snprintf(name
, sizeof(name
), "Point-To-Point");
129 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK
)
130 snprintf(name
, sizeof(name
), "Transit-Network");
131 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_STUB_NETWORK
)
132 snprintf(name
, sizeof(name
), "Stub-Network");
133 else if (lsdesc
->type
== OSPF6_ROUTER_LSDESC_VIRTUAL_LINK
)
134 snprintf(name
, sizeof(name
), "Virtual-Link");
136 snprintf(name
, sizeof(name
), "Unknown (%#x)",
140 json_loop
= json_object_new_object();
141 json_object_string_add(json_loop
, "type", name
);
142 json_object_int_add(json_loop
, "metric",
143 ntohs(lsdesc
->metric
));
144 json_object_string_add(json_loop
, "interfaceId",
146 &lsdesc
->interface_id
,
148 json_object_string_add(
149 json_loop
, "neighborInterfaceId",
151 &lsdesc
->neighbor_interface_id
, buf
,
153 json_object_string_add(
154 json_loop
, "neighborRouterId",
155 inet_ntop(AF_INET
, &lsdesc
->neighbor_router_id
,
157 json_object_array_add(json_arr
, json_loop
);
159 vty_out(vty
, " Type: %s Metric: %d\n", name
,
160 ntohs(lsdesc
->metric
));
161 vty_out(vty
, " Interface ID: %s\n",
162 inet_ntop(AF_INET
, &lsdesc
->interface_id
, buf
,
164 vty_out(vty
, " Neighbor Interface ID: %s\n",
166 &lsdesc
->neighbor_interface_id
, buf
,
168 vty_out(vty
, " Neighbor Router ID: %s\n",
169 inet_ntop(AF_INET
, &lsdesc
->neighbor_router_id
,
174 json_object_object_add(json_obj
, "lsaDescription", json_arr
);
179 static void ospf6_router_lsa_options_set(struct ospf6_area
*oa
,
180 struct ospf6_router_lsa
*router_lsa
)
182 OSPF6_OPT_CLEAR_ALL(router_lsa
->options
);
183 memcpy(router_lsa
->options
, oa
->options
, 3);
185 if (ospf6_is_router_abr(oa
->ospf6
))
186 SET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_B
);
188 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_B
);
190 if (!IS_AREA_STUB(oa
) && ospf6_asbr_is_asbr(oa
->ospf6
)) {
191 SET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_E
);
193 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_E
);
196 /* If the router is ASBR and the area-type is NSSA set the
197 * translate bit in router LSA.
200 && (ospf6_asbr_is_asbr(oa
->ospf6
) || IS_OSPF6_ABR(oa
->ospf6
))) {
201 if (oa
->NSSATranslatorRole
== OSPF6_NSSA_ROLE_ALWAYS
)
202 SET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_NT
);
204 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_NT
);
207 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_V
);
208 UNSET_FLAG(router_lsa
->bits
, OSPF6_ROUTER_BIT_W
);
211 int ospf6_router_is_stub_router(struct ospf6_lsa
*lsa
)
213 struct ospf6_router_lsa
*rtr_lsa
;
215 if (lsa
!= NULL
&& OSPF6_LSA_IS_TYPE(ROUTER
, lsa
)) {
216 rtr_lsa
= (struct ospf6_router_lsa
217 *)((caddr_t
)lsa
->header
218 + sizeof(struct ospf6_lsa_header
));
220 if (!OSPF6_OPT_ISSET(rtr_lsa
->options
, OSPF6_OPT_R
)) {
221 return OSPF6_IS_STUB_ROUTER
;
222 } else if (!OSPF6_OPT_ISSET(rtr_lsa
->options
, OSPF6_OPT_V6
)) {
223 return OSPF6_IS_STUB_ROUTER_V6
;
227 return OSPF6_NOT_STUB_ROUTER
;
230 int ospf6_router_lsa_originate(struct thread
*thread
)
232 struct ospf6_area
*oa
;
234 char buffer
[OSPF6_MAX_LSASIZE
];
235 struct ospf6_lsa_header
*lsa_header
;
236 struct ospf6_lsa
*lsa
;
238 uint32_t link_state_id
= 0;
239 struct listnode
*node
, *nnode
;
241 struct ospf6_interface
*oi
;
242 struct ospf6_neighbor
*on
, *drouter
= NULL
;
243 struct ospf6_router_lsa
*router_lsa
;
244 struct ospf6_router_lsdesc
*lsdesc
;
249 oa
= (struct ospf6_area
*)THREAD_ARG(thread
);
250 oa
->thread_router_lsa
= NULL
;
252 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER
))
253 zlog_debug("Originate Router-LSA for Area %s", oa
->name
);
255 memset(buffer
, 0, sizeof(buffer
));
256 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
258 (struct ospf6_router_lsa
*)((caddr_t
)lsa_header
259 + sizeof(struct ospf6_lsa_header
));
261 ospf6_router_lsa_options_set(oa
, router_lsa
);
263 /* describe links for each interfaces */
264 lsdesc
= (struct ospf6_router_lsdesc
265 *)((caddr_t
)router_lsa
266 + sizeof(struct ospf6_router_lsa
));
268 for (ALL_LIST_ELEMENTS(oa
->if_list
, node
, nnode
, oi
)) {
269 /* Interfaces in state Down or Loopback are not described */
270 if (oi
->state
== OSPF6_INTERFACE_DOWN
271 || oi
->state
== OSPF6_INTERFACE_LOOPBACK
)
274 /* Nor are interfaces without any full adjacencies described */
276 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
))
277 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
283 /* Multiple Router-LSA instance according to size limit setting
285 if ((oa
->router_lsa_size_limit
!= 0)
286 && ((size_t)((char *)lsdesc
- buffer
)
287 + sizeof(struct ospf6_router_lsdesc
)
288 > oa
->router_lsa_size_limit
)) {
290 == (caddr_t
)router_lsa
291 + sizeof(struct ospf6_router_lsa
)) {
292 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER
))
294 "Size limit setting for Router-LSA too short");
298 /* Fill LSA Header */
300 lsa_header
->type
= htons(OSPF6_LSTYPE_ROUTER
);
301 lsa_header
->id
= htonl(link_state_id
);
302 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
303 lsa_header
->seqnum
= ospf6_new_ls_seqnum(
304 lsa_header
->type
, lsa_header
->id
,
305 lsa_header
->adv_router
, oa
->lsdb
);
307 htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
310 ospf6_lsa_checksum(lsa_header
);
313 lsa
= ospf6_lsa_create(lsa_header
);
316 ospf6_lsa_originate_area(lsa
, oa
);
318 /* Reset Buffer to fill next Router LSA */
319 memset(buffer
, 0, sizeof(buffer
));
320 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
322 (struct ospf6_router_lsa
323 *)((caddr_t
)lsa_header
324 + sizeof(struct ospf6_lsa_header
));
326 ospf6_router_lsa_options_set(oa
, router_lsa
);
328 /* describe links for each interfaces */
329 lsdesc
= (struct ospf6_router_lsdesc
330 *)((caddr_t
)router_lsa
331 + sizeof(struct ospf6_router_lsa
));
336 /* Point-to-Point interfaces */
337 if (oi
->type
== OSPF_IFTYPE_POINTOPOINT
) {
338 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
)) {
339 if (on
->state
!= OSPF6_NEIGHBOR_FULL
)
342 lsdesc
->type
= OSPF6_ROUTER_LSDESC_POINTTOPOINT
;
343 lsdesc
->metric
= htons(oi
->cost
);
344 lsdesc
->interface_id
=
345 htonl(oi
->interface
->ifindex
);
346 lsdesc
->neighbor_interface_id
=
348 lsdesc
->neighbor_router_id
= on
->router_id
;
354 /* Broadcast and NBMA interfaces */
355 else if (oi
->type
== OSPF_IFTYPE_BROADCAST
) {
356 /* If this router is not DR,
357 and If this router not fully adjacent with DR,
358 this interface is not transit yet: ignore. */
359 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
361 ospf6_neighbor_lookup(oi
->drouter
, oi
);
363 || drouter
->state
!= OSPF6_NEIGHBOR_FULL
)
367 lsdesc
->type
= OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK
;
368 lsdesc
->metric
= htons(oi
->cost
);
369 lsdesc
->interface_id
= htonl(oi
->interface
->ifindex
);
370 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
371 lsdesc
->neighbor_interface_id
=
372 htonl(drouter
->ifindex
);
373 lsdesc
->neighbor_router_id
= drouter
->router_id
;
375 lsdesc
->neighbor_interface_id
=
376 htonl(oi
->interface
->ifindex
);
377 lsdesc
->neighbor_router_id
=
378 oi
->area
->ospf6
->router_id
;
383 assert(0); /* Unknown interface type */
388 /* Point-to-Multipoint interfaces */
392 /* Fill LSA Header */
394 lsa_header
->type
= htons(OSPF6_LSTYPE_ROUTER
);
395 lsa_header
->id
= htonl(link_state_id
);
396 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
398 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
399 lsa_header
->adv_router
, oa
->lsdb
);
400 lsa_header
->length
= htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
403 ospf6_lsa_checksum(lsa_header
);
406 lsa
= ospf6_lsa_create(lsa_header
);
409 ospf6_lsa_originate_area(lsa
, oa
);
413 /* Do premature-aging of rest, undesired Router-LSAs */
414 type
= ntohs(OSPF6_LSTYPE_ROUTER
);
415 router
= oa
->ospf6
->router_id
;
417 for (ALL_LSDB_TYPED_ADVRTR(oa
->lsdb
, type
, router
, lsa
)) {
418 if (ntohl(lsa
->header
->id
) < link_state_id
)
420 ospf6_lsa_purge(lsa
);
425 * Waiting till the LSA is actually removed from the database to trigger
426 * SPF delays network convergence. Unlike IPv4, for an ABR, when all
427 * interfaces associated with an area are gone, triggering an SPF right
429 * helps convergence with inter-area routes.
431 if (count
&& !link_state_id
)
432 ospf6_spf_schedule(oa
->ospf6
,
433 OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED
);
438 /*******************************/
439 /* RFC2740 3.4.3.2 Network-LSA */
440 /*******************************/
442 static char *ospf6_network_lsa_get_ar_id(struct ospf6_lsa
*lsa
, char *buf
,
445 char *start
, *end
, *current
;
446 struct ospf6_network_lsa
*network_lsa
;
447 struct ospf6_network_lsdesc
*lsdesc
;
450 network_lsa
= (struct ospf6_network_lsa
451 *)((caddr_t
)lsa
->header
452 + sizeof(struct ospf6_lsa_header
));
454 start
= (char *)network_lsa
+ sizeof(struct ospf6_network_lsa
);
455 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
456 current
= start
+ pos
* (sizeof(struct ospf6_network_lsdesc
));
458 if ((current
+ sizeof(struct ospf6_network_lsdesc
)) <= end
) {
459 lsdesc
= (struct ospf6_network_lsdesc
*)current
;
461 inet_ntop(AF_INET
, &lsdesc
->router_id
, buf
,
471 static int ospf6_network_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
472 json_object
*json_obj
, bool use_json
)
474 char *start
, *end
, *current
;
475 struct ospf6_network_lsa
*network_lsa
;
476 struct ospf6_network_lsdesc
*lsdesc
;
477 char buf
[128], options
[32];
478 json_object
*json_arr
;
481 (struct ospf6_network_lsa
*)((caddr_t
)lsa
->header
482 + sizeof(struct ospf6_lsa_header
));
484 ospf6_options_printbuf(network_lsa
->options
, options
, sizeof(options
));
486 json_object_string_add(json_obj
, "options", options
);
488 vty_out(vty
, " Options: %s\n", options
);
490 start
= (char *)network_lsa
+ sizeof(struct ospf6_network_lsa
);
491 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
493 json_arr
= json_object_new_array();
495 for (current
= start
;
496 current
+ sizeof(struct ospf6_network_lsdesc
) <= end
;
497 current
+= sizeof(struct ospf6_network_lsdesc
)) {
498 lsdesc
= (struct ospf6_network_lsdesc
*)current
;
499 inet_ntop(AF_INET
, &lsdesc
->router_id
, buf
, sizeof(buf
));
501 json_object_array_add(json_arr
,
502 json_object_new_string(buf
));
504 vty_out(vty
, " Attached Router: %s\n", buf
);
507 json_object_object_add(json_obj
, "attachedRouter", json_arr
);
512 int ospf6_network_lsa_originate(struct thread
*thread
)
514 struct ospf6_interface
*oi
;
516 char buffer
[OSPF6_MAX_LSASIZE
];
517 struct ospf6_lsa_header
*lsa_header
;
520 struct ospf6_lsa
*old
, *lsa
;
521 struct ospf6_network_lsa
*network_lsa
;
522 struct ospf6_network_lsdesc
*lsdesc
;
523 struct ospf6_neighbor
*on
;
524 struct ospf6_link_lsa
*link_lsa
;
528 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
529 oi
->thread_network_lsa
= NULL
;
531 /* The interface must be enabled until here. A Network-LSA of a
532 disabled interface (but was once enabled) should be flushed
533 by ospf6_lsa_refresh (), and does not come here. */
536 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_NETWORK
),
537 htonl(oi
->interface
->ifindex
),
538 oi
->area
->ospf6
->router_id
, oi
->area
->lsdb
);
540 /* Do not originate Network-LSA if not DR */
541 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
543 ospf6_lsa_purge(old
);
545 * Waiting till the LSA is actually removed from the
547 * trigger SPF delays network convergence.
551 OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED
);
556 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK
))
557 zlog_debug("Originate Network-LSA for Interface %s",
558 oi
->interface
->name
);
560 /* If none of neighbor is adjacent to us */
563 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
))
564 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
568 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK
))
569 zlog_debug("Interface stub, ignore");
571 ospf6_lsa_purge(old
);
576 memset(buffer
, 0, sizeof(buffer
));
577 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
579 (struct ospf6_network_lsa
*)((caddr_t
)lsa_header
580 + sizeof(struct ospf6_lsa_header
));
582 /* Collect the interface's Link-LSAs to describe
583 network's optional capabilities */
584 type
= htons(OSPF6_LSTYPE_LINK
);
585 for (ALL_LSDB_TYPED(oi
->lsdb
, type
, lsa
)) {
586 link_lsa
= (struct ospf6_link_lsa
587 *)((caddr_t
)lsa
->header
588 + sizeof(struct ospf6_lsa_header
));
589 network_lsa
->options
[0] |= link_lsa
->options
[0];
590 network_lsa
->options
[1] |= link_lsa
->options
[1];
591 network_lsa
->options
[2] |= link_lsa
->options
[2];
594 lsdesc
= (struct ospf6_network_lsdesc
595 *)((caddr_t
)network_lsa
596 + sizeof(struct ospf6_network_lsa
));
598 /* set Link Description to the router itself */
599 lsdesc
->router_id
= oi
->area
->ospf6
->router_id
;
602 /* Walk through the neighbors */
603 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
)) {
604 if (on
->state
!= OSPF6_NEIGHBOR_FULL
)
607 /* set this neighbor's Router-ID to LSA */
608 lsdesc
->router_id
= on
->router_id
;
612 /* Fill LSA Header */
614 lsa_header
->type
= htons(OSPF6_LSTYPE_NETWORK
);
615 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
616 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
618 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
619 lsa_header
->adv_router
, oi
->area
->lsdb
);
620 lsa_header
->length
= htons((caddr_t
)lsdesc
- (caddr_t
)buffer
);
623 ospf6_lsa_checksum(lsa_header
);
626 lsa
= ospf6_lsa_create(lsa_header
);
629 ospf6_lsa_originate_area(lsa
, oi
->area
);
635 /****************************/
636 /* RFC2740 3.4.3.6 Link-LSA */
637 /****************************/
639 static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa
*lsa
, char *buf
,
642 char *start
, *end
, *current
;
643 struct ospf6_link_lsa
*link_lsa
;
645 struct ospf6_prefix
*prefix
;
646 int cnt
= 0, prefixnum
;
649 link_lsa
= (struct ospf6_link_lsa
650 *)((caddr_t
)lsa
->header
651 + sizeof(struct ospf6_lsa_header
));
654 inet_ntop(AF_INET6
, &link_lsa
->linklocal_addr
, buf
,
659 prefixnum
= ntohl(link_lsa
->prefix_num
);
663 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
664 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
667 while (current
+ sizeof(struct ospf6_prefix
) <= end
) {
668 prefix
= (struct ospf6_prefix
*)current
;
669 if (prefix
->prefix_length
== 0
670 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
) {
674 if (cnt
< (pos
- 1)) {
675 current
+= OSPF6_PREFIX_SIZE(prefix
);
678 memset(&in6
, 0, sizeof(in6
));
679 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
681 prefix
->prefix_length
));
682 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
690 static int ospf6_link_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
691 json_object
*json_obj
, bool use_json
)
693 char *start
, *end
, *current
;
694 struct ospf6_link_lsa
*link_lsa
;
696 char buf
[128], options
[32];
697 struct ospf6_prefix
*prefix
;
699 json_object
*json_loop
;
700 json_object
*json_arr
= NULL
;
701 char prefix_string
[133];
703 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsa
->header
704 + sizeof(struct ospf6_lsa_header
));
706 ospf6_options_printbuf(link_lsa
->options
, options
, sizeof(options
));
707 inet_ntop(AF_INET6
, &link_lsa
->linklocal_addr
, buf
, sizeof(buf
));
708 prefixnum
= ntohl(link_lsa
->prefix_num
);
711 json_arr
= json_object_new_array();
712 json_object_int_add(json_obj
, "priority", link_lsa
->priority
);
713 json_object_string_add(json_obj
, "options", options
);
714 json_object_string_add(json_obj
, "linkLocalAddress", buf
);
715 json_object_int_add(json_obj
, "numberOfPrefix", prefixnum
);
717 vty_out(vty
, " Priority: %d Options: %s\n",
718 link_lsa
->priority
, options
);
719 vty_out(vty
, " LinkLocal Address: %s\n", buf
);
720 vty_out(vty
, " Number of Prefix: %d\n", prefixnum
);
723 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
724 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
725 for (current
= start
; current
< end
;
726 current
+= OSPF6_PREFIX_SIZE(prefix
)) {
727 prefix
= (struct ospf6_prefix
*)current
;
728 if (prefix
->prefix_length
== 0
729 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
)
732 ospf6_prefix_options_printbuf(prefix
->prefix_options
, buf
,
735 json_loop
= json_object_new_object();
736 json_object_string_add(json_loop
, "prefixOption", buf
);
738 vty_out(vty
, " Prefix Options: %s\n", buf
);
740 memset(&in6
, 0, sizeof(in6
));
741 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
742 OSPF6_PREFIX_SPACE(prefix
->prefix_length
));
743 inet_ntop(AF_INET6
, &in6
, buf
, sizeof(buf
));
745 snprintf(prefix_string
, sizeof(prefix_string
), "%s/%d",
746 buf
, prefix
->prefix_length
);
747 json_object_string_add(json_loop
, "prefix",
749 json_object_array_add(json_arr
, json_loop
);
751 vty_out(vty
, " Prefix: %s/%d\n", buf
,
752 prefix
->prefix_length
);
755 json_object_object_add(json_obj
, "prefix", json_arr
);
760 int ospf6_link_lsa_originate(struct thread
*thread
)
762 struct ospf6_interface
*oi
;
764 char buffer
[OSPF6_MAX_LSASIZE
];
765 struct ospf6_lsa_header
*lsa_header
;
766 struct ospf6_lsa
*old
, *lsa
;
768 struct ospf6_link_lsa
*link_lsa
;
769 struct ospf6_route
*route
;
770 struct ospf6_prefix
*op
;
771 int count
, max_addr_count
;
773 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
774 oi
->thread_link_lsa
= NULL
;
778 /* find previous LSA */
779 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_LINK
),
780 htonl(oi
->interface
->ifindex
),
781 oi
->area
->ospf6
->router_id
, oi
->lsdb
);
783 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
785 ospf6_lsa_purge(old
);
789 if (IS_OSPF6_DEBUG_ORIGINATE(LINK
))
790 zlog_debug("Originate Link-LSA for Interface %s",
791 oi
->interface
->name
);
793 /* can't make Link-LSA if linklocal address not set */
794 if (oi
->linklocal_addr
== NULL
) {
795 if (IS_OSPF6_DEBUG_ORIGINATE(LINK
))
797 "No Linklocal address on %s, defer originating",
798 oi
->interface
->name
);
800 ospf6_lsa_purge(old
);
805 memset(buffer
, 0, sizeof(buffer
));
806 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
807 link_lsa
= (struct ospf6_link_lsa
*)((caddr_t
)lsa_header
808 + sizeof(struct ospf6_lsa_header
));
811 link_lsa
->priority
= oi
->priority
;
812 memcpy(link_lsa
->options
, oi
->area
->options
, 3);
813 memcpy(&link_lsa
->linklocal_addr
, oi
->linklocal_addr
,
814 sizeof(struct in6_addr
));
816 op
= (struct ospf6_prefix
*)((caddr_t
)link_lsa
817 + sizeof(struct ospf6_link_lsa
));
819 /* connected prefix to advertise, number of interface addresses
820 * supported is based on MTU size of OSPFv3 packets
822 if (oi
->ifmtu
>= OSPF6_JUMBO_MTU
)
823 max_addr_count
= OSPF6_MAX_IF_ADDRS_JUMBO
;
825 max_addr_count
= OSPF6_MAX_IF_ADDRS
;
826 for (route
= ospf6_route_head(oi
->route_connected
), count
= 0;
827 route
&& count
< max_addr_count
;
828 route
= ospf6_route_next(route
), count
++) {
829 op
->prefix_length
= route
->prefix
.prefixlen
;
830 op
->prefix_options
= route
->path
.prefix_options
;
831 op
->prefix_metric
= htons(0);
832 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
833 OSPF6_PREFIX_SPACE(op
->prefix_length
));
834 op
= OSPF6_PREFIX_NEXT(op
);
837 link_lsa
->prefix_num
= htonl(count
);
839 /* Fill LSA Header */
841 lsa_header
->type
= htons(OSPF6_LSTYPE_LINK
);
842 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
843 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
845 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
846 lsa_header
->adv_router
, oi
->lsdb
);
847 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)buffer
);
850 ospf6_lsa_checksum(lsa_header
);
853 lsa
= ospf6_lsa_create(lsa_header
);
856 ospf6_lsa_originate_interface(lsa
, oi
);
862 /*****************************************/
863 /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
864 /*****************************************/
865 static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa
*lsa
,
866 char *buf
, int buflen
,
869 char *start
, *end
, *current
;
870 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
872 int prefixnum
, cnt
= 0;
873 struct ospf6_prefix
*prefix
;
878 (struct ospf6_intra_prefix_lsa
879 *)((caddr_t
)lsa
->header
880 + sizeof(struct ospf6_lsa_header
));
882 prefixnum
= ntohs(intra_prefix_lsa
->prefix_num
);
883 if ((pos
+ 1) > prefixnum
)
886 start
= (char *)intra_prefix_lsa
887 + sizeof(struct ospf6_intra_prefix_lsa
);
888 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
891 while (current
+ sizeof(struct ospf6_prefix
) <= end
) {
892 prefix
= (struct ospf6_prefix
*)current
;
893 if (prefix
->prefix_length
== 0
894 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
) {
899 current
+= OSPF6_PREFIX_SIZE(prefix
);
902 memset(&in6
, 0, sizeof(in6
));
903 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
905 prefix
->prefix_length
));
906 inet_ntop(AF_INET6
, &in6
, buf
, buflen
);
907 snprintf(tbuf
, sizeof(tbuf
), "/%d",
908 prefix
->prefix_length
);
909 strlcat(buf
, tbuf
, buflen
);
917 static int ospf6_intra_prefix_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
918 json_object
*json_obj
, bool use_json
)
920 char *start
, *end
, *current
;
921 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
924 struct ospf6_prefix
*prefix
;
925 char id
[16], adv_router
[16];
927 json_object
*json_loop
;
928 json_object
*json_arr
= NULL
;
929 char prefix_string
[133];
931 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
932 *)((caddr_t
)lsa
->header
933 + sizeof(struct ospf6_lsa_header
));
935 prefixnum
= ntohs(intra_prefix_lsa
->prefix_num
);
938 json_arr
= json_object_new_array();
939 json_object_int_add(json_obj
, "numberOfPrefix", prefixnum
);
941 vty_out(vty
, " Number of Prefix: %d\n", prefixnum
);
943 inet_ntop(AF_INET
, &intra_prefix_lsa
->ref_id
, id
, sizeof(id
));
944 inet_ntop(AF_INET
, &intra_prefix_lsa
->ref_adv_router
, adv_router
,
947 json_object_string_add(
948 json_obj
, "reference",
949 ospf6_lstype_name(intra_prefix_lsa
->ref_type
));
950 json_object_string_add(json_obj
, "referenceId", id
);
951 json_object_string_add(json_obj
, "referenceAdv", adv_router
);
953 vty_out(vty
, " Reference: %s Id: %s Adv: %s\n",
954 ospf6_lstype_name(intra_prefix_lsa
->ref_type
), id
,
957 start
= (char *)intra_prefix_lsa
958 + sizeof(struct ospf6_intra_prefix_lsa
);
959 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
960 for (current
= start
; current
< end
;
961 current
+= OSPF6_PREFIX_SIZE(prefix
)) {
962 prefix
= (struct ospf6_prefix
*)current
;
963 if (prefix
->prefix_length
== 0
964 || current
+ OSPF6_PREFIX_SIZE(prefix
) > end
)
967 ospf6_prefix_options_printbuf(prefix
->prefix_options
, buf
,
970 json_loop
= json_object_new_object();
971 json_object_string_add(json_loop
, "prefixOption", buf
);
973 vty_out(vty
, " Prefix Options: %s\n", buf
);
975 memset(&in6
, 0, sizeof(in6
));
976 memcpy(&in6
, OSPF6_PREFIX_BODY(prefix
),
977 OSPF6_PREFIX_SPACE(prefix
->prefix_length
));
978 inet_ntop(AF_INET6
, &in6
, buf
, sizeof(buf
));
980 snprintf(prefix_string
, sizeof(prefix_string
), "%s/%d",
981 buf
, prefix
->prefix_length
);
982 json_object_string_add(json_loop
, "prefix",
984 json_object_int_add(json_loop
, "metric",
985 ntohs(prefix
->prefix_metric
));
986 json_object_array_add(json_arr
, json_loop
);
988 vty_out(vty
, " Prefix: %s/%d\n", buf
,
989 prefix
->prefix_length
);
990 vty_out(vty
, " Metric: %d\n",
991 ntohs(prefix
->prefix_metric
));
995 json_object_object_add(json_obj
, "prefix", json_arr
);
1000 int ospf6_intra_prefix_lsa_originate_stub(struct thread
*thread
)
1002 struct ospf6_area
*oa
;
1004 char buffer
[OSPF6_MAX_LSASIZE
];
1005 struct ospf6_lsa_header
*lsa_header
;
1006 struct ospf6_lsa
*old
, *lsa
, *old_next
= NULL
;
1008 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1009 struct ospf6_interface
*oi
;
1010 struct ospf6_neighbor
*on
;
1011 struct ospf6_route
*route
;
1012 struct ospf6_prefix
*op
;
1013 struct listnode
*i
, *j
;
1015 unsigned short prefix_num
= 0;
1016 struct ospf6_route_table
*route_advertise
;
1018 int count
, max_addr_count
;
1020 oa
= (struct ospf6_area
*)THREAD_ARG(thread
);
1021 oa
->thread_intra_prefix_lsa
= NULL
;
1023 /* find previous LSA */
1024 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX
), htonl(0),
1025 oa
->ospf6
->router_id
, oa
->lsdb
);
1027 if (!IS_AREA_ENABLED(oa
)) {
1029 ospf6_lsa_purge(old
);
1030 /* find previous LSA */
1031 old_next
= ospf6_lsdb_lookup(
1032 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1033 htonl(++ls_id
), oa
->ospf6
->router_id
, oa
->lsdb
);
1036 ospf6_lsa_purge(old_next
);
1037 old_next
= ospf6_lsdb_lookup(
1038 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1039 htonl(++ls_id
), oa
->ospf6
->router_id
,
1046 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1048 "Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
1051 /* prepare buffer */
1052 memset(buffer
, 0, sizeof(buffer
));
1053 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1054 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
1055 *)((caddr_t
)lsa_header
1056 + sizeof(struct ospf6_lsa_header
));
1058 /* Fill Intra-Area-Prefix-LSA */
1059 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_ROUTER
);
1060 intra_prefix_lsa
->ref_id
= htonl(0);
1061 intra_prefix_lsa
->ref_adv_router
= oa
->ospf6
->router_id
;
1063 route_advertise
= ospf6_route_table_create(0, 0);
1064 route_advertise
->hook_add
= NULL
;
1065 route_advertise
->hook_remove
= NULL
;
1067 for (ALL_LIST_ELEMENTS_RO(oa
->if_list
, i
, oi
)) {
1068 if (oi
->state
== OSPF6_INTERFACE_DOWN
) {
1069 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1070 zlog_debug(" Interface %s is down, ignore",
1071 oi
->interface
->name
);
1077 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, j
, on
))
1078 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
1081 if (oi
->state
!= OSPF6_INTERFACE_LOOPBACK
1082 && oi
->state
!= OSPF6_INTERFACE_POINTTOPOINT
1083 && full_count
!= 0) {
1084 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1085 zlog_debug(" Interface %s is not stub, ignore",
1086 oi
->interface
->name
);
1090 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1091 zlog_debug(" Interface %s:", oi
->interface
->name
);
1093 /* connected prefix to advertise */
1094 if (oi
->ifmtu
>= OSPF6_JUMBO_MTU
)
1095 max_addr_count
= OSPF6_MAX_IF_ADDRS_JUMBO
;
1097 max_addr_count
= OSPF6_MAX_IF_ADDRS
;
1099 for (route
= ospf6_route_head(oi
->route_connected
), count
= 0;
1100 route
&& count
< max_addr_count
;
1101 route
= ospf6_route_best_next(route
), count
++) {
1102 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1103 zlog_debug(" include %pFX", &route
->prefix
);
1104 ospf6_route_add(ospf6_route_copy(route
),
1109 if (route_advertise
->count
== 0) {
1112 ospf6_lsa_purge(old
);
1113 /* find previous LSA */
1114 old_next
= ospf6_lsdb_lookup(
1115 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1116 htonl(++ls_id
), oa
->ospf6
->router_id
, oa
->lsdb
);
1119 ospf6_lsa_purge(old_next
);
1120 old_next
= ospf6_lsdb_lookup(
1121 htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1122 htonl(++ls_id
), oa
->ospf6
->router_id
,
1126 ospf6_route_table_delete(route_advertise
);
1130 /* Neighbor change to FULL, if INTRA-AREA-PREFIX LSA
1131 * has not change, Flush old LSA and Re-Originate INP,
1132 * as ospf6_flood() checks if LSA is same as DB,
1133 * it won't be updated to neighbor's DB.
1135 if (oa
->intra_prefix_originate
) {
1136 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1138 "%s: Re-originate intra prefix LSA, Current full nbrs %u",
1139 __func__
, oa
->full_nbrs
);
1141 ospf6_lsa_purge_multi_ls_id(oa
, old
);
1142 oa
->intra_prefix_originate
= 0;
1145 /* put prefixes to advertise */
1147 op
= (struct ospf6_prefix
*)((caddr_t
)intra_prefix_lsa
1148 + sizeof(struct ospf6_intra_prefix_lsa
));
1149 for (route
= ospf6_route_head(route_advertise
); route
;
1150 route
= ospf6_route_best_next(route
)) {
1151 if (((caddr_t
)op
- (caddr_t
)lsa_header
) > MAX_LSA_PAYLOAD
) {
1153 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
1155 /* Fill LSA Header */
1156 lsa_header
->age
= 0;
1157 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1158 lsa_header
->id
= htonl(ls_id
++);
1159 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
1160 lsa_header
->seqnum
= ospf6_new_ls_seqnum(
1161 lsa_header
->type
, lsa_header
->id
,
1162 lsa_header
->adv_router
, oa
->lsdb
);
1163 lsa_header
->length
=
1164 htons((caddr_t
)op
- (caddr_t
)lsa_header
);
1167 ospf6_lsa_checksum(lsa_header
);
1170 lsa
= ospf6_lsa_create(lsa_header
);
1173 ospf6_lsa_originate_area(lsa
, oa
);
1175 /* Prepare next buffer */
1176 memset(buffer
, 0, sizeof(buffer
));
1177 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1179 (struct ospf6_intra_prefix_lsa
1180 *)((caddr_t
)lsa_header
1181 + sizeof(struct ospf6_lsa_header
));
1183 /* Fill Intra-Area-Prefix-LSA */
1184 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_ROUTER
);
1185 intra_prefix_lsa
->ref_id
= htonl(0);
1186 intra_prefix_lsa
->ref_adv_router
= oa
->ospf6
->router_id
;
1188 /* Put next set of prefixes to advertise */
1190 op
= (struct ospf6_prefix
1191 *)((caddr_t
)intra_prefix_lsa
1193 ospf6_intra_prefix_lsa
));
1196 op
->prefix_length
= route
->prefix
.prefixlen
;
1197 op
->prefix_options
= route
->path
.prefix_options
;
1198 op
->prefix_metric
= htons(route
->path
.cost
);
1199 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
1200 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1203 op
= OSPF6_PREFIX_NEXT(op
);
1206 ospf6_route_table_delete(route_advertise
);
1208 if (prefix_num
== 0) {
1209 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1211 "Quit to Advertise Intra-Prefix: no route to advertise");
1215 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
1217 /* Fill LSA Header */
1218 lsa_header
->age
= 0;
1219 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1220 lsa_header
->id
= htonl(ls_id
++);
1221 lsa_header
->adv_router
= oa
->ospf6
->router_id
;
1222 lsa_header
->seqnum
=
1223 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
1224 lsa_header
->adv_router
, oa
->lsdb
);
1225 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)lsa_header
);
1228 ospf6_lsa_checksum(lsa_header
);
1231 lsa
= ospf6_lsa_create(lsa_header
);
1234 ospf6_lsa_originate_area(lsa
, oa
);
1240 int ospf6_intra_prefix_lsa_originate_transit(struct thread
*thread
)
1242 struct ospf6_interface
*oi
;
1244 char buffer
[OSPF6_MAX_LSASIZE
];
1245 struct ospf6_lsa_header
*lsa_header
;
1246 struct ospf6_lsa
*old
, *lsa
;
1248 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1249 struct ospf6_neighbor
*on
;
1250 struct ospf6_route
*route
;
1251 struct ospf6_prefix
*op
;
1254 unsigned short prefix_num
= 0;
1255 struct ospf6_route_table
*route_advertise
;
1256 struct ospf6_link_lsa
*link_lsa
;
1257 char *start
, *end
, *current
;
1260 oi
= (struct ospf6_interface
*)THREAD_ARG(thread
);
1261 oi
->thread_intra_prefix_lsa
= NULL
;
1265 /* find previous LSA */
1266 old
= ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX
),
1267 htonl(oi
->interface
->ifindex
),
1268 oi
->area
->ospf6
->router_id
, oi
->area
->lsdb
);
1270 if (CHECK_FLAG(oi
->flag
, OSPF6_INTERFACE_DISABLE
)) {
1272 ospf6_lsa_purge(old
);
1276 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1278 "Originate Intra-Area-Prefix-LSA for interface %s's prefix",
1279 oi
->interface
->name
);
1281 /* prepare buffer */
1282 memset(buffer
, 0, sizeof(buffer
));
1283 lsa_header
= (struct ospf6_lsa_header
*)buffer
;
1284 intra_prefix_lsa
= (struct ospf6_intra_prefix_lsa
1285 *)((caddr_t
)lsa_header
1286 + sizeof(struct ospf6_lsa_header
));
1288 /* Fill Intra-Area-Prefix-LSA */
1289 intra_prefix_lsa
->ref_type
= htons(OSPF6_LSTYPE_NETWORK
);
1290 intra_prefix_lsa
->ref_id
= htonl(oi
->interface
->ifindex
);
1291 intra_prefix_lsa
->ref_adv_router
= oi
->area
->ospf6
->router_id
;
1293 if (oi
->state
!= OSPF6_INTERFACE_DR
) {
1294 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1295 zlog_debug(" Interface is not DR");
1297 ospf6_lsa_purge(old
);
1302 for (ALL_LIST_ELEMENTS_RO(oi
->neighbor_list
, i
, on
))
1303 if (on
->state
== OSPF6_NEIGHBOR_FULL
)
1306 if (full_count
== 0) {
1307 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1308 zlog_debug(" Interface is stub");
1310 ospf6_lsa_purge(old
);
1314 /* connected prefix to advertise */
1315 route_advertise
= ospf6_route_table_create(0, 0);
1316 route_advertise
->hook_add
= NULL
;
1317 route_advertise
->hook_remove
= NULL
;
1319 type
= ntohs(OSPF6_LSTYPE_LINK
);
1320 for (ALL_LSDB_TYPED(oi
->lsdb
, type
, lsa
)) {
1321 if (OSPF6_LSA_IS_MAXAGE(lsa
))
1324 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1325 zlog_debug(" include prefix from %s", lsa
->name
);
1327 if (lsa
->header
->adv_router
!= oi
->area
->ospf6
->router_id
) {
1328 on
= ospf6_neighbor_lookup(lsa
->header
->adv_router
, oi
);
1329 if (on
== NULL
|| on
->state
!= OSPF6_NEIGHBOR_FULL
) {
1330 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1332 " Neighbor not found or not Full, ignore");
1337 link_lsa
= (struct ospf6_link_lsa
1338 *)((caddr_t
)lsa
->header
1339 + sizeof(struct ospf6_lsa_header
));
1341 prefix_num
= (unsigned short)ntohl(link_lsa
->prefix_num
);
1342 start
= (char *)link_lsa
+ sizeof(struct ospf6_link_lsa
);
1343 end
= (char *)lsa
->header
+ ntohs(lsa
->header
->length
);
1344 for (current
= start
; current
< end
&& prefix_num
;
1345 current
+= OSPF6_PREFIX_SIZE(op
)) {
1346 op
= (struct ospf6_prefix
*)current
;
1347 if (op
->prefix_length
== 0
1348 || current
+ OSPF6_PREFIX_SIZE(op
) > end
)
1351 route
= ospf6_route_create();
1353 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
1354 route
->prefix
.family
= AF_INET6
;
1355 route
->prefix
.prefixlen
= op
->prefix_length
;
1356 memset(&route
->prefix
.u
.prefix6
, 0,
1357 sizeof(struct in6_addr
));
1358 memcpy(&route
->prefix
.u
.prefix6
, OSPF6_PREFIX_BODY(op
),
1359 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1361 route
->path
.origin
.type
= lsa
->header
->type
;
1362 route
->path
.origin
.id
= lsa
->header
->id
;
1363 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1364 route
->path
.options
[0] = link_lsa
->options
[0];
1365 route
->path
.options
[1] = link_lsa
->options
[1];
1366 route
->path
.options
[2] = link_lsa
->options
[2];
1367 route
->path
.prefix_options
= op
->prefix_options
;
1368 route
->path
.area_id
= oi
->area
->area_id
;
1369 route
->path
.type
= OSPF6_PATH_TYPE_INTRA
;
1371 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1372 zlog_debug(" include %pFX", &route
->prefix
);
1374 ospf6_route_add(route
, route_advertise
);
1377 if (current
!= end
&& IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1378 zlog_debug("Trailing garbage in %s", lsa
->name
);
1381 op
= (struct ospf6_prefix
*)((caddr_t
)intra_prefix_lsa
1382 + sizeof(struct ospf6_intra_prefix_lsa
));
1385 for (route
= ospf6_route_head(route_advertise
); route
;
1386 route
= ospf6_route_best_next(route
)) {
1387 op
->prefix_length
= route
->prefix
.prefixlen
;
1388 op
->prefix_options
= route
->path
.prefix_options
;
1389 op
->prefix_metric
= htons(0);
1390 memcpy(OSPF6_PREFIX_BODY(op
), &route
->prefix
.u
.prefix6
,
1391 OSPF6_PREFIX_SPACE(op
->prefix_length
));
1392 op
= OSPF6_PREFIX_NEXT(op
);
1396 ospf6_route_table_delete(route_advertise
);
1398 if (prefix_num
== 0) {
1399 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX
))
1401 "Quit to Advertise Intra-Prefix: no route to advertise");
1405 intra_prefix_lsa
->prefix_num
= htons(prefix_num
);
1407 /* Fill LSA Header */
1408 lsa_header
->age
= 0;
1409 lsa_header
->type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
1410 lsa_header
->id
= htonl(oi
->interface
->ifindex
);
1411 lsa_header
->adv_router
= oi
->area
->ospf6
->router_id
;
1412 lsa_header
->seqnum
=
1413 ospf6_new_ls_seqnum(lsa_header
->type
, lsa_header
->id
,
1414 lsa_header
->adv_router
, oi
->area
->lsdb
);
1415 lsa_header
->length
= htons((caddr_t
)op
- (caddr_t
)lsa_header
);
1418 ospf6_lsa_checksum(lsa_header
);
1421 lsa
= ospf6_lsa_create(lsa_header
);
1424 ospf6_lsa_originate_area(lsa
, oi
->area
);
1429 static void ospf6_intra_prefix_update_route_origin(struct ospf6_route
*oa_route
,
1430 struct ospf6
*ospf6
)
1432 struct ospf6_path
*h_path
;
1433 struct ospf6_route
*g_route
, *nroute
;
1435 /* Update Global ospf6 route path */
1436 g_route
= ospf6_route_lookup(&oa_route
->prefix
, ospf6
->route_table
);
1440 for (ospf6_route_lock(g_route
); g_route
&&
1441 ospf6_route_is_prefix(&oa_route
->prefix
, g_route
);
1443 nroute
= ospf6_route_next(g_route
);
1444 if (g_route
->type
!= oa_route
->type
)
1446 if (g_route
->path
.area_id
!= oa_route
->path
.area_id
)
1448 if (g_route
->path
.type
!= OSPF6_PATH_TYPE_INTRA
)
1450 if (g_route
->path
.cost
!= oa_route
->path
.cost
)
1453 if (ospf6_route_is_same_origin(g_route
, oa_route
)) {
1454 h_path
= (struct ospf6_path
*)listgetdata(
1455 listhead(g_route
->paths
));
1456 g_route
->path
.origin
.type
= h_path
->origin
.type
;
1457 g_route
->path
.origin
.id
= h_path
->origin
.id
;
1458 g_route
->path
.origin
.adv_router
=
1459 h_path
->origin
.adv_router
;
1461 ospf6_route_unlock(nroute
);
1466 h_path
= (struct ospf6_path
*)listgetdata(
1467 listhead(oa_route
->paths
));
1468 oa_route
->path
.origin
.type
= h_path
->origin
.type
;
1469 oa_route
->path
.origin
.id
= h_path
->origin
.id
;
1470 oa_route
->path
.origin
.adv_router
= h_path
->origin
.adv_router
;
1473 void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area
*oa
,
1474 struct ospf6_route
*old
,
1475 struct ospf6_route
*route
)
1477 struct ospf6_route
*old_route
, *ls_entry
;
1478 struct ospf6_path
*ecmp_path
, *o_path
= NULL
;
1479 struct listnode
*anode
, *anext
;
1480 struct listnode
*nnode
, *rnode
, *rnext
;
1481 struct ospf6_nexthop
*nh
, *rnh
;
1482 char buf
[PREFIX2STR_BUFFER
];
1483 bool route_found
= false;
1484 struct interface
*ifp
= NULL
;
1485 struct ospf6_lsa
*lsa
;
1486 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1488 /* check for old entry match with new route origin,
1491 for (old_route
= old
; old_route
; old_route
= old_route
->next
) {
1492 bool route_updated
= false;
1494 if (!ospf6_route_is_same(old_route
, route
) ||
1495 (old_route
->path
.type
!= route
->path
.type
))
1498 /* Current and New route has same origin,
1501 for (ALL_LIST_ELEMENTS(old_route
->paths
, anode
, anext
,
1503 /* Check old route path and route has same
1506 if (o_path
->area_id
!= route
->path
.area_id
||
1507 (memcmp(&(o_path
)->origin
, &(route
)->path
.origin
,
1508 sizeof(struct ospf6_ls_origin
)) != 0))
1511 /* Cost is not same then delete current path */
1512 if (o_path
->cost
== route
->path
.cost
)
1515 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1517 "%s: route %pFX cost old %u new %u is not same, replace route",
1518 __func__
, &old_route
->prefix
, o_path
->cost
,
1522 /* Remove selected current path's nh from
1523 * effective nh list.
1525 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
, nnode
, nh
)) {
1526 for (ALL_LIST_ELEMENTS(old_route
->nh_list
,
1527 rnode
, rnext
, rnh
)) {
1528 if (!ospf6_nexthop_is_same(rnh
, nh
))
1530 listnode_delete(old_route
->nh_list
,
1532 ospf6_nexthop_delete(rnh
);
1533 route_updated
= true;
1537 listnode_delete(old_route
->paths
, o_path
);
1538 ospf6_path_free(o_path
);
1540 /* Current route's path (adv_router info) is similar
1541 * to route being added.
1542 * Replace current route's path with paths list head.
1543 * Update FIB with effective NHs.
1545 if (listcount(old_route
->paths
)) {
1546 if (route_updated
) {
1547 for (ALL_LIST_ELEMENTS(old_route
->paths
,
1548 anode
, anext
, o_path
)) {
1549 ospf6_merge_nexthops(
1553 /* Update ospf6 route table and
1554 * RIB/FIB with effective
1557 if (oa
->route_table
->hook_add
)
1558 (*oa
->route_table
->hook_add
)(
1561 if (old_route
->path
.origin
.id
==
1562 route
->path
.origin
.id
&&
1563 old_route
->path
.origin
.adv_router
==
1564 route
->path
.origin
.adv_router
) {
1565 ospf6_intra_prefix_update_route_origin(
1566 old_route
, oa
->ospf6
);
1571 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1573 "%s: route %pFX old cost %u new cost %u, delete old entry.",
1574 __func__
, &old_route
->prefix
,
1575 old_route
->path
.cost
,
1578 if (oa
->route_table
->hook_remove
)
1579 ospf6_route_remove(old_route
,
1582 SET_FLAG(old_route
->flag
,
1583 OSPF6_ROUTE_REMOVE
);
1591 for (old_route
= old
; old_route
; old_route
= old_route
->next
) {
1593 if (!ospf6_route_is_same(old_route
, route
) ||
1594 (old_route
->path
.type
!= route
->path
.type
))
1597 /* Old Route and New Route have Equal Cost, Merge NHs */
1598 if (old_route
->path
.cost
== route
->path
.cost
) {
1601 /* check if this path exists already in
1602 * route->paths list, if so, replace nh_list.
1604 for (ALL_LIST_ELEMENTS_RO(old_route
->paths
, anode
,
1606 if (o_path
->area_id
== route
->path
.area_id
&&
1607 (memcmp(&(o_path
)->origin
,
1608 &(route
)->path
.origin
,
1609 sizeof(struct ospf6_ls_origin
)) == 0))
1612 /* If path is not found in old_route paths's list,
1613 * add a new path to route paths list and merge
1614 * nexthops in route->path->nh_list.
1615 * Otherwise replace existing path's nh_list.
1617 if (o_path
== NULL
) {
1618 ecmp_path
= ospf6_path_dup(&route
->path
);
1620 /* Add a nh_list to new ecmp path */
1621 ospf6_copy_nexthops(ecmp_path
->nh_list
,
1623 /* Add the new path to route's path list */
1624 listnode_add_sort(old_route
->paths
, ecmp_path
);
1626 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1628 "%s: route %pFX %p another path added with nh %u, effective paths %u nh %u",
1629 __func__
, &route
->prefix
,
1631 listcount(ecmp_path
->nh_list
),
1632 old_route
->paths
? listcount(
1635 listcount(old_route
->nh_list
));
1638 list_delete_all_node(o_path
->nh_list
);
1639 ospf6_copy_nexthops(o_path
->nh_list
,
1644 list_delete_all_node(old_route
->nh_list
);
1646 for (ALL_LIST_ELEMENTS_RO(old_route
->paths
, anode
,
1648 ls_entry
= ospf6_route_lookup(
1651 if (ls_entry
== NULL
) {
1652 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1654 "%s: ls_prfix %s ls_entry not found.",
1658 lsa
= ospf6_lsdb_lookup(o_path
->origin
.type
,
1660 o_path
->origin
.adv_router
,
1663 if (IS_OSPF6_DEBUG_EXAMIN(
1665 struct prefix adv_prefix
;
1667 ospf6_linkstate_prefix(
1668 o_path
->origin
.adv_router
,
1669 o_path
->origin
.id
, &adv_prefix
);
1671 "%s: adv_router %pFX lsa not found",
1672 __func__
, &adv_prefix
);
1677 (struct ospf6_intra_prefix_lsa
*)
1678 OSPF6_LSA_HEADER_END(lsa
->header
);
1680 if (intra_prefix_lsa
->ref_adv_router
1681 == oa
->ospf6
->router_id
) {
1682 ifp
= if_lookup_prefix(
1688 /* Nexthop interface found */
1689 ospf6_route_add_nexthop(old_route
,
1693 /* The connected interfaces between
1694 * routers can be in different networks.
1695 * In this case the matching interface
1696 * is not found. Copy nexthops from the
1699 ospf6_route_merge_nexthops(old_route
,
1704 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1706 "%s: route %pFX %p with final effective paths %u nh %u",
1707 __func__
, &route
->prefix
,
1710 ? listcount(old_route
->paths
)
1712 listcount(old_route
->nh_list
));
1714 /* used in intra_route_calculation() to add to
1715 * global ospf6 route table.
1717 UNSET_FLAG(old_route
->flag
, OSPF6_ROUTE_REMOVE
);
1718 SET_FLAG(old_route
->flag
, OSPF6_ROUTE_ADD
);
1719 /* Update ospf6 route table and RIB/FIB */
1720 if (oa
->route_table
->hook_add
)
1721 (*oa
->route_table
->hook_add
)(old_route
);
1722 /* Delete the new route its info added to existing
1725 ospf6_route_delete(route
);
1732 /* Add new route to existing node in ospf6 route table. */
1733 ospf6_route_add(route
, oa
->route_table
);
1737 void ospf6_intra_prefix_lsa_add(struct ospf6_lsa
*lsa
)
1739 struct ospf6_area
*oa
;
1740 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1741 struct prefix ls_prefix
;
1742 struct ospf6_route
*route
, *ls_entry
, *old
;
1744 struct ospf6_prefix
*op
;
1745 char *start
, *current
, *end
;
1746 char buf
[PREFIX2STR_BUFFER
];
1747 struct interface
*ifp
= NULL
;
1748 int direct_connect
= 0;
1749 struct ospf6_path
*path
;
1751 if (OSPF6_LSA_IS_MAXAGE(lsa
))
1754 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1755 zlog_debug("%s: LSA %s found", __func__
, lsa
->name
);
1757 oa
= OSPF6_AREA(lsa
->lsdb
->data
);
1760 (struct ospf6_intra_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1762 if (intra_prefix_lsa
->ref_type
== htons(OSPF6_LSTYPE_ROUTER
))
1763 ospf6_linkstate_prefix(intra_prefix_lsa
->ref_adv_router
,
1764 intra_prefix_lsa
->ref_id
, &ls_prefix
);
1765 else if (intra_prefix_lsa
->ref_type
== htons(OSPF6_LSTYPE_NETWORK
))
1766 ospf6_linkstate_prefix(intra_prefix_lsa
->ref_adv_router
,
1767 intra_prefix_lsa
->ref_id
, &ls_prefix
);
1769 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1770 zlog_debug("Unknown reference LS-type: %#hx",
1771 ntohs(intra_prefix_lsa
->ref_type
));
1775 ls_entry
= ospf6_route_lookup(&ls_prefix
, oa
->spf_table
);
1776 if (ls_entry
== NULL
) {
1777 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1778 ospf6_linkstate_prefix2str(&ls_prefix
, buf
,
1780 zlog_debug("LS entry does not exist: %s", buf
);
1785 if (intra_prefix_lsa
->ref_adv_router
== oa
->ospf6
->router_id
) {
1786 /* the intra-prefix are directly connected */
1790 prefix_num
= ntohs(intra_prefix_lsa
->prefix_num
);
1791 start
= (caddr_t
)intra_prefix_lsa
1792 + sizeof(struct ospf6_intra_prefix_lsa
);
1793 end
= OSPF6_LSA_END(lsa
->header
);
1794 for (current
= start
; current
< end
; current
+= OSPF6_PREFIX_SIZE(op
)) {
1795 op
= (struct ospf6_prefix
*)current
;
1796 if (prefix_num
== 0)
1798 if (end
< current
+ OSPF6_PREFIX_SIZE(op
))
1801 /* Appendix A.4.1.1 */
1802 if (CHECK_FLAG(op
->prefix_options
, OSPF6_PREFIX_OPTION_NU
)) {
1803 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1804 ospf6_linkstate_prefix2str(
1805 (struct prefix
*)OSPF6_PREFIX_BODY(op
),
1808 "%s: Skipping Prefix %s has NU option set",
1814 route
= ospf6_route_create();
1816 memset(&route
->prefix
, 0, sizeof(struct prefix
));
1817 route
->prefix
.family
= AF_INET6
;
1818 route
->prefix
.prefixlen
= op
->prefix_length
;
1819 ospf6_prefix_in6_addr(&route
->prefix
.u
.prefix6
,
1820 intra_prefix_lsa
, op
);
1822 route
->type
= OSPF6_DEST_TYPE_NETWORK
;
1823 route
->path
.origin
.type
= lsa
->header
->type
;
1824 route
->path
.origin
.id
= lsa
->header
->id
;
1825 route
->path
.origin
.adv_router
= lsa
->header
->adv_router
;
1826 route
->path
.prefix_options
= op
->prefix_options
;
1827 route
->path
.area_id
= oa
->area_id
;
1828 route
->path
.type
= OSPF6_PATH_TYPE_INTRA
;
1829 route
->path
.metric_type
= 1;
1831 ls_entry
->path
.cost
+ ntohs(op
->prefix_metric
);
1832 memcpy(&route
->path
.ls_prefix
, &ls_prefix
,
1833 sizeof(struct prefix
));
1834 if (direct_connect
) {
1835 ifp
= if_lookup_prefix(&route
->prefix
,
1840 /* Nexthop interface found */
1841 ospf6_route_add_nexthop(route
, ifp
->ifindex
, NULL
);
1843 /* The connected interfaces between routers can be in
1844 * different networks. In this case the matching
1845 * interface is not found. Copy nexthops from the
1848 ospf6_route_copy_nexthops(route
, ls_entry
);
1851 path
= ospf6_path_dup(&route
->path
);
1852 ospf6_copy_nexthops(path
->nh_list
, route
->path
.nh_list
);
1853 listnode_add_sort(route
->paths
, path
);
1855 old
= ospf6_route_lookup(&route
->prefix
, oa
->route_table
);
1857 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1858 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1860 "%s Update route: %s old cost %u new cost %u paths %u nh %u",
1861 __func__
, buf
, old
->path
.cost
,
1863 listcount(route
->paths
),
1864 listcount(route
->nh_list
));
1866 ospf6_intra_prefix_route_ecmp_path(oa
, old
, route
);
1868 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1869 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1871 "%s route %s add with cost %u paths %u nh %u",
1872 __func__
, buf
, route
->path
.cost
,
1873 listcount(route
->paths
),
1874 listcount(route
->nh_list
));
1876 ospf6_route_add(route
, oa
->route_table
);
1881 if (current
!= end
&& IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1882 zlog_debug("Trailing garbage ignored");
1885 static void ospf6_intra_prefix_lsa_remove_update_route(struct ospf6_lsa
*lsa
,
1886 struct ospf6_area
*oa
,
1887 struct ospf6_route
*route
)
1889 struct listnode
*anode
, *anext
;
1890 struct listnode
*nnode
, *rnode
, *rnext
;
1891 struct ospf6_nexthop
*nh
, *rnh
;
1892 struct ospf6_path
*o_path
;
1893 bool nh_updated
= false;
1894 char buf
[PREFIX2STR_BUFFER
];
1896 /* Iterate all paths of route to find maching
1897 * with LSA remove info.
1898 * If route->path is same, replace
1901 for (ALL_LIST_ELEMENTS(route
->paths
, anode
, anext
, o_path
)) {
1902 if ((o_path
->origin
.type
!= lsa
->header
->type
) ||
1903 (o_path
->origin
.adv_router
!= lsa
->header
->adv_router
) ||
1904 (o_path
->origin
.id
!= lsa
->header
->id
))
1907 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1908 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1910 "%s: route %s path found with cost %u nh %u to remove.",
1911 __func__
, buf
, o_path
->cost
,
1912 listcount(o_path
->nh_list
));
1915 /* Remove found path's nh_list from
1916 * the route's nh_list.
1918 for (ALL_LIST_ELEMENTS_RO(o_path
->nh_list
, nnode
, nh
)) {
1919 for (ALL_LIST_ELEMENTS(route
->nh_list
, rnode
,
1921 if (!ospf6_nexthop_is_same(rnh
, nh
))
1923 listnode_delete(route
->nh_list
, rnh
);
1924 ospf6_nexthop_delete(rnh
);
1927 /* Delete the path from route's
1930 listnode_delete(route
->paths
, o_path
);
1931 ospf6_path_free(o_path
);
1937 /* Iterate all paths and merge nexthop,
1938 * unlesss any of the nexthop similar to
1939 * ones deleted as part of path deletion.
1941 for (ALL_LIST_ELEMENTS(route
->paths
, anode
, anext
, o_path
))
1942 ospf6_merge_nexthops(route
->nh_list
, o_path
->nh_list
);
1945 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
1946 prefix2str(&route
->prefix
, buf
, sizeof(buf
));
1948 "%s: route %s update paths %u nh %u", __func__
,
1949 buf
, route
->paths
? listcount(route
->paths
) : 0,
1950 route
->nh_list
? listcount(route
->nh_list
) : 0);
1953 /* Update Global Route table and
1954 * RIB/FIB with effective
1957 if (oa
->route_table
->hook_add
)
1958 (*oa
->route_table
->hook_add
)(route
);
1960 /* route's primary path is similar
1961 * to LSA, replace route's primary
1962 * path with route's paths list
1965 if ((route
->path
.origin
.id
== lsa
->header
->id
) &&
1966 (route
->path
.origin
.adv_router
==
1967 lsa
->header
->adv_router
)) {
1968 ospf6_intra_prefix_update_route_origin(route
,
1975 void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa
*lsa
)
1977 struct ospf6_area
*oa
;
1978 struct ospf6_intra_prefix_lsa
*intra_prefix_lsa
;
1979 struct prefix prefix
;
1980 struct ospf6_route
*route
, *nroute
;
1982 struct ospf6_prefix
*op
;
1983 char *start
, *current
, *end
;
1984 char buf
[PREFIX2STR_BUFFER
];
1986 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
1987 zlog_debug("%s: %s disappearing", __func__
, lsa
->name
);
1989 oa
= OSPF6_AREA(lsa
->lsdb
->data
);
1992 (struct ospf6_intra_prefix_lsa
*)OSPF6_LSA_HEADER_END(
1995 prefix_num
= ntohs(intra_prefix_lsa
->prefix_num
);
1996 start
= (caddr_t
)intra_prefix_lsa
1997 + sizeof(struct ospf6_intra_prefix_lsa
);
1998 end
= OSPF6_LSA_END(lsa
->header
);
1999 for (current
= start
; current
< end
; current
+= OSPF6_PREFIX_SIZE(op
)) {
2000 op
= (struct ospf6_prefix
*)current
;
2001 if (prefix_num
== 0)
2003 if (end
< current
+ OSPF6_PREFIX_SIZE(op
))
2007 memset(&prefix
, 0, sizeof(struct prefix
));
2008 prefix
.family
= AF_INET6
;
2009 prefix
.prefixlen
= op
->prefix_length
;
2010 ospf6_prefix_in6_addr(&prefix
.u
.prefix6
, intra_prefix_lsa
, op
);
2012 route
= ospf6_route_lookup(&prefix
, oa
->route_table
);
2016 for (ospf6_route_lock(route
);
2017 route
&& ospf6_route_is_prefix(&prefix
, route
);
2019 nroute
= ospf6_route_next(route
);
2020 if (route
->type
!= OSPF6_DEST_TYPE_NETWORK
)
2022 if (route
->path
.area_id
!= oa
->area_id
)
2024 if (route
->path
.type
!= OSPF6_PATH_TYPE_INTRA
)
2026 /* Route has multiple ECMP paths, remove matching
2027 * path. Update current route's effective nh list
2028 * after removal of one of the path.
2030 if (listcount(route
->paths
) > 1) {
2031 ospf6_intra_prefix_lsa_remove_update_route(
2035 if (route
->path
.origin
.type
!= lsa
->header
->type
2036 || route
->path
.origin
.id
!= lsa
->header
->id
2037 || route
->path
.origin
.adv_router
2038 != lsa
->header
->adv_router
)
2041 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
)) {
2042 prefix2str(&route
->prefix
, buf
,
2045 "%s: route remove %s with path type %u cost %u paths %u nh %u",
2046 __func__
, buf
, route
->path
.type
,
2048 listcount(route
->paths
),
2049 listcount(route
->nh_list
));
2051 ospf6_route_remove(route
, oa
->route_table
);
2055 ospf6_route_unlock(route
);
2058 if (current
!= end
&& IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
2059 zlog_debug("Trailing garbage ignored");
2062 void ospf6_intra_route_calculation(struct ospf6_area
*oa
)
2064 struct ospf6_route
*route
, *nroute
;
2066 struct ospf6_lsa
*lsa
;
2067 void (*hook_add
)(struct ospf6_route
*) = NULL
;
2068 void (*hook_remove
)(struct ospf6_route
*) = NULL
;
2070 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
2071 zlog_debug("Re-examin intra-routes for area %s", oa
->name
);
2073 hook_add
= oa
->route_table
->hook_add
;
2074 hook_remove
= oa
->route_table
->hook_remove
;
2075 oa
->route_table
->hook_add
= NULL
;
2076 oa
->route_table
->hook_remove
= NULL
;
2078 for (route
= ospf6_route_head(oa
->route_table
); route
;
2079 route
= ospf6_route_next(route
))
2080 route
->flag
= OSPF6_ROUTE_REMOVE
;
2082 type
= htons(OSPF6_LSTYPE_INTRA_PREFIX
);
2083 for (ALL_LSDB_TYPED(oa
->lsdb
, type
, lsa
))
2084 ospf6_intra_prefix_lsa_add(lsa
);
2086 oa
->route_table
->hook_add
= hook_add
;
2087 oa
->route_table
->hook_remove
= hook_remove
;
2089 for (route
= ospf6_route_head(oa
->route_table
); route
; route
= nroute
) {
2090 nroute
= ospf6_route_next(route
);
2091 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
)
2092 && CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ADD
)) {
2093 UNSET_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
);
2094 UNSET_FLAG(route
->flag
, OSPF6_ROUTE_ADD
);
2097 if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_REMOVE
))
2098 ospf6_route_remove(route
, oa
->route_table
);
2099 else if (CHECK_FLAG(route
->flag
, OSPF6_ROUTE_ADD
)
2100 || CHECK_FLAG(route
->flag
, OSPF6_ROUTE_CHANGE
)) {
2105 /* Redo the summaries as things might have changed */
2106 ospf6_abr_originate_summary(route
, oa
->ospf6
);
2111 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX
))
2112 zlog_debug("Re-examin intra-routes for area %s: Done",
2116 static void ospf6_brouter_debug_print(struct ospf6_route
*brouter
)
2118 uint32_t brouter_id
;
2119 char brouter_name
[16];
2121 char destination
[64];
2122 char installed
[64], changed
[64];
2123 struct timeval now
, res
;
2124 char id
[16], adv_router
[16];
2125 char capa
[16], options
[16];
2127 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2128 inet_ntop(AF_INET
, &brouter_id
, brouter_name
, sizeof(brouter_name
));
2129 inet_ntop(AF_INET
, &brouter
->path
.area_id
, area_name
,
2131 ospf6_linkstate_prefix2str(&brouter
->prefix
, destination
,
2132 sizeof(destination
));
2135 timersub(&now
, &brouter
->installed
, &res
);
2136 timerstring(&res
, installed
, sizeof(installed
));
2139 timersub(&now
, &brouter
->changed
, &res
);
2140 timerstring(&res
, changed
, sizeof(changed
));
2142 inet_ntop(AF_INET
, &brouter
->path
.origin
.id
, id
, sizeof(id
));
2143 inet_ntop(AF_INET
, &brouter
->path
.origin
.adv_router
, adv_router
,
2144 sizeof(adv_router
));
2146 ospf6_options_printbuf(brouter
->path
.options
, options
, sizeof(options
));
2147 ospf6_capability_printbuf(brouter
->path
.router_bits
, capa
,
2150 zlog_info("Brouter: %s via area %s", brouter_name
, area_name
);
2151 zlog_info(" memory: prev: %p this: %p next: %p parent rnode: %p",
2152 (void *)brouter
->prev
, (void *)brouter
, (void *)brouter
->next
,
2153 (void *)brouter
->rnode
);
2154 zlog_info(" type: %d prefix: %s installed: %s changed: %s",
2155 brouter
->type
, destination
, installed
, changed
);
2156 zlog_info(" lock: %d flags: %s%s%s%s", brouter
->lock
,
2157 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_BEST
) ? "B" : "-"),
2158 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
) ? "A" : "-"),
2159 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
) ? "R" : "-"),
2160 (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
) ? "C" : "-"));
2161 zlog_info(" path type: %s ls-origin %s id: %s adv-router %s",
2162 OSPF6_PATH_TYPE_NAME(brouter
->path
.type
),
2163 ospf6_lstype_name(brouter
->path
.origin
.type
), id
, adv_router
);
2164 zlog_info(" options: %s router-bits: %s metric-type: %d metric: %d/%d",
2165 options
, capa
, brouter
->path
.metric_type
, brouter
->path
.cost
,
2166 brouter
->path
.u
.cost_e2
);
2167 zlog_info(" paths %u nh %u", listcount(brouter
->paths
),
2168 listcount(brouter
->nh_list
));
2171 void ospf6_intra_brouter_calculation(struct ospf6_area
*oa
)
2173 struct ospf6_route
*brouter
, *nbrouter
, *copy
;
2174 void (*hook_add
)(struct ospf6_route
*) = NULL
;
2175 void (*hook_remove
)(struct ospf6_route
*) = NULL
;
2176 uint32_t brouter_id
;
2177 char brouter_name
[16];
2179 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa
->area_id
) ||
2180 IS_OSPF6_DEBUG_ROUTE(MEMORY
))
2181 zlog_debug("%s: border-router calculation for area %s",
2182 __func__
, oa
->name
);
2184 hook_add
= oa
->ospf6
->brouter_table
->hook_add
;
2185 hook_remove
= oa
->ospf6
->brouter_table
->hook_remove
;
2186 oa
->ospf6
->brouter_table
->hook_add
= NULL
;
2187 oa
->ospf6
->brouter_table
->hook_remove
= NULL
;
2189 /* withdraw the previous router entries for the area */
2190 for (brouter
= ospf6_route_head(oa
->ospf6
->brouter_table
); brouter
;
2191 brouter
= ospf6_route_next(brouter
)) {
2192 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2193 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
2194 sizeof(brouter_name
));
2196 if (brouter
->path
.area_id
!= oa
->area_id
)
2199 SET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
2201 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id
)
2202 || IS_OSPF6_DEBUG_ROUTE(MEMORY
)) {
2203 zlog_debug("%p: mark as removing: area %s brouter %s",
2204 (void *)brouter
, oa
->name
, brouter_name
);
2205 ospf6_brouter_debug_print(brouter
);
2209 for (brouter
= ospf6_route_head(oa
->spf_table
); brouter
;
2210 brouter
= ospf6_route_next(brouter
)) {
2211 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2212 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
2213 sizeof(brouter_name
));
2215 if (brouter
->type
!= OSPF6_DEST_TYPE_LINKSTATE
)
2218 if (ospf6_linkstate_prefix_id(&brouter
->prefix
) != htonl(0))
2221 if (!CHECK_FLAG(brouter
->path
.router_bits
, OSPF6_ROUTER_BIT_E
)
2222 && !CHECK_FLAG(brouter
->path
.router_bits
,
2223 OSPF6_ROUTER_BIT_B
))
2226 if (!OSPF6_OPT_ISSET(brouter
->path
.options
, OSPF6_OPT_V6
)
2227 || !OSPF6_OPT_ISSET(brouter
->path
.options
, OSPF6_OPT_R
))
2230 copy
= ospf6_route_copy(brouter
);
2231 copy
->type
= OSPF6_DEST_TYPE_ROUTER
;
2232 copy
->path
.area_id
= oa
->area_id
;
2233 ospf6_route_add(copy
, oa
->ospf6
->brouter_table
);
2235 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id
)
2236 || IS_OSPF6_DEBUG_ROUTE(MEMORY
)) {
2237 zlog_debug("%p: transfer: area %s brouter %s",
2238 (void *)brouter
, oa
->name
, brouter_name
);
2239 ospf6_brouter_debug_print(brouter
);
2243 oa
->ospf6
->brouter_table
->hook_add
= hook_add
;
2244 oa
->ospf6
->brouter_table
->hook_remove
= hook_remove
;
2246 for (brouter
= ospf6_route_head(oa
->ospf6
->brouter_table
); brouter
;
2247 brouter
= nbrouter
) {
2250 * brouter may have been "deleted" in the last loop iteration.
2251 * If this is the case there is still 1 final refcount lock
2252 * taken by ospf6_route_next, that will be released by the same
2253 * call and result in deletion. To avoid heap UAF we must then
2254 * skip processing the deleted route.
2256 if (brouter
->lock
== 1) {
2257 if (IS_OSPF6_DEBUG_ROUTE(MEMORY
))
2258 ospf6_brouter_debug_print(brouter
);
2259 nbrouter
= ospf6_route_next(brouter
);
2262 nbrouter
= ospf6_route_next(brouter
);
2265 brouter_id
= ADV_ROUTER_IN_PREFIX(&brouter
->prefix
);
2266 inet_ntop(AF_INET
, &brouter_id
, brouter_name
,
2267 sizeof(brouter_name
));
2269 if (brouter
->path
.area_id
!= oa
->area_id
)
2272 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_WAS_REMOVED
))
2275 /* After iterating spf_table for all routers including
2276 * intra brouter, clear mark for remove flag for
2277 * inter border router if its adv router present in
2280 if (brouter
->path
.type
== OSPF6_PATH_TYPE_INTER
) {
2281 struct prefix adv_prefix
;
2283 ospf6_linkstate_prefix(brouter
->path
.origin
.adv_router
,
2284 htonl(0), &adv_prefix
);
2286 if (ospf6_route_lookup(&adv_prefix
, oa
->spf_table
)) {
2287 if (IS_OSPF6_DEBUG_BROUTER
) {
2289 "%s: keep inter brouter %s as adv router 0x%x found in spf",
2290 __func__
, brouter_name
,
2291 brouter
->path
.origin
2293 ospf6_brouter_debug_print(brouter
);
2295 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
2299 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
)
2300 && CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
)) {
2301 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
);
2302 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
);
2305 if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_REMOVE
)) {
2306 if (IS_OSPF6_DEBUG_BROUTER
2307 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2309 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2312 "%s: brouter %s disappears via area %s",
2313 __func__
, brouter_name
, oa
->name
);
2314 /* This is used to protect nbrouter from removed from
2315 * the table. For an example, ospf6_abr_examin_summary,
2316 * removes brouters which are marked for remove.
2318 oa
->intra_brouter_calc
= 1;
2319 ospf6_route_remove(brouter
, oa
->ospf6
->brouter_table
);
2321 } else if (CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
)
2322 || CHECK_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
)) {
2323 if (IS_OSPF6_DEBUG_BROUTER
2324 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2326 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2328 zlog_info("%s: brouter %s appears via area %s",
2329 __func__
, brouter_name
, oa
->name
);
2333 (*hook_add
)(brouter
);
2335 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2337 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2340 "brouter %s still exists via area %s",
2341 brouter_name
, oa
->name
);
2342 /* But re-originate summaries */
2343 ospf6_abr_originate_summary(brouter
, oa
->ospf6
);
2347 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_ADD
);
2348 UNSET_FLAG(brouter
->flag
, OSPF6_ROUTE_CHANGE
);
2350 /* Reset for nbrouter */
2351 oa
->intra_brouter_calc
= 0;
2354 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa
->area_id
) ||
2355 IS_OSPF6_DEBUG_ROUTE(MEMORY
))
2356 zlog_debug("%s: border-router calculation for area %s: done",
2357 __func__
, oa
->name
);
2360 static struct ospf6_lsa_handler router_handler
= {
2361 .lh_type
= OSPF6_LSTYPE_ROUTER
,
2362 .lh_name
= "Router",
2363 .lh_short_name
= "Rtr",
2364 .lh_show
= ospf6_router_lsa_show
,
2365 .lh_get_prefix_str
= ospf6_router_lsa_get_nbr_id
,
2368 static struct ospf6_lsa_handler network_handler
= {
2369 .lh_type
= OSPF6_LSTYPE_NETWORK
,
2370 .lh_name
= "Network",
2371 .lh_short_name
= "Net",
2372 .lh_show
= ospf6_network_lsa_show
,
2373 .lh_get_prefix_str
= ospf6_network_lsa_get_ar_id
,
2376 static struct ospf6_lsa_handler link_handler
= {
2377 .lh_type
= OSPF6_LSTYPE_LINK
,
2379 .lh_short_name
= "Lnk",
2380 .lh_show
= ospf6_link_lsa_show
,
2381 .lh_get_prefix_str
= ospf6_link_lsa_get_prefix_str
,
2384 static struct ospf6_lsa_handler intra_prefix_handler
= {
2385 .lh_type
= OSPF6_LSTYPE_INTRA_PREFIX
,
2386 .lh_name
= "Intra-Prefix",
2387 .lh_short_name
= "INP",
2388 .lh_show
= ospf6_intra_prefix_lsa_show
,
2389 .lh_get_prefix_str
= ospf6_intra_prefix_lsa_get_prefix_str
,
2392 void ospf6_intra_init(void)
2394 ospf6_install_lsa_handler(&router_handler
);
2395 ospf6_install_lsa_handler(&network_handler
);
2396 ospf6_install_lsa_handler(&link_handler
);
2397 ospf6_install_lsa_handler(&intra_prefix_handler
);
2400 DEFUN (debug_ospf6_brouter
,
2401 debug_ospf6_brouter_cmd
,
2402 "debug ospf6 border-routers",
2405 "Debug border router\n"
2408 OSPF6_DEBUG_BROUTER_ON();
2412 DEFUN (no_debug_ospf6_brouter
,
2413 no_debug_ospf6_brouter_cmd
,
2414 "no debug ospf6 border-routers",
2418 "Debug border router\n"
2421 OSPF6_DEBUG_BROUTER_OFF();
2425 DEFUN (debug_ospf6_brouter_router
,
2426 debug_ospf6_brouter_router_cmd
,
2427 "debug ospf6 border-routers router-id A.B.C.D",
2430 "Debug border router\n"
2431 "Debug specific border router\n"
2432 "Specify border-router's router-id\n"
2437 inet_pton(AF_INET
, argv
[idx_ipv4
]->arg
, &router_id
);
2438 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON(router_id
);
2442 DEFUN (no_debug_ospf6_brouter_router
,
2443 no_debug_ospf6_brouter_router_cmd
,
2444 "no debug ospf6 border-routers router-id",
2448 "Debug border router\n"
2449 "Debug specific border router\n"
2452 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF();
2456 DEFUN (debug_ospf6_brouter_area
,
2457 debug_ospf6_brouter_area_cmd
,
2458 "debug ospf6 border-routers area-id A.B.C.D",
2461 "Debug border router\n"
2462 "Debug border routers in specific Area\n"
2468 inet_pton(AF_INET
, argv
[idx_ipv4
]->arg
, &area_id
);
2469 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON(area_id
);
2473 DEFUN (no_debug_ospf6_brouter_area
,
2474 no_debug_ospf6_brouter_area_cmd
,
2475 "no debug ospf6 border-routers area-id",
2479 "Debug border router\n"
2480 "Debug border routers in specific Area\n"
2483 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF();
2487 int config_write_ospf6_debug_brouter(struct vty
*vty
)
2490 if (IS_OSPF6_DEBUG_BROUTER
)
2491 vty_out(vty
, "debug ospf6 border-routers\n");
2492 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER
) {
2493 inet_ntop(AF_INET
, &conf_debug_ospf6_brouter_specific_router_id
,
2495 vty_out(vty
, "debug ospf6 border-routers router-id %s\n", buf
);
2497 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA
) {
2498 inet_ntop(AF_INET
, &conf_debug_ospf6_brouter_specific_area_id
,
2500 vty_out(vty
, "debug ospf6 border-routers area-id %s\n", buf
);
2505 void install_element_ospf6_debug_brouter(void)
2507 install_element(ENABLE_NODE
, &debug_ospf6_brouter_cmd
);
2508 install_element(ENABLE_NODE
, &debug_ospf6_brouter_router_cmd
);
2509 install_element(ENABLE_NODE
, &debug_ospf6_brouter_area_cmd
);
2510 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_cmd
);
2511 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_router_cmd
);
2512 install_element(ENABLE_NODE
, &no_debug_ospf6_brouter_area_cmd
);
2513 install_element(CONFIG_NODE
, &debug_ospf6_brouter_cmd
);
2514 install_element(CONFIG_NODE
, &debug_ospf6_brouter_router_cmd
);
2515 install_element(CONFIG_NODE
, &debug_ospf6_brouter_area_cmd
);
2516 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_cmd
);
2517 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_router_cmd
);
2518 install_element(CONFIG_NODE
, &no_debug_ospf6_brouter_area_cmd
);