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
;
49 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
++)
60 if ((current
- start
) % 16 == 0)
61 vty_out (vty
, "%s ", VNL
);
62 else if ((current
- start
) % 4 == 0)
65 snprintf (byte
, sizeof (byte
), "%02x", *current
);
66 vty_out (vty
, "%s", byte
);
69 vty_out (vty
, "%s%s", VNL
, VNL
);
73 struct ospf6_lsa_handler unknown_handler
=
78 ospf6_unknown_lsa_show
,
83 ospf6_install_lsa_handler (struct ospf6_lsa_handler
*handler
)
85 /* type in handler is host byte order */
86 int index
= handler
->type
& OSPF6_LSTYPE_FCODE_MASK
;
87 vector_set_index (ospf6_lsa_handler_vector
, index
, handler
);
90 struct ospf6_lsa_handler
*
91 ospf6_get_lsa_handler (u_int16_t type
)
93 struct ospf6_lsa_handler
*handler
= NULL
;
94 unsigned int index
= ntohs (type
) & OSPF6_LSTYPE_FCODE_MASK
;
96 if (index
>= vector_active (ospf6_lsa_handler_vector
))
97 handler
= &unknown_handler
;
99 handler
= vector_slot (ospf6_lsa_handler_vector
, index
);
102 handler
= &unknown_handler
;
108 ospf6_lstype_name (u_int16_t type
)
111 struct ospf6_lsa_handler
*handler
;
113 handler
= ospf6_get_lsa_handler (type
);
114 if (handler
&& handler
!= &unknown_handler
)
115 return handler
->name
;
117 snprintf (buf
, sizeof (buf
), "0x%04hx", ntohs (type
));
122 ospf6_lstype_short_name (u_int16_t type
)
125 struct ospf6_lsa_handler
*handler
;
127 handler
= ospf6_get_lsa_handler (type
);
128 if (handler
&& handler
!= &unknown_handler
)
129 return handler
->short_name
;
131 snprintf (buf
, sizeof (buf
), "0x%04hx", ntohs (type
));
136 ospf6_lstype_debug (u_int16_t type
)
138 struct ospf6_lsa_handler
*handler
;
139 handler
= ospf6_get_lsa_handler (type
);
140 return handler
->debug
;
143 /* RFC2328: Section 13.2 */
145 ospf6_lsa_is_differ (struct ospf6_lsa
*lsa1
,
146 struct ospf6_lsa
*lsa2
)
150 assert (OSPF6_LSA_IS_SAME (lsa1
, lsa2
));
152 /* XXX, Options ??? */
154 ospf6_lsa_age_current (lsa1
);
155 ospf6_lsa_age_current (lsa2
);
156 if (ntohs (lsa1
->header
->age
) == OSPF_LSA_MAXAGE
&&
157 ntohs (lsa2
->header
->age
) != OSPF_LSA_MAXAGE
)
159 if (ntohs (lsa1
->header
->age
) != OSPF_LSA_MAXAGE
&&
160 ntohs (lsa2
->header
->age
) == OSPF_LSA_MAXAGE
)
164 if (ntohs (lsa1
->header
->length
) != ntohs (lsa2
->header
->length
))
167 len
= ntohs (lsa1
->header
->length
) - sizeof (struct ospf6_lsa_header
);
168 return memcmp (lsa1
->header
+ 1, lsa2
->header
+ 1, len
);
172 ospf6_lsa_is_changed (struct ospf6_lsa
*lsa1
,
173 struct ospf6_lsa
*lsa2
)
177 if (OSPF6_LSA_IS_MAXAGE (lsa1
) ^ OSPF6_LSA_IS_MAXAGE (lsa2
))
179 if (ntohs (lsa1
->header
->length
) != ntohs (lsa2
->header
->length
))
181 /* Going beyond LSA headers to compare the payload only makes sense, when both LSAs aren't header-only. */
182 if (CHECK_FLAG (lsa1
->flag
, OSPF6_LSA_HEADERONLY
) != CHECK_FLAG (lsa2
->flag
, OSPF6_LSA_HEADERONLY
))
184 zlog_warn ("%s: only one of two (%s, %s) LSAs compared is header-only", __func__
, lsa1
->name
, lsa2
->name
);
187 if (CHECK_FLAG (lsa1
->flag
, OSPF6_LSA_HEADERONLY
))
190 length
= OSPF6_LSA_SIZE (lsa1
->header
) - sizeof (struct ospf6_lsa_header
);
191 /* Once upper layer verifies LSAs received, length underrun should become a warning. */
195 return memcmp (OSPF6_LSA_HEADER_END (lsa1
->header
),
196 OSPF6_LSA_HEADER_END (lsa2
->header
), length
);
199 /* ospf6 age functions */
200 /* calculate birth */
202 ospf6_lsa_age_set (struct ospf6_lsa
*lsa
)
206 assert (lsa
&& lsa
->header
);
210 lsa
->birth
.tv_sec
= now
.tv_sec
- ntohs (lsa
->header
->age
);
211 lsa
->birth
.tv_usec
= now
.tv_usec
;
216 /* this function calculates current age from its birth,
217 then update age field of LSA header. return value is current age */
219 ospf6_lsa_age_current (struct ospf6_lsa
*lsa
)
226 assert (lsa
->header
);
231 if (ntohs (lsa
->header
->age
) >= OSPF_LSA_MAXAGE
)
233 /* ospf6_lsa_premature_aging () sets age to MAXAGE; when using
234 relative time, we cannot compare against lsa birth time, so
235 we catch this special case here. */
236 lsa
->header
->age
= htons (OSPF_LSA_MAXAGE
);
237 return OSPF_LSA_MAXAGE
;
240 ulage
= now
.tv_sec
- lsa
->birth
.tv_sec
;
242 /* if over MAXAGE, set to it */
243 age
= (ulage
> OSPF_LSA_MAXAGE
? OSPF_LSA_MAXAGE
: ulage
);
245 lsa
->header
->age
= htons (age
);
249 /* update age field of LSA header with adding InfTransDelay */
251 ospf6_lsa_age_update_to_send (struct ospf6_lsa
*lsa
, u_int32_t transdelay
)
255 age
= ospf6_lsa_age_current (lsa
) + transdelay
;
256 if (age
> OSPF_LSA_MAXAGE
)
257 age
= OSPF_LSA_MAXAGE
;
258 lsa
->header
->age
= htons (age
);
262 ospf6_lsa_premature_aging (struct ospf6_lsa
*lsa
)
265 if (IS_OSPF6_DEBUG_LSA_TYPE (lsa
->header
->type
))
266 zlog_debug ("LSA: Premature aging: %s", lsa
->name
);
268 THREAD_OFF (lsa
->expire
);
269 THREAD_OFF (lsa
->refresh
);
272 * We clear the LSA from the neighbor retx lists now because it
273 * will not get deleted later. Essentially, changing the age to
274 * MaxAge will prevent this LSA from being matched with its
275 * existing entries in the retx list thereby causing those entries
276 * to be silently replaced with its MaxAged version, but with ever
277 * increasing retx count causing this LSA to remain forever and
278 * for the MaxAge remover thread to be called forever too.
280 * The reason the previous entry silently disappears is that when
281 * entry is added to a neighbor's retx list, it replaces the existing
282 * entry. But since the ospf6_lsdb_add() routine is generic and not aware
283 * of the special semantics of retx count, the retx count is not
284 * decremented when its replaced. Attempting to add the incr and decr
285 * retx count routines as the hook_add and hook_remove for the retx lists
286 * have a problem because the hook_remove routine is called for MaxAge
287 * entries (as will be the case in a traditional LSDB, unlike in this case
288 * where an LSDB is used as an efficient tree structure to store all kinds
289 * of data) that are added instead of calling the hook_add routine.
292 ospf6_flood_clear (lsa
);
294 lsa
->header
->age
= htons (OSPF_LSA_MAXAGE
);
295 thread_execute (master
, ospf6_lsa_expire
, lsa
, 0);
298 /* check which is more recent. if a is more recent, return -1;
299 if the same, return 0; otherwise(b is more recent), return 1 */
301 ospf6_lsa_compare (struct ospf6_lsa
*a
, struct ospf6_lsa
*b
)
303 int32_t seqnuma
, seqnumb
;
304 u_int16_t cksuma
, cksumb
;
305 u_int16_t agea
, ageb
;
307 assert (a
&& a
->header
);
308 assert (b
&& b
->header
);
309 assert (OSPF6_LSA_IS_SAME (a
, b
));
311 seqnuma
= (int32_t) ntohl (a
->header
->seqnum
);
312 seqnumb
= (int32_t) ntohl (b
->header
->seqnum
);
314 /* compare by sequence number */
315 if (seqnuma
> seqnumb
)
317 if (seqnuma
< seqnumb
)
321 cksuma
= ntohs (a
->header
->checksum
);
322 cksumb
= ntohs (b
->header
->checksum
);
329 agea
= ospf6_lsa_age_current (a
);
330 ageb
= ospf6_lsa_age_current (b
);
333 if (agea
== OSPF_LSA_MAXAGE
&& ageb
!= OSPF_LSA_MAXAGE
)
335 else if (agea
!= OSPF_LSA_MAXAGE
&& ageb
== OSPF_LSA_MAXAGE
)
339 if (agea
> ageb
&& agea
- ageb
>= OSPF_LSA_MAXAGE_DIFF
)
341 else if (agea
< ageb
&& ageb
- agea
>= OSPF_LSA_MAXAGE_DIFF
)
349 ospf6_lsa_printbuf (struct ospf6_lsa
*lsa
, char *buf
, int size
)
351 char id
[16], adv_router
[16];
352 inet_ntop (AF_INET
, &lsa
->header
->id
, id
, sizeof (id
));
353 inet_ntop (AF_INET
, &lsa
->header
->adv_router
, adv_router
,
354 sizeof (adv_router
));
355 snprintf (buf
, size
, "[%s Id:%s Adv:%s]",
356 ospf6_lstype_name (lsa
->header
->type
), id
, adv_router
);
361 ospf6_lsa_header_print_raw (struct ospf6_lsa_header
*header
)
363 char id
[16], adv_router
[16];
364 inet_ntop (AF_INET
, &header
->id
, id
, sizeof (id
));
365 inet_ntop (AF_INET
, &header
->adv_router
, adv_router
,
366 sizeof (adv_router
));
367 zlog_debug (" [%s Id:%s Adv:%s]",
368 ospf6_lstype_name (header
->type
), id
, adv_router
);
369 zlog_debug (" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
370 ntohs (header
->age
), (u_long
) ntohl (header
->seqnum
),
371 ntohs (header
->checksum
), ntohs (header
->length
));
375 ospf6_lsa_header_print (struct ospf6_lsa
*lsa
)
377 ospf6_lsa_age_current (lsa
);
378 ospf6_lsa_header_print_raw (lsa
->header
);
382 ospf6_lsa_show_summary_header (struct vty
*vty
)
384 vty_out (vty
, "%-4s %-15s%-15s%4s %8s %30s%s",
385 "Type", "LSId", "AdvRouter", "Age", "SeqNum",
390 ospf6_lsa_show_summary (struct vty
*vty
, struct ospf6_lsa
*lsa
)
392 char adv_router
[16], id
[16];
394 struct ospf6_lsa_handler
*handler
;
395 char buf
[64], tmpbuf
[80];
399 assert (lsa
->header
);
401 inet_ntop (AF_INET
, &lsa
->header
->id
, id
, sizeof (id
));
402 inet_ntop (AF_INET
, &lsa
->header
->adv_router
, adv_router
,
403 sizeof (adv_router
));
405 type
= ntohs(lsa
->header
->type
);
406 handler
= ospf6_get_lsa_handler (lsa
->header
->type
);
407 if ((type
== OSPF6_LSTYPE_INTER_PREFIX
) ||
408 (type
== OSPF6_LSTYPE_INTER_ROUTER
) ||
409 (type
== OSPF6_LSTYPE_AS_EXTERNAL
))
411 vty_out (vty
, "%-4s %-15s%-15s%4hu %8lx %30s%s",
412 ospf6_lstype_short_name (lsa
->header
->type
),
413 id
, adv_router
, ospf6_lsa_age_current (lsa
),
414 (u_long
) ntohl (lsa
->header
->seqnum
),
415 handler
->get_prefix_str(lsa
, buf
, sizeof(buf
), 0), VNL
);
417 else if (type
!= OSPF6_LSTYPE_UNKNOWN
)
419 sprintf (tmpbuf
, "%-4s %-15s%-15s%4hu %8lx",
420 ospf6_lstype_short_name (lsa
->header
->type
),
421 id
, adv_router
, ospf6_lsa_age_current (lsa
),
422 (u_long
) ntohl (lsa
->header
->seqnum
));
424 while (handler
->get_prefix_str(lsa
, buf
, sizeof(buf
), cnt
) != NULL
)
426 vty_out (vty
, "%s %30s%s", tmpbuf
, buf
, VNL
);
432 vty_out (vty
, "%-4s %-15s%-15s%4hu %8lx%s",
433 ospf6_lstype_short_name (lsa
->header
->type
),
434 id
, adv_router
, ospf6_lsa_age_current (lsa
),
435 (u_long
) ntohl (lsa
->header
->seqnum
), VNL
);
440 ospf6_lsa_show_dump (struct vty
*vty
, struct ospf6_lsa
*lsa
)
442 u_char
*start
, *end
, *current
;
445 start
= (u_char
*) lsa
->header
;
446 end
= (u_char
*) lsa
->header
+ ntohs (lsa
->header
->length
);
448 vty_out (vty
, "%s", VNL
);
449 vty_out (vty
, "%s:%s", lsa
->name
, VNL
);
451 for (current
= start
; current
< end
; current
++)
453 if ((current
- start
) % 16 == 0)
454 vty_out (vty
, "%s ", VNL
);
455 else if ((current
- start
) % 4 == 0)
458 snprintf (byte
, sizeof (byte
), "%02x", *current
);
459 vty_out (vty
, "%s", byte
);
462 vty_out (vty
, "%s%s", VNL
, VNL
);
467 ospf6_lsa_show_internal (struct vty
*vty
, struct ospf6_lsa
*lsa
)
469 char adv_router
[64], id
[64];
471 assert (lsa
&& lsa
->header
);
473 inet_ntop (AF_INET
, &lsa
->header
->id
, id
, sizeof (id
));
474 inet_ntop (AF_INET
, &lsa
->header
->adv_router
,
475 adv_router
, sizeof (adv_router
));
477 vty_out (vty
, "%s", VNL
);
478 vty_out (vty
, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa
),
479 ospf6_lstype_name (lsa
->header
->type
), VNL
);
480 vty_out (vty
, "Link State ID: %s%s", id
, VNL
);
481 vty_out (vty
, "Advertising Router: %s%s", adv_router
, VNL
);
482 vty_out (vty
, "LS Sequence Number: %#010lx%s",
483 (u_long
) ntohl (lsa
->header
->seqnum
), VNL
);
484 vty_out (vty
, "CheckSum: %#06hx Length: %hu%s",
485 ntohs (lsa
->header
->checksum
),
486 ntohs (lsa
->header
->length
), VNL
);
487 vty_out (vty
, "Flag: %x %s", lsa
->flag
, VNL
);
488 vty_out (vty
, "Lock: %d %s", lsa
->lock
, VNL
);
489 vty_out (vty
, "ReTx Count: %d%s", lsa
->retrans_count
, VNL
);
490 vty_out (vty
, "Threads: Expire: 0x%p, Refresh: 0x%p %s",
491 (void *)lsa
->expire
, (void *)lsa
->refresh
, VNL
);
492 vty_out (vty
, "%s", VNL
);
497 ospf6_lsa_show (struct vty
*vty
, struct ospf6_lsa
*lsa
)
499 char adv_router
[64], id
[64];
500 struct ospf6_lsa_handler
*handler
;
501 struct timeval now
, res
;
504 assert (lsa
&& lsa
->header
);
506 inet_ntop (AF_INET
, &lsa
->header
->id
, id
, sizeof (id
));
507 inet_ntop (AF_INET
, &lsa
->header
->adv_router
,
508 adv_router
, sizeof (adv_router
));
511 timersub (&now
, &lsa
->installed
, &res
);
512 timerstring (&res
, duration
, sizeof (duration
));
514 vty_out (vty
, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa
),
515 ospf6_lstype_name (lsa
->header
->type
), VNL
);
516 vty_out (vty
, "Link State ID: %s%s", id
, VNL
);
517 vty_out (vty
, "Advertising Router: %s%s", adv_router
, VNL
);
518 vty_out (vty
, "LS Sequence Number: %#010lx%s",
519 (u_long
) ntohl (lsa
->header
->seqnum
), VNL
);
520 vty_out (vty
, "CheckSum: %#06hx Length: %hu%s",
521 ntohs (lsa
->header
->checksum
),
522 ntohs (lsa
->header
->length
), VNL
);
523 vty_out (vty
, "Duration: %s%s", duration
, VNL
);
525 handler
= ospf6_get_lsa_handler (lsa
->header
->type
);
526 if (handler
->show
== NULL
)
527 handler
= &unknown_handler
;
528 (*handler
->show
) (vty
, lsa
);
530 vty_out (vty
, "%s", VNL
);
533 /* OSPFv3 LSA creation/deletion function */
535 ospf6_lsa_create (struct ospf6_lsa_header
*header
)
537 struct ospf6_lsa
*lsa
= NULL
;
538 struct ospf6_lsa_header
*new_header
= NULL
;
539 u_int16_t lsa_size
= 0;
541 /* size of the entire LSA */
542 lsa_size
= ntohs (header
->length
); /* XXX vulnerable */
544 /* allocate memory for this LSA */
545 new_header
= (struct ospf6_lsa_header
*)
546 XMALLOC (MTYPE_OSPF6_LSA
, lsa_size
);
548 /* copy LSA from original header */
549 memcpy (new_header
, header
, lsa_size
);
551 /* LSA information structure */
552 /* allocate memory */
553 lsa
= (struct ospf6_lsa
*)
554 XCALLOC (MTYPE_OSPF6_LSA
, sizeof (struct ospf6_lsa
));
556 lsa
->header
= (struct ospf6_lsa_header
*) new_header
;
559 ospf6_lsa_printbuf (lsa
, lsa
->name
, sizeof (lsa
->name
));
561 /* calculate birth of this lsa */
562 ospf6_lsa_age_set (lsa
);
568 ospf6_lsa_create_headeronly (struct ospf6_lsa_header
*header
)
570 struct ospf6_lsa
*lsa
= NULL
;
571 struct ospf6_lsa_header
*new_header
= NULL
;
573 /* allocate memory for this LSA */
574 new_header
= (struct ospf6_lsa_header
*)
575 XMALLOC (MTYPE_OSPF6_LSA
, sizeof (struct ospf6_lsa_header
));
577 /* copy LSA from original header */
578 memcpy (new_header
, header
, sizeof (struct ospf6_lsa_header
));
580 /* LSA information structure */
581 /* allocate memory */
582 lsa
= (struct ospf6_lsa
*)
583 XCALLOC (MTYPE_OSPF6_LSA
, sizeof (struct ospf6_lsa
));
585 lsa
->header
= (struct ospf6_lsa_header
*) new_header
;
586 SET_FLAG (lsa
->flag
, OSPF6_LSA_HEADERONLY
);
589 ospf6_lsa_printbuf (lsa
, lsa
->name
, sizeof (lsa
->name
));
591 /* calculate birth of this lsa */
592 ospf6_lsa_age_set (lsa
);
598 ospf6_lsa_delete (struct ospf6_lsa
*lsa
)
600 assert (lsa
->lock
== 0);
603 THREAD_OFF (lsa
->expire
);
604 THREAD_OFF (lsa
->refresh
);
607 XFREE (MTYPE_OSPF6_LSA
, lsa
->header
);
608 XFREE (MTYPE_OSPF6_LSA
, lsa
);
612 ospf6_lsa_copy (struct ospf6_lsa
*lsa
)
614 struct ospf6_lsa
*copy
= NULL
;
616 ospf6_lsa_age_current (lsa
);
617 if (CHECK_FLAG (lsa
->flag
, OSPF6_LSA_HEADERONLY
))
618 copy
= ospf6_lsa_create_headeronly (lsa
->header
);
620 copy
= ospf6_lsa_create (lsa
->header
);
621 assert (copy
->lock
== 0);
623 copy
->birth
= lsa
->birth
;
624 copy
->originated
= lsa
->originated
;
625 copy
->received
= lsa
->received
;
626 copy
->installed
= lsa
->installed
;
627 copy
->lsdb
= lsa
->lsdb
;
633 /* increment reference counter of struct ospf6_lsa */
635 ospf6_lsa_lock (struct ospf6_lsa
*lsa
)
641 /* decrement reference counter of struct ospf6_lsa */
643 ospf6_lsa_unlock (struct ospf6_lsa
*lsa
)
645 /* decrement reference counter */
646 assert (lsa
->lock
> 0);
652 ospf6_lsa_delete (lsa
);
656 /* ospf6 lsa expiry */
658 ospf6_lsa_expire (struct thread
*thread
)
660 struct ospf6_lsa
*lsa
;
662 lsa
= (struct ospf6_lsa
*) THREAD_ARG (thread
);
664 assert (lsa
&& lsa
->header
);
665 assert (OSPF6_LSA_IS_MAXAGE (lsa
));
666 assert (! lsa
->refresh
);
668 lsa
->expire
= (struct thread
*) NULL
;
670 if (IS_OSPF6_DEBUG_LSA_TYPE (lsa
->header
->type
))
672 zlog_debug ("LSA Expire:");
673 ospf6_lsa_header_print (lsa
);
676 if (CHECK_FLAG (lsa
->flag
, OSPF6_LSA_HEADERONLY
))
677 return 0; /* dbexchange will do something ... */
680 ospf6_install_lsa (lsa
);
683 ospf6_flood (NULL
, lsa
);
685 /* schedule maxage remover */
686 ospf6_maxage_remove (ospf6
);
692 ospf6_lsa_refresh (struct thread
*thread
)
694 struct ospf6_lsa
*old
, *self
, *new;
695 struct ospf6_lsdb
*lsdb_self
;
697 old
= (struct ospf6_lsa
*) THREAD_ARG (thread
);
698 assert (old
&& old
->header
);
700 old
->refresh
= (struct thread
*) NULL
;
702 lsdb_self
= ospf6_get_scoped_lsdb_self (old
);
703 self
= ospf6_lsdb_lookup (old
->header
->type
, old
->header
->id
,
704 old
->header
->adv_router
, lsdb_self
);
707 if (IS_OSPF6_DEBUG_LSA_TYPE (old
->header
->type
))
708 zlog_debug ("Refresh: could not find self LSA, flush %s", old
->name
);
709 ospf6_lsa_premature_aging (old
);
713 /* Reset age, increment LS sequence number. */
714 self
->header
->age
= htons (0);
715 self
->header
->seqnum
=
716 ospf6_new_ls_seqnum (self
->header
->type
, self
->header
->id
,
717 self
->header
->adv_router
, old
->lsdb
);
718 ospf6_lsa_checksum (self
->header
);
720 new = ospf6_lsa_create (self
->header
);
721 new->lsdb
= old
->lsdb
;
723 thread_add_timer(master
, ospf6_lsa_refresh
, new, OSPF_LS_REFRESH_TIME
,
726 /* store it in the LSDB for self-originated LSAs */
727 ospf6_lsdb_add (ospf6_lsa_copy (new), lsdb_self
);
729 if (IS_OSPF6_DEBUG_LSA_TYPE (new->header
->type
))
731 zlog_debug ("LSA Refresh:");
732 ospf6_lsa_header_print (new);
735 ospf6_install_lsa (new);
736 ospf6_flood (NULL
, new);
743 /* Fletcher Checksum -- Refer to RFC1008. */
745 /* All the offsets are zero-based. The offsets in the RFC1008 are
748 ospf6_lsa_checksum (struct ospf6_lsa_header
*lsa_header
)
750 u_char
*buffer
= (u_char
*) &lsa_header
->type
;
751 int type_offset
= buffer
- (u_char
*) &lsa_header
->age
; /* should be 2 */
753 /* Skip the AGE field */
754 u_int16_t len
= ntohs(lsa_header
->length
) - type_offset
;
756 /* Checksum offset starts from "type" field, not the beginning of the
757 lsa_header struct. The offset is 14, rather than 16. */
758 int checksum_offset
= (u_char
*) &lsa_header
->checksum
- buffer
;
760 return (unsigned short)fletcher_checksum(buffer
, len
, checksum_offset
);
764 ospf6_lsa_checksum_valid (struct ospf6_lsa_header
*lsa_header
)
766 u_char
*buffer
= (u_char
*) &lsa_header
->type
;
767 int type_offset
= buffer
- (u_char
*) &lsa_header
->age
; /* should be 2 */
769 /* Skip the AGE field */
770 u_int16_t len
= ntohs(lsa_header
->length
) - type_offset
;
772 return (fletcher_checksum(buffer
, len
, FLETCHER_CHECKSUM_VALIDATE
) == 0);
776 ospf6_lsa_init (void)
778 ospf6_lsa_handler_vector
= vector_init (0);
779 ospf6_install_lsa_handler (&unknown_handler
);
783 ospf6_lsa_terminate (void)
785 vector_free (ospf6_lsa_handler_vector
);
789 ospf6_lsa_handler_name (struct ospf6_lsa_handler
*h
)
793 unsigned int size
= strlen (h
->name
);
795 if (!strcmp(h
->name
, "unknown") &&
796 h
->type
!= OSPF6_LSTYPE_UNKNOWN
)
798 snprintf (buf
, sizeof (buf
), "%#04hx", h
->type
);
802 for (i
= 0; i
< MIN (size
, sizeof (buf
)); i
++)
804 if (! islower ((unsigned char)h
->name
[i
]))
805 buf
[i
] = tolower ((unsigned char)h
->name
[i
]);
813 DEFUN (debug_ospf6_lsa_type
,
814 debug_ospf6_lsa_hex_cmd
,
815 "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
818 "Debug Link State Advertisements (LSAs)\n"
819 "Display Router LSAs\n"
820 "Display Network LSAs\n"
821 "Display Inter-Area-Prefix LSAs\n"
822 "Display Inter-Router LSAs\n"
823 "Display As-External LSAs\n"
824 "Display Link LSAs\n"
825 "Display Intra-Area-Prefix LSAs\n"
826 "Display LSAs of unknown origin\n"
827 "Display details of LSAs\n"
829 "Display LSA's internal information\n")
834 struct ospf6_lsa_handler
*handler
= NULL
;
836 for (i
= 0; i
< vector_active (ospf6_lsa_handler_vector
); i
++)
838 handler
= vector_slot (ospf6_lsa_handler_vector
, i
);
841 if (strncmp (argv
[idx_lsa
]->arg
, ospf6_lsa_handler_name(handler
), strlen(argv
[idx_lsa
]->arg
)) == 0)
843 if (! strcasecmp (argv
[idx_lsa
]->arg
, handler
->name
))
849 handler
= &unknown_handler
;
853 if (strmatch(argv
[idx_type
]->text
, "originate"))
854 SET_FLAG (handler
->debug
, OSPF6_LSA_DEBUG_ORIGINATE
);
855 else if (strmatch(argv
[idx_type
]->text
, "examine"))
856 SET_FLAG (handler
->debug
, OSPF6_LSA_DEBUG_EXAMIN
);
857 else if (strmatch(argv
[idx_type
]->text
, "flooding"))
858 SET_FLAG (handler
->debug
, OSPF6_LSA_DEBUG_FLOOD
);
861 SET_FLAG (handler
->debug
, OSPF6_LSA_DEBUG
);
866 DEFUN (no_debug_ospf6_lsa_type
,
867 no_debug_ospf6_lsa_hex_cmd
,
868 "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
872 "Debug Link State Advertisements (LSAs)\n"
873 "Display Router LSAs\n"
874 "Display Network LSAs\n"
875 "Display Inter-Area-Prefix LSAs\n"
876 "Display Inter-Router LSAs\n"
877 "Display As-External LSAs\n"
878 "Display Link LSAs\n"
879 "Display Intra-Area-Prefix LSAs\n"
880 "Display LSAs of unknown origin\n"
881 "Display details of LSAs\n"
883 "Display LSA's internal information\n")
888 struct ospf6_lsa_handler
*handler
= NULL
;
890 for (i
= 0; i
< vector_active (ospf6_lsa_handler_vector
); i
++)
892 handler
= vector_slot (ospf6_lsa_handler_vector
, i
);
895 if (strncmp (argv
[idx_lsa
]->arg
, ospf6_lsa_handler_name(handler
), strlen(argv
[idx_lsa
]->arg
)) == 0)
897 if (! strcasecmp (argv
[idx_lsa
]->arg
, handler
->name
))
906 if (strmatch(argv
[idx_type
]->text
, "originate"))
907 UNSET_FLAG (handler
->debug
, OSPF6_LSA_DEBUG_ORIGINATE
);
908 if (strmatch(argv
[idx_type
]->text
, "examine"))
909 UNSET_FLAG (handler
->debug
, OSPF6_LSA_DEBUG_EXAMIN
);
910 if (strmatch(argv
[idx_type
]->text
, "flooding"))
911 UNSET_FLAG (handler
->debug
, OSPF6_LSA_DEBUG_FLOOD
);
914 UNSET_FLAG (handler
->debug
, OSPF6_LSA_DEBUG
);
920 install_element_ospf6_debug_lsa (void)
922 install_element (ENABLE_NODE
, &debug_ospf6_lsa_hex_cmd
);
923 install_element (ENABLE_NODE
, &no_debug_ospf6_lsa_hex_cmd
);
924 install_element (CONFIG_NODE
, &debug_ospf6_lsa_hex_cmd
);
925 install_element (CONFIG_NODE
, &no_debug_ospf6_lsa_hex_cmd
);
929 config_write_ospf6_debug_lsa (struct vty
*vty
)
932 struct ospf6_lsa_handler
*handler
;
934 for (i
= 0; i
< vector_active (ospf6_lsa_handler_vector
); i
++)
936 handler
= vector_slot (ospf6_lsa_handler_vector
, i
);
939 if (CHECK_FLAG (handler
->debug
, OSPF6_LSA_DEBUG
))
940 vty_out (vty
, "debug ospf6 lsa %s%s",
941 ospf6_lsa_handler_name (handler
), VNL
);
942 if (CHECK_FLAG (handler
->debug
, OSPF6_LSA_DEBUG_ORIGINATE
))
943 vty_out (vty
, "debug ospf6 lsa %s originate%s",
944 ospf6_lsa_handler_name (handler
), VNL
);
945 if (CHECK_FLAG (handler
->debug
, OSPF6_LSA_DEBUG_EXAMIN
))
946 vty_out (vty
, "debug ospf6 lsa %s examine%s",
947 ospf6_lsa_handler_name (handler
), VNL
);
948 if (CHECK_FLAG (handler
->debug
, OSPF6_LSA_DEBUG_FLOOD
))
949 vty_out (vty
, "debug ospf6 lsa %s flooding%s",
950 ospf6_lsa_handler_name (handler
), VNL
);