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