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 uint8_t *start
, *end
, *current
;
53 start
= (uint8_t *)lsa
->header
+ sizeof(struct ospf6_lsa_header
);
54 end
= (uint8_t *)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(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 struct ospf6_lsa_handler
*ospf6_get_lsa_handler(uint16_t type
)
89 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(uint16_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(uint16_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 uint8_t ospf6_lstype_debug(uint16_t type
)
131 const struct ospf6_lsa_handler
*handler
;
132 handler
= ospf6_get_lsa_handler(type
);
133 return handler
->lh_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 uint16_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
, uint32_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 uint16_t cksuma
, cksumb
;
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
), (unsigned 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 (unsigned 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 (unsigned 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 (unsigned long)ntohl(lsa
->header
->seqnum
));
418 void ospf6_lsa_show_dump(struct vty
*vty
, struct ospf6_lsa
*lsa
)
420 uint8_t *start
, *end
, *current
;
423 start
= (uint8_t *)lsa
->header
;
424 end
= (uint8_t *)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 (unsigned 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 (unsigned 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 uint16_t lsa_size
= 0;
517 /* size of the entire LSA */
518 lsa_size
= ntohs(header
->length
); /* XXX vulnerable */
520 /* allocate memory for this LSA */
521 new_header
= XMALLOC(MTYPE_OSPF6_LSA_HEADER
, lsa_size
);
523 /* copy LSA from original header */
524 memcpy(new_header
, header
, lsa_size
);
526 /* LSA information structure */
527 /* allocate memory */
528 lsa
= XCALLOC(MTYPE_OSPF6_LSA
, sizeof(struct ospf6_lsa
));
530 lsa
->header
= new_header
;
533 ospf6_lsa_printbuf(lsa
, lsa
->name
, sizeof(lsa
->name
));
535 /* calculate birth of this lsa */
536 ospf6_lsa_age_set(lsa
);
541 struct ospf6_lsa
*ospf6_lsa_create_headeronly(struct ospf6_lsa_header
*header
)
543 struct ospf6_lsa
*lsa
= NULL
;
544 struct ospf6_lsa_header
*new_header
= NULL
;
546 /* allocate memory for this LSA */
547 new_header
= XMALLOC(MTYPE_OSPF6_LSA_HEADER
,
548 sizeof(struct ospf6_lsa_header
));
550 /* copy LSA from original header */
551 memcpy(new_header
, header
, sizeof(struct ospf6_lsa_header
));
553 /* LSA information structure */
554 /* allocate memory */
555 lsa
= XCALLOC(MTYPE_OSPF6_LSA
, sizeof(struct ospf6_lsa
));
557 lsa
->header
= new_header
;
558 SET_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
);
561 ospf6_lsa_printbuf(lsa
, lsa
->name
, sizeof(lsa
->name
));
563 /* calculate birth of this lsa */
564 ospf6_lsa_age_set(lsa
);
569 void ospf6_lsa_delete(struct ospf6_lsa
*lsa
)
571 assert(lsa
->lock
== 0);
574 THREAD_OFF(lsa
->expire
);
575 THREAD_OFF(lsa
->refresh
);
578 XFREE(MTYPE_OSPF6_LSA_HEADER
, lsa
->header
);
579 XFREE(MTYPE_OSPF6_LSA
, lsa
);
582 struct ospf6_lsa
*ospf6_lsa_copy(struct ospf6_lsa
*lsa
)
584 struct ospf6_lsa
*copy
= NULL
;
586 ospf6_lsa_age_current(lsa
);
587 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
))
588 copy
= ospf6_lsa_create_headeronly(lsa
->header
);
590 copy
= ospf6_lsa_create(lsa
->header
);
591 assert(copy
->lock
== 0);
593 copy
->birth
= lsa
->birth
;
594 copy
->originated
= lsa
->originated
;
595 copy
->received
= lsa
->received
;
596 copy
->installed
= lsa
->installed
;
597 copy
->lsdb
= lsa
->lsdb
;
603 /* increment reference counter of struct ospf6_lsa */
604 void ospf6_lsa_lock(struct ospf6_lsa
*lsa
)
610 /* decrement reference counter of struct ospf6_lsa */
611 void ospf6_lsa_unlock(struct ospf6_lsa
*lsa
)
613 /* decrement reference counter */
614 assert(lsa
->lock
> 0);
620 ospf6_lsa_delete(lsa
);
624 /* ospf6 lsa expiry */
625 int ospf6_lsa_expire(struct thread
*thread
)
627 struct ospf6_lsa
*lsa
;
629 lsa
= (struct ospf6_lsa
*)THREAD_ARG(thread
);
631 assert(lsa
&& lsa
->header
);
632 assert(OSPF6_LSA_IS_MAXAGE(lsa
));
633 assert(!lsa
->refresh
);
635 lsa
->expire
= (struct thread
*)NULL
;
637 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
)) {
638 zlog_debug("LSA Expire:");
639 ospf6_lsa_header_print(lsa
);
642 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
))
643 return 0; /* dbexchange will do something ... */
646 ospf6_install_lsa(lsa
);
649 ospf6_flood(NULL
, lsa
);
651 /* schedule maxage remover */
652 ospf6_maxage_remove(ospf6
);
657 int ospf6_lsa_refresh(struct thread
*thread
)
659 struct ospf6_lsa
*old
, *self
, *new;
660 struct ospf6_lsdb
*lsdb_self
;
662 old
= (struct ospf6_lsa
*)THREAD_ARG(thread
);
663 assert(old
&& old
->header
);
665 old
->refresh
= (struct thread
*)NULL
;
667 lsdb_self
= ospf6_get_scoped_lsdb_self(old
);
668 self
= ospf6_lsdb_lookup(old
->header
->type
, old
->header
->id
,
669 old
->header
->adv_router
, lsdb_self
);
671 if (IS_OSPF6_DEBUG_LSA_TYPE(old
->header
->type
))
672 zlog_debug("Refresh: could not find self LSA, flush %s",
674 ospf6_lsa_premature_aging(old
);
678 /* Reset age, increment LS sequence number. */
679 self
->header
->age
= htons(0);
680 self
->header
->seqnum
=
681 ospf6_new_ls_seqnum(self
->header
->type
, self
->header
->id
,
682 self
->header
->adv_router
, old
->lsdb
);
683 ospf6_lsa_checksum(self
->header
);
685 new = ospf6_lsa_create(self
->header
);
686 new->lsdb
= old
->lsdb
;
688 thread_add_timer(master
, ospf6_lsa_refresh
, new, OSPF_LS_REFRESH_TIME
,
691 /* store it in the LSDB for self-originated LSAs */
692 ospf6_lsdb_add(ospf6_lsa_copy(new), lsdb_self
);
694 if (IS_OSPF6_DEBUG_LSA_TYPE(new->header
->type
)) {
695 zlog_debug("LSA Refresh:");
696 ospf6_lsa_header_print(new);
699 ospf6_install_lsa(new);
700 ospf6_flood(NULL
, new);
705 void ospf6_flush_self_originated_lsas_now(void)
707 struct listnode
*node
;
708 struct ospf6_area
*oa
;
709 struct ospf6_lsa
*lsa
;
710 const struct route_node
*end
= NULL
;
711 uint32_t type
, adv_router
;
713 ospf6
->inst_shutdown
= 1;
715 for (ALL_LIST_ELEMENTS_RO(ospf6
->area_list
, node
, oa
)) {
716 end
= ospf6_lsdb_head(oa
->lsdb_self
, 0, 0, ospf6
->router_id
,
719 /* RFC 2328 (14.1): Set MAXAGE */
720 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
721 /* Flood MAXAGE LSA*/
722 ospf6_flood(NULL
, lsa
);
724 lsa
= ospf6_lsdb_next(end
, lsa
);
728 type
= htons(OSPF6_LSTYPE_AS_EXTERNAL
);
729 adv_router
= ospf6
->router_id
;
730 for (ALL_LSDB_TYPED_ADVRTR(ospf6
->lsdb
, type
, adv_router
, lsa
)) {
731 /* RFC 2328 (14.1): Set MAXAGE */
732 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
733 ospf6_flood(NULL
, lsa
);
737 /* Fletcher Checksum -- Refer to RFC1008. */
739 /* All the offsets are zero-based. The offsets in the RFC1008 are
741 unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header
*lsa_header
)
743 uint8_t *buffer
= (uint8_t *)&lsa_header
->type
;
745 buffer
- (uint8_t *)&lsa_header
->age
; /* should be 2 */
747 /* Skip the AGE field */
748 uint16_t len
= ntohs(lsa_header
->length
) - type_offset
;
750 /* Checksum offset starts from "type" field, not the beginning of the
751 lsa_header struct. The offset is 14, rather than 16. */
752 int checksum_offset
= (uint8_t *)&lsa_header
->checksum
- buffer
;
754 return (unsigned short)fletcher_checksum(buffer
, len
, checksum_offset
);
757 int ospf6_lsa_checksum_valid(struct ospf6_lsa_header
*lsa_header
)
759 uint8_t *buffer
= (uint8_t *)&lsa_header
->type
;
761 buffer
- (uint8_t *)&lsa_header
->age
; /* should be 2 */
763 /* Skip the AGE field */
764 uint16_t len
= ntohs(lsa_header
->length
) - type_offset
;
766 return (fletcher_checksum(buffer
, len
, FLETCHER_CHECKSUM_VALIDATE
)
770 void ospf6_lsa_init(void)
772 ospf6_lsa_handler_vector
= vector_init(0);
773 ospf6_install_lsa_handler(&unknown_handler
);
776 void ospf6_lsa_terminate(void)
778 vector_free(ospf6_lsa_handler_vector
);
781 static char *ospf6_lsa_handler_name(const struct ospf6_lsa_handler
*h
)
785 unsigned int size
= strlen(h
->lh_name
);
787 if (!strcmp(h
->lh_name
, "unknown")
788 && h
->lh_type
!= OSPF6_LSTYPE_UNKNOWN
) {
789 snprintf(buf
, sizeof(buf
), "%#04hx", h
->lh_type
);
793 for (i
= 0; i
< MIN(size
, sizeof(buf
)); i
++) {
794 if (!islower((unsigned char)h
->lh_name
[i
]))
795 buf
[i
] = tolower((unsigned char)h
->lh_name
[i
]);
797 buf
[i
] = h
->lh_name
[i
];
803 DEFUN (debug_ospf6_lsa_type
,
804 debug_ospf6_lsa_hex_cmd
,
805 "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
808 "Debug Link State Advertisements (LSAs)\n"
809 "Display Router LSAs\n"
810 "Display Network LSAs\n"
811 "Display Inter-Area-Prefix LSAs\n"
812 "Display Inter-Router LSAs\n"
813 "Display As-External LSAs\n"
814 "Display Link LSAs\n"
815 "Display Intra-Area-Prefix LSAs\n"
816 "Display LSAs of unknown origin\n"
817 "Display details of LSAs\n"
819 "Display LSA's internal information\n")
824 struct ospf6_lsa_handler
*handler
= NULL
;
826 for (i
= 0; i
< vector_active(ospf6_lsa_handler_vector
); i
++) {
827 handler
= vector_slot(ospf6_lsa_handler_vector
, i
);
830 if (strncmp(argv
[idx_lsa
]->arg
, ospf6_lsa_handler_name(handler
),
831 strlen(argv
[idx_lsa
]->arg
))
834 if (!strcasecmp(argv
[idx_lsa
]->arg
, handler
->lh_name
))
840 handler
= &unknown_handler
;
843 if (strmatch(argv
[idx_type
]->text
, "originate"))
844 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_ORIGINATE
);
845 else if (strmatch(argv
[idx_type
]->text
, "examine"))
846 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_EXAMIN
);
847 else if (strmatch(argv
[idx_type
]->text
, "flooding"))
848 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_FLOOD
);
850 SET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG
);
855 DEFUN (no_debug_ospf6_lsa_type
,
856 no_debug_ospf6_lsa_hex_cmd
,
857 "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
861 "Debug Link State Advertisements (LSAs)\n"
862 "Display Router LSAs\n"
863 "Display Network LSAs\n"
864 "Display Inter-Area-Prefix LSAs\n"
865 "Display Inter-Router LSAs\n"
866 "Display As-External LSAs\n"
867 "Display Link LSAs\n"
868 "Display Intra-Area-Prefix LSAs\n"
869 "Display LSAs of unknown origin\n"
870 "Display details of LSAs\n"
872 "Display LSA's internal information\n")
877 struct ospf6_lsa_handler
*handler
= NULL
;
879 for (i
= 0; i
< vector_active(ospf6_lsa_handler_vector
); i
++) {
880 handler
= vector_slot(ospf6_lsa_handler_vector
, i
);
883 if (strncmp(argv
[idx_lsa
]->arg
, ospf6_lsa_handler_name(handler
),
884 strlen(argv
[idx_lsa
]->arg
))
887 if (!strcasecmp(argv
[idx_lsa
]->arg
, handler
->lh_name
))
895 if (strmatch(argv
[idx_type
]->text
, "originate"))
896 UNSET_FLAG(handler
->lh_debug
,
897 OSPF6_LSA_DEBUG_ORIGINATE
);
898 if (strmatch(argv
[idx_type
]->text
, "examine"))
899 UNSET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_EXAMIN
);
900 if (strmatch(argv
[idx_type
]->text
, "flooding"))
901 UNSET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_FLOOD
);
903 UNSET_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG
);
908 void install_element_ospf6_debug_lsa(void)
910 install_element(ENABLE_NODE
, &debug_ospf6_lsa_hex_cmd
);
911 install_element(ENABLE_NODE
, &no_debug_ospf6_lsa_hex_cmd
);
912 install_element(CONFIG_NODE
, &debug_ospf6_lsa_hex_cmd
);
913 install_element(CONFIG_NODE
, &no_debug_ospf6_lsa_hex_cmd
);
916 int config_write_ospf6_debug_lsa(struct vty
*vty
)
919 const struct ospf6_lsa_handler
*handler
;
921 for (i
= 0; i
< vector_active(ospf6_lsa_handler_vector
); i
++) {
922 handler
= vector_slot(ospf6_lsa_handler_vector
, i
);
925 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG
))
926 vty_out(vty
, "debug ospf6 lsa %s\n",
927 ospf6_lsa_handler_name(handler
));
928 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_ORIGINATE
))
929 vty_out(vty
, "debug ospf6 lsa %s originate\n",
930 ospf6_lsa_handler_name(handler
));
931 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_EXAMIN
))
932 vty_out(vty
, "debug ospf6 lsa %s examine\n",
933 ospf6_lsa_handler_name(handler
));
934 if (CHECK_FLAG(handler
->lh_debug
, OSPF6_LSA_DEBUG_FLOOD
))
935 vty_out(vty
, "debug ospf6 lsa %s flooding\n",
936 ospf6_lsa_handler_name(handler
));