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
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
24 /* Include other stuffs */
34 #include "ospf6_proto.h"
35 #include "ospf6_lsa.h"
36 #include "ospf6_lsdb.h"
37 #include "ospf6_message.h"
39 #include "ospf6_top.h"
40 #include "ospf6_area.h"
41 #include "ospf6_interface.h"
42 #include "ospf6_neighbor.h"
44 #include "ospf6_flood.h"
47 vector ospf6_lsa_handler_vector
;
49 static int ospf6_unknown_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
)
51 u_char
*start
, *end
, *current
;
54 start
= (u_char
*)lsa
->header
+ sizeof(struct ospf6_lsa_header
);
55 end
= (u_char
*)lsa
->header
+ ntohs(lsa
->header
->length
);
57 vty_out(vty
, " Unknown contents:%s", VNL
);
58 for (current
= start
; current
< end
; current
++) {
59 if ((current
- start
) % 16 == 0)
60 vty_out(vty
, "%s ", VNL
);
61 else if ((current
- start
) % 4 == 0)
64 snprintf(byte
, sizeof(byte
), "%02x", *current
);
65 vty_out(vty
, "%s", byte
);
68 vty_out(vty
, "%s%s", VNL
, VNL
);
72 struct ospf6_lsa_handler unknown_handler
= {
73 OSPF6_LSTYPE_UNKNOWN
, "Unknown", "Unk", ospf6_unknown_lsa_show
, NULL
};
75 void ospf6_install_lsa_handler(struct ospf6_lsa_handler
*handler
)
77 /* type in handler is host byte order */
78 int index
= handler
->type
& OSPF6_LSTYPE_FCODE_MASK
;
79 vector_set_index(ospf6_lsa_handler_vector
, index
, handler
);
82 struct ospf6_lsa_handler
*ospf6_get_lsa_handler(u_int16_t type
)
84 struct ospf6_lsa_handler
*handler
= NULL
;
85 unsigned int index
= ntohs(type
) & OSPF6_LSTYPE_FCODE_MASK
;
87 if (index
>= vector_active(ospf6_lsa_handler_vector
))
88 handler
= &unknown_handler
;
90 handler
= vector_slot(ospf6_lsa_handler_vector
, index
);
93 handler
= &unknown_handler
;
98 const char *ospf6_lstype_name(u_int16_t type
)
101 struct ospf6_lsa_handler
*handler
;
103 handler
= ospf6_get_lsa_handler(type
);
104 if (handler
&& handler
!= &unknown_handler
)
105 return handler
->name
;
107 snprintf(buf
, sizeof(buf
), "0x%04hx", ntohs(type
));
111 const char *ospf6_lstype_short_name(u_int16_t type
)
114 struct ospf6_lsa_handler
*handler
;
116 handler
= ospf6_get_lsa_handler(type
);
117 if (handler
&& handler
!= &unknown_handler
)
118 return handler
->short_name
;
120 snprintf(buf
, sizeof(buf
), "0x%04hx", ntohs(type
));
124 u_char
ospf6_lstype_debug(u_int16_t type
)
126 struct ospf6_lsa_handler
*handler
;
127 handler
= ospf6_get_lsa_handler(type
);
128 return handler
->debug
;
131 /* RFC2328: Section 13.2 */
132 int ospf6_lsa_is_differ(struct ospf6_lsa
*lsa1
, struct ospf6_lsa
*lsa2
)
136 assert(OSPF6_LSA_IS_SAME(lsa1
, lsa2
));
138 /* XXX, Options ??? */
140 ospf6_lsa_age_current(lsa1
);
141 ospf6_lsa_age_current(lsa2
);
142 if (ntohs(lsa1
->header
->age
) == OSPF_LSA_MAXAGE
143 && ntohs(lsa2
->header
->age
) != OSPF_LSA_MAXAGE
)
145 if (ntohs(lsa1
->header
->age
) != OSPF_LSA_MAXAGE
146 && ntohs(lsa2
->header
->age
) == OSPF_LSA_MAXAGE
)
150 if (ntohs(lsa1
->header
->length
) != ntohs(lsa2
->header
->length
))
153 len
= ntohs(lsa1
->header
->length
) - sizeof(struct ospf6_lsa_header
);
154 return memcmp(lsa1
->header
+ 1, lsa2
->header
+ 1, len
);
157 int ospf6_lsa_is_changed(struct ospf6_lsa
*lsa1
, struct ospf6_lsa
*lsa2
)
161 if (OSPF6_LSA_IS_MAXAGE(lsa1
) ^ OSPF6_LSA_IS_MAXAGE(lsa2
))
163 if (ntohs(lsa1
->header
->length
) != ntohs(lsa2
->header
->length
))
165 /* Going beyond LSA headers to compare the payload only makes sense,
166 * when both LSAs aren't header-only. */
167 if (CHECK_FLAG(lsa1
->flag
, OSPF6_LSA_HEADERONLY
)
168 != CHECK_FLAG(lsa2
->flag
, OSPF6_LSA_HEADERONLY
)) {
170 "%s: only one of two (%s, %s) LSAs compared is header-only",
171 __func__
, lsa1
->name
, lsa2
->name
);
174 if (CHECK_FLAG(lsa1
->flag
, OSPF6_LSA_HEADERONLY
))
177 length
= OSPF6_LSA_SIZE(lsa1
->header
) - sizeof(struct ospf6_lsa_header
);
178 /* Once upper layer verifies LSAs received, length underrun should
179 * become a warning. */
183 return memcmp(OSPF6_LSA_HEADER_END(lsa1
->header
),
184 OSPF6_LSA_HEADER_END(lsa2
->header
), length
);
187 /* ospf6 age functions */
188 /* calculate birth */
189 static void ospf6_lsa_age_set(struct ospf6_lsa
*lsa
)
193 assert(lsa
&& lsa
->header
);
197 lsa
->birth
.tv_sec
= now
.tv_sec
- ntohs(lsa
->header
->age
);
198 lsa
->birth
.tv_usec
= now
.tv_usec
;
203 /* this function calculates current age from its birth,
204 then update age field of LSA header. return value is current age */
205 u_int16_t
ospf6_lsa_age_current(struct ospf6_lsa
*lsa
)
217 if (ntohs(lsa
->header
->age
) >= OSPF_LSA_MAXAGE
) {
218 /* ospf6_lsa_premature_aging () sets age to MAXAGE; when using
219 relative time, we cannot compare against lsa birth time, so
220 we catch this special case here. */
221 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
222 return OSPF_LSA_MAXAGE
;
225 ulage
= now
.tv_sec
- lsa
->birth
.tv_sec
;
227 /* if over MAXAGE, set to it */
228 age
= (ulage
> OSPF_LSA_MAXAGE
? OSPF_LSA_MAXAGE
: ulage
);
230 lsa
->header
->age
= htons(age
);
234 /* update age field of LSA header with adding InfTransDelay */
235 void ospf6_lsa_age_update_to_send(struct ospf6_lsa
*lsa
, u_int32_t transdelay
)
239 age
= ospf6_lsa_age_current(lsa
) + transdelay
;
240 if (age
> OSPF_LSA_MAXAGE
)
241 age
= OSPF_LSA_MAXAGE
;
242 lsa
->header
->age
= htons(age
);
245 void ospf6_lsa_premature_aging(struct ospf6_lsa
*lsa
)
248 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
))
249 zlog_debug("LSA: Premature aging: %s", lsa
->name
);
251 THREAD_OFF(lsa
->expire
);
252 THREAD_OFF(lsa
->refresh
);
255 * We clear the LSA from the neighbor retx lists now because it
256 * will not get deleted later. Essentially, changing the age to
257 * MaxAge will prevent this LSA from being matched with its
258 * existing entries in the retx list thereby causing those entries
259 * to be silently replaced with its MaxAged version, but with ever
260 * increasing retx count causing this LSA to remain forever and
261 * for the MaxAge remover thread to be called forever too.
263 * The reason the previous entry silently disappears is that when
264 * entry is added to a neighbor's retx list, it replaces the existing
265 * entry. But since the ospf6_lsdb_add() routine is generic and not
267 * of the special semantics of retx count, the retx count is not
268 * decremented when its replaced. Attempting to add the incr and decr
269 * retx count routines as the hook_add and hook_remove for the retx
271 * have a problem because the hook_remove routine is called for MaxAge
272 * entries (as will be the case in a traditional LSDB, unlike in this
274 * where an LSDB is used as an efficient tree structure to store all
276 * of data) that are added instead of calling the hook_add routine.
279 ospf6_flood_clear(lsa
);
281 lsa
->header
->age
= htons(OSPF_LSA_MAXAGE
);
282 thread_execute(master
, ospf6_lsa_expire
, lsa
, 0);
285 /* check which is more recent. if a is more recent, return -1;
286 if the same, return 0; otherwise(b is more recent), return 1 */
287 int ospf6_lsa_compare(struct ospf6_lsa
*a
, struct ospf6_lsa
*b
)
289 int32_t seqnuma
, seqnumb
;
290 u_int16_t cksuma
, cksumb
;
291 u_int16_t agea
, ageb
;
293 assert(a
&& a
->header
);
294 assert(b
&& b
->header
);
295 assert(OSPF6_LSA_IS_SAME(a
, b
));
297 seqnuma
= (int32_t)ntohl(a
->header
->seqnum
);
298 seqnumb
= (int32_t)ntohl(b
->header
->seqnum
);
300 /* compare by sequence number */
301 if (seqnuma
> seqnumb
)
303 if (seqnuma
< seqnumb
)
307 cksuma
= ntohs(a
->header
->checksum
);
308 cksumb
= ntohs(b
->header
->checksum
);
315 agea
= ospf6_lsa_age_current(a
);
316 ageb
= ospf6_lsa_age_current(b
);
319 if (agea
== OSPF_LSA_MAXAGE
&& ageb
!= OSPF_LSA_MAXAGE
)
321 else if (agea
!= OSPF_LSA_MAXAGE
&& ageb
== OSPF_LSA_MAXAGE
)
325 if (agea
> ageb
&& agea
- ageb
>= OSPF_LSA_MAXAGE_DIFF
)
327 else if (agea
< ageb
&& ageb
- agea
>= OSPF_LSA_MAXAGE_DIFF
)
334 char *ospf6_lsa_printbuf(struct ospf6_lsa
*lsa
, char *buf
, int size
)
336 char id
[16], adv_router
[16];
337 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
338 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
340 snprintf(buf
, size
, "[%s Id:%s Adv:%s]",
341 ospf6_lstype_name(lsa
->header
->type
), id
, adv_router
);
345 void ospf6_lsa_header_print_raw(struct ospf6_lsa_header
*header
)
347 char id
[16], adv_router
[16];
348 inet_ntop(AF_INET
, &header
->id
, id
, sizeof(id
));
349 inet_ntop(AF_INET
, &header
->adv_router
, adv_router
, sizeof(adv_router
));
350 zlog_debug(" [%s Id:%s Adv:%s]", ospf6_lstype_name(header
->type
), id
,
352 zlog_debug(" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
353 ntohs(header
->age
), (u_long
)ntohl(header
->seqnum
),
354 ntohs(header
->checksum
), ntohs(header
->length
));
357 void ospf6_lsa_header_print(struct ospf6_lsa
*lsa
)
359 ospf6_lsa_age_current(lsa
);
360 ospf6_lsa_header_print_raw(lsa
->header
);
363 void ospf6_lsa_show_summary_header(struct vty
*vty
)
365 vty_out(vty
, "%-4s %-15s%-15s%4s %8s %30s%s", "Type", "LSId",
366 "AdvRouter", "Age", "SeqNum", "Payload", VNL
);
369 void ospf6_lsa_show_summary(struct vty
*vty
, struct ospf6_lsa
*lsa
)
371 char adv_router
[16], id
[16];
373 struct ospf6_lsa_handler
*handler
;
374 char buf
[64], tmpbuf
[80];
380 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
381 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
384 type
= ntohs(lsa
->header
->type
);
385 handler
= ospf6_get_lsa_handler(lsa
->header
->type
);
386 if ((type
== OSPF6_LSTYPE_INTER_PREFIX
)
387 || (type
== OSPF6_LSTYPE_INTER_ROUTER
)
388 || (type
== OSPF6_LSTYPE_AS_EXTERNAL
)) {
389 vty_out(vty
, "%-4s %-15s%-15s%4hu %8lx %30s%s",
390 ospf6_lstype_short_name(lsa
->header
->type
), id
,
391 adv_router
, ospf6_lsa_age_current(lsa
),
392 (u_long
)ntohl(lsa
->header
->seqnum
),
393 handler
->get_prefix_str(lsa
, buf
, sizeof(buf
), 0), VNL
);
394 } else if (type
!= OSPF6_LSTYPE_UNKNOWN
) {
395 sprintf(tmpbuf
, "%-4s %-15s%-15s%4hu %8lx",
396 ospf6_lstype_short_name(lsa
->header
->type
), id
,
397 adv_router
, ospf6_lsa_age_current(lsa
),
398 (u_long
)ntohl(lsa
->header
->seqnum
));
400 while (handler
->get_prefix_str(lsa
, buf
, sizeof(buf
), cnt
)
402 vty_out(vty
, "%s %30s%s", tmpbuf
, buf
, VNL
);
406 vty_out(vty
, "%-4s %-15s%-15s%4hu %8lx%s",
407 ospf6_lstype_short_name(lsa
->header
->type
), id
,
408 adv_router
, ospf6_lsa_age_current(lsa
),
409 (u_long
)ntohl(lsa
->header
->seqnum
), VNL
);
413 void ospf6_lsa_show_dump(struct vty
*vty
, struct ospf6_lsa
*lsa
)
415 u_char
*start
, *end
, *current
;
418 start
= (u_char
*)lsa
->header
;
419 end
= (u_char
*)lsa
->header
+ ntohs(lsa
->header
->length
);
421 vty_out(vty
, "%s", VNL
);
422 vty_out(vty
, "%s:%s", lsa
->name
, VNL
);
424 for (current
= start
; current
< end
; current
++) {
425 if ((current
- start
) % 16 == 0)
426 vty_out(vty
, "%s ", VNL
);
427 else if ((current
- start
) % 4 == 0)
430 snprintf(byte
, sizeof(byte
), "%02x", *current
);
431 vty_out(vty
, "%s", byte
);
434 vty_out(vty
, "%s%s", VNL
, VNL
);
438 void ospf6_lsa_show_internal(struct vty
*vty
, struct ospf6_lsa
*lsa
)
440 char adv_router
[64], id
[64];
442 assert(lsa
&& lsa
->header
);
444 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
445 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
448 vty_out(vty
, "%s", VNL
);
449 vty_out(vty
, "Age: %4hu Type: %s%s", ospf6_lsa_age_current(lsa
),
450 ospf6_lstype_name(lsa
->header
->type
), VNL
);
451 vty_out(vty
, "Link State ID: %s%s", id
, VNL
);
452 vty_out(vty
, "Advertising Router: %s%s", adv_router
, VNL
);
453 vty_out(vty
, "LS Sequence Number: %#010lx%s",
454 (u_long
)ntohl(lsa
->header
->seqnum
), VNL
);
455 vty_out(vty
, "CheckSum: %#06hx Length: %hu%s",
456 ntohs(lsa
->header
->checksum
), ntohs(lsa
->header
->length
), VNL
);
457 vty_out(vty
, "Flag: %x %s", lsa
->flag
, VNL
);
458 vty_out(vty
, "Lock: %d %s", lsa
->lock
, VNL
);
459 vty_out(vty
, "ReTx Count: %d%s", lsa
->retrans_count
, VNL
);
460 vty_out(vty
, "Threads: Expire: 0x%p, Refresh: 0x%p %s",
461 (void *)lsa
->expire
, (void *)lsa
->refresh
, VNL
);
462 vty_out(vty
, "%s", VNL
);
466 void ospf6_lsa_show(struct vty
*vty
, struct ospf6_lsa
*lsa
)
468 char adv_router
[64], id
[64];
469 struct ospf6_lsa_handler
*handler
;
470 struct timeval now
, res
;
473 assert(lsa
&& lsa
->header
);
475 inet_ntop(AF_INET
, &lsa
->header
->id
, id
, sizeof(id
));
476 inet_ntop(AF_INET
, &lsa
->header
->adv_router
, adv_router
,
480 timersub(&now
, &lsa
->installed
, &res
);
481 timerstring(&res
, duration
, sizeof(duration
));
483 vty_out(vty
, "Age: %4hu Type: %s%s", ospf6_lsa_age_current(lsa
),
484 ospf6_lstype_name(lsa
->header
->type
), VNL
);
485 vty_out(vty
, "Link State ID: %s%s", id
, VNL
);
486 vty_out(vty
, "Advertising Router: %s%s", adv_router
, VNL
);
487 vty_out(vty
, "LS Sequence Number: %#010lx%s",
488 (u_long
)ntohl(lsa
->header
->seqnum
), VNL
);
489 vty_out(vty
, "CheckSum: %#06hx Length: %hu%s",
490 ntohs(lsa
->header
->checksum
), ntohs(lsa
->header
->length
), VNL
);
491 vty_out(vty
, "Duration: %s%s", duration
, VNL
);
493 handler
= ospf6_get_lsa_handler(lsa
->header
->type
);
494 if (handler
->show
== NULL
)
495 handler
= &unknown_handler
;
496 (*handler
->show
)(vty
, lsa
);
498 vty_out(vty
, "%s", VNL
);
501 /* OSPFv3 LSA creation/deletion function */
502 struct ospf6_lsa
*ospf6_lsa_create(struct ospf6_lsa_header
*header
)
504 struct ospf6_lsa
*lsa
= NULL
;
505 struct ospf6_lsa_header
*new_header
= NULL
;
506 u_int16_t lsa_size
= 0;
508 /* size of the entire LSA */
509 lsa_size
= ntohs(header
->length
); /* XXX vulnerable */
511 /* allocate memory for this LSA */
513 (struct ospf6_lsa_header
*)XMALLOC(MTYPE_OSPF6_LSA
, lsa_size
);
515 /* copy LSA from original header */
516 memcpy(new_header
, header
, lsa_size
);
518 /* LSA information structure */
519 /* allocate memory */
520 lsa
= (struct ospf6_lsa
*)XCALLOC(MTYPE_OSPF6_LSA
,
521 sizeof(struct ospf6_lsa
));
523 lsa
->header
= (struct ospf6_lsa_header
*)new_header
;
526 ospf6_lsa_printbuf(lsa
, lsa
->name
, sizeof(lsa
->name
));
528 /* calculate birth of this lsa */
529 ospf6_lsa_age_set(lsa
);
534 struct ospf6_lsa
*ospf6_lsa_create_headeronly(struct ospf6_lsa_header
*header
)
536 struct ospf6_lsa
*lsa
= NULL
;
537 struct ospf6_lsa_header
*new_header
= NULL
;
539 /* allocate memory for this LSA */
540 new_header
= (struct ospf6_lsa_header
*)XMALLOC(
541 MTYPE_OSPF6_LSA
, sizeof(struct ospf6_lsa_header
));
543 /* copy LSA from original header */
544 memcpy(new_header
, header
, sizeof(struct ospf6_lsa_header
));
546 /* LSA information structure */
547 /* allocate memory */
548 lsa
= (struct ospf6_lsa
*)XCALLOC(MTYPE_OSPF6_LSA
,
549 sizeof(struct ospf6_lsa
));
551 lsa
->header
= (struct ospf6_lsa_header
*)new_header
;
552 SET_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
);
555 ospf6_lsa_printbuf(lsa
, lsa
->name
, sizeof(lsa
->name
));
557 /* calculate birth of this lsa */
558 ospf6_lsa_age_set(lsa
);
563 void ospf6_lsa_delete(struct ospf6_lsa
*lsa
)
565 assert(lsa
->lock
== 0);
568 THREAD_OFF(lsa
->expire
);
569 THREAD_OFF(lsa
->refresh
);
572 XFREE(MTYPE_OSPF6_LSA
, lsa
->header
);
573 XFREE(MTYPE_OSPF6_LSA
, lsa
);
576 struct ospf6_lsa
*ospf6_lsa_copy(struct ospf6_lsa
*lsa
)
578 struct ospf6_lsa
*copy
= NULL
;
580 ospf6_lsa_age_current(lsa
);
581 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
))
582 copy
= ospf6_lsa_create_headeronly(lsa
->header
);
584 copy
= ospf6_lsa_create(lsa
->header
);
585 assert(copy
->lock
== 0);
587 copy
->birth
= lsa
->birth
;
588 copy
->originated
= lsa
->originated
;
589 copy
->received
= lsa
->received
;
590 copy
->installed
= lsa
->installed
;
591 copy
->lsdb
= lsa
->lsdb
;
597 /* increment reference counter of struct ospf6_lsa */
598 void ospf6_lsa_lock(struct ospf6_lsa
*lsa
)
604 /* decrement reference counter of struct ospf6_lsa */
605 void ospf6_lsa_unlock(struct ospf6_lsa
*lsa
)
607 /* decrement reference counter */
608 assert(lsa
->lock
> 0);
614 ospf6_lsa_delete(lsa
);
618 /* ospf6 lsa expiry */
619 int ospf6_lsa_expire(struct thread
*thread
)
621 struct ospf6_lsa
*lsa
;
623 lsa
= (struct ospf6_lsa
*)THREAD_ARG(thread
);
625 assert(lsa
&& lsa
->header
);
626 assert(OSPF6_LSA_IS_MAXAGE(lsa
));
627 assert(!lsa
->refresh
);
629 lsa
->expire
= (struct thread
*)NULL
;
631 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa
->header
->type
)) {
632 zlog_debug("LSA Expire:");
633 ospf6_lsa_header_print(lsa
);
636 if (CHECK_FLAG(lsa
->flag
, OSPF6_LSA_HEADERONLY
))
637 return 0; /* dbexchange will do something ... */
640 ospf6_install_lsa(lsa
);
643 ospf6_flood(NULL
, lsa
);
645 /* schedule maxage remover */
646 ospf6_maxage_remove(ospf6
);
651 int ospf6_lsa_refresh(struct thread
*thread
)
653 struct ospf6_lsa
*old
, *self
, *new;
654 struct ospf6_lsdb
*lsdb_self
;
657 old
= (struct ospf6_lsa
*)THREAD_ARG(thread
);
658 assert(old
&& old
->header
);
660 old
->refresh
= (struct thread
*)NULL
;
662 lsdb_self
= ospf6_get_scoped_lsdb_self(old
);
663 self
= ospf6_lsdb_lookup(old
->header
->type
, old
->header
->id
,
664 old
->header
->adv_router
, lsdb_self
);
666 if (IS_OSPF6_DEBUG_LSA_TYPE(old
->header
->type
))
667 zlog_debug("Refresh: could not find self LSA, flush %s",
669 ospf6_lsa_premature_aging(old
);
673 /* Reset age, increment LS sequence number. */
674 self
->header
->age
= htons(0);
675 self
->header
->seqnum
=
676 ospf6_new_ls_seqnum(self
->header
->type
, self
->header
->id
,
677 self
->header
->adv_router
, old
->lsdb
);
678 ospf6_lsa_checksum(self
->header
);
680 new = ospf6_lsa_create(self
->header
);
681 new->lsdb
= old
->lsdb
;
682 new->refresh
= thread_add_timer(master
, ospf6_lsa_refresh
, new,
683 OSPF_LS_REFRESH_TIME
);
685 /* store it in the LSDB for self-originated LSAs */
686 ospf6_lsdb_add(ospf6_lsa_copy(new), lsdb_self
);
688 if (IS_OSPF6_DEBUG_LSA_TYPE(new->header
->type
)) {
689 zlog_debug("LSA Refresh:");
690 ospf6_lsa_header_print(new);
693 ospf6_install_lsa(new);
694 ospf6_flood(NULL
, new);
700 /* Fletcher Checksum -- Refer to RFC1008. */
702 /* All the offsets are zero-based. The offsets in the RFC1008 are
704 unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header
*lsa_header
)
706 u_char
*buffer
= (u_char
*)&lsa_header
->type
;
707 int type_offset
= buffer
- (u_char
*)&lsa_header
->age
; /* should be 2 */
709 /* Skip the AGE field */
710 u_int16_t len
= ntohs(lsa_header
->length
) - type_offset
;
712 /* Checksum offset starts from "type" field, not the beginning of the
713 lsa_header struct. The offset is 14, rather than 16. */
714 int checksum_offset
= (u_char
*)&lsa_header
->checksum
- buffer
;
716 return (unsigned short)fletcher_checksum(buffer
, len
, checksum_offset
);
719 int ospf6_lsa_checksum_valid(struct ospf6_lsa_header
*lsa_header
)
721 u_char
*buffer
= (u_char
*)&lsa_header
->type
;
722 int type_offset
= buffer
- (u_char
*)&lsa_header
->age
; /* should be 2 */
724 /* Skip the AGE field */
725 u_int16_t len
= ntohs(lsa_header
->length
) - type_offset
;
727 return (fletcher_checksum(buffer
, len
, FLETCHER_CHECKSUM_VALIDATE
)
731 void ospf6_lsa_init(void)
733 ospf6_lsa_handler_vector
= vector_init(0);
734 ospf6_install_lsa_handler(&unknown_handler
);
737 void ospf6_lsa_terminate(void)
739 vector_free(ospf6_lsa_handler_vector
);
742 static char *ospf6_lsa_handler_name(struct ospf6_lsa_handler
*h
)
746 unsigned int size
= strlen(h
->name
);
748 if (!strcmp(h
->name
, "unknown") && h
->type
!= OSPF6_LSTYPE_UNKNOWN
) {
749 snprintf(buf
, sizeof(buf
), "%#04hx", h
->type
);
753 for (i
= 0; i
< MIN(size
, sizeof(buf
)); i
++) {
754 if (!islower((unsigned char)h
->name
[i
]))
755 buf
[i
] = tolower((unsigned char)h
->name
[i
]);
763 DEFUN (debug_ospf6_lsa_type
,
764 debug_ospf6_lsa_hex_cmd
,
765 "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
768 "Debug Link State Advertisements (LSAs)\n"
769 "Display Router LSAs\n"
770 "Display Network LSAs\n"
771 "Display Inter-Area-Prefix LSAs\n"
772 "Display Inter-Router LSAs\n"
773 "Display As-External LSAs\n"
774 "Display Link LSAs\n"
775 "Display Intra-Area-Prefix LSAs\n"
776 "Display LSAs of unknown origin\n"
777 "Display details of LSAs\n"
779 "Display LSA's internal information\n")
784 struct ospf6_lsa_handler
*handler
= NULL
;
786 for (i
= 0; i
< vector_active(ospf6_lsa_handler_vector
); i
++) {
787 handler
= vector_slot(ospf6_lsa_handler_vector
, i
);
790 if (strncmp(argv
[idx_lsa
]->arg
, ospf6_lsa_handler_name(handler
),
791 strlen(argv
[idx_lsa
]->arg
))
794 if (!strcasecmp(argv
[idx_lsa
]->arg
, handler
->name
))
800 handler
= &unknown_handler
;
803 if (!strcmp(argv
[idx_type
]->text
, "originate"))
804 SET_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_ORIGINATE
);
805 else if (!strcmp(argv
[idx_type
]->text
, "examine"))
806 SET_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_EXAMIN
);
807 else if (!strcmp(argv
[idx_type
]->text
, "flooding"))
808 SET_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_FLOOD
);
810 SET_FLAG(handler
->debug
, OSPF6_LSA_DEBUG
);
815 DEFUN (no_debug_ospf6_lsa_type
,
816 no_debug_ospf6_lsa_hex_cmd
,
817 "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
821 "Debug Link State Advertisements (LSAs)\n"
822 "Display Router LSAs\n"
823 "Display Network LSAs\n"
824 "Display Inter-Area-Prefix LSAs\n"
825 "Display Inter-Router LSAs\n"
826 "Display As-External LSAs\n"
827 "Display Link LSAs\n"
828 "Display Intra-Area-Prefix LSAs\n"
829 "Display LSAs of unknown origin\n"
830 "Display details of LSAs\n"
832 "Display LSA's internal information\n")
837 struct ospf6_lsa_handler
*handler
= NULL
;
839 for (i
= 0; i
< vector_active(ospf6_lsa_handler_vector
); i
++) {
840 handler
= vector_slot(ospf6_lsa_handler_vector
, i
);
843 if (strncmp(argv
[idx_lsa
]->arg
, ospf6_lsa_handler_name(handler
),
844 strlen(argv
[idx_lsa
]->arg
))
847 if (!strcasecmp(argv
[idx_lsa
]->arg
, handler
->name
))
855 if (!strcmp(argv
[idx_type
]->text
, "originate"))
856 UNSET_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_ORIGINATE
);
857 if (!strcmp(argv
[idx_type
]->text
, "examine"))
858 UNSET_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_EXAMIN
);
859 if (!strcmp(argv
[idx_type
]->text
, "flooding"))
860 UNSET_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_FLOOD
);
862 UNSET_FLAG(handler
->debug
, OSPF6_LSA_DEBUG
);
868 void install_element_ospf6_debug_lsa(void)
870 install_element(ENABLE_NODE
, &debug_ospf6_lsa_hex_cmd
);
871 install_element(ENABLE_NODE
, &no_debug_ospf6_lsa_hex_cmd
);
872 install_element(CONFIG_NODE
, &debug_ospf6_lsa_hex_cmd
);
873 install_element(CONFIG_NODE
, &no_debug_ospf6_lsa_hex_cmd
);
876 int config_write_ospf6_debug_lsa(struct vty
*vty
)
879 struct ospf6_lsa_handler
*handler
;
881 for (i
= 0; i
< vector_active(ospf6_lsa_handler_vector
); i
++) {
882 handler
= vector_slot(ospf6_lsa_handler_vector
, i
);
885 if (CHECK_FLAG(handler
->debug
, OSPF6_LSA_DEBUG
))
886 vty_out(vty
, "debug ospf6 lsa %s%s",
887 ospf6_lsa_handler_name(handler
), VNL
);
888 if (CHECK_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_ORIGINATE
))
889 vty_out(vty
, "debug ospf6 lsa %s originate%s",
890 ospf6_lsa_handler_name(handler
), VNL
);
891 if (CHECK_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_EXAMIN
))
892 vty_out(vty
, "debug ospf6 lsa %s examine%s",
893 ospf6_lsa_handler_name(handler
), VNL
);
894 if (CHECK_FLAG(handler
->debug
, OSPF6_LSA_DEBUG_FLOOD
))
895 vty_out(vty
, "debug ospf6 lsa %s flooding%s",
896 ospf6_lsa_handler_name(handler
), VNL
);