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