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