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 */
34 #include "ospf6_proto.h"
35 #include "ospf6_lsa.h"
36 #include "ospf6_lsdb.h"
37 #include "ospf6_message.h"
38 #include "ospf6_asbr.h"
39 #include "ospf6_zebra.h"
41 #include "ospf6_top.h"
42 #include "ospf6_area.h"
43 #include "ospf6_interface.h"
44 #include "ospf6_neighbor.h"
46 #include "ospf6_flood.h"
49 #ifndef VTYSH_EXTRACT_PL
50 #include "ospf6d/ospf6_lsa_clippy.c"
53 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_LSA
, "OSPF6 LSA");
54 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_LSA_HEADER
, "OSPF6 LSA header");
55 DEFINE_MTYPE_STATIC(OSPF6D
, OSPF6_LSA_SUMMARY
, "OSPF6 LSA summary");
57 static struct ospf6_lsa_handler
*lsa_handlers
[OSPF6_LSTYPE_SIZE
];
59 struct ospf6
*ospf6_get_by_lsdb(struct ospf6_lsa
*lsa
)
61 struct ospf6
*ospf6
= NULL
;
63 switch (OSPF6_LSA_SCOPE(lsa
->header
->type
)) {
64 case OSPF6_SCOPE_LINKLOCAL
:
65 ospf6
= OSPF6_INTERFACE(lsa
->lsdb
->data
)->area
->ospf6
;
67 case OSPF6_SCOPE_AREA
:
68 ospf6
= OSPF6_AREA(lsa
->lsdb
->data
)->ospf6
;
71 ospf6
= OSPF6_PROCESS(lsa
->lsdb
->data
);
80 static int ospf6_unknown_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
81 json_object
*json_obj
, bool use_json
)
83 uint8_t *start
, *end
, *current
;
85 start
= (uint8_t *)lsa
->header
+ sizeof(struct ospf6_lsa_header
);
86 end
= (uint8_t *)lsa
->header
+ ntohs(lsa
->header
->length
);
88 #if CONFDATE > 20230131
89 CPP_NOTICE("Remove JSON object commands with keys starting with capital")
92 json_object_string_add(json_obj
, "LsaType", "unknown");
93 json_object_string_add(json_obj
, "lsaType", "unknown");
95 vty_out(vty
, " Unknown contents:\n");
96 for (current
= start
; current
< end
; current
++) {
97 if ((current
- start
) % 16 == 0)
99 else if ((current
- start
) % 4 == 0)
102 vty_out(vty
, "%02x", *current
);
105 vty_out(vty
, "\n\n");
110 static struct ospf6_lsa_handler unknown_handler
= {
111 .lh_type
= OSPF6_LSTYPE_UNKNOWN
,
112 .lh_name
= "Unknown",
113 .lh_short_name
= "Unk",
114 .lh_show
= ospf6_unknown_lsa_show
,
115 .lh_get_prefix_str
= NULL
,
116 .lh_debug
= 0 /* No default debug */
119 void ospf6_install_lsa_handler(struct ospf6_lsa_handler
*handler
)
121 /* type in handler is host byte order */
122 unsigned int index
= handler
->lh_type
& OSPF6_LSTYPE_FCODE_MASK
;
124 assertf(index
< array_size(lsa_handlers
), "index=%x", index
);
125 assertf(lsa_handlers
[index
] == NULL
, "old=%s, new=%s",
126 lsa_handlers
[index
]->lh_name
, handler
->lh_name
);
128 lsa_handlers
[index
] = handler
;
131 struct ospf6_lsa_handler
*ospf6_get_lsa_handler(uint16_t type
)
133 struct ospf6_lsa_handler
*handler
= NULL
;
134 unsigned int index
= ntohs(type
) & OSPF6_LSTYPE_FCODE_MASK
;
136 if (index
< array_size(lsa_handlers
))
137 handler
= lsa_handlers
[index
];
140 handler
= &unknown_handler
;
145 const char *ospf6_lstype_name(uint16_t type
)
148 const struct ospf6_lsa_handler
*handler
;
150 handler
= ospf6_get_lsa_handler(type
);
151 if (handler
&& handler
!= &unknown_handler
)
152 return handler
->lh_name
;
154 snprintf(buf
, sizeof(buf
), "0x%04hx", ntohs(type
));
158 const char *ospf6_lstype_short_name(uint16_t type
)
161 const struct ospf6_lsa_handler
*handler
;
163 handler
= ospf6_get_lsa_handler(type
);
165 return handler
->lh_short_name
;
167 snprintf(buf
, sizeof(buf
), "0x%04hx", ntohs(type
));
171 uint8_t ospf6_lstype_debug(uint16_t type
)
173 const struct ospf6_lsa_handler
*handler
;
174 handler
= ospf6_get_lsa_handler(type
);
175 return handler
->lh_debug
;
178 int metric_type(struct ospf6
*ospf6
, int type
, uint8_t instance
)
180 struct ospf6_redist
*red
;
182 red
= ospf6_redist_lookup(ospf6
, type
, instance
);
184 return ((!red
|| red
->dmetric
.type
< 0) ? DEFAULT_METRIC_TYPE
185 : red
->dmetric
.type
);
188 int metric_value(struct ospf6
*ospf6
, int type
, uint8_t instance
)
190 struct ospf6_redist
*red
;
192 red
= ospf6_redist_lookup(ospf6
, type
, instance
);
193 if (!red
|| red
->dmetric
.value
< 0) {
194 if (type
== DEFAULT_ROUTE
) {
195 if (ospf6
->default_originate
== DEFAULT_ORIGINATE_ZEBRA
)
196 return DEFAULT_DEFAULT_ORIGINATE_METRIC
;
198 return DEFAULT_DEFAULT_ALWAYS_METRIC
;
200 return DEFAULT_DEFAULT_METRIC
;
203 return red
->dmetric
.value
;
206 /* RFC2328: Section 13.2 */
207 int ospf6_lsa_is_differ(struct ospf6_lsa
*lsa1
, struct ospf6_lsa
*lsa2
)
211 assert(OSPF6_LSA_IS_SAME(lsa1
, lsa2
));
213 /* XXX, Options ??? */
215 ospf6_lsa_age_current(lsa1
);
216 ospf6_lsa_age_current(lsa2
);
217 if (ntohs(lsa1
->header
->age
) == OSPF_LSA_MAXAGE
218 && ntohs(lsa2
->header
->age
) != OSPF_LSA_MAXAGE
)
220 if (ntohs(lsa1
->header
->age
) != OSPF_LSA_MAXAGE
221 && ntohs(lsa2
->header
->age
) == OSPF_LSA_MAXAGE
)
225 if (ntohs(lsa1
->header
->length
) != ntohs(lsa2
->header
->length
))
228 len
= ntohs(lsa1
->header
->length
) - sizeof(struct ospf6_lsa_header
);
229 return memcmp(lsa1
->header
+ 1, lsa2
->header
+ 1, len
);
232 int ospf6_lsa_is_changed(struct ospf6_lsa
*lsa1
, struct ospf6_lsa
*lsa2
)
236 if (OSPF6_LSA_IS_MAXAGE(lsa1
) ^ OSPF6_LSA_IS_MAXAGE(lsa2
))
238 if (ntohs(lsa1
->header
->length
) != ntohs(lsa2
->header
->length
))
240 /* Going beyond LSA headers to compare the payload only makes sense,
241 * when both LSAs aren't header-only. */
242 if (CHECK_FLAG(lsa1
->flag
, OSPF6_LSA_HEADERONLY
)
243 != CHECK_FLAG(lsa2
->flag
, OSPF6_LSA_HEADERONLY
)) {
245 "%s: only one of two (%s, %s) LSAs compared is header-only",
246 __func__
, lsa1
->name
, lsa2
->name
);
249 if (CHECK_FLAG(lsa1
->flag
, OSPF6_LSA_HEADERONLY
))
252 length
= OSPF6_LSA_SIZE(lsa1
->header
) - sizeof(struct ospf6_lsa_header
);
253 /* Once upper layer verifies LSAs received, length underrun should
254 * become a warning. */
258 return memcmp(OSPF6_LSA_HEADER_END(lsa1
->header
),
259 OSPF6_LSA_HEADER_END(lsa2
->header
), length
);
262 /* ospf6 age functions */
263 /* calculate birth */
264 void ospf6_lsa_age_set(struct ospf6_lsa
*lsa
)
268 assert(lsa
&& lsa
->header
);
272 lsa
->birth
.tv_sec
= now
.tv_sec
- ntohs(lsa
->header
->age
);
273 lsa
->birth
.tv_usec
= now
.tv_usec
;
278 /* this function calculates current age from its birth,
279 then update age field of LSA header. return value is current age */
280 uint16_t ospf6_lsa_age_current(struct ospf6_lsa
*lsa
)
292 if (ntohs(lsa
->header
->age
) >= OSPF_LSA_MAXAGE
) {
293 /* ospf6_lsa_premature_aging () sets age to MAXAGE; when using
294 relative time, we cannot compare against lsa birth time, so
295 we catch this special case here. */
296 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
297 return OSPF_LSA_MAXAGE
;
300 ulage
= now
.tv_sec
- lsa
->birth
.tv_sec
;
302 /* if over MAXAGE, set to it */
303 age
= (ulage
> OSPF_LSA_MAXAGE
? OSPF_LSA_MAXAGE
: ulage
);
305 lsa
->header
->age
= htons(age
);
309 /* update age field of LSA header with adding InfTransDelay */
310 void ospf6_lsa_age_update_to_send(struct ospf6_lsa
*lsa
, uint32_t transdelay
)
314 age
= ospf6_lsa_age_current(lsa
) + transdelay
;
315 if (age
> OSPF_LSA_MAXAGE
)
316 age
= OSPF_LSA_MAXAGE
;
317 lsa
->header
->age
= htons(age
);
320 void ospf6_lsa_premature_aging(struct ospf6_lsa
*lsa
)
323 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
))
324 zlog_debug("LSA: Premature aging: %s", lsa
->name
);
326 THREAD_OFF(lsa
->expire
);
327 THREAD_OFF(lsa
->refresh
);
330 * We clear the LSA from the neighbor retx lists now because it
331 * will not get deleted later. Essentially, changing the age to
332 * MaxAge will prevent this LSA from being matched with its
333 * existing entries in the retx list thereby causing those entries
334 * to be silently replaced with its MaxAged version, but with ever
335 * increasing retx count causing this LSA to remain forever and
336 * for the MaxAge remover thread to be called forever too.
338 * The reason the previous entry silently disappears is that when
339 * entry is added to a neighbor's retx list, it replaces the existing
340 * entry. But since the ospf6_lsdb_add() routine is generic and not
342 * of the special semantics of retx count, the retx count is not
343 * decremented when its replaced. Attempting to add the incr and decr
344 * retx count routines as the hook_add and hook_remove for the retx
346 * have a problem because the hook_remove routine is called for MaxAge
347 * entries (as will be the case in a traditional LSDB, unlike in this
349 * where an LSDB is used as an efficient tree structure to store all
351 * of data) that are added instead of calling the hook_add routine.
354 ospf6_flood_clear(lsa
);
356 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
357 thread_execute(master
, ospf6_lsa_expire
, lsa
, 0);
360 /* check which is more recent. if a is more recent, return -1;
361 if the same, return 0; otherwise(b is more recent), return 1 */
362 int ospf6_lsa_compare(struct ospf6_lsa
*a
, struct ospf6_lsa
*b
)
364 int32_t seqnuma
, seqnumb
;
365 uint16_t cksuma
, cksumb
;
368 assert(a
&& a
->header
);
369 assert(b
&& b
->header
);
370 assert(OSPF6_LSA_IS_SAME(a
, b
));
372 seqnuma
= (int32_t)ntohl(a
->header
->seqnum
);
373 seqnumb
= (int32_t)ntohl(b
->header
->seqnum
);
375 /* compare by sequence number */
376 if (seqnuma
> seqnumb
)
378 if (seqnuma
< seqnumb
)
382 cksuma
= ntohs(a
->header
->checksum
);
383 cksumb
= ntohs(b
->header
->checksum
);
390 agea
= ospf6_lsa_age_current(a
);
391 ageb
= ospf6_lsa_age_current(b
);
394 if (agea
== OSPF_LSA_MAXAGE
&& ageb
!= OSPF_LSA_MAXAGE
)
396 else if (agea
!= OSPF_LSA_MAXAGE
&& ageb
== OSPF_LSA_MAXAGE
)
400 if (agea
> ageb
&& agea
- ageb
>= OSPF_LSA_MAXAGE_DIFF
)
402 else if (agea
< ageb
&& ageb
- agea
>= OSPF_LSA_MAXAGE_DIFF
)
409 char *ospf6_lsa_printbuf(struct ospf6_lsa
*lsa
, char *buf
, int size
)
411 char id
[16], adv_router
[16];
412 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
413 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
415 snprintf(buf
, size
, "[%s Id:%s Adv:%s]",
416 ospf6_lstype_name(lsa
->header
->type
), id
, adv_router
);
420 void ospf6_lsa_header_print_raw(struct ospf6_lsa_header
*header
)
422 char id
[16], adv_router
[16];
423 inet_ntop(AF_INET
, &header
->id
, id
, sizeof(id
));
424 inet_ntop(AF_INET
, &header
->adv_router
, adv_router
, sizeof(adv_router
));
425 zlog_debug(" [%s Id:%s Adv:%s]", ospf6_lstype_name(header
->type
), id
,
427 zlog_debug(" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
428 ntohs(header
->age
), (unsigned long)ntohl(header
->seqnum
),
429 ntohs(header
->checksum
), ntohs(header
->length
));
432 void ospf6_lsa_header_print(struct ospf6_lsa
*lsa
)
434 ospf6_lsa_age_current(lsa
);
435 ospf6_lsa_header_print_raw(lsa
->header
);
438 void ospf6_lsa_show_summary_header(struct vty
*vty
)
440 vty_out(vty
, "%-4s %-15s%-15s%4s %8s %30s\n", "Type", "LSId",
441 "AdvRouter", "Age", "SeqNum", "Payload");
444 void ospf6_lsa_show_summary(struct vty
*vty
, struct ospf6_lsa
*lsa
,
445 json_object
*json_array
, bool use_json
)
447 char adv_router
[16], id
[16];
449 const struct ospf6_lsa_handler
*handler
;
452 json_object
*json_obj
= NULL
;
457 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
458 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
461 type
= ntohs(lsa
->header
->type
);
462 handler
= ospf6_get_lsa_handler(lsa
->header
->type
);
465 json_obj
= json_object_new_object();
468 case OSPF6_LSTYPE_INTER_PREFIX
:
469 case OSPF6_LSTYPE_INTER_ROUTER
:
470 case OSPF6_LSTYPE_AS_EXTERNAL
:
471 case OSPF6_LSTYPE_TYPE_7
:
473 json_object_string_add(
475 ospf6_lstype_short_name(lsa
->header
->type
));
476 json_object_string_add(json_obj
, "lsId", id
);
477 json_object_string_add(json_obj
, "advRouter",
479 json_object_int_add(json_obj
, "age",
480 ospf6_lsa_age_current(lsa
));
483 (unsigned long)ntohl(lsa
->header
->seqnum
));
484 json_object_string_add(
486 handler
->lh_get_prefix_str(lsa
, buf
,
488 json_object_array_add(json_array
, json_obj
);
490 vty_out(vty
, "%-4s %-15s%-15s%4hu %8lx %30s\n",
491 ospf6_lstype_short_name(lsa
->header
->type
), id
,
492 adv_router
, ospf6_lsa_age_current(lsa
),
493 (unsigned long)ntohl(lsa
->header
->seqnum
),
494 handler
->lh_get_prefix_str(lsa
, buf
,
497 case OSPF6_LSTYPE_ROUTER
:
498 case OSPF6_LSTYPE_NETWORK
:
499 case OSPF6_LSTYPE_GROUP_MEMBERSHIP
:
500 case OSPF6_LSTYPE_LINK
:
501 case OSPF6_LSTYPE_INTRA_PREFIX
:
502 while (handler
->lh_get_prefix_str(lsa
, buf
, sizeof(buf
), cnt
)
505 json_object_string_add(
507 ospf6_lstype_short_name(
509 json_object_string_add(json_obj
, "lsId", id
);
510 json_object_string_add(json_obj
, "advRouter",
512 json_object_int_add(json_obj
, "age",
513 ospf6_lsa_age_current(lsa
));
516 (unsigned long)ntohl(
517 lsa
->header
->seqnum
));
518 json_object_string_add(json_obj
, "payload",
520 json_object_array_add(json_array
, json_obj
);
521 json_obj
= json_object_new_object();
523 vty_out(vty
, "%-4s %-15s%-15s%4hu %8lx %30s\n",
524 ospf6_lstype_short_name(
527 ospf6_lsa_age_current(lsa
),
528 (unsigned long)ntohl(
529 lsa
->header
->seqnum
),
534 json_object_free(json_obj
);
538 json_object_string_add(
540 ospf6_lstype_short_name(lsa
->header
->type
));
541 json_object_string_add(json_obj
, "lsId", id
);
542 json_object_string_add(json_obj
, "advRouter",
544 json_object_int_add(json_obj
, "age",
545 ospf6_lsa_age_current(lsa
));
548 (unsigned long)ntohl(lsa
->header
->seqnum
));
549 json_object_array_add(json_array
, json_obj
);
551 vty_out(vty
, "%-4s %-15s%-15s%4hu %8lx\n",
552 ospf6_lstype_short_name(lsa
->header
->type
), id
,
553 adv_router
, ospf6_lsa_age_current(lsa
),
554 (unsigned long)ntohl(lsa
->header
->seqnum
));
559 void ospf6_lsa_show_dump(struct vty
*vty
, struct ospf6_lsa
*lsa
,
560 json_object
*json_array
, bool use_json
)
562 uint8_t *start
= NULL
;
564 uint8_t *current
= NULL
;
566 char *header_str
= NULL
;
567 char adv_router
[INET6_ADDRSTRLEN
];
568 char id
[INET6_ADDRSTRLEN
];
569 json_object
*json
= NULL
;
571 start
= (uint8_t *)lsa
->header
;
572 end
= (uint8_t *)lsa
->header
+ ntohs(lsa
->header
->length
);
575 json
= json_object_new_object();
576 size_t header_str_sz
= (2 * (end
- start
)) + 1;
578 header_str
= XMALLOC(MTYPE_TMP
, header_str_sz
);
580 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
581 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
584 frrstr_hex(header_str
, header_str_sz
, start
, end
- start
);
586 json_object_string_add(json
, "linkStateId", id
);
587 json_object_string_add(json
, "advertisingRouter", adv_router
);
588 json_object_string_add(json
, "header", header_str
);
589 json_object_array_add(json_array
, json
);
591 XFREE(MTYPE_TMP
, header_str
);
593 vty_out(vty
, "\n%s:\n", lsa
->name
);
595 for (current
= start
; current
< end
; current
++) {
596 if ((current
- start
) % 16 == 0)
598 else if ((current
- start
) % 4 == 0)
601 snprintf(byte
, sizeof(byte
), "%02x", *current
);
602 vty_out(vty
, "%s", byte
);
605 vty_out(vty
, "\n\n");
611 void ospf6_lsa_show_internal(struct vty
*vty
, struct ospf6_lsa
*lsa
,
612 json_object
*json_array
, bool use_json
)
614 char adv_router
[64], id
[64];
615 json_object
*json_obj
;
617 assert(lsa
&& lsa
->header
);
619 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
620 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
624 json_obj
= json_object_new_object();
625 json_object_int_add(json_obj
, "age",
626 ospf6_lsa_age_current(lsa
));
627 json_object_string_add(json_obj
, "type",
628 ospf6_lstype_name(lsa
->header
->type
));
629 json_object_string_add(json_obj
, "linkStateId", id
);
630 json_object_string_add(json_obj
, "advertisingRouter",
632 json_object_int_add(json_obj
, "lsSequenceNumber",
633 (unsigned long)ntohl(lsa
->header
->seqnum
));
634 json_object_int_add(json_obj
, "checksum",
635 ntohs(lsa
->header
->checksum
));
636 json_object_int_add(json_obj
, "length",
637 ntohs(lsa
->header
->length
));
638 json_object_int_add(json_obj
, "flag", lsa
->flag
);
639 json_object_int_add(json_obj
, "lock", lsa
->lock
);
640 json_object_int_add(json_obj
, "reTxCount", lsa
->retrans_count
);
642 /* Threads Data not added */
643 json_object_array_add(json_array
, json_obj
);
646 vty_out(vty
, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa
),
647 ospf6_lstype_name(lsa
->header
->type
));
648 vty_out(vty
, "Link State ID: %s\n", id
);
649 vty_out(vty
, "Advertising Router: %s\n", adv_router
);
650 vty_out(vty
, "LS Sequence Number: %#010lx\n",
651 (unsigned long)ntohl(lsa
->header
->seqnum
));
652 vty_out(vty
, "CheckSum: %#06hx Length: %hu\n",
653 ntohs(lsa
->header
->checksum
),
654 ntohs(lsa
->header
->length
));
655 vty_out(vty
, "Flag: %x \n", lsa
->flag
);
656 vty_out(vty
, "Lock: %d \n", lsa
->lock
);
657 vty_out(vty
, "ReTx Count: %d\n", lsa
->retrans_count
);
658 vty_out(vty
, "Threads: Expire: %p, Refresh: %p\n", lsa
->expire
,
665 void ospf6_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
,
666 json_object
*json_array
, bool use_json
)
668 char adv_router
[64], id
[64];
669 const struct ospf6_lsa_handler
*handler
;
670 struct timeval now
, res
;
672 json_object
*json_obj
= NULL
;
674 assert(lsa
&& lsa
->header
);
676 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
677 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
681 timersub(&now
, &lsa
->installed
, &res
);
682 timerstring(&res
, duration
, sizeof(duration
));
684 json_obj
= json_object_new_object();
685 json_object_int_add(json_obj
, "age",
686 ospf6_lsa_age_current(lsa
));
687 json_object_string_add(json_obj
, "type",
688 ospf6_lstype_name(lsa
->header
->type
));
689 json_object_string_add(json_obj
, "linkStateId", id
);
690 json_object_string_add(json_obj
, "advertisingRouter",
692 json_object_int_add(json_obj
, "lsSequenceNumber",
693 (unsigned long)ntohl(lsa
->header
->seqnum
));
694 json_object_int_add(json_obj
, "checksum",
695 ntohs(lsa
->header
->checksum
));
696 json_object_int_add(json_obj
, "length",
697 ntohs(lsa
->header
->length
));
698 json_object_string_add(json_obj
, "duration", duration
);
700 vty_out(vty
, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa
),
701 ospf6_lstype_name(lsa
->header
->type
));
702 vty_out(vty
, "Link State ID: %s\n", id
);
703 vty_out(vty
, "Advertising Router: %s\n", adv_router
);
704 vty_out(vty
, "LS Sequence Number: %#010lx\n",
705 (unsigned long)ntohl(lsa
->header
->seqnum
));
706 vty_out(vty
, "CheckSum: %#06hx Length: %hu\n",
707 ntohs(lsa
->header
->checksum
),
708 ntohs(lsa
->header
->length
));
709 vty_out(vty
, "Duration: %s\n", duration
);
712 handler
= ospf6_get_lsa_handler(lsa
->header
->type
);
714 if (handler
->lh_show
!= NULL
)
715 handler
->lh_show(vty
, lsa
, json_obj
, use_json
);
717 assert(unknown_handler
.lh_show
!= NULL
);
718 unknown_handler
.lh_show(vty
, lsa
, json_obj
, use_json
);
722 json_object_array_add(json_array
, json_obj
);
727 struct ospf6_lsa
*ospf6_lsa_alloc(size_t lsa_length
)
729 struct ospf6_lsa
*lsa
;
731 lsa
= XCALLOC(MTYPE_OSPF6_LSA
, sizeof(struct ospf6_lsa
));
732 lsa
->header
= XMALLOC(MTYPE_OSPF6_LSA_HEADER
, lsa_length
);
737 /* OSPFv3 LSA creation/deletion function */
738 struct ospf6_lsa
*ospf6_lsa_create(struct ospf6_lsa_header
*header
)
740 struct ospf6_lsa
*lsa
= NULL
;
741 uint16_t lsa_size
= 0;
743 /* size of the entire LSA */
744 lsa_size
= ntohs(header
->length
); /* XXX vulnerable */
746 lsa
= ospf6_lsa_alloc(lsa_size
);
748 /* copy LSA from original header */
749 memcpy(lsa
->header
, header
, lsa_size
);
752 ospf6_lsa_printbuf(lsa
, lsa
->name
, sizeof(lsa
->name
));
754 /* calculate birth of this lsa */
755 ospf6_lsa_age_set(lsa
);
760 struct ospf6_lsa
*ospf6_lsa_create_headeronly(struct ospf6_lsa_header
*header
)
762 struct ospf6_lsa
*lsa
= NULL
;
764 lsa
= ospf6_lsa_alloc(sizeof(struct ospf6_lsa_header
));
766 memcpy(lsa
->header
, header
, sizeof(struct ospf6_lsa_header
));
768 SET_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
);
771 ospf6_lsa_printbuf(lsa
, lsa
->name
, sizeof(lsa
->name
));
773 /* calculate birth of this lsa */
774 ospf6_lsa_age_set(lsa
);
779 void ospf6_lsa_delete(struct ospf6_lsa
*lsa
)
781 assert(lsa
->lock
== 0);
784 THREAD_OFF(lsa
->expire
);
785 THREAD_OFF(lsa
->refresh
);
788 XFREE(MTYPE_OSPF6_LSA_HEADER
, lsa
->header
);
789 XFREE(MTYPE_OSPF6_LSA
, lsa
);
792 struct ospf6_lsa
*ospf6_lsa_copy(struct ospf6_lsa
*lsa
)
794 struct ospf6_lsa
*copy
= NULL
;
796 ospf6_lsa_age_current(lsa
);
797 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
))
798 copy
= ospf6_lsa_create_headeronly(lsa
->header
);
800 copy
= ospf6_lsa_create(lsa
->header
);
801 assert(copy
->lock
== 0);
803 copy
->birth
= lsa
->birth
;
804 copy
->originated
= lsa
->originated
;
805 copy
->received
= lsa
->received
;
806 copy
->installed
= lsa
->installed
;
807 copy
->lsdb
= lsa
->lsdb
;
813 /* increment reference counter of struct ospf6_lsa */
814 struct ospf6_lsa
*ospf6_lsa_lock(struct ospf6_lsa
*lsa
)
820 /* decrement reference counter of struct ospf6_lsa */
821 struct ospf6_lsa
*ospf6_lsa_unlock(struct ospf6_lsa
*lsa
)
823 /* decrement reference counter */
824 assert(lsa
->lock
> 0);
830 ospf6_lsa_delete(lsa
);
835 /* ospf6 lsa expiry */
836 void ospf6_lsa_expire(struct thread
*thread
)
838 struct ospf6_lsa
*lsa
;
841 lsa
= (struct ospf6_lsa
*)THREAD_ARG(thread
);
843 assert(lsa
&& lsa
->header
);
844 assert(OSPF6_LSA_IS_MAXAGE(lsa
));
845 assert(!lsa
->refresh
);
847 lsa
->expire
= (struct thread
*)NULL
;
849 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
)) {
850 zlog_debug("LSA Expire:");
851 ospf6_lsa_header_print(lsa
);
854 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
))
855 return; /* dbexchange will do something ... */
856 ospf6
= ospf6_get_by_lsdb(lsa
);
860 ospf6_install_lsa(lsa
);
863 ospf6_flood(NULL
, lsa
);
865 /* schedule maxage remover */
866 ospf6_maxage_remove(ospf6
);
869 void ospf6_lsa_refresh(struct thread
*thread
)
871 struct ospf6_lsa
*old
, *self
, *new;
872 struct ospf6_lsdb
*lsdb_self
;
874 old
= (struct ospf6_lsa
*)THREAD_ARG(thread
);
875 assert(old
&& old
->header
);
877 old
->refresh
= (struct thread
*)NULL
;
879 lsdb_self
= ospf6_get_scoped_lsdb_self(old
);
880 self
= ospf6_lsdb_lookup(old
->header
->type
, old
->header
->id
,
881 old
->header
->adv_router
, lsdb_self
);
883 if (IS_OSPF6_DEBUG_LSA_TYPE(old
->header
->type
))
884 zlog_debug("Refresh: could not find self LSA, flush %s",
886 ospf6_lsa_premature_aging(old
);
890 /* Reset age, increment LS sequence number. */
891 self
->header
->age
= htons(0);
892 self
->header
->seqnum
=
893 ospf6_new_ls_seqnum(self
->header
->type
, self
->header
->id
,
894 self
->header
->adv_router
, old
->lsdb
);
895 ospf6_lsa_checksum(self
->header
);
897 new = ospf6_lsa_create(self
->header
);
898 new->lsdb
= old
->lsdb
;
899 thread_add_timer(master
, ospf6_lsa_refresh
, new, OSPF_LS_REFRESH_TIME
,
902 /* store it in the LSDB for self-originated LSAs */
903 ospf6_lsdb_add(ospf6_lsa_copy(new), lsdb_self
);
905 if (IS_OSPF6_DEBUG_LSA_TYPE(new->header
->type
)) {
906 zlog_debug("LSA Refresh:");
907 ospf6_lsa_header_print(new);
910 ospf6_install_lsa(new);
911 ospf6_flood(NULL
, new);
914 void ospf6_flush_self_originated_lsas_now(struct ospf6
*ospf6
)
916 struct listnode
*node
, *nnode
;
917 struct ospf6_area
*oa
;
918 struct ospf6_lsa
*lsa
;
919 const struct route_node
*end
= NULL
;
920 uint32_t type
, adv_router
;
921 struct ospf6_interface
*oi
;
923 ospf6
->inst_shutdown
= 1;
925 for (ALL_LIST_ELEMENTS_RO(ospf6
->area_list
, node
, oa
)) {
926 end
= ospf6_lsdb_head(oa
->lsdb_self
, 0, 0, ospf6
->router_id
,
929 /* RFC 2328 (14.1): Set MAXAGE */
930 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
931 /* Flood MAXAGE LSA*/
932 ospf6_flood(NULL
, lsa
);
934 lsa
= ospf6_lsdb_next(end
, lsa
);
937 for (ALL_LIST_ELEMENTS(oa
->if_list
, node
, nnode
, oi
)) {
938 end
= ospf6_lsdb_head(oi
->lsdb_self
, 0, 0,
939 ospf6
->router_id
, &lsa
);
941 /* RFC 2328 (14.1): Set MAXAGE */
942 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
943 /* Flood MAXAGE LSA*/
944 ospf6_flood(NULL
, lsa
);
946 lsa
= ospf6_lsdb_next(end
, lsa
);
951 type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
952 adv_router
= ospf6
->router_id
;
953 for (ALL_LSDB_TYPED_ADVRTR(ospf6
->lsdb
, type
, adv_router
, lsa
)) {
954 /* RFC 2328 (14.1): Set MAXAGE */
955 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
956 ospf6_flood(NULL
, lsa
);
960 /* Fletcher Checksum -- Refer to RFC1008. */
962 /* All the offsets are zero-based. The offsets in the RFC1008 are
964 unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header
*lsa_header
)
966 uint8_t *buffer
= (uint8_t *)&lsa_header
->type
;
968 buffer
- (uint8_t *)&lsa_header
->age
; /* should be 2 */
970 /* Skip the AGE field */
971 uint16_t len
= ntohs(lsa_header
->length
) - type_offset
;
973 /* Checksum offset starts from "type" field, not the beginning of the
974 lsa_header struct. The offset is 14, rather than 16. */
975 int checksum_offset
= (uint8_t *)&lsa_header
->checksum
- buffer
;
977 return (unsigned short)fletcher_checksum(buffer
, len
, checksum_offset
);
980 int ospf6_lsa_checksum_valid(struct ospf6_lsa_header
*lsa_header
)
982 uint8_t *buffer
= (uint8_t *)&lsa_header
->type
;
984 buffer
- (uint8_t *)&lsa_header
->age
; /* should be 2 */
986 /* Skip the AGE field */
987 uint16_t len
= ntohs(lsa_header
->length
) - type_offset
;
989 return (fletcher_checksum(buffer
, len
, FLETCHER_CHECKSUM_VALIDATE
)
993 void ospf6_lsa_init(void)
995 ospf6_install_lsa_handler(&unknown_handler
);
998 void ospf6_lsa_terminate(void)
1002 static char *ospf6_lsa_handler_name(const struct ospf6_lsa_handler
*h
)
1004 static char buf
[64];
1006 unsigned int size
= strlen(h
->lh_name
);
1008 if (!strcmp(h
->lh_name
, "unknown")
1009 && h
->lh_type
!= OSPF6_LSTYPE_UNKNOWN
) {
1010 snprintf(buf
, sizeof(buf
), "%#04hx", h
->lh_type
);
1014 for (i
= 0; i
< MIN(size
, sizeof(buf
)); i
++) {
1015 if (!islower((unsigned char)h
->lh_name
[i
]))
1016 buf
[i
] = tolower((unsigned char)h
->lh_name
[i
]);
1018 buf
[i
] = h
->lh_name
[i
];
1024 void ospf6_lsa_debug_set_all(bool val
)
1027 struct ospf6_lsa_handler
*handler
= NULL
;
1029 for (i
= 0; i
< array_size(lsa_handlers
); i
++) {
1030 handler
= lsa_handlers
[i
];
1031 if (handler
== NULL
)
1034 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_ALL
);
1036 UNSET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_ALL
);
1040 DEFPY (debug_ospf6_lsa_all
,
1041 debug_ospf6_lsa_all_cmd
,
1042 "[no$no] debug ospf6 lsa all",
1046 "Debug Link State Advertisements (LSAs)\n"
1047 "Display for all types of LSAs\n")
1049 ospf6_lsa_debug_set_all(!no
);
1053 DEFPY (debug_ospf6_lsa_aggregation
,
1054 debug_ospf6_lsa_aggregation_cmd
,
1055 "[no] debug ospf6 lsa aggregation",
1059 "Debug Link State Advertisements (LSAs)\n"
1060 "External LSA Aggregation\n")
1063 struct ospf6_lsa_handler
*handler
;
1065 handler
= ospf6_get_lsa_handler(OSPF6_LSTYPE_AS_EXTERNAL
);
1066 if (handler
== NULL
)
1067 return CMD_WARNING_CONFIG_FAILED
;
1070 UNSET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_AGGR
);
1072 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_AGGR
);
1077 DEFUN (debug_ospf6_lsa_type
,
1078 debug_ospf6_lsa_hex_cmd
,
1079 "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]",
1082 "Debug Link State Advertisements (LSAs)\n"
1083 "Display Router LSAs\n"
1084 "Display Network LSAs\n"
1085 "Display Inter-Area-Prefix LSAs\n"
1086 "Display Inter-Router LSAs\n"
1087 "Display As-External LSAs\n"
1088 "Display NSSA LSAs\n"
1089 "Display Link LSAs\n"
1090 "Display Intra-Area-Prefix LSAs\n"
1091 "Display LSAs of unknown origin\n"
1092 "Display details of LSAs\n"
1094 "Display LSA's internal information\n")
1099 struct ospf6_lsa_handler
*handler
= NULL
;
1101 for (i
= 0; i
< array_size(lsa_handlers
); i
++) {
1102 handler
= lsa_handlers
[i
];
1103 if (handler
== NULL
)
1105 if (strncmp(argv
[idx_lsa
]->arg
, ospf6_lsa_handler_name(handler
),
1106 strlen(argv
[idx_lsa
]->arg
))
1109 if (!strcasecmp(argv
[idx_lsa
]->arg
, handler
->lh_name
))
1114 if (handler
== NULL
)
1115 handler
= &unknown_handler
;
1118 if (strmatch(argv
[idx_type
]->text
, "originate"))
1119 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_ORIGINATE
);
1120 else if (strmatch(argv
[idx_type
]->text
, "examine"))
1121 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_EXAMIN
);
1122 else if (strmatch(argv
[idx_type
]->text
, "flooding"))
1123 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_FLOOD
);
1125 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG
);
1130 DEFUN (no_debug_ospf6_lsa_type
,
1131 no_debug_ospf6_lsa_hex_cmd
,
1132 "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|nssa|link|intra-prefix|unknown> [<originate|examine|flooding>]",
1136 "Debug Link State Advertisements (LSAs)\n"
1137 "Display Router LSAs\n"
1138 "Display Network LSAs\n"
1139 "Display Inter-Area-Prefix LSAs\n"
1140 "Display Inter-Router LSAs\n"
1141 "Display As-External LSAs\n"
1142 "Display NSSA LSAs\n"
1143 "Display Link LSAs\n"
1144 "Display Intra-Area-Prefix LSAs\n"
1145 "Display LSAs of unknown origin\n"
1146 "Display details of LSAs\n"
1148 "Display LSA's internal information\n")
1153 struct ospf6_lsa_handler
*handler
= NULL
;
1155 for (i
= 0; i
< array_size(lsa_handlers
); i
++) {
1156 handler
= lsa_handlers
[i
];
1157 if (handler
== NULL
)
1159 if (strncmp(argv
[idx_lsa
]->arg
, ospf6_lsa_handler_name(handler
),
1160 strlen(argv
[idx_lsa
]->arg
))
1163 if (!strcasecmp(argv
[idx_lsa
]->arg
, handler
->lh_name
))
1167 if (handler
== NULL
)
1171 if (strmatch(argv
[idx_type
]->text
, "originate"))
1172 UNSET_FLAG(handler
->lh_debug
,
1173 OSPF6_LSA_DEBUG_ORIGINATE
);
1174 if (strmatch(argv
[idx_type
]->text
, "examine"))
1175 UNSET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_EXAMIN
);
1176 if (strmatch(argv
[idx_type
]->text
, "flooding"))
1177 UNSET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_FLOOD
);
1179 UNSET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG
);
1184 void install_element_ospf6_debug_lsa(void)
1186 install_element(ENABLE_NODE
, &debug_ospf6_lsa_all_cmd
);
1187 install_element(CONFIG_NODE
, &debug_ospf6_lsa_all_cmd
);
1188 install_element(ENABLE_NODE
, &debug_ospf6_lsa_hex_cmd
);
1189 install_element(ENABLE_NODE
, &no_debug_ospf6_lsa_hex_cmd
);
1190 install_element(CONFIG_NODE
, &debug_ospf6_lsa_hex_cmd
);
1191 install_element(CONFIG_NODE
, &no_debug_ospf6_lsa_hex_cmd
);
1193 install_element(ENABLE_NODE
, &debug_ospf6_lsa_aggregation_cmd
);
1194 install_element(CONFIG_NODE
, &debug_ospf6_lsa_aggregation_cmd
);
1197 int config_write_ospf6_debug_lsa(struct vty
*vty
)
1200 const struct ospf6_lsa_handler
*handler
;
1201 bool debug_all
= true;
1203 for (i
= 0; i
< array_size(lsa_handlers
); i
++) {
1204 handler
= lsa_handlers
[i
];
1205 if (handler
== NULL
)
1207 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_ALL
)
1208 < OSPF6_LSA_DEBUG_ALL
) {
1215 vty_out(vty
, "debug ospf6 lsa all\n");
1219 for (i
= 0; i
< array_size(lsa_handlers
); i
++) {
1220 handler
= lsa_handlers
[i
];
1221 if (handler
== NULL
)
1223 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG
))
1224 vty_out(vty
, "debug ospf6 lsa %s\n",
1225 ospf6_lsa_handler_name(handler
));
1226 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_ORIGINATE
))
1227 vty_out(vty
, "debug ospf6 lsa %s originate\n",
1228 ospf6_lsa_handler_name(handler
));
1229 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_EXAMIN
))
1230 vty_out(vty
, "debug ospf6 lsa %s examine\n",
1231 ospf6_lsa_handler_name(handler
));
1232 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_FLOOD
))
1233 vty_out(vty
, "debug ospf6 lsa %s flooding\n",
1234 ospf6_lsa_handler_name(handler
));
1235 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_AGGR
))
1236 vty_out(vty
, "debug ospf6 lsa aggregation\n");