1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2003 Yasuhiro Ohara
8 /* Include other stuffs */
19 #include "ospf6_proto.h"
20 #include "ospf6_lsa.h"
21 #include "ospf6_lsdb.h"
22 #include "ospf6_message.h"
23 #include "ospf6_asbr.h"
24 #include "ospf6_zebra.h"
26 #include "ospf6_top.h"
27 #include "ospf6_area.h"
28 #include "ospf6_interface.h"
29 #include "ospf6_neighbor.h"
31 #include "ospf6_flood.h"
34 #include "ospf6d/ospf6_lsa_clippy.c"
36 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_LSA
, "OSPF6 LSA");
37 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_LSA_HEADER
, "OSPF6 LSA header");
38 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_LSA_SUMMARY
, "OSPF6 LSA summary");
40 static struct ospf6_lsa_handler
*lsa_handlers
[OSPF6_LSTYPE_SIZE
];
42 struct ospf6
*ospf6_get_by_lsdb(struct ospf6_lsa
*lsa
)
44 struct ospf6
*ospf6
= NULL
;
46 switch (OSPF6_LSA_SCOPE(lsa
->header
->type
)) {
47 case OSPF6_SCOPE_LINKLOCAL
:
48 ospf6
= OSPF6_INTERFACE(lsa
->lsdb
->data
)->area
->ospf6
;
50 case OSPF6_SCOPE_AREA
:
51 ospf6
= OSPF6_AREA(lsa
->lsdb
->data
)->ospf6
;
54 ospf6
= OSPF6_PROCESS(lsa
->lsdb
->data
);
63 static int ospf6_unknown_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
64 json_object
*json_obj
, bool use_json
)
66 uint8_t *start
, *end
, *current
;
68 start
= (uint8_t *)lsa
->header
+ sizeof(struct ospf6_lsa_header
);
69 end
= (uint8_t *)lsa
->header
+ ntohs(lsa
->header
->length
);
72 json_object_string_add(json_obj
, "lsaType", "unknown");
74 vty_out(vty
, " Unknown contents:\n");
75 for (current
= start
; current
< end
; current
++) {
76 if ((current
- start
) % 16 == 0)
78 else if ((current
- start
) % 4 == 0)
81 vty_out(vty
, "%02x", *current
);
89 static struct ospf6_lsa_handler unknown_handler
= {
90 .lh_type
= OSPF6_LSTYPE_UNKNOWN
,
92 .lh_short_name
= "Unk",
93 .lh_show
= ospf6_unknown_lsa_show
,
94 .lh_get_prefix_str
= NULL
,
95 .lh_debug
= 0 /* No default debug */
98 void ospf6_install_lsa_handler(struct ospf6_lsa_handler
*handler
)
100 /* type in handler is host byte order */
101 unsigned int index
= handler
->lh_type
& OSPF6_LSTYPE_FCODE_MASK
;
103 assertf(index
< array_size(lsa_handlers
), "index=%x", index
);
104 assertf(lsa_handlers
[index
] == NULL
, "old=%s, new=%s",
105 lsa_handlers
[index
]->lh_name
, handler
->lh_name
);
107 lsa_handlers
[index
] = handler
;
110 struct ospf6_lsa_handler
*ospf6_get_lsa_handler(uint16_t type
)
112 struct ospf6_lsa_handler
*handler
= NULL
;
113 unsigned int index
= ntohs(type
) & OSPF6_LSTYPE_FCODE_MASK
;
115 if (index
< array_size(lsa_handlers
))
116 handler
= lsa_handlers
[index
];
119 handler
= &unknown_handler
;
124 const char *ospf6_lstype_name(uint16_t type
)
127 const struct ospf6_lsa_handler
*handler
;
129 handler
= ospf6_get_lsa_handler(type
);
130 if (handler
&& handler
!= &unknown_handler
)
131 return handler
->lh_name
;
133 snprintf(buf
, sizeof(buf
), "0x%04hx", ntohs(type
));
137 const char *ospf6_lstype_short_name(uint16_t type
)
140 const struct ospf6_lsa_handler
*handler
;
142 handler
= ospf6_get_lsa_handler(type
);
144 return handler
->lh_short_name
;
146 snprintf(buf
, sizeof(buf
), "0x%04hx", ntohs(type
));
150 uint8_t ospf6_lstype_debug(uint16_t type
)
152 const struct ospf6_lsa_handler
*handler
;
153 handler
= ospf6_get_lsa_handler(type
);
154 return handler
->lh_debug
;
157 int metric_type(struct ospf6
*ospf6
, int type
, uint8_t instance
)
159 struct ospf6_redist
*red
;
161 red
= ospf6_redist_lookup(ospf6
, type
, instance
);
163 return ((!red
|| red
->dmetric
.type
< 0) ? DEFAULT_METRIC_TYPE
164 : red
->dmetric
.type
);
167 int metric_value(struct ospf6
*ospf6
, int type
, uint8_t instance
)
169 struct ospf6_redist
*red
;
171 red
= ospf6_redist_lookup(ospf6
, type
, instance
);
172 if (!red
|| red
->dmetric
.value
< 0) {
173 if (type
== DEFAULT_ROUTE
) {
174 if (ospf6
->default_originate
== DEFAULT_ORIGINATE_ZEBRA
)
175 return DEFAULT_DEFAULT_ORIGINATE_METRIC
;
177 return DEFAULT_DEFAULT_ALWAYS_METRIC
;
179 return DEFAULT_DEFAULT_METRIC
;
182 return red
->dmetric
.value
;
185 /* RFC2328: Section 13.2 */
186 int ospf6_lsa_is_differ(struct ospf6_lsa
*lsa1
, struct ospf6_lsa
*lsa2
)
190 assert(OSPF6_LSA_IS_SAME(lsa1
, lsa2
));
192 /* XXX, Options ??? */
194 ospf6_lsa_age_current(lsa1
);
195 ospf6_lsa_age_current(lsa2
);
196 if (ntohs(lsa1
->header
->age
) == OSPF_LSA_MAXAGE
197 && ntohs(lsa2
->header
->age
) != OSPF_LSA_MAXAGE
)
199 if (ntohs(lsa1
->header
->age
) != OSPF_LSA_MAXAGE
200 && ntohs(lsa2
->header
->age
) == OSPF_LSA_MAXAGE
)
204 if (ntohs(lsa1
->header
->length
) != ntohs(lsa2
->header
->length
))
207 len
= ntohs(lsa1
->header
->length
) - sizeof(struct ospf6_lsa_header
);
208 return memcmp(lsa1
->header
+ 1, lsa2
->header
+ 1, len
);
211 int ospf6_lsa_is_changed(struct ospf6_lsa
*lsa1
, struct ospf6_lsa
*lsa2
)
215 if (OSPF6_LSA_IS_MAXAGE(lsa1
) ^ OSPF6_LSA_IS_MAXAGE(lsa2
))
217 if (ntohs(lsa1
->header
->length
) != ntohs(lsa2
->header
->length
))
219 /* Going beyond LSA headers to compare the payload only makes sense,
220 * when both LSAs aren't header-only. */
221 if (CHECK_FLAG(lsa1
->flag
, OSPF6_LSA_HEADERONLY
)
222 != CHECK_FLAG(lsa2
->flag
, OSPF6_LSA_HEADERONLY
)) {
224 "%s: only one of two (%s, %s) LSAs compared is header-only",
225 __func__
, lsa1
->name
, lsa2
->name
);
228 if (CHECK_FLAG(lsa1
->flag
, OSPF6_LSA_HEADERONLY
))
231 length
= OSPF6_LSA_SIZE(lsa1
->header
) - sizeof(struct ospf6_lsa_header
);
232 /* Once upper layer verifies LSAs received, length underrun should
233 * become a warning. */
237 return memcmp(OSPF6_LSA_HEADER_END(lsa1
->header
),
238 OSPF6_LSA_HEADER_END(lsa2
->header
), length
);
241 /* ospf6 age functions */
242 /* calculate birth */
243 void ospf6_lsa_age_set(struct ospf6_lsa
*lsa
)
247 assert(lsa
&& lsa
->header
);
251 lsa
->birth
.tv_sec
= now
.tv_sec
- ntohs(lsa
->header
->age
);
252 lsa
->birth
.tv_usec
= now
.tv_usec
;
257 /* this function calculates current age from its birth,
258 then update age field of LSA header. return value is current age */
259 uint16_t ospf6_lsa_age_current(struct ospf6_lsa
*lsa
)
271 if (ntohs(lsa
->header
->age
) >= OSPF_LSA_MAXAGE
) {
272 /* ospf6_lsa_premature_aging () sets age to MAXAGE; when using
273 relative time, we cannot compare against lsa birth time, so
274 we catch this special case here. */
275 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
276 return OSPF_LSA_MAXAGE
;
279 ulage
= now
.tv_sec
- lsa
->birth
.tv_sec
;
281 /* if over MAXAGE, set to it */
282 age
= (ulage
> OSPF_LSA_MAXAGE
? OSPF_LSA_MAXAGE
: ulage
);
284 lsa
->header
->age
= htons(age
);
288 /* update age field of LSA header with adding InfTransDelay */
289 void ospf6_lsa_age_update_to_send(struct ospf6_lsa
*lsa
, uint32_t transdelay
)
293 age
= ospf6_lsa_age_current(lsa
) + transdelay
;
294 if (age
> OSPF_LSA_MAXAGE
)
295 age
= OSPF_LSA_MAXAGE
;
296 lsa
->header
->age
= htons(age
);
299 void ospf6_lsa_premature_aging(struct ospf6_lsa
*lsa
)
302 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
))
303 zlog_debug("LSA: Premature aging: %s", lsa
->name
);
305 THREAD_OFF(lsa
->expire
);
306 THREAD_OFF(lsa
->refresh
);
309 * We clear the LSA from the neighbor retx lists now because it
310 * will not get deleted later. Essentially, changing the age to
311 * MaxAge will prevent this LSA from being matched with its
312 * existing entries in the retx list thereby causing those entries
313 * to be silently replaced with its MaxAged version, but with ever
314 * increasing retx count causing this LSA to remain forever and
315 * for the MaxAge remover thread to be called forever too.
317 * The reason the previous entry silently disappears is that when
318 * entry is added to a neighbor's retx list, it replaces the existing
319 * entry. But since the ospf6_lsdb_add() routine is generic and not
321 * of the special semantics of retx count, the retx count is not
322 * decremented when its replaced. Attempting to add the incr and decr
323 * retx count routines as the hook_add and hook_remove for the retx
325 * have a problem because the hook_remove routine is called for MaxAge
326 * entries (as will be the case in a traditional LSDB, unlike in this
328 * where an LSDB is used as an efficient tree structure to store all
330 * of data) that are added instead of calling the hook_add routine.
333 ospf6_flood_clear(lsa
);
335 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
336 thread_execute(master
, ospf6_lsa_expire
, lsa
, 0);
339 /* check which is more recent. if a is more recent, return -1;
340 if the same, return 0; otherwise(b is more recent), return 1 */
341 int ospf6_lsa_compare(struct ospf6_lsa
*a
, struct ospf6_lsa
*b
)
343 int32_t seqnuma
, seqnumb
;
344 uint16_t cksuma
, cksumb
;
347 assert(a
&& a
->header
);
348 assert(b
&& b
->header
);
349 assert(OSPF6_LSA_IS_SAME(a
, b
));
351 seqnuma
= (int32_t)ntohl(a
->header
->seqnum
);
352 seqnumb
= (int32_t)ntohl(b
->header
->seqnum
);
354 /* compare by sequence number */
355 if (seqnuma
> seqnumb
)
357 if (seqnuma
< seqnumb
)
361 cksuma
= ntohs(a
->header
->checksum
);
362 cksumb
= ntohs(b
->header
->checksum
);
369 agea
= ospf6_lsa_age_current(a
);
370 ageb
= ospf6_lsa_age_current(b
);
373 if (agea
== OSPF_LSA_MAXAGE
&& ageb
!= OSPF_LSA_MAXAGE
)
375 else if (agea
!= OSPF_LSA_MAXAGE
&& ageb
== OSPF_LSA_MAXAGE
)
379 if (agea
> ageb
&& agea
- ageb
>= OSPF_LSA_MAXAGE_DIFF
)
381 else if (agea
< ageb
&& ageb
- agea
>= OSPF_LSA_MAXAGE_DIFF
)
388 char *ospf6_lsa_printbuf(struct ospf6_lsa
*lsa
, char *buf
, int size
)
390 char id
[16], adv_router
[16];
391 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
392 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
394 snprintf(buf
, size
, "[%s Id:%s Adv:%s]",
395 ospf6_lstype_name(lsa
->header
->type
), id
, adv_router
);
399 void ospf6_lsa_header_print_raw(struct ospf6_lsa_header
*header
)
401 char id
[16], adv_router
[16];
402 inet_ntop(AF_INET
, &header
->id
, id
, sizeof(id
));
403 inet_ntop(AF_INET
, &header
->adv_router
, adv_router
, sizeof(adv_router
));
404 zlog_debug(" [%s Id:%s Adv:%s]", ospf6_lstype_name(header
->type
), id
,
406 zlog_debug(" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
407 ntohs(header
->age
), (unsigned long)ntohl(header
->seqnum
),
408 ntohs(header
->checksum
), ntohs(header
->length
));
411 void ospf6_lsa_header_print(struct ospf6_lsa
*lsa
)
413 ospf6_lsa_age_current(lsa
);
414 ospf6_lsa_header_print_raw(lsa
->header
);
417 void ospf6_lsa_show_summary_header(struct vty
*vty
)
419 vty_out(vty
, "%-4s %-15s%-15s%4s %8s %30s\n", "Type", "LSId",
420 "AdvRouter", "Age", "SeqNum", "Payload");
423 void ospf6_lsa_show_summary(struct vty
*vty
, struct ospf6_lsa
*lsa
,
424 json_object
*json_array
, bool use_json
)
426 char adv_router
[16], id
[16];
428 const struct ospf6_lsa_handler
*handler
;
431 json_object
*json_obj
= NULL
;
436 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
437 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
440 type
= ntohs(lsa
->header
->type
);
441 handler
= ospf6_get_lsa_handler(lsa
->header
->type
);
444 json_obj
= json_object_new_object();
447 case OSPF6_LSTYPE_INTER_PREFIX
:
448 case OSPF6_LSTYPE_INTER_ROUTER
:
449 case OSPF6_LSTYPE_AS_EXTERNAL
:
450 case OSPF6_LSTYPE_TYPE_7
:
452 json_object_string_add(
454 ospf6_lstype_short_name(lsa
->header
->type
));
455 json_object_string_add(json_obj
, "lsId", id
);
456 json_object_string_add(json_obj
, "advRouter",
458 json_object_int_add(json_obj
, "age",
459 ospf6_lsa_age_current(lsa
));
462 (unsigned long)ntohl(lsa
->header
->seqnum
));
463 json_object_string_add(
465 handler
->lh_get_prefix_str(lsa
, buf
,
467 json_object_array_add(json_array
, json_obj
);
469 vty_out(vty
, "%-4s %-15s%-15s%4hu %8lx %30s\n",
470 ospf6_lstype_short_name(lsa
->header
->type
), id
,
471 adv_router
, ospf6_lsa_age_current(lsa
),
472 (unsigned long)ntohl(lsa
->header
->seqnum
),
473 handler
->lh_get_prefix_str(lsa
, buf
,
476 case OSPF6_LSTYPE_ROUTER
:
477 case OSPF6_LSTYPE_NETWORK
:
478 case OSPF6_LSTYPE_GROUP_MEMBERSHIP
:
479 case OSPF6_LSTYPE_LINK
:
480 case OSPF6_LSTYPE_INTRA_PREFIX
:
481 while (handler
->lh_get_prefix_str(lsa
, buf
, sizeof(buf
), cnt
)
484 json_object_string_add(
486 ospf6_lstype_short_name(
488 json_object_string_add(json_obj
, "lsId", id
);
489 json_object_string_add(json_obj
, "advRouter",
491 json_object_int_add(json_obj
, "age",
492 ospf6_lsa_age_current(lsa
));
495 (unsigned long)ntohl(
496 lsa
->header
->seqnum
));
497 json_object_string_add(json_obj
, "payload",
499 json_object_array_add(json_array
, json_obj
);
500 json_obj
= json_object_new_object();
502 vty_out(vty
, "%-4s %-15s%-15s%4hu %8lx %30s\n",
503 ospf6_lstype_short_name(
506 ospf6_lsa_age_current(lsa
),
507 (unsigned long)ntohl(
508 lsa
->header
->seqnum
),
513 json_object_free(json_obj
);
517 json_object_string_add(
519 ospf6_lstype_short_name(lsa
->header
->type
));
520 json_object_string_add(json_obj
, "lsId", id
);
521 json_object_string_add(json_obj
, "advRouter",
523 json_object_int_add(json_obj
, "age",
524 ospf6_lsa_age_current(lsa
));
527 (unsigned long)ntohl(lsa
->header
->seqnum
));
528 json_object_array_add(json_array
, json_obj
);
530 vty_out(vty
, "%-4s %-15s%-15s%4hu %8lx\n",
531 ospf6_lstype_short_name(lsa
->header
->type
), id
,
532 adv_router
, ospf6_lsa_age_current(lsa
),
533 (unsigned long)ntohl(lsa
->header
->seqnum
));
538 void ospf6_lsa_show_dump(struct vty
*vty
, struct ospf6_lsa
*lsa
,
539 json_object
*json_array
, bool use_json
)
541 uint8_t *start
= NULL
;
543 uint8_t *current
= NULL
;
545 char *header_str
= NULL
;
546 char adv_router
[INET6_ADDRSTRLEN
];
547 char id
[INET6_ADDRSTRLEN
];
548 json_object
*json
= NULL
;
550 start
= (uint8_t *)lsa
->header
;
551 end
= (uint8_t *)lsa
->header
+ ntohs(lsa
->header
->length
);
554 json
= json_object_new_object();
555 size_t header_str_sz
= (2 * (end
- start
)) + 1;
557 header_str
= XMALLOC(MTYPE_OSPF6_LSA_HEADER
, header_str_sz
);
559 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
560 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
563 frrstr_hex(header_str
, header_str_sz
, start
, end
- start
);
565 json_object_string_add(json
, "linkStateId", id
);
566 json_object_string_add(json
, "advertisingRouter", adv_router
);
567 json_object_string_add(json
, "header", header_str
);
568 json_object_array_add(json_array
, json
);
570 XFREE(MTYPE_OSPF6_LSA_HEADER
, header_str
);
572 vty_out(vty
, "\n%s:\n", lsa
->name
);
574 for (current
= start
; current
< end
; current
++) {
575 if ((current
- start
) % 16 == 0)
577 else if ((current
- start
) % 4 == 0)
580 snprintf(byte
, sizeof(byte
), "%02x", *current
);
581 vty_out(vty
, "%s", byte
);
584 vty_out(vty
, "\n\n");
590 void ospf6_lsa_show_internal(struct vty
*vty
, struct ospf6_lsa
*lsa
,
591 json_object
*json_array
, bool use_json
)
593 char adv_router
[64], id
[64];
594 json_object
*json_obj
;
596 assert(lsa
&& lsa
->header
);
598 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
599 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
603 json_obj
= json_object_new_object();
604 json_object_int_add(json_obj
, "age",
605 ospf6_lsa_age_current(lsa
));
606 json_object_string_add(json_obj
, "type",
607 ospf6_lstype_name(lsa
->header
->type
));
608 json_object_string_add(json_obj
, "linkStateId", id
);
609 json_object_string_add(json_obj
, "advertisingRouter",
611 json_object_int_add(json_obj
, "lsSequenceNumber",
612 (unsigned long)ntohl(lsa
->header
->seqnum
));
613 json_object_int_add(json_obj
, "checksum",
614 ntohs(lsa
->header
->checksum
));
615 json_object_int_add(json_obj
, "length",
616 ntohs(lsa
->header
->length
));
617 json_object_int_add(json_obj
, "flag", lsa
->flag
);
618 json_object_int_add(json_obj
, "lock", lsa
->lock
);
619 json_object_int_add(json_obj
, "reTxCount", lsa
->retrans_count
);
621 /* Threads Data not added */
622 json_object_array_add(json_array
, json_obj
);
625 vty_out(vty
, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa
),
626 ospf6_lstype_name(lsa
->header
->type
));
627 vty_out(vty
, "Link State ID: %s\n", id
);
628 vty_out(vty
, "Advertising Router: %s\n", adv_router
);
629 vty_out(vty
, "LS Sequence Number: %#010lx\n",
630 (unsigned long)ntohl(lsa
->header
->seqnum
));
631 vty_out(vty
, "CheckSum: %#06hx Length: %hu\n",
632 ntohs(lsa
->header
->checksum
),
633 ntohs(lsa
->header
->length
));
634 vty_out(vty
, "Flag: %x \n", lsa
->flag
);
635 vty_out(vty
, "Lock: %d \n", lsa
->lock
);
636 vty_out(vty
, "ReTx Count: %d\n", lsa
->retrans_count
);
637 vty_out(vty
, "Threads: Expire: %p, Refresh: %p\n", lsa
->expire
,
644 void ospf6_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
645 json_object
*json_array
, bool use_json
)
647 char adv_router
[64], id
[64];
648 const struct ospf6_lsa_handler
*handler
;
649 struct timeval now
, res
;
651 json_object
*json_obj
= NULL
;
653 assert(lsa
&& lsa
->header
);
655 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
656 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
660 timersub(&now
, &lsa
->installed
, &res
);
661 timerstring(&res
, duration
, sizeof(duration
));
663 json_obj
= json_object_new_object();
664 json_object_int_add(json_obj
, "age",
665 ospf6_lsa_age_current(lsa
));
666 json_object_string_add(json_obj
, "type",
667 ospf6_lstype_name(lsa
->header
->type
));
668 json_object_string_add(json_obj
, "linkStateId", id
);
669 json_object_string_add(json_obj
, "advertisingRouter",
671 json_object_int_add(json_obj
, "lsSequenceNumber",
672 (unsigned long)ntohl(lsa
->header
->seqnum
));
673 json_object_int_add(json_obj
, "checksum",
674 ntohs(lsa
->header
->checksum
));
675 json_object_int_add(json_obj
, "length",
676 ntohs(lsa
->header
->length
));
677 json_object_string_add(json_obj
, "duration", duration
);
679 vty_out(vty
, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa
),
680 ospf6_lstype_name(lsa
->header
->type
));
681 vty_out(vty
, "Link State ID: %s\n", id
);
682 vty_out(vty
, "Advertising Router: %s\n", adv_router
);
683 vty_out(vty
, "LS Sequence Number: %#010lx\n",
684 (unsigned long)ntohl(lsa
->header
->seqnum
));
685 vty_out(vty
, "CheckSum: %#06hx Length: %hu\n",
686 ntohs(lsa
->header
->checksum
),
687 ntohs(lsa
->header
->length
));
688 vty_out(vty
, "Duration: %s\n", duration
);
691 handler
= ospf6_get_lsa_handler(lsa
->header
->type
);
693 if (handler
->lh_show
!= NULL
)
694 handler
->lh_show(vty
, lsa
, json_obj
, use_json
);
696 assert(unknown_handler
.lh_show
!= NULL
);
697 unknown_handler
.lh_show(vty
, lsa
, json_obj
, use_json
);
701 json_object_array_add(json_array
, json_obj
);
706 struct ospf6_lsa
*ospf6_lsa_alloc(size_t lsa_length
)
708 struct ospf6_lsa
*lsa
;
710 lsa
= XCALLOC(MTYPE_OSPF6_LSA
, sizeof(struct ospf6_lsa
));
711 lsa
->header
= XMALLOC(MTYPE_OSPF6_LSA_HEADER
, lsa_length
);
716 /* OSPFv3 LSA creation/deletion function */
717 struct ospf6_lsa
*ospf6_lsa_create(struct ospf6_lsa_header
*header
)
719 struct ospf6_lsa
*lsa
= NULL
;
720 uint16_t lsa_size
= 0;
722 /* size of the entire LSA */
723 lsa_size
= ntohs(header
->length
); /* XXX vulnerable */
725 lsa
= ospf6_lsa_alloc(lsa_size
);
727 /* copy LSA from original header */
728 memcpy(lsa
->header
, header
, lsa_size
);
731 ospf6_lsa_printbuf(lsa
, lsa
->name
, sizeof(lsa
->name
));
733 /* calculate birth of this lsa */
734 ospf6_lsa_age_set(lsa
);
739 struct ospf6_lsa
*ospf6_lsa_create_headeronly(struct ospf6_lsa_header
*header
)
741 struct ospf6_lsa
*lsa
= NULL
;
743 lsa
= ospf6_lsa_alloc(sizeof(struct ospf6_lsa_header
));
745 memcpy(lsa
->header
, header
, sizeof(struct ospf6_lsa_header
));
747 SET_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
);
750 ospf6_lsa_printbuf(lsa
, lsa
->name
, sizeof(lsa
->name
));
752 /* calculate birth of this lsa */
753 ospf6_lsa_age_set(lsa
);
758 void ospf6_lsa_delete(struct ospf6_lsa
*lsa
)
760 assert(lsa
->lock
== 0);
763 THREAD_OFF(lsa
->expire
);
764 THREAD_OFF(lsa
->refresh
);
767 XFREE(MTYPE_OSPF6_LSA_HEADER
, lsa
->header
);
768 XFREE(MTYPE_OSPF6_LSA
, lsa
);
771 struct ospf6_lsa
*ospf6_lsa_copy(struct ospf6_lsa
*lsa
)
773 struct ospf6_lsa
*copy
= NULL
;
775 ospf6_lsa_age_current(lsa
);
776 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
))
777 copy
= ospf6_lsa_create_headeronly(lsa
->header
);
779 copy
= ospf6_lsa_create(lsa
->header
);
780 assert(copy
->lock
== 0);
782 copy
->birth
= lsa
->birth
;
783 copy
->originated
= lsa
->originated
;
784 copy
->received
= lsa
->received
;
785 copy
->installed
= lsa
->installed
;
786 copy
->lsdb
= lsa
->lsdb
;
792 /* increment reference counter of struct ospf6_lsa */
793 struct ospf6_lsa
*ospf6_lsa_lock(struct ospf6_lsa
*lsa
)
799 /* decrement reference counter of struct ospf6_lsa */
800 struct ospf6_lsa
*ospf6_lsa_unlock(struct ospf6_lsa
*lsa
)
802 /* decrement reference counter */
803 assert(lsa
->lock
> 0);
809 ospf6_lsa_delete(lsa
);
814 /* ospf6 lsa expiry */
815 void ospf6_lsa_expire(struct thread
*thread
)
817 struct ospf6_lsa
*lsa
;
820 lsa
= (struct ospf6_lsa
*)THREAD_ARG(thread
);
822 assert(lsa
&& lsa
->header
);
823 assert(OSPF6_LSA_IS_MAXAGE(lsa
));
824 assert(!lsa
->refresh
);
826 lsa
->expire
= (struct thread
*)NULL
;
828 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
)) {
829 zlog_debug("LSA Expire:");
830 ospf6_lsa_header_print(lsa
);
833 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
))
834 return; /* dbexchange will do something ... */
835 ospf6
= ospf6_get_by_lsdb(lsa
);
839 ospf6_install_lsa(lsa
);
842 ospf6_flood(NULL
, lsa
);
844 /* schedule maxage remover */
845 ospf6_maxage_remove(ospf6
);
848 void ospf6_lsa_refresh(struct thread
*thread
)
850 struct ospf6_lsa
*old
, *self
, *new;
851 struct ospf6_lsdb
*lsdb_self
;
853 old
= (struct ospf6_lsa
*)THREAD_ARG(thread
);
854 assert(old
&& old
->header
);
856 old
->refresh
= (struct thread
*)NULL
;
858 lsdb_self
= ospf6_get_scoped_lsdb_self(old
);
859 self
= ospf6_lsdb_lookup(old
->header
->type
, old
->header
->id
,
860 old
->header
->adv_router
, lsdb_self
);
862 if (IS_OSPF6_DEBUG_LSA_TYPE(old
->header
->type
))
863 zlog_debug("Refresh: could not find self LSA, flush %s",
865 ospf6_lsa_premature_aging(old
);
869 /* Reset age, increment LS sequence number. */
870 self
->header
->age
= htons(0);
871 self
->header
->seqnum
=
872 ospf6_new_ls_seqnum(self
->header
->type
, self
->header
->id
,
873 self
->header
->adv_router
, old
->lsdb
);
874 ospf6_lsa_checksum(self
->header
);
876 new = ospf6_lsa_create(self
->header
);
877 new->lsdb
= old
->lsdb
;
878 thread_add_timer(master
, ospf6_lsa_refresh
, new, OSPF_LS_REFRESH_TIME
,
881 /* store it in the LSDB for self-originated LSAs */
882 ospf6_lsdb_add(ospf6_lsa_copy(new), lsdb_self
);
884 if (IS_OSPF6_DEBUG_LSA_TYPE(new->header
->type
)) {
885 zlog_debug("LSA Refresh:");
886 ospf6_lsa_header_print(new);
889 ospf6_install_lsa(new);
890 ospf6_flood(NULL
, new);
893 void ospf6_flush_self_originated_lsas_now(struct ospf6
*ospf6
)
895 struct listnode
*node
, *nnode
;
896 struct ospf6_area
*oa
;
897 struct ospf6_lsa
*lsa
;
898 const struct route_node
*end
= NULL
;
899 uint32_t type
, adv_router
;
900 struct ospf6_interface
*oi
;
902 ospf6
->inst_shutdown
= 1;
904 for (ALL_LIST_ELEMENTS_RO(ospf6
->area_list
, node
, oa
)) {
905 end
= ospf6_lsdb_head(oa
->lsdb_self
, 0, 0, ospf6
->router_id
,
908 /* RFC 2328 (14.1): Set MAXAGE */
909 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
910 /* Flood MAXAGE LSA*/
911 ospf6_flood(NULL
, lsa
);
913 lsa
= ospf6_lsdb_next(end
, lsa
);
916 for (ALL_LIST_ELEMENTS(oa
->if_list
, node
, nnode
, oi
)) {
917 end
= ospf6_lsdb_head(oi
->lsdb_self
, 0, 0,
918 ospf6
->router_id
, &lsa
);
920 /* RFC 2328 (14.1): Set MAXAGE */
921 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
922 /* Flood MAXAGE LSA*/
923 ospf6_flood(NULL
, lsa
);
925 lsa
= ospf6_lsdb_next(end
, lsa
);
930 type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
931 adv_router
= ospf6
->router_id
;
932 for (ALL_LSDB_TYPED_ADVRTR(ospf6
->lsdb
, type
, adv_router
, lsa
)) {
933 /* RFC 2328 (14.1): Set MAXAGE */
934 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
935 ospf6_flood(NULL
, lsa
);
939 /* Fletcher Checksum -- Refer to RFC1008. */
941 /* All the offsets are zero-based. The offsets in the RFC1008 are
943 unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header
*lsa_header
)
945 uint8_t *buffer
= (uint8_t *)&lsa_header
->type
;
947 buffer
- (uint8_t *)&lsa_header
->age
; /* should be 2 */
949 /* Skip the AGE field */
950 uint16_t len
= ntohs(lsa_header
->length
) - type_offset
;
952 /* Checksum offset starts from "type" field, not the beginning of the
953 lsa_header struct. The offset is 14, rather than 16. */
954 int checksum_offset
= (uint8_t *)&lsa_header
->checksum
- buffer
;
956 return (unsigned short)fletcher_checksum(buffer
, len
, checksum_offset
);
959 int ospf6_lsa_checksum_valid(struct ospf6_lsa_header
*lsa_header
)
961 uint8_t *buffer
= (uint8_t *)&lsa_header
->type
;
963 buffer
- (uint8_t *)&lsa_header
->age
; /* should be 2 */
965 /* Skip the AGE field */
966 uint16_t len
= ntohs(lsa_header
->length
) - type_offset
;
968 return (fletcher_checksum(buffer
, len
, FLETCHER_CHECKSUM_VALIDATE
)
972 void ospf6_lsa_init(void)
974 ospf6_install_lsa_handler(&unknown_handler
);
977 void ospf6_lsa_terminate(void)
981 static char *ospf6_lsa_handler_name(const struct ospf6_lsa_handler
*h
)
985 unsigned int size
= strlen(h
->lh_name
);
987 if (!strcmp(h
->lh_name
, "unknown")
988 && h
->lh_type
!= OSPF6_LSTYPE_UNKNOWN
) {
989 snprintf(buf
, sizeof(buf
), "%#04hx", h
->lh_type
);
993 for (i
= 0; i
< MIN(size
, sizeof(buf
)); i
++) {
994 if (!islower((unsigned char)h
->lh_name
[i
]))
995 buf
[i
] = tolower((unsigned char)h
->lh_name
[i
]);
997 buf
[i
] = h
->lh_name
[i
];
1003 void ospf6_lsa_debug_set_all(bool val
)
1006 struct ospf6_lsa_handler
*handler
= NULL
;
1008 for (i
= 0; i
< array_size(lsa_handlers
); i
++) {
1009 handler
= lsa_handlers
[i
];
1010 if (handler
== NULL
)
1013 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_ALL
);
1015 UNSET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_ALL
);
1019 DEFPY (debug_ospf6_lsa_all
,
1020 debug_ospf6_lsa_all_cmd
,
1021 "[no$no] debug ospf6 lsa all",
1025 "Debug Link State Advertisements (LSAs)\n"
1026 "Display for all types of LSAs\n")
1028 ospf6_lsa_debug_set_all(!no
);
1032 DEFPY (debug_ospf6_lsa_aggregation
,
1033 debug_ospf6_lsa_aggregation_cmd
,
1034 "[no] debug ospf6 lsa aggregation",
1038 "Debug Link State Advertisements (LSAs)\n"
1039 "External LSA Aggregation\n")
1042 struct ospf6_lsa_handler
*handler
;
1044 handler
= ospf6_get_lsa_handler(OSPF6_LSTYPE_AS_EXTERNAL
);
1045 if (handler
== NULL
)
1046 return CMD_WARNING_CONFIG_FAILED
;
1049 UNSET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_AGGR
);
1051 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_AGGR
);
1056 DEFUN (debug_ospf6_lsa_type
,
1057 debug_ospf6_lsa_hex_cmd
,
1058 "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]",
1061 "Debug Link State Advertisements (LSAs)\n"
1062 "Display Router LSAs\n"
1063 "Display Network LSAs\n"
1064 "Display Inter-Area-Prefix LSAs\n"
1065 "Display Inter-Router LSAs\n"
1066 "Display As-External LSAs\n"
1067 "Display NSSA LSAs\n"
1068 "Display Link LSAs\n"
1069 "Display Intra-Area-Prefix LSAs\n"
1070 "Display LSAs of unknown origin\n"
1071 "Display details of LSAs\n"
1073 "Display LSA's internal information\n")
1078 struct ospf6_lsa_handler
*handler
= NULL
;
1080 for (i
= 0; i
< array_size(lsa_handlers
); i
++) {
1081 handler
= lsa_handlers
[i
];
1082 if (handler
== NULL
)
1084 if (strncmp(argv
[idx_lsa
]->arg
, ospf6_lsa_handler_name(handler
),
1085 strlen(argv
[idx_lsa
]->arg
))
1088 if (!strcasecmp(argv
[idx_lsa
]->arg
, handler
->lh_name
))
1093 if (handler
== NULL
)
1094 handler
= &unknown_handler
;
1097 if (strmatch(argv
[idx_type
]->text
, "originate"))
1098 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_ORIGINATE
);
1099 else if (strmatch(argv
[idx_type
]->text
, "examine"))
1100 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_EXAMIN
);
1101 else if (strmatch(argv
[idx_type
]->text
, "flooding"))
1102 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_FLOOD
);
1104 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG
);
1109 DEFUN (no_debug_ospf6_lsa_type
,
1110 no_debug_ospf6_lsa_hex_cmd
,
1111 "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]",
1115 "Debug Link State Advertisements (LSAs)\n"
1116 "Display Router LSAs\n"
1117 "Display Network LSAs\n"
1118 "Display Inter-Area-Prefix LSAs\n"
1119 "Display Inter-Router LSAs\n"
1120 "Display As-External LSAs\n"
1121 "Display NSSA LSAs\n"
1122 "Display Link LSAs\n"
1123 "Display Intra-Area-Prefix LSAs\n"
1124 "Display LSAs of unknown origin\n"
1125 "Display details of LSAs\n"
1127 "Display LSA's internal information\n")
1132 struct ospf6_lsa_handler
*handler
= NULL
;
1134 for (i
= 0; i
< array_size(lsa_handlers
); i
++) {
1135 handler
= lsa_handlers
[i
];
1136 if (handler
== NULL
)
1138 if (strncmp(argv
[idx_lsa
]->arg
, ospf6_lsa_handler_name(handler
),
1139 strlen(argv
[idx_lsa
]->arg
))
1142 if (!strcasecmp(argv
[idx_lsa
]->arg
, handler
->lh_name
))
1146 if (handler
== NULL
)
1150 if (strmatch(argv
[idx_type
]->text
, "originate"))
1151 UNSET_FLAG(handler
->lh_debug
,
1152 OSPF6_LSA_DEBUG_ORIGINATE
);
1153 if (strmatch(argv
[idx_type
]->text
, "examine"))
1154 UNSET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_EXAMIN
);
1155 if (strmatch(argv
[idx_type
]->text
, "flooding"))
1156 UNSET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_FLOOD
);
1158 UNSET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG
);
1163 void install_element_ospf6_debug_lsa(void)
1165 install_element(ENABLE_NODE
, &debug_ospf6_lsa_all_cmd
);
1166 install_element(CONFIG_NODE
, &debug_ospf6_lsa_all_cmd
);
1167 install_element(ENABLE_NODE
, &debug_ospf6_lsa_hex_cmd
);
1168 install_element(ENABLE_NODE
, &no_debug_ospf6_lsa_hex_cmd
);
1169 install_element(CONFIG_NODE
, &debug_ospf6_lsa_hex_cmd
);
1170 install_element(CONFIG_NODE
, &no_debug_ospf6_lsa_hex_cmd
);
1172 install_element(ENABLE_NODE
, &debug_ospf6_lsa_aggregation_cmd
);
1173 install_element(CONFIG_NODE
, &debug_ospf6_lsa_aggregation_cmd
);
1176 int config_write_ospf6_debug_lsa(struct vty
*vty
)
1179 const struct ospf6_lsa_handler
*handler
;
1180 bool debug_all
= true;
1182 for (i
= 0; i
< array_size(lsa_handlers
); i
++) {
1183 handler
= lsa_handlers
[i
];
1184 if (handler
== NULL
)
1186 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_ALL
)
1187 < OSPF6_LSA_DEBUG_ALL
) {
1194 vty_out(vty
, "debug ospf6 lsa all\n");
1198 for (i
= 0; i
< array_size(lsa_handlers
); i
++) {
1199 handler
= lsa_handlers
[i
];
1200 if (handler
== NULL
)
1202 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG
))
1203 vty_out(vty
, "debug ospf6 lsa %s\n",
1204 ospf6_lsa_handler_name(handler
));
1205 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_ORIGINATE
))
1206 vty_out(vty
, "debug ospf6 lsa %s originate\n",
1207 ospf6_lsa_handler_name(handler
));
1208 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_EXAMIN
))
1209 vty_out(vty
, "debug ospf6 lsa %s examine\n",
1210 ospf6_lsa_handler_name(handler
));
1211 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_FLOOD
))
1212 vty_out(vty
, "debug ospf6 lsa %s flooding\n",
1213 ospf6_lsa_handler_name(handler
));
1214 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_AGGR
))
1215 vty_out(vty
, "debug ospf6 lsa aggregation\n");