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"
38 #include "ospf6_top.h"
39 #include "ospf6_area.h"
40 #include "ospf6_interface.h"
41 #include "ospf6_neighbor.h"
43 #include "ospf6_flood.h"
46 vector ospf6_lsa_handler_vector
;
48 static int ospf6_unknown_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
)
50 u_char
*start
, *end
, *current
;
53 start
= (u_char
*)lsa
->header
+ sizeof(struct ospf6_lsa_header
);
54 end
= (u_char
*)lsa
->header
+ ntohs(lsa
->header
->length
);
56 vty_out(vty
, " Unknown contents:\n");
57 for (current
= start
; current
< end
; current
++) {
58 if ((current
- start
) % 16 == 0)
60 else if ((current
- start
) % 4 == 0)
63 snprintf(byte
, sizeof(byte
), "%02x", *current
);
64 vty_out(vty
, "%s", byte
);
71 static struct ospf6_lsa_handler unknown_handler
= {
72 .lh_type
= OSPF6_LSTYPE_UNKNOWN
,
74 .lh_short_name
= "Unk",
75 .lh_show
= ospf6_unknown_lsa_show
,
76 .lh_get_prefix_str
= NULL
,
77 .lh_debug
= 0 /* No default debug */
80 void ospf6_install_lsa_handler(const struct ospf6_lsa_handler
*handler
)
82 /* type in handler is host byte order */
83 int index
= handler
->lh_type
& OSPF6_LSTYPE_FCODE_MASK
;
84 vector_set_index(ospf6_lsa_handler_vector
, index
, (void *)handler
);
87 const struct ospf6_lsa_handler
*ospf6_get_lsa_handler(u_int16_t type
)
89 const struct ospf6_lsa_handler
*handler
= NULL
;
90 unsigned int index
= ntohs(type
) & OSPF6_LSTYPE_FCODE_MASK
;
92 if (index
>= vector_active(ospf6_lsa_handler_vector
))
93 handler
= &unknown_handler
;
95 handler
= vector_slot(ospf6_lsa_handler_vector
, index
);
98 handler
= &unknown_handler
;
103 const char *ospf6_lstype_name(u_int16_t type
)
106 const struct ospf6_lsa_handler
*handler
;
108 handler
= ospf6_get_lsa_handler(type
);
109 if (handler
&& handler
!= &unknown_handler
)
110 return handler
->lh_name
;
112 snprintf(buf
, sizeof(buf
), "0x%04hx", ntohs(type
));
116 const char *ospf6_lstype_short_name(u_int16_t type
)
119 const struct ospf6_lsa_handler
*handler
;
121 handler
= ospf6_get_lsa_handler(type
);
122 if (handler
&& handler
!= &unknown_handler
)
123 return handler
->lh_short_name
;
125 snprintf(buf
, sizeof(buf
), "0x%04hx", ntohs(type
));
129 u_char
ospf6_lstype_debug(u_int16_t type
)
131 const struct ospf6_lsa_handler
*handler
;
132 handler
= ospf6_get_lsa_handler(type
);
133 return handler
->debug
;
136 /* RFC2328: Section 13.2 */
137 int ospf6_lsa_is_differ(struct ospf6_lsa
*lsa1
, struct ospf6_lsa
*lsa2
)
141 assert(OSPF6_LSA_IS_SAME(lsa1
, lsa2
));
143 /* XXX, Options ??? */
145 ospf6_lsa_age_current(lsa1
);
146 ospf6_lsa_age_current(lsa2
);
147 if (ntohs(lsa1
->header
->age
) == OSPF_LSA_MAXAGE
148 && ntohs(lsa2
->header
->age
) != OSPF_LSA_MAXAGE
)
150 if (ntohs(lsa1
->header
->age
) != OSPF_LSA_MAXAGE
151 && ntohs(lsa2
->header
->age
) == OSPF_LSA_MAXAGE
)
155 if (ntohs(lsa1
->header
->length
) != ntohs(lsa2
->header
->length
))
158 len
= ntohs(lsa1
->header
->length
) - sizeof(struct ospf6_lsa_header
);
159 return memcmp(lsa1
->header
+ 1, lsa2
->header
+ 1, len
);
162 int ospf6_lsa_is_changed(struct ospf6_lsa
*lsa1
, struct ospf6_lsa
*lsa2
)
166 if (OSPF6_LSA_IS_MAXAGE(lsa1
) ^ OSPF6_LSA_IS_MAXAGE(lsa2
))
168 if (ntohs(lsa1
->header
->length
) != ntohs(lsa2
->header
->length
))
170 /* Going beyond LSA headers to compare the payload only makes sense,
171 * when both LSAs aren't header-only. */
172 if (CHECK_FLAG(lsa1
->flag
, OSPF6_LSA_HEADERONLY
)
173 != CHECK_FLAG(lsa2
->flag
, OSPF6_LSA_HEADERONLY
)) {
175 "%s: only one of two (%s, %s) LSAs compared is header-only",
176 __func__
, lsa1
->name
, lsa2
->name
);
179 if (CHECK_FLAG(lsa1
->flag
, OSPF6_LSA_HEADERONLY
))
182 length
= OSPF6_LSA_SIZE(lsa1
->header
) - sizeof(struct ospf6_lsa_header
);
183 /* Once upper layer verifies LSAs received, length underrun should
184 * become a warning. */
188 return memcmp(OSPF6_LSA_HEADER_END(lsa1
->header
),
189 OSPF6_LSA_HEADER_END(lsa2
->header
), length
);
192 /* ospf6 age functions */
193 /* calculate birth */
194 void ospf6_lsa_age_set(struct ospf6_lsa
*lsa
)
198 assert(lsa
&& lsa
->header
);
202 lsa
->birth
.tv_sec
= now
.tv_sec
- ntohs(lsa
->header
->age
);
203 lsa
->birth
.tv_usec
= now
.tv_usec
;
208 /* this function calculates current age from its birth,
209 then update age field of LSA header. return value is current age */
210 u_int16_t
ospf6_lsa_age_current(struct ospf6_lsa
*lsa
)
222 if (ntohs(lsa
->header
->age
) >= OSPF_LSA_MAXAGE
) {
223 /* ospf6_lsa_premature_aging () sets age to MAXAGE; when using
224 relative time, we cannot compare against lsa birth time, so
225 we catch this special case here. */
226 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
227 return OSPF_LSA_MAXAGE
;
230 ulage
= now
.tv_sec
- lsa
->birth
.tv_sec
;
232 /* if over MAXAGE, set to it */
233 age
= (ulage
> OSPF_LSA_MAXAGE
? OSPF_LSA_MAXAGE
: ulage
);
235 lsa
->header
->age
= htons(age
);
239 /* update age field of LSA header with adding InfTransDelay */
240 void ospf6_lsa_age_update_to_send(struct ospf6_lsa
*lsa
, u_int32_t transdelay
)
244 age
= ospf6_lsa_age_current(lsa
) + transdelay
;
245 if (age
> OSPF_LSA_MAXAGE
)
246 age
= OSPF_LSA_MAXAGE
;
247 lsa
->header
->age
= htons(age
);
250 void ospf6_lsa_premature_aging(struct ospf6_lsa
*lsa
)
253 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
))
254 zlog_debug("LSA: Premature aging: %s", lsa
->name
);
256 THREAD_OFF(lsa
->expire
);
257 THREAD_OFF(lsa
->refresh
);
260 * We clear the LSA from the neighbor retx lists now because it
261 * will not get deleted later. Essentially, changing the age to
262 * MaxAge will prevent this LSA from being matched with its
263 * existing entries in the retx list thereby causing those entries
264 * to be silently replaced with its MaxAged version, but with ever
265 * increasing retx count causing this LSA to remain forever and
266 * for the MaxAge remover thread to be called forever too.
268 * The reason the previous entry silently disappears is that when
269 * entry is added to a neighbor's retx list, it replaces the existing
270 * entry. But since the ospf6_lsdb_add() routine is generic and not
272 * of the special semantics of retx count, the retx count is not
273 * decremented when its replaced. Attempting to add the incr and decr
274 * retx count routines as the hook_add and hook_remove for the retx
276 * have a problem because the hook_remove routine is called for MaxAge
277 * entries (as will be the case in a traditional LSDB, unlike in this
279 * where an LSDB is used as an efficient tree structure to store all
281 * of data) that are added instead of calling the hook_add routine.
284 ospf6_flood_clear(lsa
);
286 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
287 thread_execute(master
, ospf6_lsa_expire
, lsa
, 0);
290 /* check which is more recent. if a is more recent, return -1;
291 if the same, return 0; otherwise(b is more recent), return 1 */
292 int ospf6_lsa_compare(struct ospf6_lsa
*a
, struct ospf6_lsa
*b
)
294 int32_t seqnuma
, seqnumb
;
295 u_int16_t cksuma
, cksumb
;
296 u_int16_t agea
, ageb
;
298 assert(a
&& a
->header
);
299 assert(b
&& b
->header
);
300 assert(OSPF6_LSA_IS_SAME(a
, b
));
302 seqnuma
= (int32_t)ntohl(a
->header
->seqnum
);
303 seqnumb
= (int32_t)ntohl(b
->header
->seqnum
);
305 /* compare by sequence number */
306 if (seqnuma
> seqnumb
)
308 if (seqnuma
< seqnumb
)
312 cksuma
= ntohs(a
->header
->checksum
);
313 cksumb
= ntohs(b
->header
->checksum
);
320 agea
= ospf6_lsa_age_current(a
);
321 ageb
= ospf6_lsa_age_current(b
);
324 if (agea
== OSPF_LSA_MAXAGE
&& ageb
!= OSPF_LSA_MAXAGE
)
326 else if (agea
!= OSPF_LSA_MAXAGE
&& ageb
== OSPF_LSA_MAXAGE
)
330 if (agea
> ageb
&& agea
- ageb
>= OSPF_LSA_MAXAGE_DIFF
)
332 else if (agea
< ageb
&& ageb
- agea
>= OSPF_LSA_MAXAGE_DIFF
)
339 char *ospf6_lsa_printbuf(struct ospf6_lsa
*lsa
, char *buf
, int size
)
341 char id
[16], adv_router
[16];
342 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
343 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
345 snprintf(buf
, size
, "[%s Id:%s Adv:%s]",
346 ospf6_lstype_name(lsa
->header
->type
), id
, adv_router
);
350 void ospf6_lsa_header_print_raw(struct ospf6_lsa_header
*header
)
352 char id
[16], adv_router
[16];
353 inet_ntop(AF_INET
, &header
->id
, id
, sizeof(id
));
354 inet_ntop(AF_INET
, &header
->adv_router
, adv_router
, sizeof(adv_router
));
355 zlog_debug(" [%s Id:%s Adv:%s]", ospf6_lstype_name(header
->type
), id
,
357 zlog_debug(" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
358 ntohs(header
->age
), (u_long
)ntohl(header
->seqnum
),
359 ntohs(header
->checksum
), ntohs(header
->length
));
362 void ospf6_lsa_header_print(struct ospf6_lsa
*lsa
)
364 ospf6_lsa_age_current(lsa
);
365 ospf6_lsa_header_print_raw(lsa
->header
);
368 void ospf6_lsa_show_summary_header(struct vty
*vty
)
370 vty_out(vty
, "%-4s %-15s%-15s%4s %8s %30s\n", "Type", "LSId",
371 "AdvRouter", "Age", "SeqNum", "Payload");
374 void ospf6_lsa_show_summary(struct vty
*vty
, struct ospf6_lsa
*lsa
)
376 char adv_router
[16], id
[16];
378 const struct ospf6_lsa_handler
*handler
;
379 char buf
[64], tmpbuf
[80];
385 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
386 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
389 type
= ntohs(lsa
->header
->type
);
390 handler
= ospf6_get_lsa_handler(lsa
->header
->type
);
391 if ((type
== OSPF6_LSTYPE_INTER_PREFIX
)
392 || (type
== OSPF6_LSTYPE_INTER_ROUTER
)
393 || (type
== OSPF6_LSTYPE_AS_EXTERNAL
)) {
394 vty_out(vty
, "%-4s %-15s%-15s%4hu %8lx %30s\n",
395 ospf6_lstype_short_name(lsa
->header
->type
), id
,
396 adv_router
, ospf6_lsa_age_current(lsa
),
397 (u_long
)ntohl(lsa
->header
->seqnum
),
398 handler
->lh_get_prefix_str(lsa
, buf
, sizeof(buf
), 0));
399 } else if (type
!= OSPF6_LSTYPE_UNKNOWN
) {
400 sprintf(tmpbuf
, "%-4s %-15s%-15s%4hu %8lx",
401 ospf6_lstype_short_name(lsa
->header
->type
), id
,
402 adv_router
, ospf6_lsa_age_current(lsa
),
403 (u_long
)ntohl(lsa
->header
->seqnum
));
405 while (handler
->lh_get_prefix_str(lsa
, buf
, sizeof(buf
), cnt
)
407 vty_out(vty
, "%s %30s\n", tmpbuf
, buf
);
411 vty_out(vty
, "%-4s %-15s%-15s%4hu %8lx\n",
412 ospf6_lstype_short_name(lsa
->header
->type
), id
,
413 adv_router
, ospf6_lsa_age_current(lsa
),
414 (u_long
)ntohl(lsa
->header
->seqnum
));
418 void ospf6_lsa_show_dump(struct vty
*vty
, struct ospf6_lsa
*lsa
)
420 u_char
*start
, *end
, *current
;
423 start
= (u_char
*)lsa
->header
;
424 end
= (u_char
*)lsa
->header
+ ntohs(lsa
->header
->length
);
427 vty_out(vty
, "%s:\n", lsa
->name
);
429 for (current
= start
; current
< end
; current
++) {
430 if ((current
- start
) % 16 == 0)
432 else if ((current
- start
) % 4 == 0)
435 snprintf(byte
, sizeof(byte
), "%02x", *current
);
436 vty_out(vty
, "%s", byte
);
439 vty_out(vty
, "\n\n");
443 void ospf6_lsa_show_internal(struct vty
*vty
, struct ospf6_lsa
*lsa
)
445 char adv_router
[64], id
[64];
447 assert(lsa
&& lsa
->header
);
449 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
450 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
454 vty_out(vty
, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa
),
455 ospf6_lstype_name(lsa
->header
->type
));
456 vty_out(vty
, "Link State ID: %s\n", id
);
457 vty_out(vty
, "Advertising Router: %s\n", adv_router
);
458 vty_out(vty
, "LS Sequence Number: %#010lx\n",
459 (u_long
)ntohl(lsa
->header
->seqnum
));
460 vty_out(vty
, "CheckSum: %#06hx Length: %hu\n",
461 ntohs(lsa
->header
->checksum
), ntohs(lsa
->header
->length
));
462 vty_out(vty
, "Flag: %x \n", lsa
->flag
);
463 vty_out(vty
, "Lock: %d \n", lsa
->lock
);
464 vty_out(vty
, "ReTx Count: %d\n", lsa
->retrans_count
);
465 vty_out(vty
, "Threads: Expire: 0x%p, Refresh: 0x%p \n",
466 (void *)lsa
->expire
, (void *)lsa
->refresh
);
471 void ospf6_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
)
473 char adv_router
[64], id
[64];
474 const struct ospf6_lsa_handler
*handler
;
475 struct timeval now
, res
;
478 assert(lsa
&& lsa
->header
);
480 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
481 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
485 timersub(&now
, &lsa
->installed
, &res
);
486 timerstring(&res
, duration
, sizeof(duration
));
488 vty_out(vty
, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa
),
489 ospf6_lstype_name(lsa
->header
->type
));
490 vty_out(vty
, "Link State ID: %s\n", id
);
491 vty_out(vty
, "Advertising Router: %s\n", adv_router
);
492 vty_out(vty
, "LS Sequence Number: %#010lx\n",
493 (u_long
)ntohl(lsa
->header
->seqnum
));
494 vty_out(vty
, "CheckSum: %#06hx Length: %hu\n",
495 ntohs(lsa
->header
->checksum
), ntohs(lsa
->header
->length
));
496 vty_out(vty
, "Duration: %s\n", duration
);
498 handler
= ospf6_get_lsa_handler(lsa
->header
->type
);
500 if (handler
->lh_show
!= NULL
)
501 handler
->lh_show(vty
, lsa
);
503 assert(unknown_handler
.lh_show
!= NULL
);
504 unknown_handler
.lh_show(vty
, lsa
);
510 /* OSPFv3 LSA creation/deletion function */
511 struct ospf6_lsa
*ospf6_lsa_create(struct ospf6_lsa_header
*header
)
513 struct ospf6_lsa
*lsa
= NULL
;
514 struct ospf6_lsa_header
*new_header
= NULL
;
515 u_int16_t lsa_size
= 0;
517 /* size of the entire LSA */
518 lsa_size
= ntohs(header
->length
); /* XXX vulnerable */
520 /* allocate memory for this LSA */
522 (struct ospf6_lsa_header
*)XMALLOC(MTYPE_OSPF6_LSA_HEADER
,
525 /* copy LSA from original header */
526 memcpy(new_header
, header
, lsa_size
);
528 /* LSA information structure */
529 /* allocate memory */
530 lsa
= (struct ospf6_lsa
*)XCALLOC(MTYPE_OSPF6_LSA
,
531 sizeof(struct ospf6_lsa
));
533 lsa
->header
= (struct ospf6_lsa_header
*)new_header
;
536 ospf6_lsa_printbuf(lsa
, lsa
->name
, sizeof(lsa
->name
));
538 /* calculate birth of this lsa */
539 ospf6_lsa_age_set(lsa
);
544 struct ospf6_lsa
*ospf6_lsa_create_headeronly(struct ospf6_lsa_header
*header
)
546 struct ospf6_lsa
*lsa
= NULL
;
547 struct ospf6_lsa_header
*new_header
= NULL
;
549 /* allocate memory for this LSA */
550 new_header
= (struct ospf6_lsa_header
*)XMALLOC(
551 MTYPE_OSPF6_LSA_HEADER
, sizeof(struct ospf6_lsa_header
));
553 /* copy LSA from original header */
554 memcpy(new_header
, header
, sizeof(struct ospf6_lsa_header
));
556 /* LSA information structure */
557 /* allocate memory */
558 lsa
= (struct ospf6_lsa
*)XCALLOC(MTYPE_OSPF6_LSA
,
559 sizeof(struct ospf6_lsa
));
561 lsa
->header
= (struct ospf6_lsa_header
*)new_header
;
562 SET_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
);
565 ospf6_lsa_printbuf(lsa
, lsa
->name
, sizeof(lsa
->name
));
567 /* calculate birth of this lsa */
568 ospf6_lsa_age_set(lsa
);
573 void ospf6_lsa_delete(struct ospf6_lsa
*lsa
)
575 assert(lsa
->lock
== 0);
578 THREAD_OFF(lsa
->expire
);
579 THREAD_OFF(lsa
->refresh
);
582 XFREE(MTYPE_OSPF6_LSA_HEADER
, lsa
->header
);
583 XFREE(MTYPE_OSPF6_LSA
, lsa
);
586 struct ospf6_lsa
*ospf6_lsa_copy(struct ospf6_lsa
*lsa
)
588 struct ospf6_lsa
*copy
= NULL
;
590 ospf6_lsa_age_current(lsa
);
591 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
))
592 copy
= ospf6_lsa_create_headeronly(lsa
->header
);
594 copy
= ospf6_lsa_create(lsa
->header
);
595 assert(copy
->lock
== 0);
597 copy
->birth
= lsa
->birth
;
598 copy
->originated
= lsa
->originated
;
599 copy
->received
= lsa
->received
;
600 copy
->installed
= lsa
->installed
;
601 copy
->lsdb
= lsa
->lsdb
;
607 /* increment reference counter of struct ospf6_lsa */
608 void ospf6_lsa_lock(struct ospf6_lsa
*lsa
)
614 /* decrement reference counter of struct ospf6_lsa */
615 void ospf6_lsa_unlock(struct ospf6_lsa
*lsa
)
617 /* decrement reference counter */
618 assert(lsa
->lock
> 0);
624 ospf6_lsa_delete(lsa
);
628 /* ospf6 lsa expiry */
629 int ospf6_lsa_expire(struct thread
*thread
)
631 struct ospf6_lsa
*lsa
;
633 lsa
= (struct ospf6_lsa
*)THREAD_ARG(thread
);
635 assert(lsa
&& lsa
->header
);
636 assert(OSPF6_LSA_IS_MAXAGE(lsa
));
637 assert(!lsa
->refresh
);
639 lsa
->expire
= (struct thread
*)NULL
;
641 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
)) {
642 zlog_debug("LSA Expire:");
643 ospf6_lsa_header_print(lsa
);
646 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
))
647 return 0; /* dbexchange will do something ... */
650 ospf6_install_lsa(lsa
);
653 ospf6_flood(NULL
, lsa
);
655 /* schedule maxage remover */
656 ospf6_maxage_remove(ospf6
);
661 int ospf6_lsa_refresh(struct thread
*thread
)
663 struct ospf6_lsa
*old
, *self
, *new;
664 struct ospf6_lsdb
*lsdb_self
;
666 old
= (struct ospf6_lsa
*)THREAD_ARG(thread
);
667 assert(old
&& old
->header
);
669 old
->refresh
= (struct thread
*)NULL
;
671 lsdb_self
= ospf6_get_scoped_lsdb_self(old
);
672 self
= ospf6_lsdb_lookup(old
->header
->type
, old
->header
->id
,
673 old
->header
->adv_router
, lsdb_self
);
675 if (IS_OSPF6_DEBUG_LSA_TYPE(old
->header
->type
))
676 zlog_debug("Refresh: could not find self LSA, flush %s",
678 ospf6_lsa_premature_aging(old
);
682 /* Reset age, increment LS sequence number. */
683 self
->header
->age
= htons(0);
684 self
->header
->seqnum
=
685 ospf6_new_ls_seqnum(self
->header
->type
, self
->header
->id
,
686 self
->header
->adv_router
, old
->lsdb
);
687 ospf6_lsa_checksum(self
->header
);
689 new = ospf6_lsa_create(self
->header
);
690 new->lsdb
= old
->lsdb
;
692 thread_add_timer(master
, ospf6_lsa_refresh
, new, OSPF_LS_REFRESH_TIME
,
695 /* store it in the LSDB for self-originated LSAs */
696 ospf6_lsdb_add(ospf6_lsa_copy(new), lsdb_self
);
698 if (IS_OSPF6_DEBUG_LSA_TYPE(new->header
->type
)) {
699 zlog_debug("LSA Refresh:");
700 ospf6_lsa_header_print(new);
703 ospf6_install_lsa(new);
704 ospf6_flood(NULL
, new);
710 /* Fletcher Checksum -- Refer to RFC1008. */
712 /* All the offsets are zero-based. The offsets in the RFC1008 are
714 unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header
*lsa_header
)
716 u_char
*buffer
= (u_char
*)&lsa_header
->type
;
717 int type_offset
= buffer
- (u_char
*)&lsa_header
->age
; /* should be 2 */
719 /* Skip the AGE field */
720 u_int16_t len
= ntohs(lsa_header
->length
) - type_offset
;
722 /* Checksum offset starts from "type" field, not the beginning of the
723 lsa_header struct. The offset is 14, rather than 16. */
724 int checksum_offset
= (u_char
*)&lsa_header
->checksum
- buffer
;
726 return (unsigned short)fletcher_checksum(buffer
, len
, checksum_offset
);
729 int ospf6_lsa_checksum_valid(struct ospf6_lsa_header
*lsa_header
)
731 u_char
*buffer
= (u_char
*)&lsa_header
->type
;
732 int type_offset
= buffer
- (u_char
*)&lsa_header
->age
; /* should be 2 */
734 /* Skip the AGE field */
735 u_int16_t len
= ntohs(lsa_header
->length
) - type_offset
;
737 return (fletcher_checksum(buffer
, len
, FLETCHER_CHECKSUM_VALIDATE
)
741 void ospf6_lsa_init(void)
743 ospf6_lsa_handler_vector
= vector_init(0);
744 ospf6_install_lsa_handler(&unknown_handler
);
747 void ospf6_lsa_terminate(void)
749 vector_free(ospf6_lsa_handler_vector
);
752 static char *ospf6_lsa_handler_name(const struct ospf6_lsa_handler
*h
)
756 unsigned int size
= strlen(h
->lh_name
);
758 if (!strcmp(h
->lh_name
, "unknown") && h
->lh_type
!= OSPF6_LSTYPE_UNKNOWN
) {
759 snprintf(buf
, sizeof(buf
), "%#04hx", h
->lh_type
);
763 for (i
= 0; i
< MIN(size
, sizeof(buf
)); i
++) {
764 if (!islower((unsigned char)h
->lh_name
[i
]))
765 buf
[i
] = tolower((unsigned char)h
->lh_name
[i
]);
767 buf
[i
] = h
->lh_name
[i
];
773 DEFUN (debug_ospf6_lsa_type
,
774 debug_ospf6_lsa_hex_cmd
,
775 "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
778 "Debug Link State Advertisements (LSAs)\n"
779 "Display Router LSAs\n"
780 "Display Network LSAs\n"
781 "Display Inter-Area-Prefix LSAs\n"
782 "Display Inter-Router LSAs\n"
783 "Display As-External LSAs\n"
784 "Display Link LSAs\n"
785 "Display Intra-Area-Prefix LSAs\n"
786 "Display LSAs of unknown origin\n"
787 "Display details of LSAs\n"
789 "Display LSA's internal information\n")
794 struct ospf6_lsa_handler
*handler
= NULL
;
796 for (i
= 0; i
< vector_active(ospf6_lsa_handler_vector
); i
++) {
797 handler
= vector_slot(ospf6_lsa_handler_vector
, i
);
800 if (strncmp(argv
[idx_lsa
]->arg
, ospf6_lsa_handler_name(handler
),
801 strlen(argv
[idx_lsa
]->arg
))
804 if (!strcasecmp(argv
[idx_lsa
]->arg
, handler
->lh_name
))
810 handler
= &unknown_handler
;
813 if (strmatch(argv
[idx_type
]->text
, "originate"))
814 SET_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_ORIGINATE
);
815 else if (strmatch(argv
[idx_type
]->text
, "examine"))
816 SET_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_EXAMIN
);
817 else if (strmatch(argv
[idx_type
]->text
, "flooding"))
818 SET_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_FLOOD
);
820 SET_FLAG(handler
->debug
, OSPF6_LSA_DEBUG
);
825 DEFUN (no_debug_ospf6_lsa_type
,
826 no_debug_ospf6_lsa_hex_cmd
,
827 "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
831 "Debug Link State Advertisements (LSAs)\n"
832 "Display Router LSAs\n"
833 "Display Network LSAs\n"
834 "Display Inter-Area-Prefix LSAs\n"
835 "Display Inter-Router LSAs\n"
836 "Display As-External LSAs\n"
837 "Display Link LSAs\n"
838 "Display Intra-Area-Prefix LSAs\n"
839 "Display LSAs of unknown origin\n"
840 "Display details of LSAs\n"
842 "Display LSA's internal information\n")
847 struct ospf6_lsa_handler
*handler
= NULL
;
849 for (i
= 0; i
< vector_active(ospf6_lsa_handler_vector
); i
++) {
850 handler
= vector_slot(ospf6_lsa_handler_vector
, i
);
853 if (strncmp(argv
[idx_lsa
]->arg
, ospf6_lsa_handler_name(handler
),
854 strlen(argv
[idx_lsa
]->arg
))
857 if (!strcasecmp(argv
[idx_lsa
]->arg
, handler
->lh_name
))
865 if (strmatch(argv
[idx_type
]->text
, "originate"))
866 UNSET_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_ORIGINATE
);
867 if (strmatch(argv
[idx_type
]->text
, "examine"))
868 UNSET_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_EXAMIN
);
869 if (strmatch(argv
[idx_type
]->text
, "flooding"))
870 UNSET_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_FLOOD
);
872 UNSET_FLAG(handler
->debug
, OSPF6_LSA_DEBUG
);
877 void install_element_ospf6_debug_lsa(void)
879 install_element(ENABLE_NODE
, &debug_ospf6_lsa_hex_cmd
);
880 install_element(ENABLE_NODE
, &no_debug_ospf6_lsa_hex_cmd
);
881 install_element(CONFIG_NODE
, &debug_ospf6_lsa_hex_cmd
);
882 install_element(CONFIG_NODE
, &no_debug_ospf6_lsa_hex_cmd
);
885 int config_write_ospf6_debug_lsa(struct vty
*vty
)
888 const struct ospf6_lsa_handler
*handler
;
890 for (i
= 0; i
< vector_active(ospf6_lsa_handler_vector
); i
++) {
891 handler
= vector_slot(ospf6_lsa_handler_vector
, i
);
894 if (CHECK_FLAG(handler
->debug
, OSPF6_LSA_DEBUG
))
895 vty_out(vty
, "debug ospf6 lsa %s\n",
896 ospf6_lsa_handler_name(handler
));
897 if (CHECK_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_ORIGINATE
))
898 vty_out(vty
, "debug ospf6 lsa %s originate\n",
899 ospf6_lsa_handler_name(handler
));
900 if (CHECK_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_EXAMIN
))
901 vty_out(vty
, "debug ospf6 lsa %s examine\n",
902 ospf6_lsa_handler_name(handler
));
903 if (CHECK_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_FLOOD
))
904 vty_out(vty
, "debug ospf6 lsa %s flooding\n",
905 ospf6_lsa_handler_name(handler
));