]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_lsa.c
Merge pull request #1756 from qlyoung/stylechecker
[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{
d62a17ae 50 u_char *start, *end, *current;
51 char byte[4];
1e05838a 52
d62a17ae 53 start = (u_char *)lsa->header + sizeof(struct ospf6_lsa_header);
54 end = (u_char *)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
3981b5c7 87const struct ospf6_lsa_handler *ospf6_get_lsa_handler(u_int16_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
d62a17ae 103const char *ospf6_lstype_name(u_int16_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
d62a17ae 116const char *ospf6_lstype_short_name(u_int16_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
d62a17ae 129u_char ospf6_lstype_debug(u_int16_t type)
1e05838a 130{
3981b5c7 131 const struct ospf6_lsa_handler *handler;
d62a17ae 132 handler = ospf6_get_lsa_handler(type);
133 return handler->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 */
d62a17ae 210u_int16_t ospf6_lsa_age_current(struct ospf6_lsa *lsa)
718e3744 211{
d62a17ae 212 struct timeval now;
213 u_int32_t ulage;
214 u_int16_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 */
d62a17ae 240void ospf6_lsa_age_update_to_send(struct ospf6_lsa *lsa, u_int32_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
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;
295 u_int16_t cksuma, cksumb;
296 u_int16_t agea, ageb;
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",
358 ntohs(header->age), (u_long)ntohl(header->seqnum),
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),
397 (u_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),
403 (u_long)ntohl(lsa->header->seqnum));
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),
414 (u_long)ntohl(lsa->header->seqnum));
e68a6767 415 }
d62a17ae 416}
417
418void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa)
419{
420 u_char *start, *end, *current;
421 char byte[4];
422
423 start = (u_char *)lsa->header;
424 end = (u_char *)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
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",
459 (u_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
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",
493 (u_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);
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;
515 u_int16_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 */
521 new_header =
d107621d
CS
522 (struct ospf6_lsa_header *)XMALLOC(MTYPE_OSPF6_LSA_HEADER,
523 lsa_size);
718e3744 524
d62a17ae 525 /* copy LSA from original header */
526 memcpy(new_header, header, lsa_size);
718e3744 527
d62a17ae 528 /* LSA information structure */
529 /* allocate memory */
530 lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA,
531 sizeof(struct ospf6_lsa));
718e3744 532
d62a17ae 533 lsa->header = (struct ospf6_lsa_header *)new_header;
718e3744 534
d62a17ae 535 /* dump string */
536 ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
718e3744 537
d62a17ae 538 /* calculate birth of this lsa */
539 ospf6_lsa_age_set(lsa);
718e3744 540
d62a17ae 541 return lsa;
718e3744 542}
543
d62a17ae 544struct ospf6_lsa *ospf6_lsa_create_headeronly(struct ospf6_lsa_header *header)
718e3744 545{
d62a17ae 546 struct ospf6_lsa *lsa = NULL;
547 struct ospf6_lsa_header *new_header = NULL;
718e3744 548
d62a17ae 549 /* allocate memory for this LSA */
550 new_header = (struct ospf6_lsa_header *)XMALLOC(
d107621d 551 MTYPE_OSPF6_LSA_HEADER, sizeof(struct ospf6_lsa_header));
718e3744 552
d62a17ae 553 /* copy LSA from original header */
554 memcpy(new_header, header, sizeof(struct ospf6_lsa_header));
718e3744 555
d62a17ae 556 /* LSA information structure */
557 /* allocate memory */
558 lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA,
559 sizeof(struct ospf6_lsa));
718e3744 560
d62a17ae 561 lsa->header = (struct ospf6_lsa_header *)new_header;
562 SET_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY);
718e3744 563
d62a17ae 564 /* dump string */
565 ospf6_lsa_printbuf(lsa, lsa->name, sizeof(lsa->name));
718e3744 566
d62a17ae 567 /* calculate birth of this lsa */
568 ospf6_lsa_age_set(lsa);
718e3744 569
d62a17ae 570 return lsa;
718e3744 571}
572
d62a17ae 573void ospf6_lsa_delete(struct ospf6_lsa *lsa)
718e3744 574{
d62a17ae 575 assert(lsa->lock == 0);
718e3744 576
d62a17ae 577 /* cancel threads */
578 THREAD_OFF(lsa->expire);
579 THREAD_OFF(lsa->refresh);
718e3744 580
d62a17ae 581 /* do free */
d107621d 582 XFREE(MTYPE_OSPF6_LSA_HEADER, lsa->header);
d62a17ae 583 XFREE(MTYPE_OSPF6_LSA, lsa);
508e53e2 584}
718e3744 585
d62a17ae 586struct ospf6_lsa *ospf6_lsa_copy(struct ospf6_lsa *lsa)
508e53e2 587{
d62a17ae 588 struct ospf6_lsa *copy = NULL;
508e53e2 589
d62a17ae 590 ospf6_lsa_age_current(lsa);
591 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY))
592 copy = ospf6_lsa_create_headeronly(lsa->header);
593 else
594 copy = ospf6_lsa_create(lsa->header);
595 assert(copy->lock == 0);
508e53e2 596
d62a17ae 597 copy->birth = lsa->birth;
598 copy->originated = lsa->originated;
599 copy->received = lsa->received;
600 copy->installed = lsa->installed;
601 copy->lsdb = lsa->lsdb;
602 copy->rn = NULL;
508e53e2 603
d62a17ae 604 return copy;
718e3744 605}
606
508e53e2 607/* increment reference counter of struct ospf6_lsa */
d62a17ae 608void ospf6_lsa_lock(struct ospf6_lsa *lsa)
718e3744 609{
d62a17ae 610 lsa->lock++;
611 return;
718e3744 612}
613
508e53e2 614/* decrement reference counter of struct ospf6_lsa */
d62a17ae 615void ospf6_lsa_unlock(struct ospf6_lsa *lsa)
718e3744 616{
d62a17ae 617 /* decrement reference counter */
618 assert(lsa->lock > 0);
619 lsa->lock--;
718e3744 620
d62a17ae 621 if (lsa->lock != 0)
622 return;
508e53e2 623
d62a17ae 624 ospf6_lsa_delete(lsa);
718e3744 625}
626
6b0655a2 627
508e53e2 628/* ospf6 lsa expiry */
d62a17ae 629int ospf6_lsa_expire(struct thread *thread)
718e3744 630{
d62a17ae 631 struct ospf6_lsa *lsa;
718e3744 632
d62a17ae 633 lsa = (struct ospf6_lsa *)THREAD_ARG(thread);
718e3744 634
d62a17ae 635 assert(lsa && lsa->header);
636 assert(OSPF6_LSA_IS_MAXAGE(lsa));
637 assert(!lsa->refresh);
718e3744 638
d62a17ae 639 lsa->expire = (struct thread *)NULL;
718e3744 640
d62a17ae 641 if (IS_OSPF6_DEBUG_LSA_TYPE(lsa->header->type)) {
642 zlog_debug("LSA Expire:");
643 ospf6_lsa_header_print(lsa);
644 }
718e3744 645
d62a17ae 646 if (CHECK_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY))
647 return 0; /* dbexchange will do something ... */
718e3744 648
d62a17ae 649 /* reinstall lsa */
650 ospf6_install_lsa(lsa);
508e53e2 651
d62a17ae 652 /* reflood lsa */
653 ospf6_flood(NULL, lsa);
bf986da7 654
d62a17ae 655 /* schedule maxage remover */
656 ospf6_maxage_remove(ospf6);
718e3744 657
d62a17ae 658 return 0;
718e3744 659}
660
d62a17ae 661int ospf6_lsa_refresh(struct thread *thread)
718e3744 662{
d62a17ae 663 struct ospf6_lsa *old, *self, *new;
664 struct ospf6_lsdb *lsdb_self;
6452df09 665
d62a17ae 666 old = (struct ospf6_lsa *)THREAD_ARG(thread);
667 assert(old && old->header);
6452df09 668
d62a17ae 669 old->refresh = (struct thread *)NULL;
6452df09 670
d62a17ae 671 lsdb_self = ospf6_get_scoped_lsdb_self(old);
672 self = ospf6_lsdb_lookup(old->header->type, old->header->id,
673 old->header->adv_router, lsdb_self);
674 if (self == NULL) {
675 if (IS_OSPF6_DEBUG_LSA_TYPE(old->header->type))
676 zlog_debug("Refresh: could not find self LSA, flush %s",
677 old->name);
678 ospf6_lsa_premature_aging(old);
679 return 0;
680 }
718e3744 681
d62a17ae 682 /* Reset age, increment LS sequence number. */
683 self->header->age = htons(0);
684 self->header->seqnum =
685 ospf6_new_ls_seqnum(self->header->type, self->header->id,
686 self->header->adv_router, old->lsdb);
687 ospf6_lsa_checksum(self->header);
688
689 new = ospf6_lsa_create(self->header);
690 new->lsdb = old->lsdb;
691 new->refresh = NULL;
692 thread_add_timer(master, ospf6_lsa_refresh, new, OSPF_LS_REFRESH_TIME,
693 &new->refresh);
694
695 /* store it in the LSDB for self-originated LSAs */
696 ospf6_lsdb_add(ospf6_lsa_copy(new), lsdb_self);
697
698 if (IS_OSPF6_DEBUG_LSA_TYPE(new->header->type)) {
699 zlog_debug("LSA Refresh:");
700 ospf6_lsa_header_print(new);
701 }
718e3744 702
d62a17ae 703 ospf6_install_lsa(new);
704 ospf6_flood(NULL, new);
6452df09 705
d62a17ae 706 return 0;
718e3744 707}
708
76249532
CS
709void ospf6_flush_self_originated_lsas_now(void)
710{
711 struct listnode *node;
712 struct ospf6_area *oa;
713 struct ospf6_lsa *lsa;
714 const struct route_node *end = NULL;
715 uint32_t type, adv_router;
716
717 ospf6->inst_shutdown = 1;
718
719 for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
720 end = ospf6_lsdb_head(oa->lsdb_self, 0, 0,
721 ospf6->router_id, &lsa);
722 while (lsa) {
723 /* RFC 2328 (14.1): Set MAXAGE */
724 lsa->header->age = htons(OSPF_LSA_MAXAGE);
725 /* Flood MAXAGE LSA*/
726 ospf6_flood(NULL, lsa);
727
728 lsa = ospf6_lsdb_next(end, lsa);
729 }
730 }
731
732 type = htons(OSPF6_LSTYPE_AS_EXTERNAL);
733 adv_router = ospf6->router_id;
734 for (ALL_LSDB_TYPED_ADVRTR(ospf6->lsdb, type, adv_router, lsa)) {
735 /* RFC 2328 (14.1): Set MAXAGE */
736 lsa->header->age = htons(OSPF_LSA_MAXAGE);
737 ospf6_flood(NULL, lsa);
738 }
739}
6b0655a2 740
d8a4e42b 741/* Fletcher Checksum -- Refer to RFC1008. */
718e3744 742
d8a4e42b
JR
743/* All the offsets are zero-based. The offsets in the RFC1008 are
744 one-based. */
d62a17ae 745unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header *lsa_header)
718e3744 746{
d62a17ae 747 u_char *buffer = (u_char *)&lsa_header->type;
748 int type_offset = buffer - (u_char *)&lsa_header->age; /* should be 2 */
718e3744 749
d62a17ae 750 /* Skip the AGE field */
751 u_int16_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. */
755 int checksum_offset = (u_char *)&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{
d62a17ae 762 u_char *buffer = (u_char *)&lsa_header->type;
763 int type_offset = buffer - (u_char *)&lsa_header->age; /* should be 2 */
718e3744 764
d62a17ae 765 /* Skip the AGE field */
766 u_int16_t len = ntohs(lsa_header->length) - type_offset;
718e3744 767
d62a17ae 768 return (fletcher_checksum(buffer, len, FLETCHER_CHECKSUM_VALIDATE)
769 == 0);
718e3744 770}
771
d62a17ae 772void ospf6_lsa_init(void)
6452df09 773{
d62a17ae 774 ospf6_lsa_handler_vector = vector_init(0);
775 ospf6_install_lsa_handler(&unknown_handler);
718e3744 776}
777
d62a17ae 778void ospf6_lsa_terminate(void)
ae2254aa 779{
d62a17ae 780 vector_free(ospf6_lsa_handler_vector);
ae2254aa 781}
6b0655a2 782
3981b5c7 783static char *ospf6_lsa_handler_name(const struct ospf6_lsa_handler *h)
1e05838a 784{
d62a17ae 785 static char buf[64];
786 unsigned int i;
3981b5c7 787 unsigned int size = strlen(h->lh_name);
1e05838a 788
3981b5c7
VJ
789 if (!strcmp(h->lh_name, "unknown") && h->lh_type != OSPF6_LSTYPE_UNKNOWN) {
790 snprintf(buf, sizeof(buf), "%#04hx", h->lh_type);
d62a17ae 791 return buf;
792 }
1e05838a 793
d62a17ae 794 for (i = 0; i < MIN(size, sizeof(buf)); i++) {
3981b5c7
VJ
795 if (!islower((unsigned char)h->lh_name[i]))
796 buf[i] = tolower((unsigned char)h->lh_name[i]);
d62a17ae 797 else
3981b5c7 798 buf[i] = h->lh_name[i];
d62a17ae 799 }
800 buf[size] = '\0';
801 return buf;
1e05838a 802}
718e3744 803
1e05838a 804DEFUN (debug_ospf6_lsa_type,
805 debug_ospf6_lsa_hex_cmd,
6de69f83 806 "debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
508e53e2 807 DEBUG_STR
808 OSPF6_STR
809 "Debug Link State Advertisements (LSAs)\n"
3a2d747c
QY
810 "Display Router LSAs\n"
811 "Display Network LSAs\n"
812 "Display Inter-Area-Prefix LSAs\n"
813 "Display Inter-Router LSAs\n"
814 "Display As-External LSAs\n"
815 "Display Link LSAs\n"
816 "Display Intra-Area-Prefix LSAs\n"
817 "Display LSAs of unknown origin\n"
818 "Display details of LSAs\n"
819 "Dump LSAs\n"
820 "Display LSA's internal information\n")
508e53e2 821{
d62a17ae 822 int idx_lsa = 3;
823 int idx_type = 4;
824 unsigned int i;
825 struct ospf6_lsa_handler *handler = NULL;
826
827 for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
828 handler = vector_slot(ospf6_lsa_handler_vector, i);
829 if (handler == NULL)
830 continue;
831 if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
832 strlen(argv[idx_lsa]->arg))
833 == 0)
834 break;
3981b5c7 835 if (!strcasecmp(argv[idx_lsa]->arg, handler->lh_name))
d62a17ae 836 break;
837 handler = NULL;
838 }
839
840 if (handler == NULL)
841 handler = &unknown_handler;
842
843 if (argc == 5) {
844 if (strmatch(argv[idx_type]->text, "originate"))
845 SET_FLAG(handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
846 else if (strmatch(argv[idx_type]->text, "examine"))
847 SET_FLAG(handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
848 else if (strmatch(argv[idx_type]->text, "flooding"))
849 SET_FLAG(handler->debug, OSPF6_LSA_DEBUG_FLOOD);
850 } else
851 SET_FLAG(handler->debug, OSPF6_LSA_DEBUG);
852
853 return CMD_SUCCESS;
508e53e2 854}
855
1e05838a 856DEFUN (no_debug_ospf6_lsa_type,
857 no_debug_ospf6_lsa_hex_cmd,
6de69f83 858 "no debug ospf6 lsa <router|network|inter-prefix|inter-router|as-external|link|intra-prefix|unknown> [<originate|examine|flooding>]",
508e53e2 859 NO_STR
860 DEBUG_STR
861 OSPF6_STR
862 "Debug Link State Advertisements (LSAs)\n"
16cedbb0
QY
863 "Display Router LSAs\n"
864 "Display Network LSAs\n"
865 "Display Inter-Area-Prefix LSAs\n"
3a2d747c 866 "Display Inter-Router LSAs\n"
16cedbb0
QY
867 "Display As-External LSAs\n"
868 "Display Link LSAs\n"
869 "Display Intra-Area-Prefix LSAs\n"
3a2d747c 870 "Display LSAs of unknown origin\n"
16cedbb0
QY
871 "Display details of LSAs\n"
872 "Dump LSAs\n"
873 "Display LSA's internal information\n")
508e53e2 874{
d62a17ae 875 int idx_lsa = 4;
876 int idx_type = 5;
877 u_int i;
878 struct ospf6_lsa_handler *handler = NULL;
879
880 for (i = 0; i < vector_active(ospf6_lsa_handler_vector); i++) {
881 handler = vector_slot(ospf6_lsa_handler_vector, i);
882 if (handler == NULL)
883 continue;
884 if (strncmp(argv[idx_lsa]->arg, ospf6_lsa_handler_name(handler),
885 strlen(argv[idx_lsa]->arg))
886 == 0)
887 break;
3981b5c7 888 if (!strcasecmp(argv[idx_lsa]->arg, handler->lh_name))
d62a17ae 889 break;
890 }
718e3744 891
d62a17ae 892 if (handler == NULL)
893 return CMD_SUCCESS;
894
895 if (argc == 6) {
896 if (strmatch(argv[idx_type]->text, "originate"))
897 UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
898 if (strmatch(argv[idx_type]->text, "examine"))
899 UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
900 if (strmatch(argv[idx_type]->text, "flooding"))
901 UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG_FLOOD);
902 } else
903 UNSET_FLAG(handler->debug, OSPF6_LSA_DEBUG);
904
905 return CMD_SUCCESS;
906}
907
908void 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
916int config_write_ospf6_debug_lsa(struct vty *vty)
917{
918 u_int i;
3981b5c7 919 const struct ospf6_lsa_handler *handler;
d62a17ae 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->debug, OSPF6_LSA_DEBUG))
926 vty_out(vty, "debug ospf6 lsa %s\n",
927 ospf6_lsa_handler_name(handler));
928 if (CHECK_FLAG(handler->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->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->debug, OSPF6_LSA_DEBUG_FLOOD))
935 vty_out(vty, "debug ospf6 lsa %s flooding\n",
936 ospf6_lsa_handler_name(handler));
937 }
718e3744 938
d62a17ae 939 return 0;
940}