]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_lsa.c
staticd: Do not ready prefix for printing till it's decoded
[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"
718e3744 32
33#include "ospf6_proto.h"
718e3744 34#include "ospf6_lsa.h"
35#include "ospf6_lsdb.h"
36#include "ospf6_message.h"
718e3744 37
38#include "ospf6_top.h"
39#include "ospf6_area.h"
40#include "ospf6_interface.h"
41#include "ospf6_neighbor.h"
718e3744 42
508e53e2 43#include "ospf6_flood.h"
049207c3 44#include "ospf6d.h"
718e3744 45
1e05838a 46vector ospf6_lsa_handler_vector;
718e3744 47
d62a17ae 48static int ospf6_unknown_lsa_show(struct vty *vty, struct ospf6_lsa *lsa)
1e05838a 49{
d7c0a89a 50 uint8_t *start, *end, *current;
d62a17ae 51 char byte[4];
1e05838a 52
d7c0a89a
QY
53 start = (uint8_t *)lsa->header + sizeof(struct ospf6_lsa_header);
54 end = (uint8_t *)lsa->header + ntohs(lsa->header->length);
1e05838a 55
d62a17ae 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, " ");
718e3744 62
d62a17ae 63 snprintf(byte, sizeof(byte), "%02x", *current);
64 vty_out(vty, "%s", byte);
65 }
1e05838a 66
d62a17ae 67 vty_out(vty, "\n\n");
68 return 0;
1e05838a 69}
70
3981b5c7
VJ
71static 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};
1e05838a 79
3981b5c7 80void ospf6_install_lsa_handler(const struct ospf6_lsa_handler *handler)
1e05838a 81{
d62a17ae 82 /* type in handler is host byte order */
3981b5c7
VJ
83 int index = handler->lh_type & OSPF6_LSTYPE_FCODE_MASK;
84 vector_set_index(ospf6_lsa_handler_vector, index, (void *)handler);
1e05838a 85}
86
d7c0a89a 87const struct ospf6_lsa_handler *ospf6_get_lsa_handler(uint16_t type)
1e05838a 88{
3981b5c7 89 const struct ospf6_lsa_handler *handler = NULL;
d62a17ae 90 unsigned int index = ntohs(type) & OSPF6_LSTYPE_FCODE_MASK;
1e05838a 91
d62a17ae 92 if (index >= vector_active(ospf6_lsa_handler_vector))
93 handler = &unknown_handler;
94 else
95 handler = vector_slot(ospf6_lsa_handler_vector, index);
1e05838a 96
d62a17ae 97 if (handler == NULL)
98 handler = &unknown_handler;
2680aa2b 99
d62a17ae 100 return handler;
1e05838a 101}
718e3744 102
d7c0a89a 103const char *ospf6_lstype_name(uint16_t type)
508e53e2 104{
d62a17ae 105 static char buf[8];
3981b5c7 106 const struct ospf6_lsa_handler *handler;
508e53e2 107
d62a17ae 108 handler = ospf6_get_lsa_handler(type);
109 if (handler && handler != &unknown_handler)
3981b5c7 110 return handler->lh_name;
718e3744 111
d62a17ae 112 snprintf(buf, sizeof(buf), "0x%04hx", ntohs(type));
113 return buf;
718e3744 114}
115
d7c0a89a 116const char *ospf6_lstype_short_name(uint16_t type)
e68a6767 117{
d62a17ae 118 static char buf[8];
3981b5c7 119 const struct ospf6_lsa_handler *handler;
e68a6767 120
d62a17ae 121 handler = ospf6_get_lsa_handler(type);
122 if (handler && handler != &unknown_handler)
3981b5c7 123 return handler->lh_short_name;
e68a6767 124
d62a17ae 125 snprintf(buf, sizeof(buf), "0x%04hx", ntohs(type));
126 return buf;
e68a6767
DD
127}
128
d7c0a89a 129uint8_t ospf6_lstype_debug(uint16_t type)
1e05838a 130{
3981b5c7 131 const struct ospf6_lsa_handler *handler;
d62a17ae 132 handler = ospf6_get_lsa_handler(type);
01db90cd 133 return handler->lh_debug;
1e05838a 134}
135
718e3744 136/* RFC2328: Section 13.2 */
d62a17ae 137int ospf6_lsa_is_differ(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
718e3744 138{
d62a17ae 139 int len;
718e3744 140
d62a17ae 141 assert(OSPF6_LSA_IS_SAME(lsa1, lsa2));
718e3744 142
d62a17ae 143 /* XXX, Options ??? */
718e3744 144
d62a17ae 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;
718e3744 153
d62a17ae 154 /* compare body */
155 if (ntohs(lsa1->header->length) != ntohs(lsa2->header->length))
156 return 1;
718e3744 157
d62a17ae 158 len = ntohs(lsa1->header->length) - sizeof(struct ospf6_lsa_header);
159 return memcmp(lsa1->header + 1, lsa2->header + 1, len);
718e3744 160}
161
d62a17ae 162int ospf6_lsa_is_changed(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
718e3744 163{
d62a17ae 164 int length;
718e3744 165
d62a17ae 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;
718e3744 181
d62a17ae 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;
718e3744 187
d62a17ae 188 return memcmp(OSPF6_LSA_HEADER_END(lsa1->header),
189 OSPF6_LSA_HEADER_END(lsa2->header), length);
718e3744 190}
191
192/* ospf6 age functions */
3b68735f 193/* calculate birth */
da086a3b 194void ospf6_lsa_age_set(struct ospf6_lsa *lsa)
718e3744 195{
d62a17ae 196 struct timeval now;
718e3744 197
d62a17ae 198 assert(lsa && lsa->header);
718e3744 199
d62a17ae 200 monotime(&now);
718e3744 201
d62a17ae 202 lsa->birth.tv_sec = now.tv_sec - ntohs(lsa->header->age);
203 lsa->birth.tv_usec = now.tv_usec;
3b68735f 204
d62a17ae 205 return;
718e3744 206}
207
208/* this function calculates current age from its birth,
209 then update age field of LSA header. return value is current age */
d7c0a89a 210uint16_t ospf6_lsa_age_current(struct ospf6_lsa *lsa)
718e3744 211{
d62a17ae 212 struct timeval now;
d7c0a89a
QY
213 uint32_t ulage;
214 uint16_t age;
718e3744 215
d62a17ae 216 assert(lsa);
217 assert(lsa->header);
718e3744 218
d62a17ae 219 /* current time */
220 monotime(&now);
718e3744 221
d62a17ae 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;
718e3744 231
d62a17ae 232 /* if over MAXAGE, set to it */
233 age = (ulage > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : ulage);
718e3744 234
d62a17ae 235 lsa->header->age = htons(age);
236 return age;
718e3744 237}
238
239/* update age field of LSA header with adding InfTransDelay */
d7c0a89a 240void ospf6_lsa_age_update_to_send(struct ospf6_lsa *lsa, uint32_t transdelay)
d62a17ae 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
250void 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);
718e3744 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 */
d62a17ae 292int ospf6_lsa_compare(struct ospf6_lsa *a, struct ospf6_lsa *b)
718e3744 293{
d62a17ae 294 int32_t seqnuma, seqnumb;
d7c0a89a
QY
295 uint16_t cksuma, cksumb;
296 uint16_t agea, ageb;
d62a17ae 297
298 assert(a && a->header);
299 assert(b && b->header);
300 assert(OSPF6_LSA_IS_SAME(a, b));
718e3744 301
d62a17ae 302 seqnuma = (int32_t)ntohl(a->header->seqnum);
303 seqnumb = (int32_t)ntohl(b->header->seqnum);
718e3744 304
d62a17ae 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
339char *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
350void 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",
d7c0a89a 358 ntohs(header->age), (unsigned long)ntohl(header->seqnum),
d62a17ae 359 ntohs(header->checksum), ntohs(header->length));
360}
361
362void 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
368void 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
374void ospf6_lsa_show_summary(struct vty *vty, struct ospf6_lsa *lsa)
375{
376 char adv_router[16], id[16];
377 int type;
3981b5c7 378 const struct ospf6_lsa_handler *handler;
d62a17ae 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),
d7c0a89a 397 (unsigned long)ntohl(lsa->header->seqnum),
3981b5c7 398 handler->lh_get_prefix_str(lsa, buf, sizeof(buf), 0));
d62a17ae 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),
d7c0a89a 403 (unsigned long)ntohl(lsa->header->seqnum));
d62a17ae 404
3981b5c7 405 while (handler->lh_get_prefix_str(lsa, buf, sizeof(buf), cnt)
d62a17ae 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),
d7c0a89a 414 (unsigned long)ntohl(lsa->header->seqnum));
e68a6767 415 }
d62a17ae 416}
417
418void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa)
419{
d7c0a89a 420 uint8_t *start, *end, *current;
d62a17ae 421 char byte[4];
422
d7c0a89a
QY
423 start = (uint8_t *)lsa->header;
424 end = (uint8_t *)lsa->header + ntohs(lsa->header->length);
d62a17ae 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
443void 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",
d7c0a89a 459 (unsigned long)ntohl(lsa->header->seqnum));
d62a17ae 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
471void ospf6_lsa_show(struct vty *vty, struct ospf6_lsa *lsa)
472{
473 char adv_router[64], id[64];
3981b5c7 474 const struct ospf6_lsa_handler *handler;
d62a17ae 475 struct timeval now, res;
68bfcc05 476 char duration[64];
d62a17ae 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",
d7c0a89a 493 (unsigned long)ntohl(lsa->header->seqnum));
d62a17ae 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);
3981b5c7
VJ
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 }
d62a17ae 506
507 vty_out(vty, "\n");
6452df09 508}
509
510/* OSPFv3 LSA creation/deletion function */
d62a17ae 511struct ospf6_lsa *ospf6_lsa_create(struct ospf6_lsa_header *header)
718e3744 512{
d62a17ae 513 struct ospf6_lsa *lsa = NULL;
514 struct ospf6_lsa_header *new_header = NULL;
d7c0a89a 515 uint16_t lsa_size = 0;
718e3744 516
d62a17ae 517 /* size of the entire LSA */
518 lsa_size = ntohs(header->length); /* XXX vulnerable */
718e3744 519
d62a17ae 520 /* allocate memory for this LSA */
996c9314
LB
521 new_header = (struct ospf6_lsa_header *)XMALLOC(MTYPE_OSPF6_LSA_HEADER,
522 lsa_size);
718e3744 523
d62a17ae 524 /* copy LSA from original header */
525 memcpy(new_header, header, lsa_size);
718e3744 526
d62a17ae 527 /* LSA information structure */
528 /* allocate memory */
529 lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA,
530 sizeof(struct ospf6_lsa));
718e3744 531
d62a17ae 532 lsa->header = (struct ospf6_lsa_header *)new_header;
718e3744 533
d62a17ae 534 /* dump string */
535 ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
718e3744 536
d62a17ae 537 /* calculate birth of this lsa */
538 ospf6_lsa_age_set(lsa);
718e3744 539
d62a17ae 540 return lsa;
718e3744 541}
542
d62a17ae 543struct ospf6_lsa *ospf6_lsa_create_headeronly(struct ospf6_lsa_header *header)
718e3744 544{
d62a17ae 545 struct ospf6_lsa *lsa = NULL;
546 struct ospf6_lsa_header *new_header = NULL;
718e3744 547
d62a17ae 548 /* allocate memory for this LSA */
549 new_header = (struct ospf6_lsa_header *)XMALLOC(
d107621d 550 MTYPE_OSPF6_LSA_HEADER, sizeof(struct ospf6_lsa_header));
718e3744 551
d62a17ae 552 /* copy LSA from original header */
553 memcpy(new_header, header, sizeof(struct ospf6_lsa_header));
718e3744 554
d62a17ae 555 /* LSA information structure */
556 /* allocate memory */
557 lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA,
558 sizeof(struct ospf6_lsa));
718e3744 559
d62a17ae 560 lsa->header = (struct ospf6_lsa_header *)new_header;
561 SET_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY);
718e3744 562
d62a17ae 563 /* dump string */
564 ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
718e3744 565
d62a17ae 566 /* calculate birth of this lsa */
567 ospf6_lsa_age_set(lsa);
718e3744 568
d62a17ae 569 return lsa;
718e3744 570}
571
d62a17ae 572void ospf6_lsa_delete(struct ospf6_lsa *lsa)
718e3744 573{
d62a17ae 574 assert(lsa->lock == 0);
718e3744 575
d62a17ae 576 /* cancel threads */
577 THREAD_OFF(lsa->expire);
578 THREAD_OFF(lsa->refresh);
718e3744 579
d62a17ae 580 /* do free */
d107621d 581 XFREE(MTYPE_OSPF6_LSA_HEADER, lsa->header);
d62a17ae 582 XFREE(MTYPE_OSPF6_LSA, lsa);
508e53e2 583}
718e3744 584
d62a17ae 585struct ospf6_lsa *ospf6_lsa_copy(struct ospf6_lsa *lsa)
508e53e2 586{
d62a17ae 587 struct ospf6_lsa *copy = NULL;
508e53e2 588
d62a17ae 589 ospf6_lsa_age_current(lsa);
590 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY))
591 copy = ospf6_lsa_create_headeronly(lsa->header);
592 else
593 copy = ospf6_lsa_create(lsa->header);
594 assert(copy->lock == 0);
508e53e2 595
d62a17ae 596 copy->birth = lsa->birth;
597 copy->originated = lsa->originated;
598 copy->received = lsa->received;
599 copy->installed = lsa->installed;
600 copy->lsdb = lsa->lsdb;
601 copy->rn = NULL;
508e53e2 602
d62a17ae 603 return copy;
718e3744 604}
605
508e53e2 606/* increment reference counter of struct ospf6_lsa */
d62a17ae 607void ospf6_lsa_lock(struct ospf6_lsa *lsa)
718e3744 608{
d62a17ae 609 lsa->lock++;
610 return;
718e3744 611}
612
508e53e2 613/* decrement reference counter of struct ospf6_lsa */
d62a17ae 614void ospf6_lsa_unlock(struct ospf6_lsa *lsa)
718e3744 615{
d62a17ae 616 /* decrement reference counter */
617 assert(lsa->lock > 0);
618 lsa->lock--;
718e3744 619
d62a17ae 620 if (lsa->lock != 0)
621 return;
508e53e2 622
d62a17ae 623 ospf6_lsa_delete(lsa);
718e3744 624}
625
6b0655a2 626
508e53e2 627/* ospf6 lsa expiry */
d62a17ae 628int ospf6_lsa_expire(struct thread *thread)
718e3744 629{
d62a17ae 630 struct ospf6_lsa *lsa;
718e3744 631
d62a17ae 632 lsa = (struct ospf6_lsa *)THREAD_ARG(thread);
718e3744 633
d62a17ae 634 assert(lsa && lsa->header);
635 assert(OSPF6_LSA_IS_MAXAGE(lsa));
636 assert(!lsa->refresh);
718e3744 637
d62a17ae 638 lsa->expire = (struct thread *)NULL;
718e3744 639
d62a17ae 640 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)) {
641 zlog_debug("LSA Expire:");
642 ospf6_lsa_header_print(lsa);
643 }
718e3744 644
d62a17ae 645 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY))
646 return 0; /* dbexchange will do something ... */
718e3744 647
d62a17ae 648 /* reinstall lsa */
649 ospf6_install_lsa(lsa);
508e53e2 650
d62a17ae 651 /* reflood lsa */
652 ospf6_flood(NULL, lsa);
bf986da7 653
d62a17ae 654 /* schedule maxage remover */
655 ospf6_maxage_remove(ospf6);
718e3744 656
d62a17ae 657 return 0;
718e3744 658}
659
d62a17ae 660int ospf6_lsa_refresh(struct thread *thread)
718e3744 661{
d62a17ae 662 struct ospf6_lsa *old, *self, *new;
663 struct ospf6_lsdb *lsdb_self;
6452df09 664
d62a17ae 665 old = (struct ospf6_lsa *)THREAD_ARG(thread);
666 assert(old && old->header);
6452df09 667
d62a17ae 668 old->refresh = (struct thread *)NULL;
6452df09 669
d62a17ae 670 lsdb_self = ospf6_get_scoped_lsdb_self(old);
671 self = ospf6_lsdb_lookup(old->header->type, old->header->id,
672 old->header->adv_router, lsdb_self);
673 if (self == NULL) {
674 if (IS_OSPF6_DEBUG_LSA_TYPE(old->header->type))
675 zlog_debug("Refresh: could not find self LSA, flush %s",
676 old->name);
677 ospf6_lsa_premature_aging(old);
678 return 0;
679 }
718e3744 680
d62a17ae 681 /* Reset age, increment LS sequence number. */
682 self->header->age = htons(0);
683 self->header->seqnum =
684 ospf6_new_ls_seqnum(self->header->type, self->header->id,
685 self->header->adv_router, old->lsdb);
686 ospf6_lsa_checksum(self->header);
687
688 new = ospf6_lsa_create(self->header);
689 new->lsdb = old->lsdb;
690 new->refresh = NULL;
691 thread_add_timer(master, ospf6_lsa_refresh, new, OSPF_LS_REFRESH_TIME,
692 &new->refresh);
693
694 /* store it in the LSDB for self-originated LSAs */
695 ospf6_lsdb_add(ospf6_lsa_copy(new), lsdb_self);
696
697 if (IS_OSPF6_DEBUG_LSA_TYPE(new->header->type)) {
698 zlog_debug("LSA Refresh:");
699 ospf6_lsa_header_print(new);
700 }
718e3744 701
d62a17ae 702 ospf6_install_lsa(new);
703 ospf6_flood(NULL, new);
6452df09 704
d62a17ae 705 return 0;
718e3744 706}
707
76249532
CS
708void ospf6_flush_self_originated_lsas_now(void)
709{
710 struct listnode *node;
711 struct ospf6_area *oa;
712 struct ospf6_lsa *lsa;
713 const struct route_node *end = NULL;
714 uint32_t type, adv_router;
715
716 ospf6->inst_shutdown = 1;
717
718 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
996c9314
LB
719 end = ospf6_lsdb_head(oa->lsdb_self, 0, 0, ospf6->router_id,
720 &lsa);
76249532
CS
721 while (lsa) {
722 /* RFC 2328 (14.1): Set MAXAGE */
723 lsa->header->age = htons(OSPF_LSA_MAXAGE);
724 /* Flood MAXAGE LSA*/
725 ospf6_flood(NULL, lsa);
726
727 lsa = ospf6_lsdb_next(end, lsa);
728 }
729 }
730
731 type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
732 adv_router = ospf6->router_id;
733 for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, adv_router, lsa)) {
734 /* RFC 2328 (14.1): Set MAXAGE */
735 lsa->header->age = htons(OSPF_LSA_MAXAGE);
736 ospf6_flood(NULL, lsa);
737 }
738}
6b0655a2 739
d8a4e42b 740/* Fletcher Checksum -- Refer to RFC1008. */
718e3744 741
d8a4e42b
JR
742/* All the offsets are zero-based. The offsets in the RFC1008 are
743 one-based. */
d62a17ae 744unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header *lsa_header)
718e3744 745{
d7c0a89a
QY
746 uint8_t *buffer = (uint8_t *)&lsa_header->type;
747 int type_offset =
748 buffer - (uint8_t *)&lsa_header->age; /* should be 2 */
718e3744 749
d62a17ae 750 /* Skip the AGE field */
d7c0a89a 751 uint16_t len = ntohs(lsa_header->length) - type_offset;
718e3744 752
d62a17ae 753 /* Checksum offset starts from "type" field, not the beginning of the
754 lsa_header struct. The offset is 14, rather than 16. */
d7c0a89a 755 int checksum_offset = (uint8_t *)&lsa_header->checksum - buffer;
d8a4e42b 756
d62a17ae 757 return (unsigned short)fletcher_checksum(buffer, len, checksum_offset);
d8a4e42b 758}
718e3744 759
d62a17ae 760int ospf6_lsa_checksum_valid(struct ospf6_lsa_header *lsa_header)
d8a4e42b 761{
d7c0a89a
QY
762 uint8_t *buffer = (uint8_t *)&lsa_header->type;
763 int type_offset =
764 buffer - (uint8_t *)&lsa_header->age; /* should be 2 */
718e3744 765
d62a17ae 766 /* Skip the AGE field */
d7c0a89a 767 uint16_t len = ntohs(lsa_header->length) - type_offset;
718e3744 768
d62a17ae 769 return (fletcher_checksum(buffer, len, FLETCHER_CHECKSUM_VALIDATE)
770 == 0);
718e3744 771}
772
d62a17ae 773void ospf6_lsa_init(void)
6452df09 774{
d62a17ae 775 ospf6_lsa_handler_vector = vector_init(0);
776 ospf6_install_lsa_handler(&unknown_handler);
718e3744 777}
778
d62a17ae 779void ospf6_lsa_terminate(void)
ae2254aa 780{
d62a17ae 781 vector_free(ospf6_lsa_handler_vector);
ae2254aa 782}
6b0655a2 783
3981b5c7 784static char *ospf6_lsa_handler_name(const struct ospf6_lsa_handler *h)
1e05838a 785{
d62a17ae 786 static char buf[64];
787 unsigned int i;
3981b5c7 788 unsigned int size = strlen(h->lh_name);
1e05838a 789
996c9314
LB
790 if (!strcmp(h->lh_name, "unknown")
791 && h->lh_type != OSPF6_LSTYPE_UNKNOWN) {
3981b5c7 792 snprintf(buf, sizeof(buf), "%#04hx", h->lh_type);
d62a17ae 793 return buf;
794 }
1e05838a 795
d62a17ae 796 for (i = 0; i < MIN(size, sizeof(buf)); i++) {
3981b5c7
VJ
797 if (!islower((unsigned char)h->lh_name[i]))
798 buf[i] = tolower((unsigned char)h->lh_name[i]);
d62a17ae 799 else
3981b5c7 800 buf[i] = h->lh_name[i];
d62a17ae 801 }
802 buf[size] = '\0';
803 return buf;
1e05838a 804}
718e3744 805
1e05838a 806DEFUN (debug_ospf6_lsa_type,
807 debug_ospf6_lsa_hex_cmd,
6de69f83 808 "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
508e53e2 809 DEBUG_STR
810 OSPF6_STR
811 "Debug Link State Advertisements (LSAs)\n"
3a2d747c
QY
812 "Display Router LSAs\n"
813 "Display Network LSAs\n"
814 "Display Inter-Area-Prefix LSAs\n"
815 "Display Inter-Router LSAs\n"
816 "Display As-External LSAs\n"
817 "Display Link LSAs\n"
818 "Display Intra-Area-Prefix LSAs\n"
819 "Display LSAs of unknown origin\n"
820 "Display details of LSAs\n"
821 "Dump LSAs\n"
822 "Display LSA's internal information\n")
508e53e2 823{
d62a17ae 824 int idx_lsa = 3;
825 int idx_type = 4;
826 unsigned int i;
827 struct ospf6_lsa_handler *handler = NULL;
828
829 for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
830 handler = vector_slot(ospf6_lsa_handler_vector, i);
831 if (handler == NULL)
832 continue;
833 if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
834 strlen(argv[idx_lsa]->arg))
835 == 0)
836 break;
3981b5c7 837 if (!strcasecmp(argv[idx_lsa]->arg, handler->lh_name))
d62a17ae 838 break;
839 handler = NULL;
840 }
841
842 if (handler == NULL)
843 handler = &unknown_handler;
844
845 if (argc == 5) {
846 if (strmatch(argv[idx_type]->text, "originate"))
01db90cd 847 SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ORIGINATE);
d62a17ae 848 else if (strmatch(argv[idx_type]->text, "examine"))
01db90cd 849 SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN);
d62a17ae 850 else if (strmatch(argv[idx_type]->text, "flooding"))
01db90cd 851 SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD);
d62a17ae 852 } else
01db90cd 853 SET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG);
d62a17ae 854
855 return CMD_SUCCESS;
508e53e2 856}
857
1e05838a 858DEFUN (no_debug_ospf6_lsa_type,
859 no_debug_ospf6_lsa_hex_cmd,
6de69f83 860 "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
508e53e2 861 NO_STR
862 DEBUG_STR
863 OSPF6_STR
864 "Debug Link State Advertisements (LSAs)\n"
16cedbb0
QY
865 "Display Router LSAs\n"
866 "Display Network LSAs\n"
867 "Display Inter-Area-Prefix LSAs\n"
3a2d747c 868 "Display Inter-Router LSAs\n"
16cedbb0
QY
869 "Display As-External LSAs\n"
870 "Display Link LSAs\n"
871 "Display Intra-Area-Prefix LSAs\n"
3a2d747c 872 "Display LSAs of unknown origin\n"
16cedbb0
QY
873 "Display details of LSAs\n"
874 "Dump LSAs\n"
875 "Display LSA's internal information\n")
508e53e2 876{
d62a17ae 877 int idx_lsa = 4;
878 int idx_type = 5;
d7c0a89a 879 unsigned int i;
d62a17ae 880 struct ospf6_lsa_handler *handler = NULL;
881
882 for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
883 handler = vector_slot(ospf6_lsa_handler_vector, i);
884 if (handler == NULL)
885 continue;
886 if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
887 strlen(argv[idx_lsa]->arg))
888 == 0)
889 break;
3981b5c7 890 if (!strcasecmp(argv[idx_lsa]->arg, handler->lh_name))
d62a17ae 891 break;
892 }
718e3744 893
d62a17ae 894 if (handler == NULL)
895 return CMD_SUCCESS;
896
897 if (argc == 6) {
898 if (strmatch(argv[idx_type]->text, "originate"))
01db90cd
DL
899 UNSET_FLAG(handler->lh_debug,
900 OSPF6_LSA_DEBUG_ORIGINATE);
d62a17ae 901 if (strmatch(argv[idx_type]->text, "examine"))
01db90cd 902 UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN);
d62a17ae 903 if (strmatch(argv[idx_type]->text, "flooding"))
01db90cd 904 UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD);
d62a17ae 905 } else
01db90cd 906 UNSET_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG);
d62a17ae 907
908 return CMD_SUCCESS;
909}
910
911void install_element_ospf6_debug_lsa(void)
912{
913 install_element(ENABLE_NODE, &debug_ospf6_lsa_hex_cmd);
914 install_element(ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd);
915 install_element(CONFIG_NODE, &debug_ospf6_lsa_hex_cmd);
916 install_element(CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd);
917}
918
919int config_write_ospf6_debug_lsa(struct vty *vty)
920{
d7c0a89a 921 unsigned int i;
3981b5c7 922 const struct ospf6_lsa_handler *handler;
d62a17ae 923
924 for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
925 handler = vector_slot(ospf6_lsa_handler_vector, i);
926 if (handler == NULL)
927 continue;
01db90cd 928 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG))
d62a17ae 929 vty_out(vty, "debug ospf6 lsa %s\n",
930 ospf6_lsa_handler_name(handler));
01db90cd 931 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_ORIGINATE))
d62a17ae 932 vty_out(vty, "debug ospf6 lsa %s originate\n",
933 ospf6_lsa_handler_name(handler));
01db90cd 934 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_EXAMIN))
d62a17ae 935 vty_out(vty, "debug ospf6 lsa %s examine\n",
936 ospf6_lsa_handler_name(handler));
01db90cd 937 if (CHECK_FLAG(handler->lh_debug, OSPF6_LSA_DEBUG_FLOOD))
d62a17ae 938 vty_out(vty, "debug ospf6 lsa %s flooding\n",
939 ospf6_lsa_handler_name(handler));
940 }
718e3744 941
d62a17ae 942 return 0;
943}