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