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
23 /* Include other stuffs */
33 #include "ospf6_proto.h"
34 #include "ospf6_lsa.h"
35 #include "ospf6_lsdb.h"
36 #include "ospf6_message.h"
37 #include "ospf6_asbr.h"
38 #include "ospf6_zebra.h"
40 #include "ospf6_top.h"
41 #include "ospf6_area.h"
42 #include "ospf6_interface.h"
43 #include "ospf6_neighbor.h"
45 #include "ospf6_flood.h"
48 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_LSA
, "OSPF6 LSA");
49 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_LSA_HEADER
, "OSPF6 LSA header");
50 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_LSA_SUMMARY
, "OSPF6 LSA summary");
52 vector ospf6_lsa_handler_vector
;
54 struct ospf6
*ospf6_get_by_lsdb(struct ospf6_lsa
*lsa
)
56 struct ospf6
*ospf6
= NULL
;
58 switch (OSPF6_LSA_SCOPE(lsa
->header
->type
)) {
59 case OSPF6_SCOPE_LINKLOCAL
:
60 ospf6
= OSPF6_INTERFACE(lsa
->lsdb
->data
)->area
->ospf6
;
62 case OSPF6_SCOPE_AREA
:
63 ospf6
= OSPF6_AREA(lsa
->lsdb
->data
)->ospf6
;
66 ospf6
= OSPF6_PROCESS(lsa
->lsdb
->data
);
75 static int ospf6_unknown_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
76 json_object
*json_obj
, bool use_json
)
78 uint8_t *start
, *end
, *current
;
81 start
= (uint8_t *)lsa
->header
+ sizeof(struct ospf6_lsa_header
);
82 end
= (uint8_t *)lsa
->header
+ ntohs(lsa
->header
->length
);
85 json_object_string_add(json_obj
, "LsaType", "unknown");
87 vty_out(vty
, " Unknown contents:\n");
88 for (current
= start
; current
< end
; current
++) {
89 if ((current
- start
) % 16 == 0)
91 else if ((current
- start
) % 4 == 0)
94 snprintf(byte
, sizeof(byte
), "%02x", *current
);
95 vty_out(vty
, "%s", byte
);
103 static struct ospf6_lsa_handler unknown_handler
= {
104 .lh_type
= OSPF6_LSTYPE_UNKNOWN
,
105 .lh_name
= "Unknown",
106 .lh_short_name
= "Unk",
107 .lh_show
= ospf6_unknown_lsa_show
,
108 .lh_get_prefix_str
= NULL
,
109 .lh_debug
= 0 /* No default debug */
112 void ospf6_install_lsa_handler(struct ospf6_lsa_handler
*handler
)
114 /* type in handler is host byte order */
115 int index
= handler
->lh_type
& OSPF6_LSTYPE_FCODE_MASK
;
116 vector_set_index(ospf6_lsa_handler_vector
, index
, (void *)handler
);
119 struct ospf6_lsa_handler
*ospf6_get_lsa_handler(uint16_t type
)
121 struct ospf6_lsa_handler
*handler
= NULL
;
122 unsigned int index
= ntohs(type
) & OSPF6_LSTYPE_FCODE_MASK
;
124 if (index
>= vector_active(ospf6_lsa_handler_vector
))
125 handler
= &unknown_handler
;
127 handler
= vector_slot(ospf6_lsa_handler_vector
, index
);
130 handler
= &unknown_handler
;
135 const char *ospf6_lstype_name(uint16_t type
)
138 const struct ospf6_lsa_handler
*handler
;
140 handler
= ospf6_get_lsa_handler(type
);
141 if (handler
&& handler
!= &unknown_handler
)
142 return handler
->lh_name
;
144 snprintf(buf
, sizeof(buf
), "0x%04hx", ntohs(type
));
148 const char *ospf6_lstype_short_name(uint16_t type
)
151 const struct ospf6_lsa_handler
*handler
;
153 handler
= ospf6_get_lsa_handler(type
);
155 return handler
->lh_short_name
;
157 snprintf(buf
, sizeof(buf
), "0x%04hx", ntohs(type
));
161 uint8_t ospf6_lstype_debug(uint16_t type
)
163 const struct ospf6_lsa_handler
*handler
;
164 handler
= ospf6_get_lsa_handler(type
);
165 return handler
->lh_debug
;
168 int metric_type(struct ospf6
*ospf6
, int type
, uint8_t instance
)
170 struct ospf6_redist
*red
;
172 red
= ospf6_redist_lookup(ospf6
, type
, instance
);
174 return ((!red
|| red
->dmetric
.type
< 0) ? DEFAULT_METRIC_TYPE
175 : red
->dmetric
.type
);
178 int metric_value(struct ospf6
*ospf6
, int type
, uint8_t instance
)
180 struct ospf6_redist
*red
;
182 red
= ospf6_redist_lookup(ospf6
, type
, instance
);
183 if (!red
|| red
->dmetric
.value
< 0) {
184 if (type
== DEFAULT_ROUTE
) {
185 if (ospf6
->default_originate
== DEFAULT_ORIGINATE_ZEBRA
)
186 return DEFAULT_DEFAULT_ORIGINATE_METRIC
;
188 return DEFAULT_DEFAULT_ALWAYS_METRIC
;
190 return DEFAULT_DEFAULT_METRIC
;
193 return red
->dmetric
.value
;
196 /* RFC2328: Section 13.2 */
197 int ospf6_lsa_is_differ(struct ospf6_lsa
*lsa1
, struct ospf6_lsa
*lsa2
)
201 assert(OSPF6_LSA_IS_SAME(lsa1
, lsa2
));
203 /* XXX, Options ??? */
205 ospf6_lsa_age_current(lsa1
);
206 ospf6_lsa_age_current(lsa2
);
207 if (ntohs(lsa1
->header
->age
) == OSPF_LSA_MAXAGE
208 && ntohs(lsa2
->header
->age
) != OSPF_LSA_MAXAGE
)
210 if (ntohs(lsa1
->header
->age
) != OSPF_LSA_MAXAGE
211 && ntohs(lsa2
->header
->age
) == OSPF_LSA_MAXAGE
)
215 if (ntohs(lsa1
->header
->length
) != ntohs(lsa2
->header
->length
))
218 len
= ntohs(lsa1
->header
->length
) - sizeof(struct ospf6_lsa_header
);
219 return memcmp(lsa1
->header
+ 1, lsa2
->header
+ 1, len
);
222 int ospf6_lsa_is_changed(struct ospf6_lsa
*lsa1
, struct ospf6_lsa
*lsa2
)
226 if (OSPF6_LSA_IS_MAXAGE(lsa1
) ^ OSPF6_LSA_IS_MAXAGE(lsa2
))
228 if (ntohs(lsa1
->header
->length
) != ntohs(lsa2
->header
->length
))
230 /* Going beyond LSA headers to compare the payload only makes sense,
231 * when both LSAs aren't header-only. */
232 if (CHECK_FLAG(lsa1
->flag
, OSPF6_LSA_HEADERONLY
)
233 != CHECK_FLAG(lsa2
->flag
, OSPF6_LSA_HEADERONLY
)) {
235 "%s: only one of two (%s, %s) LSAs compared is header-only",
236 __func__
, lsa1
->name
, lsa2
->name
);
239 if (CHECK_FLAG(lsa1
->flag
, OSPF6_LSA_HEADERONLY
))
242 length
= OSPF6_LSA_SIZE(lsa1
->header
) - sizeof(struct ospf6_lsa_header
);
243 /* Once upper layer verifies LSAs received, length underrun should
244 * become a warning. */
248 return memcmp(OSPF6_LSA_HEADER_END(lsa1
->header
),
249 OSPF6_LSA_HEADER_END(lsa2
->header
), length
);
252 /* ospf6 age functions */
253 /* calculate birth */
254 void ospf6_lsa_age_set(struct ospf6_lsa
*lsa
)
258 assert(lsa
&& lsa
->header
);
262 lsa
->birth
.tv_sec
= now
.tv_sec
- ntohs(lsa
->header
->age
);
263 lsa
->birth
.tv_usec
= now
.tv_usec
;
268 /* this function calculates current age from its birth,
269 then update age field of LSA header. return value is current age */
270 uint16_t ospf6_lsa_age_current(struct ospf6_lsa
*lsa
)
282 if (ntohs(lsa
->header
->age
) >= OSPF_LSA_MAXAGE
) {
283 /* ospf6_lsa_premature_aging () sets age to MAXAGE; when using
284 relative time, we cannot compare against lsa birth time, so
285 we catch this special case here. */
286 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
287 return OSPF_LSA_MAXAGE
;
290 ulage
= now
.tv_sec
- lsa
->birth
.tv_sec
;
292 /* if over MAXAGE, set to it */
293 age
= (ulage
> OSPF_LSA_MAXAGE
? OSPF_LSA_MAXAGE
: ulage
);
295 lsa
->header
->age
= htons(age
);
299 /* update age field of LSA header with adding InfTransDelay */
300 void ospf6_lsa_age_update_to_send(struct ospf6_lsa
*lsa
, uint32_t transdelay
)
304 age
= ospf6_lsa_age_current(lsa
) + transdelay
;
305 if (age
> OSPF_LSA_MAXAGE
)
306 age
= OSPF_LSA_MAXAGE
;
307 lsa
->header
->age
= htons(age
);
310 void ospf6_lsa_premature_aging(struct ospf6_lsa
*lsa
)
313 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
))
314 zlog_debug("LSA: Premature aging: %s", lsa
->name
);
316 THREAD_OFF(lsa
->expire
);
317 THREAD_OFF(lsa
->refresh
);
320 * We clear the LSA from the neighbor retx lists now because it
321 * will not get deleted later. Essentially, changing the age to
322 * MaxAge will prevent this LSA from being matched with its
323 * existing entries in the retx list thereby causing those entries
324 * to be silently replaced with its MaxAged version, but with ever
325 * increasing retx count causing this LSA to remain forever and
326 * for the MaxAge remover thread to be called forever too.
328 * The reason the previous entry silently disappears is that when
329 * entry is added to a neighbor's retx list, it replaces the existing
330 * entry. But since the ospf6_lsdb_add() routine is generic and not
332 * of the special semantics of retx count, the retx count is not
333 * decremented when its replaced. Attempting to add the incr and decr
334 * retx count routines as the hook_add and hook_remove for the retx
336 * have a problem because the hook_remove routine is called for MaxAge
337 * entries (as will be the case in a traditional LSDB, unlike in this
339 * where an LSDB is used as an efficient tree structure to store all
341 * of data) that are added instead of calling the hook_add routine.
344 ospf6_flood_clear(lsa
);
346 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
347 thread_execute(master
, ospf6_lsa_expire
, lsa
, 0);
350 /* check which is more recent. if a is more recent, return -1;
351 if the same, return 0; otherwise(b is more recent), return 1 */
352 int ospf6_lsa_compare(struct ospf6_lsa
*a
, struct ospf6_lsa
*b
)
354 int32_t seqnuma
, seqnumb
;
355 uint16_t cksuma
, cksumb
;
358 assert(a
&& a
->header
);
359 assert(b
&& b
->header
);
360 assert(OSPF6_LSA_IS_SAME(a
, b
));
362 seqnuma
= (int32_t)ntohl(a
->header
->seqnum
);
363 seqnumb
= (int32_t)ntohl(b
->header
->seqnum
);
365 /* compare by sequence number */
366 if (seqnuma
> seqnumb
)
368 if (seqnuma
< seqnumb
)
372 cksuma
= ntohs(a
->header
->checksum
);
373 cksumb
= ntohs(b
->header
->checksum
);
380 agea
= ospf6_lsa_age_current(a
);
381 ageb
= ospf6_lsa_age_current(b
);
384 if (agea
== OSPF_LSA_MAXAGE
&& ageb
!= OSPF_LSA_MAXAGE
)
386 else if (agea
!= OSPF_LSA_MAXAGE
&& ageb
== OSPF_LSA_MAXAGE
)
390 if (agea
> ageb
&& agea
- ageb
>= OSPF_LSA_MAXAGE_DIFF
)
392 else if (agea
< ageb
&& ageb
- agea
>= OSPF_LSA_MAXAGE_DIFF
)
399 char *ospf6_lsa_printbuf(struct ospf6_lsa
*lsa
, char *buf
, int size
)
401 char id
[16], adv_router
[16];
402 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
403 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
405 snprintf(buf
, size
, "[%s Id:%s Adv:%s]",
406 ospf6_lstype_name(lsa
->header
->type
), id
, adv_router
);
410 void ospf6_lsa_header_print_raw(struct ospf6_lsa_header
*header
)
412 char id
[16], adv_router
[16];
413 inet_ntop(AF_INET
, &header
->id
, id
, sizeof(id
));
414 inet_ntop(AF_INET
, &header
->adv_router
, adv_router
, sizeof(adv_router
));
415 zlog_debug(" [%s Id:%s Adv:%s]", ospf6_lstype_name(header
->type
), id
,
417 zlog_debug(" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
418 ntohs(header
->age
), (unsigned long)ntohl(header
->seqnum
),
419 ntohs(header
->checksum
), ntohs(header
->length
));
422 void ospf6_lsa_header_print(struct ospf6_lsa
*lsa
)
424 ospf6_lsa_age_current(lsa
);
425 ospf6_lsa_header_print_raw(lsa
->header
);
428 void ospf6_lsa_show_summary_header(struct vty
*vty
)
430 vty_out(vty
, "%-4s %-15s%-15s%4s %8s %30s\n", "Type", "LSId",
431 "AdvRouter", "Age", "SeqNum", "Payload");
434 void ospf6_lsa_show_summary(struct vty
*vty
, struct ospf6_lsa
*lsa
,
435 json_object
*json_array
, bool use_json
)
437 char adv_router
[16], id
[16];
439 const struct ospf6_lsa_handler
*handler
;
442 json_object
*json_obj
= NULL
;
447 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
448 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
451 type
= ntohs(lsa
->header
->type
);
452 handler
= ospf6_get_lsa_handler(lsa
->header
->type
);
455 json_obj
= json_object_new_object();
458 case OSPF6_LSTYPE_INTER_PREFIX
:
459 case OSPF6_LSTYPE_INTER_ROUTER
:
460 case OSPF6_LSTYPE_AS_EXTERNAL
:
461 case OSPF6_LSTYPE_TYPE_7
:
463 json_object_string_add(
465 ospf6_lstype_short_name(lsa
->header
->type
));
466 json_object_string_add(json_obj
, "lsId", id
);
467 json_object_string_add(json_obj
, "advRouter",
469 json_object_int_add(json_obj
, "age",
470 ospf6_lsa_age_current(lsa
));
473 (unsigned long)ntohl(lsa
->header
->seqnum
));
474 json_object_string_add(
476 handler
->lh_get_prefix_str(lsa
, buf
,
478 json_object_array_add(json_array
, json_obj
);
480 vty_out(vty
, "%-4s %-15s%-15s%4hu %8lx %30s\n",
481 ospf6_lstype_short_name(lsa
->header
->type
), id
,
482 adv_router
, ospf6_lsa_age_current(lsa
),
483 (unsigned long)ntohl(lsa
->header
->seqnum
),
484 handler
->lh_get_prefix_str(lsa
, buf
,
487 case OSPF6_LSTYPE_ROUTER
:
488 case OSPF6_LSTYPE_NETWORK
:
489 case OSPF6_LSTYPE_GROUP_MEMBERSHIP
:
490 case OSPF6_LSTYPE_LINK
:
491 case OSPF6_LSTYPE_INTRA_PREFIX
:
492 while (handler
->lh_get_prefix_str(lsa
, buf
, sizeof(buf
), cnt
)
495 json_object_string_add(
497 ospf6_lstype_short_name(
499 json_object_string_add(json_obj
, "lsId", id
);
500 json_object_string_add(json_obj
, "advRouter",
502 json_object_int_add(json_obj
, "age",
503 ospf6_lsa_age_current(lsa
));
506 (unsigned long)ntohl(
507 lsa
->header
->seqnum
));
508 json_object_string_add(json_obj
, "payload",
510 json_object_array_add(json_array
, json_obj
);
511 json_obj
= json_object_new_object();
513 vty_out(vty
, "%-4s %-15s%-15s%4hu %8lx %30s\n",
514 ospf6_lstype_short_name(
517 ospf6_lsa_age_current(lsa
),
518 (unsigned long)ntohl(
519 lsa
->header
->seqnum
),
524 json_object_free(json_obj
);
528 json_object_string_add(
530 ospf6_lstype_short_name(lsa
->header
->type
));
531 json_object_string_add(json_obj
, "lsId", id
);
532 json_object_string_add(json_obj
, "advRouter",
534 json_object_int_add(json_obj
, "age",
535 ospf6_lsa_age_current(lsa
));
538 (unsigned long)ntohl(lsa
->header
->seqnum
));
539 json_object_array_add(json_array
, json_obj
);
541 vty_out(vty
, "%-4s %-15s%-15s%4hu %8lx\n",
542 ospf6_lstype_short_name(lsa
->header
->type
), id
,
543 adv_router
, ospf6_lsa_age_current(lsa
),
544 (unsigned long)ntohl(lsa
->header
->seqnum
));
549 void ospf6_lsa_show_dump(struct vty
*vty
, struct ospf6_lsa
*lsa
,
550 json_object
*json_array
, bool use_json
)
552 uint8_t *start
, *end
, *current
;
555 start
= (uint8_t *)lsa
->header
;
556 end
= (uint8_t *)lsa
->header
+ ntohs(lsa
->header
->length
);
562 vty_out(vty
, "%s:\n", lsa
->name
);
564 for (current
= start
; current
< end
; current
++) {
565 if ((current
- start
) % 16 == 0)
567 else if ((current
- start
) % 4 == 0)
570 snprintf(byte
, sizeof(byte
), "%02x", *current
);
571 vty_out(vty
, "%s", byte
);
574 vty_out(vty
, "\n\n");
579 void ospf6_lsa_show_internal(struct vty
*vty
, struct ospf6_lsa
*lsa
,
580 json_object
*json_array
, bool use_json
)
582 char adv_router
[64], id
[64];
583 json_object
*json_obj
;
585 assert(lsa
&& lsa
->header
);
587 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
588 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
592 json_obj
= json_object_new_object();
593 json_object_int_add(json_obj
, "age",
594 ospf6_lsa_age_current(lsa
));
595 json_object_string_add(json_obj
, "type",
596 ospf6_lstype_name(lsa
->header
->type
));
597 json_object_string_add(json_obj
, "linkStateId", id
);
598 json_object_string_add(json_obj
, "advertisingRouter",
600 json_object_int_add(json_obj
, "lsSequenceNumber",
601 (unsigned long)ntohl(lsa
->header
->seqnum
));
602 json_object_int_add(json_obj
, "checksum",
603 ntohs(lsa
->header
->checksum
));
604 json_object_int_add(json_obj
, "length",
605 ntohs(lsa
->header
->length
));
606 json_object_int_add(json_obj
, "flag", lsa
->flag
);
607 json_object_int_add(json_obj
, "lock", lsa
->lock
);
608 json_object_int_add(json_obj
, "reTxCount", lsa
->retrans_count
);
610 /* Threads Data not added */
611 json_object_array_add(json_array
, json_obj
);
614 vty_out(vty
, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa
),
615 ospf6_lstype_name(lsa
->header
->type
));
616 vty_out(vty
, "Link State ID: %s\n", id
);
617 vty_out(vty
, "Advertising Router: %s\n", adv_router
);
618 vty_out(vty
, "LS Sequence Number: %#010lx\n",
619 (unsigned long)ntohl(lsa
->header
->seqnum
));
620 vty_out(vty
, "CheckSum: %#06hx Length: %hu\n",
621 ntohs(lsa
->header
->checksum
),
622 ntohs(lsa
->header
->length
));
623 vty_out(vty
, "Flag: %x \n", lsa
->flag
);
624 vty_out(vty
, "Lock: %d \n", lsa
->lock
);
625 vty_out(vty
, "ReTx Count: %d\n", lsa
->retrans_count
);
626 vty_out(vty
, "Threads: Expire: 0x%p, Refresh: 0x%p \n",
627 (void *)lsa
->expire
, (void *)lsa
->refresh
);
633 void ospf6_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
634 json_object
*json_array
, bool use_json
)
636 char adv_router
[64], id
[64];
637 const struct ospf6_lsa_handler
*handler
;
638 struct timeval now
, res
;
640 json_object
*json_obj
= NULL
;
642 assert(lsa
&& lsa
->header
);
644 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
645 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
649 timersub(&now
, &lsa
->installed
, &res
);
650 timerstring(&res
, duration
, sizeof(duration
));
652 json_obj
= json_object_new_object();
653 json_object_int_add(json_obj
, "age",
654 ospf6_lsa_age_current(lsa
));
655 json_object_string_add(json_obj
, "type",
656 ospf6_lstype_name(lsa
->header
->type
));
657 json_object_string_add(json_obj
, "advertisingRouter",
659 json_object_int_add(json_obj
, "lsSequenceNumber",
660 (unsigned long)ntohl(lsa
->header
->seqnum
));
661 json_object_int_add(json_obj
, "checkSum",
662 ntohs(lsa
->header
->checksum
));
663 json_object_int_add(json_obj
, "length",
664 ntohs(lsa
->header
->length
));
665 json_object_string_add(json_obj
, "duration", duration
);
667 vty_out(vty
, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa
),
668 ospf6_lstype_name(lsa
->header
->type
));
669 vty_out(vty
, "Link State ID: %s\n", id
);
670 vty_out(vty
, "Advertising Router: %s\n", adv_router
);
671 vty_out(vty
, "LS Sequence Number: %#010lx\n",
672 (unsigned long)ntohl(lsa
->header
->seqnum
));
673 vty_out(vty
, "CheckSum: %#06hx Length: %hu\n",
674 ntohs(lsa
->header
->checksum
),
675 ntohs(lsa
->header
->length
));
676 vty_out(vty
, "Duration: %s\n", duration
);
679 handler
= ospf6_get_lsa_handler(lsa
->header
->type
);
681 if (handler
->lh_show
!= NULL
)
682 handler
->lh_show(vty
, lsa
, json_obj
, use_json
);
684 assert(unknown_handler
.lh_show
!= NULL
);
685 unknown_handler
.lh_show(vty
, lsa
, json_obj
, use_json
);
689 json_object_array_add(json_array
, json_obj
);
694 struct ospf6_lsa
*ospf6_lsa_alloc(size_t lsa_length
)
696 struct ospf6_lsa
*lsa
;
698 lsa
= XCALLOC(MTYPE_OSPF6_LSA
, sizeof(struct ospf6_lsa
));
699 lsa
->header
= XMALLOC(MTYPE_OSPF6_LSA_HEADER
, lsa_length
);
704 /* OSPFv3 LSA creation/deletion function */
705 struct ospf6_lsa
*ospf6_lsa_create(struct ospf6_lsa_header
*header
)
707 struct ospf6_lsa
*lsa
= NULL
;
708 uint16_t lsa_size
= 0;
710 /* size of the entire LSA */
711 lsa_size
= ntohs(header
->length
); /* XXX vulnerable */
713 lsa
= ospf6_lsa_alloc(lsa_size
);
715 /* copy LSA from original header */
716 memcpy(lsa
->header
, header
, lsa_size
);
719 ospf6_lsa_printbuf(lsa
, lsa
->name
, sizeof(lsa
->name
));
721 /* calculate birth of this lsa */
722 ospf6_lsa_age_set(lsa
);
727 struct ospf6_lsa
*ospf6_lsa_create_headeronly(struct ospf6_lsa_header
*header
)
729 struct ospf6_lsa
*lsa
= NULL
;
731 lsa
= ospf6_lsa_alloc(sizeof(struct ospf6_lsa_header
));
733 memcpy(lsa
->header
, header
, sizeof(struct ospf6_lsa_header
));
735 SET_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
);
738 ospf6_lsa_printbuf(lsa
, lsa
->name
, sizeof(lsa
->name
));
740 /* calculate birth of this lsa */
741 ospf6_lsa_age_set(lsa
);
746 void ospf6_lsa_delete(struct ospf6_lsa
*lsa
)
748 assert(lsa
->lock
== 0);
751 THREAD_OFF(lsa
->expire
);
752 THREAD_OFF(lsa
->refresh
);
755 XFREE(MTYPE_OSPF6_LSA_HEADER
, lsa
->header
);
756 XFREE(MTYPE_OSPF6_LSA
, lsa
);
759 struct ospf6_lsa
*ospf6_lsa_copy(struct ospf6_lsa
*lsa
)
761 struct ospf6_lsa
*copy
= NULL
;
763 ospf6_lsa_age_current(lsa
);
764 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
))
765 copy
= ospf6_lsa_create_headeronly(lsa
->header
);
767 copy
= ospf6_lsa_create(lsa
->header
);
768 assert(copy
->lock
== 0);
770 copy
->birth
= lsa
->birth
;
771 copy
->originated
= lsa
->originated
;
772 copy
->received
= lsa
->received
;
773 copy
->installed
= lsa
->installed
;
774 copy
->lsdb
= lsa
->lsdb
;
780 /* increment reference counter of struct ospf6_lsa */
781 struct ospf6_lsa
*ospf6_lsa_lock(struct ospf6_lsa
*lsa
)
787 /* decrement reference counter of struct ospf6_lsa */
788 struct ospf6_lsa
*ospf6_lsa_unlock(struct ospf6_lsa
*lsa
)
790 /* decrement reference counter */
791 assert(lsa
->lock
> 0);
797 ospf6_lsa_delete(lsa
);
802 /* ospf6 lsa expiry */
803 int ospf6_lsa_expire(struct thread
*thread
)
805 struct ospf6_lsa
*lsa
;
808 lsa
= (struct ospf6_lsa
*)THREAD_ARG(thread
);
810 assert(lsa
&& lsa
->header
);
811 assert(OSPF6_LSA_IS_MAXAGE(lsa
));
812 assert(!lsa
->refresh
);
814 lsa
->expire
= (struct thread
*)NULL
;
816 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
)) {
817 zlog_debug("LSA Expire:");
818 ospf6_lsa_header_print(lsa
);
821 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
))
822 return 0; /* dbexchange will do something ... */
823 ospf6
= ospf6_get_by_lsdb(lsa
);
825 ospf6_install_lsa(lsa
);
828 ospf6_flood(NULL
, lsa
);
830 /* schedule maxage remover */
831 ospf6_maxage_remove(ospf6
);
836 int ospf6_lsa_refresh(struct thread
*thread
)
838 struct ospf6_lsa
*old
, *self
, *new;
839 struct ospf6_lsdb
*lsdb_self
;
841 old
= (struct ospf6_lsa
*)THREAD_ARG(thread
);
842 assert(old
&& old
->header
);
844 old
->refresh
= (struct thread
*)NULL
;
846 lsdb_self
= ospf6_get_scoped_lsdb_self(old
);
847 self
= ospf6_lsdb_lookup(old
->header
->type
, old
->header
->id
,
848 old
->header
->adv_router
, lsdb_self
);
850 if (IS_OSPF6_DEBUG_LSA_TYPE(old
->header
->type
))
851 zlog_debug("Refresh: could not find self LSA, flush %s",
853 ospf6_lsa_premature_aging(old
);
857 /* Reset age, increment LS sequence number. */
858 self
->header
->age
= htons(0);
859 self
->header
->seqnum
=
860 ospf6_new_ls_seqnum(self
->header
->type
, self
->header
->id
,
861 self
->header
->adv_router
, old
->lsdb
);
862 ospf6_lsa_checksum(self
->header
);
864 new = ospf6_lsa_create(self
->header
);
865 new->lsdb
= old
->lsdb
;
867 thread_add_timer(master
, ospf6_lsa_refresh
, new, OSPF_LS_REFRESH_TIME
,
870 /* store it in the LSDB for self-originated LSAs */
871 ospf6_lsdb_add(ospf6_lsa_copy(new), lsdb_self
);
873 if (IS_OSPF6_DEBUG_LSA_TYPE(new->header
->type
)) {
874 zlog_debug("LSA Refresh:");
875 ospf6_lsa_header_print(new);
878 ospf6_install_lsa(new);
879 ospf6_flood(NULL
, new);
884 void ospf6_flush_self_originated_lsas_now(struct ospf6
*ospf6
)
886 struct listnode
*node
, *nnode
;
887 struct ospf6_area
*oa
;
888 struct ospf6_lsa
*lsa
;
889 const struct route_node
*end
= NULL
;
890 uint32_t type
, adv_router
;
891 struct ospf6_interface
*oi
;
893 ospf6
->inst_shutdown
= 1;
895 for (ALL_LIST_ELEMENTS_RO(ospf6
->area_list
, node
, oa
)) {
896 end
= ospf6_lsdb_head(oa
->lsdb_self
, 0, 0, ospf6
->router_id
,
899 /* RFC 2328 (14.1): Set MAXAGE */
900 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
901 /* Flood MAXAGE LSA*/
902 ospf6_flood(NULL
, lsa
);
904 lsa
= ospf6_lsdb_next(end
, lsa
);
907 for (ALL_LIST_ELEMENTS(oa
->if_list
, node
, nnode
, oi
)) {
908 end
= ospf6_lsdb_head(oi
->lsdb_self
, 0, 0,
909 ospf6
->router_id
, &lsa
);
911 /* RFC 2328 (14.1): Set MAXAGE */
912 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
913 /* Flood MAXAGE LSA*/
914 ospf6_flood(NULL
, lsa
);
916 lsa
= ospf6_lsdb_next(end
, lsa
);
921 type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
922 adv_router
= ospf6
->router_id
;
923 for (ALL_LSDB_TYPED_ADVRTR(ospf6
->lsdb
, type
, adv_router
, lsa
)) {
924 /* RFC 2328 (14.1): Set MAXAGE */
925 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
926 ospf6_flood(NULL
, lsa
);
930 /* Fletcher Checksum -- Refer to RFC1008. */
932 /* All the offsets are zero-based. The offsets in the RFC1008 are
934 unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header
*lsa_header
)
936 uint8_t *buffer
= (uint8_t *)&lsa_header
->type
;
938 buffer
- (uint8_t *)&lsa_header
->age
; /* should be 2 */
940 /* Skip the AGE field */
941 uint16_t len
= ntohs(lsa_header
->length
) - type_offset
;
943 /* Checksum offset starts from "type" field, not the beginning of the
944 lsa_header struct. The offset is 14, rather than 16. */
945 int checksum_offset
= (uint8_t *)&lsa_header
->checksum
- buffer
;
947 return (unsigned short)fletcher_checksum(buffer
, len
, checksum_offset
);
950 int ospf6_lsa_checksum_valid(struct ospf6_lsa_header
*lsa_header
)
952 uint8_t *buffer
= (uint8_t *)&lsa_header
->type
;
954 buffer
- (uint8_t *)&lsa_header
->age
; /* should be 2 */
956 /* Skip the AGE field */
957 uint16_t len
= ntohs(lsa_header
->length
) - type_offset
;
959 return (fletcher_checksum(buffer
, len
, FLETCHER_CHECKSUM_VALIDATE
)
963 void ospf6_lsa_init(void)
965 ospf6_lsa_handler_vector
= vector_init(0);
966 ospf6_install_lsa_handler(&unknown_handler
);
969 void ospf6_lsa_terminate(void)
971 vector_free(ospf6_lsa_handler_vector
);
974 static char *ospf6_lsa_handler_name(const struct ospf6_lsa_handler
*h
)
978 unsigned int size
= strlen(h
->lh_name
);
980 if (!strcmp(h
->lh_name
, "unknown")
981 && h
->lh_type
!= OSPF6_LSTYPE_UNKNOWN
) {
982 snprintf(buf
, sizeof(buf
), "%#04hx", h
->lh_type
);
986 for (i
= 0; i
< MIN(size
, sizeof(buf
)); i
++) {
987 if (!islower((unsigned char)h
->lh_name
[i
]))
988 buf
[i
] = tolower((unsigned char)h
->lh_name
[i
]);
990 buf
[i
] = h
->lh_name
[i
];
996 DEFUN (debug_ospf6_lsa_type
,
997 debug_ospf6_lsa_hex_cmd
,
998 "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
1001 "Debug Link State Advertisements (LSAs)\n"
1002 "Display Router LSAs\n"
1003 "Display Network LSAs\n"
1004 "Display Inter-Area-Prefix LSAs\n"
1005 "Display Inter-Router LSAs\n"
1006 "Display As-External LSAs\n"
1007 "Display Link LSAs\n"
1008 "Display Intra-Area-Prefix LSAs\n"
1009 "Display LSAs of unknown origin\n"
1010 "Display details of LSAs\n"
1012 "Display LSA's internal information\n")
1017 struct ospf6_lsa_handler
*handler
= NULL
;
1019 for (i
= 0; i
< vector_active(ospf6_lsa_handler_vector
); i
++) {
1020 handler
= vector_slot(ospf6_lsa_handler_vector
, i
);
1021 if (handler
== NULL
)
1023 if (strncmp(argv
[idx_lsa
]->arg
, ospf6_lsa_handler_name(handler
),
1024 strlen(argv
[idx_lsa
]->arg
))
1027 if (!strcasecmp(argv
[idx_lsa
]->arg
, handler
->lh_name
))
1032 if (handler
== NULL
)
1033 handler
= &unknown_handler
;
1036 if (strmatch(argv
[idx_type
]->text
, "originate"))
1037 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_ORIGINATE
);
1038 else if (strmatch(argv
[idx_type
]->text
, "examine"))
1039 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_EXAMIN
);
1040 else if (strmatch(argv
[idx_type
]->text
, "flooding"))
1041 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_FLOOD
);
1043 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG
);
1048 DEFUN (no_debug_ospf6_lsa_type
,
1049 no_debug_ospf6_lsa_hex_cmd
,
1050 "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
1054 "Debug Link State Advertisements (LSAs)\n"
1055 "Display Router LSAs\n"
1056 "Display Network LSAs\n"
1057 "Display Inter-Area-Prefix LSAs\n"
1058 "Display Inter-Router LSAs\n"
1059 "Display As-External LSAs\n"
1060 "Display Link LSAs\n"
1061 "Display Intra-Area-Prefix LSAs\n"
1062 "Display LSAs of unknown origin\n"
1063 "Display details of LSAs\n"
1065 "Display LSA's internal information\n")
1070 struct ospf6_lsa_handler
*handler
= NULL
;
1072 for (i
= 0; i
< vector_active(ospf6_lsa_handler_vector
); i
++) {
1073 handler
= vector_slot(ospf6_lsa_handler_vector
, i
);
1074 if (handler
== NULL
)
1076 if (strncmp(argv
[idx_lsa
]->arg
, ospf6_lsa_handler_name(handler
),
1077 strlen(argv
[idx_lsa
]->arg
))
1080 if (!strcasecmp(argv
[idx_lsa
]->arg
, handler
->lh_name
))
1084 if (handler
== NULL
)
1088 if (strmatch(argv
[idx_type
]->text
, "originate"))
1089 UNSET_FLAG(handler
->lh_debug
,
1090 OSPF6_LSA_DEBUG_ORIGINATE
);
1091 if (strmatch(argv
[idx_type
]->text
, "examine"))
1092 UNSET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_EXAMIN
);
1093 if (strmatch(argv
[idx_type
]->text
, "flooding"))
1094 UNSET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_FLOOD
);
1096 UNSET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG
);
1101 void install_element_ospf6_debug_lsa(void)
1103 install_element(ENABLE_NODE
, &debug_ospf6_lsa_hex_cmd
);
1104 install_element(ENABLE_NODE
, &no_debug_ospf6_lsa_hex_cmd
);
1105 install_element(CONFIG_NODE
, &debug_ospf6_lsa_hex_cmd
);
1106 install_element(CONFIG_NODE
, &no_debug_ospf6_lsa_hex_cmd
);
1109 int config_write_ospf6_debug_lsa(struct vty
*vty
)
1112 const struct ospf6_lsa_handler
*handler
;
1114 for (i
= 0; i
< vector_active(ospf6_lsa_handler_vector
); i
++) {
1115 handler
= vector_slot(ospf6_lsa_handler_vector
, i
);
1116 if (handler
== NULL
)
1118 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG
))
1119 vty_out(vty
, "debug ospf6 lsa %s\n",
1120 ospf6_lsa_handler_name(handler
));
1121 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_ORIGINATE
))
1122 vty_out(vty
, "debug ospf6 lsa %s originate\n",
1123 ospf6_lsa_handler_name(handler
));
1124 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_EXAMIN
))
1125 vty_out(vty
, "debug ospf6 lsa %s examine\n",
1126 ospf6_lsa_handler_name(handler
));
1127 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_FLOOD
))
1128 vty_out(vty
, "debug ospf6 lsa %s flooding\n",
1129 ospf6_lsa_handler_name(handler
));