]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_lsa.c
debianpkg: Add missing XSBC-Original-Maintainer field (fixes merge error)
[mirror_frr.git] / ospf6d / ospf6_lsa.c
CommitLineData
718e3744 1/*
508e53e2 2 * Copyright (C) 2003 Yasuhiro Ohara
718e3744 3 *
4 * This file is part of GNU Zebra.
5 *
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
9 * later version.
10 *
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.
15 *
16 * You should have received a copy of the GNU General Public License
ac4d0be5 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.
718e3744 20 */
21
22#include <zebra.h>
23
24/* Include other stuffs */
718e3744 25#include "log.h"
718e3744 26#include "linklist.h"
1e05838a 27#include "vector.h"
28#include "vty.h"
718e3744 29#include "command.h"
30#include "memory.h"
718e3744 31#include "thread.h"
d8a4e42b 32#include "checksum.h"
718e3744 33
34#include "ospf6_proto.h"
718e3744 35#include "ospf6_lsa.h"
36#include "ospf6_lsdb.h"
37#include "ospf6_message.h"
718e3744 38
39#include "ospf6_top.h"
40#include "ospf6_area.h"
41#include "ospf6_interface.h"
42#include "ospf6_neighbor.h"
718e3744 43
508e53e2 44#include "ospf6_flood.h"
049207c3 45#include "ospf6d.h"
718e3744 46
1e05838a 47vector ospf6_lsa_handler_vector;
718e3744 48
ac4d0be5 49static int ospf6_unknown_lsa_show(struct vty *vty, struct ospf6_lsa *lsa)
1e05838a 50{
ac4d0be5 51 u_char *start, *end, *current;
52 char byte[4];
1e05838a 53
ac4d0be5 54 start = (u_char *)lsa->header + sizeof(struct ospf6_lsa_header);
55 end = (u_char *)lsa->header + ntohs(lsa->header->length);
1e05838a 56
ac4d0be5 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)
62 vty_out(vty, " ");
718e3744 63
ac4d0be5 64 snprintf(byte, sizeof(byte), "%02x", *current);
65 vty_out(vty, "%s", byte);
66 }
1e05838a 67
ac4d0be5 68 vty_out(vty, "%s%s", VNL, VNL);
69 return 0;
1e05838a 70}
71
ac4d0be5 72struct ospf6_lsa_handler unknown_handler = {
73 OSPF6_LSTYPE_UNKNOWN, "Unknown", "Unk", ospf6_unknown_lsa_show, NULL};
1e05838a 74
ac4d0be5 75void ospf6_install_lsa_handler(struct ospf6_lsa_handler *handler)
1e05838a 76{
ac4d0be5 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);
1e05838a 80}
81
ac4d0be5 82struct ospf6_lsa_handler *ospf6_get_lsa_handler(u_int16_t type)
1e05838a 83{
ac4d0be5 84 struct ospf6_lsa_handler *handler = NULL;
85 unsigned int index = ntohs(type) & OSPF6_LSTYPE_FCODE_MASK;
1e05838a 86
ac4d0be5 87 if (index >= vector_active(ospf6_lsa_handler_vector))
88 handler = &unknown_handler;
89 else
90 handler = vector_slot(ospf6_lsa_handler_vector, index);
1e05838a 91
ac4d0be5 92 if (handler == NULL)
93 handler = &unknown_handler;
2680aa2b 94
ac4d0be5 95 return handler;
1e05838a 96}
718e3744 97
ac4d0be5 98const char *ospf6_lstype_name(u_int16_t type)
508e53e2 99{
ac4d0be5 100 static char buf[8];
101 struct ospf6_lsa_handler *handler;
508e53e2 102
ac4d0be5 103 handler = ospf6_get_lsa_handler(type);
104 if (handler && handler != &unknown_handler)
105 return handler->name;
718e3744 106
ac4d0be5 107 snprintf(buf, sizeof(buf), "0x%04hx", ntohs(type));
108 return buf;
718e3744 109}
110
ac4d0be5 111const char *ospf6_lstype_short_name(u_int16_t type)
e68a6767 112{
ac4d0be5 113 static char buf[8];
114 struct ospf6_lsa_handler *handler;
e68a6767 115
ac4d0be5 116 handler = ospf6_get_lsa_handler(type);
117 if (handler && handler != &unknown_handler)
118 return handler->short_name;
e68a6767 119
ac4d0be5 120 snprintf(buf, sizeof(buf), "0x%04hx", ntohs(type));
121 return buf;
e68a6767
DD
122}
123
ac4d0be5 124u_char ospf6_lstype_debug(u_int16_t type)
1e05838a 125{
ac4d0be5 126 struct ospf6_lsa_handler *handler;
127 handler = ospf6_get_lsa_handler(type);
128 return handler->debug;
1e05838a 129}
130
718e3744 131/* RFC2328: Section 13.2 */
ac4d0be5 132int ospf6_lsa_is_differ(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
718e3744 133{
ac4d0be5 134 int len;
718e3744 135
ac4d0be5 136 assert(OSPF6_LSA_IS_SAME(lsa1, lsa2));
718e3744 137
ac4d0be5 138 /* XXX, Options ??? */
718e3744 139
ac4d0be5 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)
144 return 1;
145 if (ntohs(lsa1->header->age) != OSPF_LSA_MAXAGE
146 && ntohs(lsa2->header->age) == OSPF_LSA_MAXAGE)
147 return 1;
718e3744 148
ac4d0be5 149 /* compare body */
150 if (ntohs(lsa1->header->length) != ntohs(lsa2->header->length))
151 return 1;
718e3744 152
ac4d0be5 153 len = ntohs(lsa1->header->length) - sizeof(struct ospf6_lsa_header);
154 return memcmp(lsa1->header + 1, lsa2->header + 1, len);
718e3744 155}
156
ac4d0be5 157int ospf6_lsa_is_changed(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
718e3744 158{
ac4d0be5 159 int length;
718e3744 160
ac4d0be5 161 if (OSPF6_LSA_IS_MAXAGE(lsa1) ^ OSPF6_LSA_IS_MAXAGE(lsa2))
162 return 1;
163 if (ntohs(lsa1->header->length) != ntohs(lsa2->header->length))
164 return 1;
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)) {
169 zlog_warn(
170 "%s: only one of two (%s, %s) LSAs compared is header-only",
171 __func__, lsa1->name, lsa2->name);
172 return 1;
173 }
174 if (CHECK_FLAG(lsa1->flag, OSPF6_LSA_HEADERONLY))
175 return 0;
718e3744 176
ac4d0be5 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. */
180 if (length <= 0)
181 return 0;
718e3744 182
ac4d0be5 183 return memcmp(OSPF6_LSA_HEADER_END(lsa1->header),
184 OSPF6_LSA_HEADER_END(lsa2->header), length);
718e3744 185}
186
187/* ospf6 age functions */
3b68735f 188/* calculate birth */
ac4d0be5 189static void ospf6_lsa_age_set(struct ospf6_lsa *lsa)
718e3744 190{
ac4d0be5 191 struct timeval now;
718e3744 192
ac4d0be5 193 assert(lsa && lsa->header);
718e3744 194
ac4d0be5 195 monotime(&now);
718e3744 196
ac4d0be5 197 lsa->birth.tv_sec = now.tv_sec - ntohs(lsa->header->age);
198 lsa->birth.tv_usec = now.tv_usec;
3b68735f 199
ac4d0be5 200 return;
718e3744 201}
202
203/* this function calculates current age from its birth,
204 then update age field of LSA header. return value is current age */
ac4d0be5 205u_int16_t ospf6_lsa_age_current(struct ospf6_lsa *lsa)
718e3744 206{
ac4d0be5 207 struct timeval now;
208 u_int32_t ulage;
209 u_int16_t age;
718e3744 210
ac4d0be5 211 assert(lsa);
212 assert(lsa->header);
718e3744 213
ac4d0be5 214 /* current time */
215 monotime(&now);
718e3744 216
ac4d0be5 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;
223 }
224 /* calculate age */
225 ulage = now.tv_sec - lsa->birth.tv_sec;
718e3744 226
ac4d0be5 227 /* if over MAXAGE, set to it */
228 age = (ulage > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : ulage);
718e3744 229
ac4d0be5 230 lsa->header->age = htons(age);
231 return age;
718e3744 232}
233
234/* update age field of LSA header with adding InfTransDelay */
ac4d0be5 235void ospf6_lsa_age_update_to_send(struct ospf6_lsa *lsa, u_int32_t transdelay)
236{
237 unsigned short age;
238
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);
243}
244
245void ospf6_lsa_premature_aging(struct ospf6_lsa *lsa)
246{
247 /* log */
248 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type))
249 zlog_debug("LSA: Premature aging: %s", lsa->name);
250
251 THREAD_OFF(lsa->expire);
252 THREAD_OFF(lsa->refresh);
253
254 /*
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.
262 *
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
266 * aware
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
270 * lists
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
273 * case
274 * where an LSDB is used as an efficient tree structure to store all
275 * kinds
276 * of data) that are added instead of calling the hook_add routine.
277 */
278
279 ospf6_flood_clear(lsa);
280
281 lsa->header->age = htons(OSPF_LSA_MAXAGE);
282 thread_execute(master, ospf6_lsa_expire, lsa, 0);
718e3744 283}
284
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 */
ac4d0be5 287int ospf6_lsa_compare(struct ospf6_lsa *a, struct ospf6_lsa *b)
718e3744 288{
ac4d0be5 289 int32_t seqnuma, seqnumb;
290 u_int16_t cksuma, cksumb;
291 u_int16_t agea, ageb;
292
293 assert(a && a->header);
294 assert(b && b->header);
295 assert(OSPF6_LSA_IS_SAME(a, b));
296
297 seqnuma = (int32_t)ntohl(a->header->seqnum);
298 seqnumb = (int32_t)ntohl(b->header->seqnum);
299
300 /* compare by sequence number */
301 if (seqnuma > seqnumb)
302 return -1;
303 if (seqnuma < seqnumb)
304 return 1;
305
306 /* Checksum */
307 cksuma = ntohs(a->header->checksum);
308 cksumb = ntohs(b->header->checksum);
309 if (cksuma > cksumb)
310 return -1;
311 if (cksuma < cksumb)
312 return 0;
313
314 /* Update Age */
315 agea = ospf6_lsa_age_current(a);
316 ageb = ospf6_lsa_age_current(b);
317
318 /* MaxAge check */
319 if (agea == OSPF_LSA_MAXAGE && ageb != OSPF_LSA_MAXAGE)
320 return -1;
321 else if (agea != OSPF_LSA_MAXAGE && ageb == OSPF_LSA_MAXAGE)
322 return 1;
323
324 /* Age check */
325 if (agea > ageb && agea - ageb >= OSPF_LSA_MAXAGE_DIFF)
326 return 1;
327 else if (agea < ageb && ageb - agea >= OSPF_LSA_MAXAGE_DIFF)
328 return -1;
329
330 /* neither recent */
331 return 0;
332}
333
334char *ospf6_lsa_printbuf(struct ospf6_lsa *lsa, char *buf, int size)
335{
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,
339 sizeof(adv_router));
340 snprintf(buf, size, "[%s Id:%s Adv:%s]",
341 ospf6_lstype_name(lsa->header->type), id, adv_router);
342 return buf;
343}
344
345void ospf6_lsa_header_print_raw(struct ospf6_lsa_header *header)
346{
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,
351 adv_router);
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));
355}
356
357void ospf6_lsa_header_print(struct ospf6_lsa *lsa)
358{
359 ospf6_lsa_age_current(lsa);
360 ospf6_lsa_header_print_raw(lsa->header);
361}
362
363void ospf6_lsa_show_summary_header(struct vty *vty)
364{
365 vty_out(vty, "%-4s %-15s%-15s%4s %8s %30s%s", "Type", "LSId",
366 "AdvRouter", "Age", "SeqNum", "Payload", VNL);
367}
368
369void ospf6_lsa_show_summary(struct vty *vty, struct ospf6_lsa *lsa)
370{
371 char adv_router[16], id[16];
372 int type;
373 struct ospf6_lsa_handler *handler;
374 char buf[64], tmpbuf[80];
375 int cnt = 0;
376
377 assert(lsa);
378 assert(lsa->header);
379
380 inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
381 inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
382 sizeof(adv_router));
383
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));
399
400 while (handler->get_prefix_str(lsa, buf, sizeof(buf), cnt)
401 != NULL) {
402 vty_out(vty, "%s %30s%s", tmpbuf, buf, VNL);
403 cnt++;
404 }
405 } else {
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);
410 }
411}
412
413void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa)
414{
415 u_char *start, *end, *current;
416 char byte[4];
417
418 start = (u_char *)lsa->header;
419 end = (u_char *)lsa->header + ntohs(lsa->header->length);
420
421 vty_out(vty, "%s", VNL);
422 vty_out(vty, "%s:%s", lsa->name, VNL);
718e3744 423
ac4d0be5 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)
428 vty_out(vty, " ");
718e3744 429
ac4d0be5 430 snprintf(byte, sizeof(byte), "%02x", *current);
431 vty_out(vty, "%s", byte);
e68a6767 432 }
ac4d0be5 433
434 vty_out(vty, "%s%s", VNL, VNL);
435 return;
436}
437
438void ospf6_lsa_show_internal(struct vty *vty, struct ospf6_lsa *lsa)
439{
440 char adv_router[64], id[64];
441
442 assert(lsa && lsa->header);
443
444 inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
445 inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
446 sizeof(adv_router));
447
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);
463 return;
464}
465
466void ospf6_lsa_show(struct vty *vty, struct ospf6_lsa *lsa)
467{
468 char adv_router[64], id[64];
469 struct ospf6_lsa_handler *handler;
470 struct timeval now, res;
471 char duration[16];
472
473 assert(lsa && lsa->header);
474
475 inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
476 inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
477 sizeof(adv_router));
478
479 monotime(&now);
480 timersub(&now, &lsa->installed, &res);
481 timerstring(&res, duration, sizeof(duration));
482
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);
492
493 handler = ospf6_get_lsa_handler(lsa->header->type);
494 if (handler->show == NULL)
495 handler = &unknown_handler;
496 (*handler->show)(vty, lsa);
497
498 vty_out(vty, "%s", VNL);
6452df09 499}
500
501/* OSPFv3 LSA creation/deletion function */
ac4d0be5 502struct ospf6_lsa *ospf6_lsa_create(struct ospf6_lsa_header *header)
718e3744 503{
ac4d0be5 504 struct ospf6_lsa *lsa = NULL;
505 struct ospf6_lsa_header *new_header = NULL;
506 u_int16_t lsa_size = 0;
718e3744 507
ac4d0be5 508 /* size of the entire LSA */
509 lsa_size = ntohs(header->length); /* XXX vulnerable */
718e3744 510
ac4d0be5 511 /* allocate memory for this LSA */
512 new_header =
513 (struct ospf6_lsa_header *)XMALLOC(MTYPE_OSPF6_LSA, lsa_size);
718e3744 514
ac4d0be5 515 /* copy LSA from original header */
516 memcpy(new_header, header, lsa_size);
718e3744 517
ac4d0be5 518 /* LSA information structure */
519 /* allocate memory */
520 lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA,
521 sizeof(struct ospf6_lsa));
718e3744 522
ac4d0be5 523 lsa->header = (struct ospf6_lsa_header *)new_header;
718e3744 524
ac4d0be5 525 /* dump string */
526 ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
718e3744 527
ac4d0be5 528 /* calculate birth of this lsa */
529 ospf6_lsa_age_set(lsa);
718e3744 530
ac4d0be5 531 return lsa;
718e3744 532}
533
ac4d0be5 534struct ospf6_lsa *ospf6_lsa_create_headeronly(struct ospf6_lsa_header *header)
718e3744 535{
ac4d0be5 536 struct ospf6_lsa *lsa = NULL;
537 struct ospf6_lsa_header *new_header = NULL;
718e3744 538
ac4d0be5 539 /* allocate memory for this LSA */
540 new_header = (struct ospf6_lsa_header *)XMALLOC(
541 MTYPE_OSPF6_LSA, sizeof(struct ospf6_lsa_header));
718e3744 542
ac4d0be5 543 /* copy LSA from original header */
544 memcpy(new_header, header, sizeof(struct ospf6_lsa_header));
718e3744 545
ac4d0be5 546 /* LSA information structure */
547 /* allocate memory */
548 lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA,
549 sizeof(struct ospf6_lsa));
718e3744 550
ac4d0be5 551 lsa->header = (struct ospf6_lsa_header *)new_header;
552 SET_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY);
718e3744 553
ac4d0be5 554 /* dump string */
555 ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
718e3744 556
ac4d0be5 557 /* calculate birth of this lsa */
558 ospf6_lsa_age_set(lsa);
718e3744 559
ac4d0be5 560 return lsa;
718e3744 561}
562
ac4d0be5 563void ospf6_lsa_delete(struct ospf6_lsa *lsa)
718e3744 564{
ac4d0be5 565 assert(lsa->lock == 0);
718e3744 566
ac4d0be5 567 /* cancel threads */
568 THREAD_OFF(lsa->expire);
569 THREAD_OFF(lsa->refresh);
718e3744 570
ac4d0be5 571 /* do free */
572 XFREE(MTYPE_OSPF6_LSA, lsa->header);
573 XFREE(MTYPE_OSPF6_LSA, lsa);
508e53e2 574}
718e3744 575
ac4d0be5 576struct ospf6_lsa *ospf6_lsa_copy(struct ospf6_lsa *lsa)
508e53e2 577{
ac4d0be5 578 struct ospf6_lsa *copy = NULL;
508e53e2 579
ac4d0be5 580 ospf6_lsa_age_current(lsa);
581 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY))
582 copy = ospf6_lsa_create_headeronly(lsa->header);
583 else
584 copy = ospf6_lsa_create(lsa->header);
585 assert(copy->lock == 0);
508e53e2 586
ac4d0be5 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;
592 copy->rn = NULL;
508e53e2 593
ac4d0be5 594 return copy;
718e3744 595}
596
508e53e2 597/* increment reference counter of struct ospf6_lsa */
ac4d0be5 598void ospf6_lsa_lock(struct ospf6_lsa *lsa)
718e3744 599{
ac4d0be5 600 lsa->lock++;
601 return;
718e3744 602}
603
508e53e2 604/* decrement reference counter of struct ospf6_lsa */
ac4d0be5 605void ospf6_lsa_unlock(struct ospf6_lsa *lsa)
718e3744 606{
ac4d0be5 607 /* decrement reference counter */
608 assert(lsa->lock > 0);
609 lsa->lock--;
718e3744 610
ac4d0be5 611 if (lsa->lock != 0)
612 return;
508e53e2 613
ac4d0be5 614 ospf6_lsa_delete(lsa);
718e3744 615}
616
6b0655a2 617
508e53e2 618/* ospf6 lsa expiry */
ac4d0be5 619int ospf6_lsa_expire(struct thread *thread)
718e3744 620{
ac4d0be5 621 struct ospf6_lsa *lsa;
718e3744 622
ac4d0be5 623 lsa = (struct ospf6_lsa *)THREAD_ARG(thread);
718e3744 624
ac4d0be5 625 assert(lsa && lsa->header);
626 assert(OSPF6_LSA_IS_MAXAGE(lsa));
627 assert(!lsa->refresh);
718e3744 628
ac4d0be5 629 lsa->expire = (struct thread *)NULL;
718e3744 630
ac4d0be5 631 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)) {
632 zlog_debug("LSA Expire:");
633 ospf6_lsa_header_print(lsa);
634 }
718e3744 635
ac4d0be5 636 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY))
637 return 0; /* dbexchange will do something ... */
718e3744 638
ac4d0be5 639 /* reinstall lsa */
640 ospf6_install_lsa(lsa);
508e53e2 641
ac4d0be5 642 /* reflood lsa */
643 ospf6_flood(NULL, lsa);
bf986da7 644
ac4d0be5 645 /* schedule maxage remover */
646 ospf6_maxage_remove(ospf6);
718e3744 647
ac4d0be5 648 return 0;
718e3744 649}
650
ac4d0be5 651int ospf6_lsa_refresh(struct thread *thread)
718e3744 652{
ac4d0be5 653 struct ospf6_lsa *old, *self, *new;
654 struct ospf6_lsdb *lsdb_self;
718e3744 655
ac4d0be5 656 assert(thread);
657 old = (struct ospf6_lsa *)THREAD_ARG(thread);
658 assert(old && old->header);
718e3744 659
ac4d0be5 660 old->refresh = (struct thread *)NULL;
6452df09 661
ac4d0be5 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);
665 if (self == NULL) {
666 if (IS_OSPF6_DEBUG_LSA_TYPE(old->header->type))
667 zlog_debug("Refresh: could not find self LSA, flush %s",
668 old->name);
669 ospf6_lsa_premature_aging(old);
670 return 0;
671 }
6452df09 672
ac4d0be5 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);
6452df09 679
ac4d0be5 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);
718e3744 684
ac4d0be5 685 /* store it in the LSDB for self-originated LSAs */
686 ospf6_lsdb_add(ospf6_lsa_copy(new), lsdb_self);
718e3744 687
ac4d0be5 688 if (IS_OSPF6_DEBUG_LSA_TYPE(new->header->type)) {
689 zlog_debug("LSA Refresh:");
690 ospf6_lsa_header_print(new);
691 }
718e3744 692
ac4d0be5 693 ospf6_install_lsa(new);
694 ospf6_flood(NULL, new);
6452df09 695
ac4d0be5 696 return 0;
718e3744 697}
698
6b0655a2 699
d8a4e42b 700/* Fletcher Checksum -- Refer to RFC1008. */
718e3744 701
d8a4e42b
JR
702/* All the offsets are zero-based. The offsets in the RFC1008 are
703 one-based. */
ac4d0be5 704unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header *lsa_header)
718e3744 705{
ac4d0be5 706 u_char *buffer = (u_char *)&lsa_header->type;
707 int type_offset = buffer - (u_char *)&lsa_header->age; /* should be 2 */
718e3744 708
ac4d0be5 709 /* Skip the AGE field */
710 u_int16_t len = ntohs(lsa_header->length) - type_offset;
718e3744 711
ac4d0be5 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;
d8a4e42b 715
ac4d0be5 716 return (unsigned short)fletcher_checksum(buffer, len, checksum_offset);
d8a4e42b 717}
718e3744 718
ac4d0be5 719int ospf6_lsa_checksum_valid(struct ospf6_lsa_header *lsa_header)
d8a4e42b 720{
ac4d0be5 721 u_char *buffer = (u_char *)&lsa_header->type;
722 int type_offset = buffer - (u_char *)&lsa_header->age; /* should be 2 */
718e3744 723
ac4d0be5 724 /* Skip the AGE field */
725 u_int16_t len = ntohs(lsa_header->length) - type_offset;
718e3744 726
ac4d0be5 727 return (fletcher_checksum(buffer, len, FLETCHER_CHECKSUM_VALIDATE)
728 == 0);
718e3744 729}
730
ac4d0be5 731void ospf6_lsa_init(void)
6452df09 732{
ac4d0be5 733 ospf6_lsa_handler_vector = vector_init(0);
734 ospf6_install_lsa_handler(&unknown_handler);
718e3744 735}
736
ac4d0be5 737void ospf6_lsa_terminate(void)
ae2254aa 738{
ac4d0be5 739 vector_free(ospf6_lsa_handler_vector);
ae2254aa 740}
6b0655a2 741
ac4d0be5 742static char *ospf6_lsa_handler_name(struct ospf6_lsa_handler *h)
1e05838a 743{
ac4d0be5 744 static char buf[64];
745 unsigned int i;
746 unsigned int size = strlen(h->name);
1e05838a 747
ac4d0be5 748 if (!strcmp(h->name, "unknown") && h->type != OSPF6_LSTYPE_UNKNOWN) {
749 snprintf(buf, sizeof(buf), "%#04hx", h->type);
750 return buf;
751 }
1e05838a 752
ac4d0be5 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]);
756 else
757 buf[i] = h->name[i];
758 }
759 buf[size] = '\0';
760 return buf;
1e05838a 761}
718e3744 762
1e05838a 763DEFUN (debug_ospf6_lsa_type,
764 debug_ospf6_lsa_hex_cmd,
6de69f83 765 "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
508e53e2 766 DEBUG_STR
767 OSPF6_STR
768 "Debug Link State Advertisements (LSAs)\n"
3a2d747c
QY
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"
778 "Dump LSAs\n"
779 "Display LSA's internal information\n")
508e53e2 780{
ac4d0be5 781 int idx_lsa = 3;
782 int idx_type = 4;
783 unsigned int i;
784 struct ospf6_lsa_handler *handler = NULL;
785
786 for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
787 handler = vector_slot(ospf6_lsa_handler_vector, i);
788 if (handler == NULL)
789 continue;
790 if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
791 strlen(argv[idx_lsa]->arg))
792 == 0)
793 break;
794 if (!strcasecmp(argv[idx_lsa]->arg, handler->name))
795 break;
796 handler = NULL;
797 }
798
799 if (handler == NULL)
800 handler = &unknown_handler;
801
802 if (argc == 5) {
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);
809 } else
810 SET_FLAG(handler->debug, OSPF6_LSA_DEBUG);
811
812 return CMD_SUCCESS;
508e53e2 813}
814
1e05838a 815DEFUN (no_debug_ospf6_lsa_type,
816 no_debug_ospf6_lsa_hex_cmd,
6de69f83 817 "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
508e53e2 818 NO_STR
819 DEBUG_STR
820 OSPF6_STR
821 "Debug Link State Advertisements (LSAs)\n"
16cedbb0
QY
822 "Display Router LSAs\n"
823 "Display Network LSAs\n"
824 "Display Inter-Area-Prefix LSAs\n"
3a2d747c 825 "Display Inter-Router LSAs\n"
16cedbb0
QY
826 "Display As-External LSAs\n"
827 "Display Link LSAs\n"
828 "Display Intra-Area-Prefix LSAs\n"
3a2d747c 829 "Display LSAs of unknown origin\n"
16cedbb0
QY
830 "Display details of LSAs\n"
831 "Dump LSAs\n"
832 "Display LSA's internal information\n")
508e53e2 833{
ac4d0be5 834 int idx_lsa = 4;
835 int idx_type = 5;
836 u_int i;
837 struct ospf6_lsa_handler *handler = NULL;
838
839 for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
840 handler = vector_slot(ospf6_lsa_handler_vector, i);
841 if (handler == NULL)
842 continue;
843 if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
844 strlen(argv[idx_lsa]->arg))
845 == 0)
846 break;
847 if (!strcasecmp(argv[idx_lsa]->arg, handler->name))
848 break;
849 }
850
851 if (handler == NULL)
852 return CMD_SUCCESS;
853
854 if (argc == 6) {
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);
861 } else
862 UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG);
863
864 return CMD_SUCCESS;
865}
866
867
868void install_element_ospf6_debug_lsa(void)
869{
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);
718e3744 874}
875
ac4d0be5 876int config_write_ospf6_debug_lsa(struct vty *vty)
877{
878 u_int i;
879 struct ospf6_lsa_handler *handler;
880
881 for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
882 handler = vector_slot(ospf6_lsa_handler_vector, i);
883 if (handler == NULL)
884 continue;
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);
897 }
718e3744 898
ac4d0be5 899 return 0;
900}