]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_lsa.c
ospf6d: split off ospf6_lsa_alloc()
[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 *
896014f4
DL
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
718e3744 19 */
20
21#include <zebra.h>
22
23/* Include other stuffs */
718e3744 24#include "log.h"
718e3744 25#include "linklist.h"
1e05838a 26#include "vector.h"
27#include "vty.h"
718e3744 28#include "command.h"
29#include "memory.h"
718e3744 30#include "thread.h"
d8a4e42b 31#include "checksum.h"
718e3744 32
33#include "ospf6_proto.h"
718e3744 34#include "ospf6_lsa.h"
35#include "ospf6_lsdb.h"
36#include "ospf6_message.h"
718e3744 37
38#include "ospf6_top.h"
39#include "ospf6_area.h"
40#include "ospf6_interface.h"
41#include "ospf6_neighbor.h"
718e3744 42
508e53e2 43#include "ospf6_flood.h"
049207c3 44#include "ospf6d.h"
718e3744 45
1e05838a 46vector ospf6_lsa_handler_vector;
718e3744 47
beadc736 48struct ospf6 *ospf6_get_by_lsdb(struct ospf6_lsa *lsa)
49{
50 struct ospf6 *ospf6 = NULL;
51
52 switch (OSPF6_LSA_SCOPE(lsa->header->type)) {
53 case OSPF6_SCOPE_LINKLOCAL:
54 ospf6 = OSPF6_INTERFACE(lsa->lsdb->data)->area->ospf6;
55 break;
56 case OSPF6_SCOPE_AREA:
57 ospf6 = OSPF6_AREA(lsa->lsdb->data)->ospf6;
58 break;
59 case OSPF6_SCOPE_AS:
60 ospf6 = OSPF6_PROCESS(lsa->lsdb->data);
61 break;
62 default:
63 assert(0);
64 break;
65 }
66 return ospf6;
67}
68
e4bacbaa
YR
69static int ospf6_unknown_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
70 json_object *json_obj, bool use_json)
1e05838a 71{
d7c0a89a 72 uint8_t *start, *end, *current;
d62a17ae 73 char byte[4];
1e05838a 74
d7c0a89a
QY
75 start = (uint8_t *)lsa->header + sizeof(struct ospf6_lsa_header);
76 end = (uint8_t *)lsa->header + ntohs(lsa->header->length);
1e05838a 77
e4bacbaa
YR
78 if (use_json)
79 json_object_string_add(json_obj, "LsaType", "unknown");
80 else {
81 vty_out(vty, " Unknown contents:\n");
82 for (current = start; current < end; current++) {
83 if ((current - start) % 16 == 0)
84 vty_out(vty, "\n ");
85 else if ((current - start) % 4 == 0)
86 vty_out(vty, " ");
87
88 snprintf(byte, sizeof(byte), "%02x", *current);
89 vty_out(vty, "%s", byte);
90 }
718e3744 91
e4bacbaa 92 vty_out(vty, "\n\n");
d62a17ae 93 }
d62a17ae 94 return 0;
1e05838a 95}
96
3981b5c7
VJ
97static struct ospf6_lsa_handler unknown_handler = {
98 .lh_type = OSPF6_LSTYPE_UNKNOWN,
99 .lh_name = "Unknown",
100 .lh_short_name = "Unk",
101 .lh_show = ospf6_unknown_lsa_show,
102 .lh_get_prefix_str = NULL,
103 .lh_debug = 0 /* No default debug */
104};
1e05838a 105
4062abfa 106void ospf6_install_lsa_handler(struct ospf6_lsa_handler *handler)
1e05838a 107{
d62a17ae 108 /* type in handler is host byte order */
3981b5c7
VJ
109 int index = handler->lh_type & OSPF6_LSTYPE_FCODE_MASK;
110 vector_set_index(ospf6_lsa_handler_vector, index, (void *)handler);
1e05838a 111}
112
4062abfa 113struct ospf6_lsa_handler *ospf6_get_lsa_handler(uint16_t type)
1e05838a 114{
4062abfa 115 struct ospf6_lsa_handler *handler = NULL;
d62a17ae 116 unsigned int index = ntohs(type) & OSPF6_LSTYPE_FCODE_MASK;
1e05838a 117
d62a17ae 118 if (index >= vector_active(ospf6_lsa_handler_vector))
119 handler = &unknown_handler;
120 else
121 handler = vector_slot(ospf6_lsa_handler_vector, index);
1e05838a 122
d62a17ae 123 if (handler == NULL)
124 handler = &unknown_handler;
2680aa2b 125
d62a17ae 126 return handler;
1e05838a 127}
718e3744 128
d7c0a89a 129const char *ospf6_lstype_name(uint16_t type)
508e53e2 130{
d62a17ae 131 static char buf[8];
3981b5c7 132 const struct ospf6_lsa_handler *handler;
508e53e2 133
d62a17ae 134 handler = ospf6_get_lsa_handler(type);
135 if (handler && handler != &unknown_handler)
3981b5c7 136 return handler->lh_name;
718e3744 137
d62a17ae 138 snprintf(buf, sizeof(buf), "0x%04hx", ntohs(type));
139 return buf;
718e3744 140}
141
d7c0a89a 142const char *ospf6_lstype_short_name(uint16_t type)
e68a6767 143{
d62a17ae 144 static char buf[8];
3981b5c7 145 const struct ospf6_lsa_handler *handler;
e68a6767 146
d62a17ae 147 handler = ospf6_get_lsa_handler(type);
3e67830c 148 if (handler)
3981b5c7 149 return handler->lh_short_name;
e68a6767 150
d62a17ae 151 snprintf(buf, sizeof(buf), "0x%04hx", ntohs(type));
152 return buf;
e68a6767
DD
153}
154
d7c0a89a 155uint8_t ospf6_lstype_debug(uint16_t type)
1e05838a 156{
3981b5c7 157 const struct ospf6_lsa_handler *handler;
d62a17ae 158 handler = ospf6_get_lsa_handler(type);
01db90cd 159 return handler->lh_debug;
1e05838a 160}
161
718e3744 162/* RFC2328: Section 13.2 */
d62a17ae 163int ospf6_lsa_is_differ(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
718e3744 164{
d62a17ae 165 int len;
718e3744 166
d62a17ae 167 assert(OSPF6_LSA_IS_SAME(lsa1, lsa2));
718e3744 168
d62a17ae 169 /* XXX, Options ??? */
718e3744 170
d62a17ae 171 ospf6_lsa_age_current(lsa1);
172 ospf6_lsa_age_current(lsa2);
173 if (ntohs(lsa1->header->age) == OSPF_LSA_MAXAGE
174 && ntohs(lsa2->header->age) != OSPF_LSA_MAXAGE)
175 return 1;
176 if (ntohs(lsa1->header->age) != OSPF_LSA_MAXAGE
177 && ntohs(lsa2->header->age) == OSPF_LSA_MAXAGE)
178 return 1;
718e3744 179
d62a17ae 180 /* compare body */
181 if (ntohs(lsa1->header->length) != ntohs(lsa2->header->length))
182 return 1;
718e3744 183
d62a17ae 184 len = ntohs(lsa1->header->length) - sizeof(struct ospf6_lsa_header);
185 return memcmp(lsa1->header + 1, lsa2->header + 1, len);
718e3744 186}
187
d62a17ae 188int ospf6_lsa_is_changed(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
718e3744 189{
d62a17ae 190 int length;
718e3744 191
d62a17ae 192 if (OSPF6_LSA_IS_MAXAGE(lsa1) ^ OSPF6_LSA_IS_MAXAGE(lsa2))
193 return 1;
194 if (ntohs(lsa1->header->length) != ntohs(lsa2->header->length))
195 return 1;
196 /* Going beyond LSA headers to compare the payload only makes sense,
197 * when both LSAs aren't header-only. */
198 if (CHECK_FLAG(lsa1->flag, OSPF6_LSA_HEADERONLY)
199 != CHECK_FLAG(lsa2->flag, OSPF6_LSA_HEADERONLY)) {
200 zlog_warn(
201 "%s: only one of two (%s, %s) LSAs compared is header-only",
202 __func__, lsa1->name, lsa2->name);
203 return 1;
204 }
205 if (CHECK_FLAG(lsa1->flag, OSPF6_LSA_HEADERONLY))
206 return 0;
718e3744 207
d62a17ae 208 length = OSPF6_LSA_SIZE(lsa1->header) - sizeof(struct ospf6_lsa_header);
209 /* Once upper layer verifies LSAs received, length underrun should
210 * become a warning. */
211 if (length <= 0)
212 return 0;
718e3744 213
d62a17ae 214 return memcmp(OSPF6_LSA_HEADER_END(lsa1->header),
215 OSPF6_LSA_HEADER_END(lsa2->header), length);
718e3744 216}
217
218/* ospf6 age functions */
3b68735f 219/* calculate birth */
da086a3b 220void ospf6_lsa_age_set(struct ospf6_lsa *lsa)
718e3744 221{
d62a17ae 222 struct timeval now;
718e3744 223
d62a17ae 224 assert(lsa && lsa->header);
718e3744 225
d62a17ae 226 monotime(&now);
718e3744 227
d62a17ae 228 lsa->birth.tv_sec = now.tv_sec - ntohs(lsa->header->age);
229 lsa->birth.tv_usec = now.tv_usec;
3b68735f 230
d62a17ae 231 return;
718e3744 232}
233
234/* this function calculates current age from its birth,
235 then update age field of LSA header. return value is current age */
d7c0a89a 236uint16_t ospf6_lsa_age_current(struct ospf6_lsa *lsa)
718e3744 237{
d62a17ae 238 struct timeval now;
d7c0a89a
QY
239 uint32_t ulage;
240 uint16_t age;
718e3744 241
d62a17ae 242 assert(lsa);
243 assert(lsa->header);
718e3744 244
d62a17ae 245 /* current time */
246 monotime(&now);
718e3744 247
d62a17ae 248 if (ntohs(lsa->header->age) >= OSPF_LSA_MAXAGE) {
249 /* ospf6_lsa_premature_aging () sets age to MAXAGE; when using
250 relative time, we cannot compare against lsa birth time, so
251 we catch this special case here. */
252 lsa->header->age = htons(OSPF_LSA_MAXAGE);
253 return OSPF_LSA_MAXAGE;
254 }
255 /* calculate age */
256 ulage = now.tv_sec - lsa->birth.tv_sec;
718e3744 257
d62a17ae 258 /* if over MAXAGE, set to it */
259 age = (ulage > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : ulage);
718e3744 260
d62a17ae 261 lsa->header->age = htons(age);
262 return age;
718e3744 263}
264
265/* update age field of LSA header with adding InfTransDelay */
d7c0a89a 266void ospf6_lsa_age_update_to_send(struct ospf6_lsa *lsa, uint32_t transdelay)
d62a17ae 267{
268 unsigned short age;
269
270 age = ospf6_lsa_age_current(lsa) + transdelay;
271 if (age > OSPF_LSA_MAXAGE)
272 age = OSPF_LSA_MAXAGE;
273 lsa->header->age = htons(age);
274}
275
276void ospf6_lsa_premature_aging(struct ospf6_lsa *lsa)
277{
278 /* log */
279 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type))
280 zlog_debug("LSA: Premature aging: %s", lsa->name);
281
282 THREAD_OFF(lsa->expire);
283 THREAD_OFF(lsa->refresh);
284
285 /*
286 * We clear the LSA from the neighbor retx lists now because it
287 * will not get deleted later. Essentially, changing the age to
288 * MaxAge will prevent this LSA from being matched with its
289 * existing entries in the retx list thereby causing those entries
290 * to be silently replaced with its MaxAged version, but with ever
291 * increasing retx count causing this LSA to remain forever and
292 * for the MaxAge remover thread to be called forever too.
293 *
294 * The reason the previous entry silently disappears is that when
295 * entry is added to a neighbor's retx list, it replaces the existing
296 * entry. But since the ospf6_lsdb_add() routine is generic and not
297 * aware
298 * of the special semantics of retx count, the retx count is not
299 * decremented when its replaced. Attempting to add the incr and decr
300 * retx count routines as the hook_add and hook_remove for the retx
301 * lists
302 * have a problem because the hook_remove routine is called for MaxAge
303 * entries (as will be the case in a traditional LSDB, unlike in this
304 * case
305 * where an LSDB is used as an efficient tree structure to store all
306 * kinds
307 * of data) that are added instead of calling the hook_add routine.
308 */
309
310 ospf6_flood_clear(lsa);
311
312 lsa->header->age = htons(OSPF_LSA_MAXAGE);
313 thread_execute(master, ospf6_lsa_expire, lsa, 0);
718e3744 314}
315
316/* check which is more recent. if a is more recent, return -1;
317 if the same, return 0; otherwise(b is more recent), return 1 */
d62a17ae 318int ospf6_lsa_compare(struct ospf6_lsa *a, struct ospf6_lsa *b)
718e3744 319{
d62a17ae 320 int32_t seqnuma, seqnumb;
d7c0a89a
QY
321 uint16_t cksuma, cksumb;
322 uint16_t agea, ageb;
d62a17ae 323
324 assert(a && a->header);
325 assert(b && b->header);
326 assert(OSPF6_LSA_IS_SAME(a, b));
718e3744 327
d62a17ae 328 seqnuma = (int32_t)ntohl(a->header->seqnum);
329 seqnumb = (int32_t)ntohl(b->header->seqnum);
718e3744 330
d62a17ae 331 /* compare by sequence number */
332 if (seqnuma > seqnumb)
333 return -1;
334 if (seqnuma < seqnumb)
335 return 1;
336
337 /* Checksum */
338 cksuma = ntohs(a->header->checksum);
339 cksumb = ntohs(b->header->checksum);
340 if (cksuma > cksumb)
341 return -1;
342 if (cksuma < cksumb)
343 return 0;
344
345 /* Update Age */
346 agea = ospf6_lsa_age_current(a);
347 ageb = ospf6_lsa_age_current(b);
348
349 /* MaxAge check */
350 if (agea == OSPF_LSA_MAXAGE && ageb != OSPF_LSA_MAXAGE)
351 return -1;
352 else if (agea != OSPF_LSA_MAXAGE && ageb == OSPF_LSA_MAXAGE)
353 return 1;
354
355 /* Age check */
356 if (agea > ageb && agea - ageb >= OSPF_LSA_MAXAGE_DIFF)
357 return 1;
358 else if (agea < ageb && ageb - agea >= OSPF_LSA_MAXAGE_DIFF)
359 return -1;
360
361 /* neither recent */
362 return 0;
363}
364
365char *ospf6_lsa_printbuf(struct ospf6_lsa *lsa, char *buf, int size)
366{
367 char id[16], adv_router[16];
368 inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
369 inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
370 sizeof(adv_router));
371 snprintf(buf, size, "[%s Id:%s Adv:%s]",
372 ospf6_lstype_name(lsa->header->type), id, adv_router);
373 return buf;
374}
375
376void ospf6_lsa_header_print_raw(struct ospf6_lsa_header *header)
377{
378 char id[16], adv_router[16];
379 inet_ntop(AF_INET, &header->id, id, sizeof(id));
380 inet_ntop(AF_INET, &header->adv_router, adv_router, sizeof(adv_router));
381 zlog_debug(" [%s Id:%s Adv:%s]", ospf6_lstype_name(header->type), id,
382 adv_router);
383 zlog_debug(" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
d7c0a89a 384 ntohs(header->age), (unsigned long)ntohl(header->seqnum),
d62a17ae 385 ntohs(header->checksum), ntohs(header->length));
386}
387
388void ospf6_lsa_header_print(struct ospf6_lsa *lsa)
389{
390 ospf6_lsa_age_current(lsa);
391 ospf6_lsa_header_print_raw(lsa->header);
392}
393
394void ospf6_lsa_show_summary_header(struct vty *vty)
395{
396 vty_out(vty, "%-4s %-15s%-15s%4s %8s %30s\n", "Type", "LSId",
397 "AdvRouter", "Age", "SeqNum", "Payload");
398}
399
e4bacbaa
YR
400void ospf6_lsa_show_summary(struct vty *vty, struct ospf6_lsa *lsa,
401 json_object *json_array, bool use_json)
d62a17ae 402{
403 char adv_router[16], id[16];
404 int type;
3981b5c7 405 const struct ospf6_lsa_handler *handler;
e4bacbaa 406 char buf[64];
d62a17ae 407 int cnt = 0;
e4bacbaa 408 json_object *json_obj = NULL;
d62a17ae 409
410 assert(lsa);
411 assert(lsa->header);
412
413 inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
414 inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
415 sizeof(adv_router));
416
417 type = ntohs(lsa->header->type);
418 handler = ospf6_get_lsa_handler(lsa->header->type);
e4bacbaa
YR
419
420 if (use_json)
421 json_obj = json_object_new_object();
422
3e67830c 423 switch (type) {
424 case OSPF6_LSTYPE_INTER_PREFIX:
425 case OSPF6_LSTYPE_INTER_ROUTER:
426 case OSPF6_LSTYPE_AS_EXTERNAL:
e4bacbaa
YR
427 if (use_json) {
428 json_object_string_add(
429 json_obj, "type",
430 ospf6_lstype_short_name(lsa->header->type));
431 json_object_string_add(json_obj, "lsId", id);
432 json_object_string_add(json_obj, "advRouter",
433 adv_router);
434 json_object_int_add(json_obj, "age",
435 ospf6_lsa_age_current(lsa));
436 json_object_int_add(
437 json_obj, "seqNum",
438 (unsigned long)ntohl(lsa->header->seqnum));
439 json_object_string_add(
440 json_obj, "payload",
441 handler->lh_get_prefix_str(lsa, buf,
442 sizeof(buf), 0));
443 json_object_array_add(json_array, json_obj);
444 } else
445 vty_out(vty, "%-4s %-15s%-15s%4hu %8lx %30s\n",
446 ospf6_lstype_short_name(lsa->header->type), id,
447 adv_router, ospf6_lsa_age_current(lsa),
448 (unsigned long)ntohl(lsa->header->seqnum),
449 handler->lh_get_prefix_str(lsa, buf,
450 sizeof(buf), 0));
3e67830c 451 break;
452 case OSPF6_LSTYPE_ROUTER:
453 case OSPF6_LSTYPE_NETWORK:
454 case OSPF6_LSTYPE_GROUP_MEMBERSHIP:
455 case OSPF6_LSTYPE_TYPE_7:
456 case OSPF6_LSTYPE_LINK:
457 case OSPF6_LSTYPE_INTRA_PREFIX:
3981b5c7 458 while (handler->lh_get_prefix_str(lsa, buf, sizeof(buf), cnt)
d62a17ae 459 != NULL) {
e4bacbaa
YR
460 if (use_json) {
461 json_object_string_add(
462 json_obj, "type",
463 ospf6_lstype_short_name(
464 lsa->header->type));
465 json_object_string_add(json_obj, "lsId", id);
466 json_object_string_add(json_obj, "advRouter",
467 adv_router);
468 json_object_int_add(json_obj, "age",
469 ospf6_lsa_age_current(lsa));
470 json_object_int_add(
471 json_obj, "seqNum",
472 (unsigned long)ntohl(
473 lsa->header->seqnum));
474 json_object_string_add(json_obj, "payload",
475 buf);
476 json_object_array_add(json_array, json_obj);
477 json_obj = json_object_new_object();
478 } else
479 vty_out(vty, "%-4s %-15s%-15s%4hu %8lx %30s\n",
480 ospf6_lstype_short_name(
481 lsa->header->type),
482 id, adv_router,
483 ospf6_lsa_age_current(lsa),
484 (unsigned long)ntohl(
485 lsa->header->seqnum),
486 buf);
d62a17ae 487 cnt++;
488 }
e4bacbaa
YR
489 if (use_json)
490 json_object_free(json_obj);
3e67830c 491 break;
492 default:
e4bacbaa
YR
493 if (use_json) {
494 json_object_string_add(
495 json_obj, "type",
496 ospf6_lstype_short_name(lsa->header->type));
497 json_object_string_add(json_obj, "lsId", id);
498 json_object_string_add(json_obj, "advRouter",
499 adv_router);
500 json_object_int_add(json_obj, "age",
501 ospf6_lsa_age_current(lsa));
502 json_object_int_add(
503 json_obj, "seqNum",
504 (unsigned long)ntohl(lsa->header->seqnum));
505 json_object_array_add(json_array, json_obj);
506 } else
507 vty_out(vty, "%-4s %-15s%-15s%4hu %8lx\n",
508 ospf6_lstype_short_name(lsa->header->type), id,
509 adv_router, ospf6_lsa_age_current(lsa),
510 (unsigned long)ntohl(lsa->header->seqnum));
3e67830c 511 break;
e68a6767 512 }
d62a17ae 513}
514
e4bacbaa
YR
515void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa,
516 json_object *json_array, bool use_json)
d62a17ae 517{
d7c0a89a 518 uint8_t *start, *end, *current;
d62a17ae 519 char byte[4];
520
d7c0a89a
QY
521 start = (uint8_t *)lsa->header;
522 end = (uint8_t *)lsa->header + ntohs(lsa->header->length);
d62a17ae 523
e4bacbaa
YR
524 if (use_json)
525 return;
526
d62a17ae 527 vty_out(vty, "\n");
528 vty_out(vty, "%s:\n", lsa->name);
529
530 for (current = start; current < end; current++) {
531 if ((current - start) % 16 == 0)
532 vty_out(vty, "\n ");
533 else if ((current - start) % 4 == 0)
534 vty_out(vty, " ");
535
536 snprintf(byte, sizeof(byte), "%02x", *current);
537 vty_out(vty, "%s", byte);
538 }
539
540 vty_out(vty, "\n\n");
e4bacbaa 541
d62a17ae 542 return;
543}
544
e4bacbaa
YR
545void ospf6_lsa_show_internal(struct vty *vty, struct ospf6_lsa *lsa,
546 json_object *json_array, bool use_json)
d62a17ae 547{
548 char adv_router[64], id[64];
e4bacbaa 549 json_object *json_obj;
d62a17ae 550
551 assert(lsa && lsa->header);
552
553 inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
554 inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
555 sizeof(adv_router));
556
e4bacbaa
YR
557 if (use_json) {
558 json_obj = json_object_new_object();
559 json_object_int_add(json_obj, "age",
560 ospf6_lsa_age_current(lsa));
561 json_object_string_add(json_obj, "type",
562 ospf6_lstype_name(lsa->header->type));
563 json_object_string_add(json_obj, "linkStateId", id);
564 json_object_string_add(json_obj, "advertisingRouter",
565 adv_router);
566 json_object_int_add(json_obj, "lsSequenceNumber",
567 (unsigned long)ntohl(lsa->header->seqnum));
568 json_object_int_add(json_obj, "checksum",
569 ntohs(lsa->header->checksum));
570 json_object_int_add(json_obj, "length",
571 ntohs(lsa->header->length));
572 json_object_int_add(json_obj, "flag", lsa->flag);
573 json_object_int_add(json_obj, "lock", lsa->lock);
574 json_object_int_add(json_obj, "reTxCount", lsa->retrans_count);
575
576 /* Threads Data not added */
577 json_object_array_add(json_array, json_obj);
578 } else {
579 vty_out(vty, "\n");
580 vty_out(vty, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa),
581 ospf6_lstype_name(lsa->header->type));
582 vty_out(vty, "Link State ID: %s\n", id);
583 vty_out(vty, "Advertising Router: %s\n", adv_router);
584 vty_out(vty, "LS Sequence Number: %#010lx\n",
585 (unsigned long)ntohl(lsa->header->seqnum));
586 vty_out(vty, "CheckSum: %#06hx Length: %hu\n",
587 ntohs(lsa->header->checksum),
588 ntohs(lsa->header->length));
589 vty_out(vty, "Flag: %x \n", lsa->flag);
590 vty_out(vty, "Lock: %d \n", lsa->lock);
591 vty_out(vty, "ReTx Count: %d\n", lsa->retrans_count);
592 vty_out(vty, "Threads: Expire: 0x%p, Refresh: 0x%p \n",
593 (void *)lsa->expire, (void *)lsa->refresh);
594 vty_out(vty, "\n");
595 }
d62a17ae 596 return;
597}
598
e4bacbaa
YR
599void ospf6_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
600 json_object *json_array, bool use_json)
d62a17ae 601{
602 char adv_router[64], id[64];
3981b5c7 603 const struct ospf6_lsa_handler *handler;
d62a17ae 604 struct timeval now, res;
68bfcc05 605 char duration[64];
e4bacbaa 606 json_object *json_obj = NULL;
d62a17ae 607
608 assert(lsa && lsa->header);
609
610 inet_ntop(AF_INET, &lsa->header->id, id, sizeof(id));
611 inet_ntop(AF_INET, &lsa->header->adv_router, adv_router,
612 sizeof(adv_router));
613
614 monotime(&now);
615 timersub(&now, &lsa->installed, &res);
616 timerstring(&res, duration, sizeof(duration));
e4bacbaa
YR
617 if (use_json) {
618 json_obj = json_object_new_object();
619 json_object_int_add(json_obj, "age",
620 ospf6_lsa_age_current(lsa));
621 json_object_string_add(json_obj, "type",
622 ospf6_lstype_name(lsa->header->type));
623 json_object_string_add(json_obj, "advertisingRouter",
624 adv_router);
625 json_object_int_add(json_obj, "lsSequenceNumber",
626 (unsigned long)ntohl(lsa->header->seqnum));
627 json_object_int_add(json_obj, "checkSum",
628 ntohs(lsa->header->checksum));
629 json_object_int_add(json_obj, "length",
630 ntohs(lsa->header->length));
631 json_object_string_add(json_obj, "duration", duration);
632 } else {
633 vty_out(vty, "Age: %4hu Type: %s\n", ospf6_lsa_age_current(lsa),
634 ospf6_lstype_name(lsa->header->type));
635 vty_out(vty, "Link State ID: %s\n", id);
636 vty_out(vty, "Advertising Router: %s\n", adv_router);
637 vty_out(vty, "LS Sequence Number: %#010lx\n",
638 (unsigned long)ntohl(lsa->header->seqnum));
639 vty_out(vty, "CheckSum: %#06hx Length: %hu\n",
640 ntohs(lsa->header->checksum),
641 ntohs(lsa->header->length));
642 vty_out(vty, "Duration: %s\n", duration);
643 }
d62a17ae 644
645 handler = ospf6_get_lsa_handler(lsa->header->type);
3981b5c7
VJ
646
647 if (handler->lh_show != NULL)
e4bacbaa 648 handler->lh_show(vty, lsa, json_obj, use_json);
3981b5c7
VJ
649 else {
650 assert(unknown_handler.lh_show != NULL);
e4bacbaa 651 unknown_handler.lh_show(vty, lsa, json_obj, use_json);
3981b5c7 652 }
d62a17ae 653
e4bacbaa
YR
654 if (use_json)
655 json_object_array_add(json_array, json_obj);
656 else
657 vty_out(vty, "\n");
6452df09 658}
659
771e1fbe
DL
660struct ospf6_lsa *ospf6_lsa_alloc(size_t lsa_length)
661{
662 lsa = XCALLOC(MTYPE_OSPF6_LSA, sizeof(struct ospf6_lsa));
663 lsa->header = XMALLOC(MTYPE_OSPF6_LSA_HEADER, lsa_length);
664
665 return lsa;
666}
667
6452df09 668/* OSPFv3 LSA creation/deletion function */
d62a17ae 669struct ospf6_lsa *ospf6_lsa_create(struct ospf6_lsa_header *header)
718e3744 670{
d62a17ae 671 struct ospf6_lsa *lsa = NULL;
d7c0a89a 672 uint16_t lsa_size = 0;
718e3744 673
d62a17ae 674 /* size of the entire LSA */
675 lsa_size = ntohs(header->length); /* XXX vulnerable */
718e3744 676
771e1fbe 677 lsa = ospf6_lsa_alloc(lsa_size);
718e3744 678
d62a17ae 679 /* copy LSA from original header */
771e1fbe 680 memcpy(lsa->header, header, lsa_size);
718e3744 681
d62a17ae 682 /* dump string */
683 ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
718e3744 684
d62a17ae 685 /* calculate birth of this lsa */
686 ospf6_lsa_age_set(lsa);
718e3744 687
d62a17ae 688 return lsa;
718e3744 689}
690
d62a17ae 691struct ospf6_lsa *ospf6_lsa_create_headeronly(struct ospf6_lsa_header *header)
718e3744 692{
d62a17ae 693 struct ospf6_lsa *lsa = NULL;
718e3744 694
771e1fbe 695 lsa = ospf6_lsa_alloc(sizeof(struct ospf6_lsa_header));
718e3744 696
771e1fbe 697 memcpy(lsa->header, header, sizeof(struct ospf6_lsa_header));
718e3744 698
d62a17ae 699 SET_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY);
718e3744 700
d62a17ae 701 /* dump string */
702 ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
718e3744 703
d62a17ae 704 /* calculate birth of this lsa */
705 ospf6_lsa_age_set(lsa);
718e3744 706
d62a17ae 707 return lsa;
718e3744 708}
709
d62a17ae 710void ospf6_lsa_delete(struct ospf6_lsa *lsa)
718e3744 711{
d62a17ae 712 assert(lsa->lock == 0);
718e3744 713
d62a17ae 714 /* cancel threads */
715 THREAD_OFF(lsa->expire);
716 THREAD_OFF(lsa->refresh);
718e3744 717
d62a17ae 718 /* do free */
d107621d 719 XFREE(MTYPE_OSPF6_LSA_HEADER, lsa->header);
d62a17ae 720 XFREE(MTYPE_OSPF6_LSA, lsa);
508e53e2 721}
718e3744 722
d62a17ae 723struct ospf6_lsa *ospf6_lsa_copy(struct ospf6_lsa *lsa)
508e53e2 724{
d62a17ae 725 struct ospf6_lsa *copy = NULL;
508e53e2 726
d62a17ae 727 ospf6_lsa_age_current(lsa);
728 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY))
729 copy = ospf6_lsa_create_headeronly(lsa->header);
730 else
731 copy = ospf6_lsa_create(lsa->header);
732 assert(copy->lock == 0);
508e53e2 733
d62a17ae 734 copy->birth = lsa->birth;
735 copy->originated = lsa->originated;
736 copy->received = lsa->received;
737 copy->installed = lsa->installed;
738 copy->lsdb = lsa->lsdb;
739 copy->rn = NULL;
508e53e2 740
d62a17ae 741 return copy;
718e3744 742}
743
508e53e2 744/* increment reference counter of struct ospf6_lsa */
62270cc3 745struct ospf6_lsa *ospf6_lsa_lock(struct ospf6_lsa *lsa)
718e3744 746{
d62a17ae 747 lsa->lock++;
62270cc3 748 return lsa;
718e3744 749}
750
508e53e2 751/* decrement reference counter of struct ospf6_lsa */
744ba569 752struct ospf6_lsa *ospf6_lsa_unlock(struct ospf6_lsa *lsa)
718e3744 753{
d62a17ae 754 /* decrement reference counter */
755 assert(lsa->lock > 0);
756 lsa->lock--;
718e3744 757
d62a17ae 758 if (lsa->lock != 0)
744ba569 759 return lsa;
508e53e2 760
d62a17ae 761 ospf6_lsa_delete(lsa);
744ba569 762 return NULL;
718e3744 763}
764
6b0655a2 765
508e53e2 766/* ospf6 lsa expiry */
d62a17ae 767int ospf6_lsa_expire(struct thread *thread)
718e3744 768{
d62a17ae 769 struct ospf6_lsa *lsa;
beadc736 770 struct ospf6 *ospf6;
718e3744 771
d62a17ae 772 lsa = (struct ospf6_lsa *)THREAD_ARG(thread);
718e3744 773
d62a17ae 774 assert(lsa && lsa->header);
775 assert(OSPF6_LSA_IS_MAXAGE(lsa));
776 assert(!lsa->refresh);
718e3744 777
d62a17ae 778 lsa->expire = (struct thread *)NULL;
718e3744 779
d62a17ae 780 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)) {
781 zlog_debug("LSA Expire:");
782 ospf6_lsa_header_print(lsa);
783 }
718e3744 784
d62a17ae 785 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY))
786 return 0; /* dbexchange will do something ... */
beadc736 787 ospf6 = ospf6_get_by_lsdb(lsa);
d62a17ae 788 /* reinstall lsa */
789 ospf6_install_lsa(lsa);
508e53e2 790
d62a17ae 791 /* reflood lsa */
792 ospf6_flood(NULL, lsa);
bf986da7 793
d62a17ae 794 /* schedule maxage remover */
795 ospf6_maxage_remove(ospf6);
718e3744 796
d62a17ae 797 return 0;
718e3744 798}
799
d62a17ae 800int ospf6_lsa_refresh(struct thread *thread)
718e3744 801{
d62a17ae 802 struct ospf6_lsa *old, *self, *new;
803 struct ospf6_lsdb *lsdb_self;
6452df09 804
d62a17ae 805 old = (struct ospf6_lsa *)THREAD_ARG(thread);
806 assert(old && old->header);
6452df09 807
d62a17ae 808 old->refresh = (struct thread *)NULL;
6452df09 809
d62a17ae 810 lsdb_self = ospf6_get_scoped_lsdb_self(old);
811 self = ospf6_lsdb_lookup(old->header->type, old->header->id,
812 old->header->adv_router, lsdb_self);
813 if (self == NULL) {
814 if (IS_OSPF6_DEBUG_LSA_TYPE(old->header->type))
815 zlog_debug("Refresh: could not find self LSA, flush %s",
816 old->name);
817 ospf6_lsa_premature_aging(old);
818 return 0;
819 }
718e3744 820
d62a17ae 821 /* Reset age, increment LS sequence number. */
822 self->header->age = htons(0);
823 self->header->seqnum =
824 ospf6_new_ls_seqnum(self->header->type, self->header->id,
825 self->header->adv_router, old->lsdb);
826 ospf6_lsa_checksum(self->header);
827
828 new = ospf6_lsa_create(self->header);
829 new->lsdb = old->lsdb;
830 new->refresh = NULL;
831 thread_add_timer(master, ospf6_lsa_refresh, new, OSPF_LS_REFRESH_TIME,
832 &new->refresh);
833
834 /* store it in the LSDB for self-originated LSAs */
835 ospf6_lsdb_add(ospf6_lsa_copy(new), lsdb_self);
836
837 if (IS_OSPF6_DEBUG_LSA_TYPE(new->header->type)) {
838 zlog_debug("LSA Refresh:");
839 ospf6_lsa_header_print(new);
840 }
718e3744 841
d62a17ae 842 ospf6_install_lsa(new);
843 ospf6_flood(NULL, new);
6452df09 844
d62a17ae 845 return 0;
718e3744 846}
847
beadc736 848void ospf6_flush_self_originated_lsas_now(struct ospf6 *ospf6)
76249532
CS
849{
850 struct listnode *node;
851 struct ospf6_area *oa;
852 struct ospf6_lsa *lsa;
853 const struct route_node *end = NULL;
854 uint32_t type, adv_router;
855
856 ospf6->inst_shutdown = 1;
857
858 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
996c9314
LB
859 end = ospf6_lsdb_head(oa->lsdb_self, 0, 0, ospf6->router_id,
860 &lsa);
76249532
CS
861 while (lsa) {
862 /* RFC 2328 (14.1): Set MAXAGE */
863 lsa->header->age = htons(OSPF_LSA_MAXAGE);
864 /* Flood MAXAGE LSA*/
865 ospf6_flood(NULL, lsa);
866
867 lsa = ospf6_lsdb_next(end, lsa);
868 }
869 }
870
871 type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
872 adv_router = ospf6->router_id;
873 for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, adv_router, lsa)) {
874 /* RFC 2328 (14.1): Set MAXAGE */
875 lsa->header->age = htons(OSPF_LSA_MAXAGE);
876 ospf6_flood(NULL, lsa);
877 }
878}
6b0655a2 879
d8a4e42b 880/* Fletcher Checksum -- Refer to RFC1008. */
718e3744 881
d8a4e42b
JR
882/* All the offsets are zero-based. The offsets in the RFC1008 are
883 one-based. */
d62a17ae 884unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header *lsa_header)
718e3744 885{
d7c0a89a
QY
886 uint8_t *buffer = (uint8_t *)&lsa_header->type;
887 int type_offset =
888 buffer - (uint8_t *)&lsa_header->age; /* should be 2 */
718e3744 889
d62a17ae 890 /* Skip the AGE field */
d7c0a89a 891 uint16_t len = ntohs(lsa_header->length) - type_offset;
718e3744 892
d62a17ae 893 /* Checksum offset starts from "type" field, not the beginning of the
894 lsa_header struct. The offset is 14, rather than 16. */
d7c0a89a 895 int checksum_offset = (uint8_t *)&lsa_header->checksum - buffer;
d8a4e42b 896
d62a17ae 897 return (unsigned short)fletcher_checksum(buffer, len, checksum_offset);
d8a4e42b 898}
718e3744 899
d62a17ae 900int ospf6_lsa_checksum_valid(struct ospf6_lsa_header *lsa_header)
d8a4e42b 901{
d7c0a89a
QY
902 uint8_t *buffer = (uint8_t *)&lsa_header->type;
903 int type_offset =
904 buffer - (uint8_t *)&lsa_header->age; /* should be 2 */
718e3744 905
d62a17ae 906 /* Skip the AGE field */
d7c0a89a 907 uint16_t len = ntohs(lsa_header->length) - type_offset;
718e3744 908
d62a17ae 909 return (fletcher_checksum(buffer, len, FLETCHER_CHECKSUM_VALIDATE)
910 == 0);
718e3744 911}
912
d62a17ae 913void ospf6_lsa_init(void)
6452df09 914{
d62a17ae 915 ospf6_lsa_handler_vector = vector_init(0);
916 ospf6_install_lsa_handler(&unknown_handler);
718e3744 917}
918
d62a17ae 919void ospf6_lsa_terminate(void)
ae2254aa 920{
d62a17ae 921 vector_free(ospf6_lsa_handler_vector);
ae2254aa 922}
6b0655a2 923
3981b5c7 924static char *ospf6_lsa_handler_name(const struct ospf6_lsa_handler *h)
1e05838a 925{
d62a17ae 926 static char buf[64];
927 unsigned int i;
3981b5c7 928 unsigned int size = strlen(h->lh_name);
1e05838a 929
996c9314
LB
930 if (!strcmp(h->lh_name, "unknown")
931 && h->lh_type != OSPF6_LSTYPE_UNKNOWN) {
3981b5c7 932 snprintf(buf, sizeof(buf), "%#04hx", h->lh_type);
d62a17ae 933 return buf;
934 }
1e05838a 935
d62a17ae 936 for (i = 0; i < MIN(size, sizeof(buf)); i++) {
3981b5c7
VJ
937 if (!islower((unsigned char)h->lh_name[i]))
938 buf[i] = tolower((unsigned char)h->lh_name[i]);
d62a17ae 939 else
3981b5c7 940 buf[i] = h->lh_name[i];
d62a17ae 941 }
942 buf[size] = '\0';
943 return buf;
1e05838a 944}
718e3744 945
1e05838a 946DEFUN (debug_ospf6_lsa_type,
947 debug_ospf6_lsa_hex_cmd,
6de69f83 948 "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
508e53e2 949 DEBUG_STR
950 OSPF6_STR
951 "Debug Link State Advertisements (LSAs)\n"
3a2d747c
QY
952 "Display Router LSAs\n"
953 "Display Network LSAs\n"
954 "Display Inter-Area-Prefix LSAs\n"
955 "Display Inter-Router LSAs\n"
956 "Display As-External LSAs\n"
957 "Display Link LSAs\n"
958 "Display Intra-Area-Prefix LSAs\n"
959 "Display LSAs of unknown origin\n"
960 "Display details of LSAs\n"
961 "Dump LSAs\n"
962 "Display LSA's internal information\n")
508e53e2 963{
d62a17ae 964 int idx_lsa = 3;
965 int idx_type = 4;
966 unsigned int i;
967 struct ospf6_lsa_handler *handler = NULL;
968
969 for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
970 handler = vector_slot(ospf6_lsa_handler_vector, i);
971 if (handler == NULL)
972 continue;
973 if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
974 strlen(argv[idx_lsa]->arg))
975 == 0)
976 break;
3981b5c7 977 if (!strcasecmp(argv[idx_lsa]->arg, handler->lh_name))
d62a17ae 978 break;
979 handler = NULL;
980 }
981
982 if (handler == NULL)
983 handler = &unknown_handler;
984
985 if (argc == 5) {
986 if (strmatch(argv[idx_type]->text, "originate"))
01db90cd 987 SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ORIGINATE);
d62a17ae 988 else if (strmatch(argv[idx_type]->text, "examine"))
01db90cd 989 SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN);
d62a17ae 990 else if (strmatch(argv[idx_type]->text, "flooding"))
01db90cd 991 SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD);
d62a17ae 992 } else
01db90cd 993 SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG);
d62a17ae 994
995 return CMD_SUCCESS;
508e53e2 996}
997
1e05838a 998DEFUN (no_debug_ospf6_lsa_type,
999 no_debug_ospf6_lsa_hex_cmd,
6de69f83 1000 "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
508e53e2 1001 NO_STR
1002 DEBUG_STR
1003 OSPF6_STR
1004 "Debug Link State Advertisements (LSAs)\n"
16cedbb0
QY
1005 "Display Router LSAs\n"
1006 "Display Network LSAs\n"
1007 "Display Inter-Area-Prefix LSAs\n"
3a2d747c 1008 "Display Inter-Router LSAs\n"
16cedbb0
QY
1009 "Display As-External LSAs\n"
1010 "Display Link LSAs\n"
1011 "Display Intra-Area-Prefix LSAs\n"
3a2d747c 1012 "Display LSAs of unknown origin\n"
16cedbb0
QY
1013 "Display details of LSAs\n"
1014 "Dump LSAs\n"
1015 "Display LSA's internal information\n")
508e53e2 1016{
d62a17ae 1017 int idx_lsa = 4;
1018 int idx_type = 5;
d7c0a89a 1019 unsigned int i;
d62a17ae 1020 struct ospf6_lsa_handler *handler = NULL;
1021
1022 for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
1023 handler = vector_slot(ospf6_lsa_handler_vector, i);
1024 if (handler == NULL)
1025 continue;
1026 if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
1027 strlen(argv[idx_lsa]->arg))
1028 == 0)
1029 break;
3981b5c7 1030 if (!strcasecmp(argv[idx_lsa]->arg, handler->lh_name))
d62a17ae 1031 break;
1032 }
718e3744 1033
d62a17ae 1034 if (handler == NULL)
1035 return CMD_SUCCESS;
1036
1037 if (argc == 6) {
1038 if (strmatch(argv[idx_type]->text, "originate"))
01db90cd
DL
1039 UNSET_FLAG(handler->lh_debug,
1040 OSPF6_LSA_DEBUG_ORIGINATE);
d62a17ae 1041 if (strmatch(argv[idx_type]->text, "examine"))
01db90cd 1042 UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN);
d62a17ae 1043 if (strmatch(argv[idx_type]->text, "flooding"))
01db90cd 1044 UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD);
d62a17ae 1045 } else
01db90cd 1046 UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG);
d62a17ae 1047
1048 return CMD_SUCCESS;
1049}
1050
1051void install_element_ospf6_debug_lsa(void)
1052{
1053 install_element(ENABLE_NODE, &debug_ospf6_lsa_hex_cmd);
1054 install_element(ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd);
1055 install_element(CONFIG_NODE, &debug_ospf6_lsa_hex_cmd);
1056 install_element(CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd);
1057}
1058
1059int config_write_ospf6_debug_lsa(struct vty *vty)
1060{
d7c0a89a 1061 unsigned int i;
3981b5c7 1062 const struct ospf6_lsa_handler *handler;
d62a17ae 1063
1064 for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
1065 handler = vector_slot(ospf6_lsa_handler_vector, i);
1066 if (handler == NULL)
1067 continue;
01db90cd 1068 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG))
d62a17ae 1069 vty_out(vty, "debug ospf6 lsa %s\n",
1070 ospf6_lsa_handler_name(handler));
01db90cd 1071 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ORIGINATE))
d62a17ae 1072 vty_out(vty, "debug ospf6 lsa %s originate\n",
1073 ospf6_lsa_handler_name(handler));
01db90cd 1074 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN))
d62a17ae 1075 vty_out(vty, "debug ospf6 lsa %s examine\n",
1076 ospf6_lsa_handler_name(handler));
01db90cd 1077 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD))
d62a17ae 1078 vty_out(vty, "debug ospf6 lsa %s flooding\n",
1079 ospf6_lsa_handler_name(handler));
1080 }
718e3744 1081
d62a17ae 1082 return 0;
1083}