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