blob: c031a2d9c024a7ad5f24632fc6f3f10a74497535 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
hasso508e53e2004-05-18 18:57:06 +00002 * Copyright (C) 2003 Yasuhiro Ohara
paul718e3742002-12-13 20:15:29 +00003 *
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
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
24/* Include other stuffs */
paul718e3742002-12-13 20:15:29 +000025#include "log.h"
paul718e3742002-12-13 20:15:29 +000026#include "linklist.h"
paul718e3742002-12-13 20:15:29 +000027#include "command.h"
28#include "memory.h"
paul718e3742002-12-13 20:15:29 +000029#include "thread.h"
paul718e3742002-12-13 20:15:29 +000030
31#include "ospf6_proto.h"
paul718e3742002-12-13 20:15:29 +000032#include "ospf6_lsa.h"
33#include "ospf6_lsdb.h"
34#include "ospf6_message.h"
paul718e3742002-12-13 20:15:29 +000035
36#include "ospf6_top.h"
37#include "ospf6_area.h"
38#include "ospf6_interface.h"
39#include "ospf6_neighbor.h"
paul718e3742002-12-13 20:15:29 +000040
hasso508e53e2004-05-18 18:57:06 +000041#include "ospf6_flood.h"
hasso049207c2004-08-04 20:02:13 +000042#include "ospf6d.h"
paul718e3742002-12-13 20:15:29 +000043
hasso508e53e2004-05-18 18:57:06 +000044unsigned char conf_debug_ospf6_lsa = 0;
45
hasso6452df02004-08-15 05:52:07 +000046struct ospf6_lsa_handler *ospf6_lsa_handler[OSPF6_LSTYPE_SIZE];
hasso508e53e2004-05-18 18:57:06 +000047
48char *ospf6_lstype_str[OSPF6_LSTYPE_SIZE] =
49 {"Unknown", "Router", "Network", "Inter-Prefix", "Inter-Router",
50 "AS-External", "Group-Membership", "Type-7", "Link", "Intra-Prefix"};
51
52char *
53ospf6_lstype_name (u_int16_t type)
paul718e3742002-12-13 20:15:29 +000054{
hasso508e53e2004-05-18 18:57:06 +000055 static char buf[8];
hasso6452df02004-08-15 05:52:07 +000056 int index = OSPF6_LSTYPE_INDEX (type);
paul718e3742002-12-13 20:15:29 +000057
hasso6452df02004-08-15 05:52:07 +000058 if (ospf6_lsa_handler[index])
59 return ospf6_lsa_handler[index]->name;
paul718e3742002-12-13 20:15:29 +000060
hasso508e53e2004-05-18 18:57:06 +000061 snprintf (buf, sizeof (buf), "0x%04hx", ntohs (type));
62 return buf;
paul718e3742002-12-13 20:15:29 +000063}
64
65/* RFC2328: Section 13.2 */
66int
hasso508e53e2004-05-18 18:57:06 +000067ospf6_lsa_is_differ (struct ospf6_lsa *lsa1,
68 struct ospf6_lsa *lsa2)
paul718e3742002-12-13 20:15:29 +000069{
hasso508e53e2004-05-18 18:57:06 +000070 int len;
paul718e3742002-12-13 20:15:29 +000071
hasso508e53e2004-05-18 18:57:06 +000072 assert (OSPF6_LSA_IS_SAME (lsa1, lsa2));
paul718e3742002-12-13 20:15:29 +000073
hasso508e53e2004-05-18 18:57:06 +000074 /* XXX, Options ??? */
paul718e3742002-12-13 20:15:29 +000075
76 ospf6_lsa_age_current (lsa1);
77 ospf6_lsa_age_current (lsa2);
78 if (ntohs (lsa1->header->age) == MAXAGE &&
79 ntohs (lsa2->header->age) != MAXAGE)
80 return 1;
81 if (ntohs (lsa1->header->age) != MAXAGE &&
82 ntohs (lsa2->header->age) == MAXAGE)
83 return 1;
84
85 /* compare body */
86 if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length))
87 return 1;
88
hasso508e53e2004-05-18 18:57:06 +000089 len = ntohs (lsa1->header->length) - sizeof (struct ospf6_lsa_header);
90 return memcmp (lsa1->header + 1, lsa2->header + 1, len);
paul718e3742002-12-13 20:15:29 +000091}
92
93int
hasso508e53e2004-05-18 18:57:06 +000094ospf6_lsa_is_changed (struct ospf6_lsa *lsa1,
95 struct ospf6_lsa *lsa2)
paul718e3742002-12-13 20:15:29 +000096{
hasso508e53e2004-05-18 18:57:06 +000097 int length;
paul718e3742002-12-13 20:15:29 +000098
hasso508e53e2004-05-18 18:57:06 +000099 if (OSPF6_LSA_IS_MAXAGE (lsa1) ^ OSPF6_LSA_IS_MAXAGE (lsa2))
100 return 1;
101 if (ntohs (lsa1->header->length) != ntohs (lsa2->header->length))
102 return 1;
paul718e3742002-12-13 20:15:29 +0000103
hasso508e53e2004-05-18 18:57:06 +0000104 length = OSPF6_LSA_SIZE (lsa1->header) - sizeof (struct ospf6_lsa_header);
105 assert (length > 0);
paul718e3742002-12-13 20:15:29 +0000106
hasso508e53e2004-05-18 18:57:06 +0000107 return memcmp (OSPF6_LSA_HEADER_END (lsa1->header),
108 OSPF6_LSA_HEADER_END (lsa2->header), length);
paul718e3742002-12-13 20:15:29 +0000109}
110
111/* ospf6 age functions */
112/* calculate birth and set expire timer */
113static void
114ospf6_lsa_age_set (struct ospf6_lsa *lsa)
115{
116 struct timeval now;
117
118 assert (lsa && lsa->header);
119
120 if (gettimeofday (&now, (struct timezone *)NULL) < 0)
121 zlog_warn ("LSA: gettimeofday failed, may fail LSA AGEs: %s",
122 strerror (errno));
123
124 lsa->birth.tv_sec = now.tv_sec - ntohs (lsa->header->age);
125 lsa->birth.tv_usec = now.tv_usec;
126 if (ntohs (lsa->header->age) != MAXAGE)
127 lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa,
hasso6452df02004-08-15 05:52:07 +0000128 MAXAGE + lsa->birth.tv_sec - now.tv_sec);
paul718e3742002-12-13 20:15:29 +0000129 else
130 lsa->expire = NULL;
131 return;
132}
133
134/* this function calculates current age from its birth,
135 then update age field of LSA header. return value is current age */
136u_int16_t
137ospf6_lsa_age_current (struct ospf6_lsa *lsa)
138{
139 struct timeval now;
140 u_int32_t ulage;
141 u_int16_t age;
142
143 assert (lsa);
144 assert (lsa->header);
145
146 /* current time */
147 if (gettimeofday (&now, (struct timezone *)NULL) < 0)
hasso508e53e2004-05-18 18:57:06 +0000148 zlog_warn ("LSA: gettimeofday failed, may fail LSA AGEs: %s",
paul718e3742002-12-13 20:15:29 +0000149 strerror (errno));
150
151 /* calculate age */
152 ulage = now.tv_sec - lsa->birth.tv_sec;
153
154 /* if over MAXAGE, set to it */
hasso508e53e2004-05-18 18:57:06 +0000155 age = (ulage > MAXAGE ? MAXAGE : ulage);
paul718e3742002-12-13 20:15:29 +0000156
157 lsa->header->age = htons (age);
158 return age;
159}
160
161/* update age field of LSA header with adding InfTransDelay */
162void
163ospf6_lsa_age_update_to_send (struct ospf6_lsa *lsa, u_int32_t transdelay)
164{
165 unsigned short age;
166
167 age = ospf6_lsa_age_current (lsa) + transdelay;
168 if (age > MAXAGE)
169 age = MAXAGE;
170 lsa->header->age = htons (age);
paul718e3742002-12-13 20:15:29 +0000171}
172
173void
174ospf6_lsa_premature_aging (struct ospf6_lsa *lsa)
175{
176 /* log */
hasso508e53e2004-05-18 18:57:06 +0000177 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
178 zlog_info ("LSA: Premature aging: %s", lsa->name);
paul718e3742002-12-13 20:15:29 +0000179
hasso508e53e2004-05-18 18:57:06 +0000180 THREAD_OFF (lsa->expire);
181 THREAD_OFF (lsa->refresh);
paul718e3742002-12-13 20:15:29 +0000182
183 memset (&lsa->birth, 0, sizeof (struct timeval));
184 thread_execute (master, ospf6_lsa_expire, lsa, 0);
185}
186
187/* check which is more recent. if a is more recent, return -1;
188 if the same, return 0; otherwise(b is more recent), return 1 */
189int
hasso508e53e2004-05-18 18:57:06 +0000190ospf6_lsa_compare (struct ospf6_lsa *a, struct ospf6_lsa *b)
paul718e3742002-12-13 20:15:29 +0000191{
192 signed long seqnuma, seqnumb;
193 u_int16_t cksuma, cksumb;
194 u_int16_t agea, ageb;
195
196 assert (a && a->header);
197 assert (b && b->header);
hasso508e53e2004-05-18 18:57:06 +0000198 assert (OSPF6_LSA_IS_SAME (a, b));
paul718e3742002-12-13 20:15:29 +0000199
200 seqnuma = ((signed long) ntohl (a->header->seqnum))
201 - (signed long) INITIAL_SEQUENCE_NUMBER;
202 seqnumb = ((signed long) ntohl (b->header->seqnum))
203 - (signed long) INITIAL_SEQUENCE_NUMBER;
204
205 /* compare by sequence number */
hasso508e53e2004-05-18 18:57:06 +0000206 /* XXX, LS sequence number wrapping */
paul718e3742002-12-13 20:15:29 +0000207 if (seqnuma > seqnumb)
208 return -1;
209 else if (seqnuma < seqnumb)
210 return 1;
211
212 /* Checksum */
213 cksuma = ntohs (a->header->checksum);
214 cksumb = ntohs (b->header->checksum);
215 if (cksuma > cksumb)
216 return -1;
217 if (cksuma < cksumb)
218 return 0;
219
hasso508e53e2004-05-18 18:57:06 +0000220 /* Update Age */
paul718e3742002-12-13 20:15:29 +0000221 agea = ospf6_lsa_age_current (a);
222 ageb = ospf6_lsa_age_current (b);
223
hasso508e53e2004-05-18 18:57:06 +0000224 /* MaxAge check */
225 if (agea == MAXAGE && ageb != MAXAGE)
paul718e3742002-12-13 20:15:29 +0000226 return -1;
hasso508e53e2004-05-18 18:57:06 +0000227 else if (agea != MAXAGE && ageb == MAXAGE)
paul718e3742002-12-13 20:15:29 +0000228 return 1;
229
hasso508e53e2004-05-18 18:57:06 +0000230 /* Age check */
231 if (agea > ageb && agea - ageb >= MAX_AGE_DIFF)
paul718e3742002-12-13 20:15:29 +0000232 return 1;
hasso508e53e2004-05-18 18:57:06 +0000233 else if (agea < ageb && ageb - agea >= MAX_AGE_DIFF)
paul718e3742002-12-13 20:15:29 +0000234 return -1;
235
236 /* neither recent */
paul718e3742002-12-13 20:15:29 +0000237 return 0;
238}
239
hasso508e53e2004-05-18 18:57:06 +0000240char *
241ospf6_lsa_printbuf (struct ospf6_lsa *lsa, char *buf, int size)
paul718e3742002-12-13 20:15:29 +0000242{
hasso508e53e2004-05-18 18:57:06 +0000243 char id[16], adv_router[16];
244 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
245 inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
246 sizeof (adv_router));
247 snprintf (buf, size, "[%s Id:%s Adv:%s]",
248 OSPF6_LSTYPE_NAME (lsa->header->type), id, adv_router);
249 return buf;
paul718e3742002-12-13 20:15:29 +0000250}
251
hasso508e53e2004-05-18 18:57:06 +0000252void
253ospf6_lsa_header_print_raw (struct ospf6_lsa_header *header)
paul718e3742002-12-13 20:15:29 +0000254{
hasso508e53e2004-05-18 18:57:06 +0000255 char id[16], adv_router[16];
256 inet_ntop (AF_INET, &header->id, id, sizeof (id));
257 inet_ntop (AF_INET, &header->adv_router, adv_router,
258 sizeof (adv_router));
259 zlog_info (" [%s Id:%s Adv:%s]",
260 OSPF6_LSTYPE_NAME (header->type), id, adv_router);
261 zlog_info (" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
262 ntohs (header->age), (u_long) ntohl (header->seqnum),
263 ntohs (header->checksum), ntohs (header->length));
paul718e3742002-12-13 20:15:29 +0000264}
265
hasso508e53e2004-05-18 18:57:06 +0000266void
267ospf6_lsa_header_print (struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000268{
hasso508e53e2004-05-18 18:57:06 +0000269 ospf6_lsa_age_current (lsa);
270 ospf6_lsa_header_print_raw (lsa->header);
paul718e3742002-12-13 20:15:29 +0000271}
272
273void
paul718e3742002-12-13 20:15:29 +0000274ospf6_lsa_show_summary_header (struct vty *vty)
275{
276 vty_out (vty, "%-12s %-15s %-15s %4s %8s %4s %4s %-8s%s",
277 "Type", "LSId", "AdvRouter", "Age", "SeqNum",
hasso049207c2004-08-04 20:02:13 +0000278 "Cksm", "Len", "Duration", VNL);
paul718e3742002-12-13 20:15:29 +0000279}
280
281void
282ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa)
283{
hasso508e53e2004-05-18 18:57:06 +0000284 char adv_router[16], id[16];
paul718e3742002-12-13 20:15:29 +0000285 struct timeval now, res;
286 char duration[16];
287
288 assert (lsa);
289 assert (lsa->header);
290
paul718e3742002-12-13 20:15:29 +0000291 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
292 inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
293 sizeof (adv_router));
294
295 gettimeofday (&now, NULL);
hasso508e53e2004-05-18 18:57:06 +0000296 timersub (&now, &lsa->installed, &res);
297 timerstring (&res, duration, sizeof (duration));
paul718e3742002-12-13 20:15:29 +0000298
299 vty_out (vty, "%-12s %-15s %-15s %4hu %8lx %04hx %4hu %8s%s",
hasso508e53e2004-05-18 18:57:06 +0000300 OSPF6_LSTYPE_NAME (lsa->header->type),
301 id, adv_router, ospf6_lsa_age_current (lsa),
paul718e3742002-12-13 20:15:29 +0000302 (u_long) ntohl (lsa->header->seqnum),
303 ntohs (lsa->header->checksum), ntohs (lsa->header->length),
hasso049207c2004-08-04 20:02:13 +0000304 duration, VNL);
paul718e3742002-12-13 20:15:29 +0000305}
306
307void
308ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa)
309{
310 u_char *start, *end, *current;
311 char byte[4];
312
313 start = (char *) lsa->header;
314 end = (char *) lsa->header + ntohs (lsa->header->length);
315
hasso049207c2004-08-04 20:02:13 +0000316 vty_out (vty, "%s", VNL);
317 vty_out (vty, "%s:%s", lsa->name, VNL);
paul718e3742002-12-13 20:15:29 +0000318
319 for (current = start; current < end; current ++)
320 {
321 if ((current - start) % 16 == 0)
hasso049207c2004-08-04 20:02:13 +0000322 vty_out (vty, "%s ", VNL);
paul718e3742002-12-13 20:15:29 +0000323 else if ((current - start) % 4 == 0)
324 vty_out (vty, " ");
325
326 snprintf (byte, sizeof (byte), "%02x", *current);
327 vty_out (vty, "%s", byte);
328 }
329
hasso049207c2004-08-04 20:02:13 +0000330 vty_out (vty, "%s%s", VNL, VNL);
hasso6452df02004-08-15 05:52:07 +0000331 return;
paul718e3742002-12-13 20:15:29 +0000332}
333
hasso508e53e2004-05-18 18:57:06 +0000334void
335ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa)
336{
337 char adv_router[64], id[64];
338
339 assert (lsa && lsa->header);
340
341 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
342 inet_ntop (AF_INET, &lsa->header->adv_router,
343 adv_router, sizeof (adv_router));
344
hasso049207c2004-08-04 20:02:13 +0000345 vty_out (vty, "%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000346 vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
hasso049207c2004-08-04 20:02:13 +0000347 OSPF6_LSTYPE_NAME (lsa->header->type), VNL);
348 vty_out (vty, "Link State ID: %s%s", id, VNL);
349 vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
hasso508e53e2004-05-18 18:57:06 +0000350 vty_out (vty, "LS Sequence Number: %#010lx%s",
hasso049207c2004-08-04 20:02:13 +0000351 (u_long) ntohl (lsa->header->seqnum), VNL);
hasso508e53e2004-05-18 18:57:06 +0000352 vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
353 ntohs (lsa->header->checksum),
hasso049207c2004-08-04 20:02:13 +0000354 ntohs (lsa->header->length), VNL);
hasso508e53e2004-05-18 18:57:06 +0000355 vty_out (vty, " Prev: %p This: %p Next: %p%s",
hasso049207c2004-08-04 20:02:13 +0000356 lsa->prev, lsa, lsa->next, VNL);
357 vty_out (vty, "%s", VNL);
hasso6452df02004-08-15 05:52:07 +0000358 return;
359}
360
361void
362ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
363{
364 char adv_router[64], id[64];
365 int index;
366
367 assert (lsa && lsa->header);
368
369 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
370 inet_ntop (AF_INET, &lsa->header->adv_router,
371 adv_router, sizeof (adv_router));
372
373 vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
374 OSPF6_LSTYPE_NAME (lsa->header->type), VNL);
375 vty_out (vty, "Link State ID: %s%s", id, VNL);
376 vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
377 vty_out (vty, "LS Sequence Number: %#010lx%s",
378 (u_long) ntohl (lsa->header->seqnum), VNL);
379 vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
380 ntohs (lsa->header->checksum),
381 ntohs (lsa->header->length), VNL);
382
383 index = OSPF6_LSTYPE_INDEX (lsa->header->type);
384 if (ospf6_lsa_handler[index]->show)
385 (*ospf6_lsa_handler[index]->show) (vty, lsa);
386 else
387 {
388 ospf6_lsa_show_dump (vty, lsa);
389 vty_out (vty, "%sUnknown LSA type ...%s", VNL, VNL);
390 }
391
392 vty_out (vty, "%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000393}
394
paul718e3742002-12-13 20:15:29 +0000395/* OSPFv3 LSA creation/deletion function */
paul718e3742002-12-13 20:15:29 +0000396struct ospf6_lsa *
hasso508e53e2004-05-18 18:57:06 +0000397ospf6_lsa_create (struct ospf6_lsa_header *header)
paul718e3742002-12-13 20:15:29 +0000398{
399 struct ospf6_lsa *lsa = NULL;
hasso508e53e2004-05-18 18:57:06 +0000400 struct ospf6_lsa_header *new_header = NULL;
paul718e3742002-12-13 20:15:29 +0000401 u_int16_t lsa_size = 0;
paul718e3742002-12-13 20:15:29 +0000402
hasso508e53e2004-05-18 18:57:06 +0000403 /* size of the entire LSA */
404 lsa_size = ntohs (header->length); /* XXX vulnerable */
paul718e3742002-12-13 20:15:29 +0000405
406 /* allocate memory for this LSA */
hasso508e53e2004-05-18 18:57:06 +0000407 new_header = (struct ospf6_lsa_header *)
paul718e3742002-12-13 20:15:29 +0000408 XMALLOC (MTYPE_OSPF6_LSA, lsa_size);
paul718e3742002-12-13 20:15:29 +0000409
hasso508e53e2004-05-18 18:57:06 +0000410 /* copy LSA from original header */
411 memcpy (new_header, header, lsa_size);
paul718e3742002-12-13 20:15:29 +0000412
413 /* LSA information structure */
414 /* allocate memory */
415 lsa = (struct ospf6_lsa *)
hasso508e53e2004-05-18 18:57:06 +0000416 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
paul718e3742002-12-13 20:15:29 +0000417 memset (lsa, 0, sizeof (struct ospf6_lsa));
418
hasso508e53e2004-05-18 18:57:06 +0000419 lsa->header = (struct ospf6_lsa_header *) new_header;
paul718e3742002-12-13 20:15:29 +0000420
421 /* dump string */
hasso508e53e2004-05-18 18:57:06 +0000422 ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
paul718e3742002-12-13 20:15:29 +0000423
424 /* calculate birth, expire and refresh of this lsa */
425 ospf6_lsa_age_set (lsa);
426
hasso508e53e2004-05-18 18:57:06 +0000427 if (IS_OSPF6_DEBUG_LSA (MEMORY))
428 zlog_info ("Create LSA Memory: %s (%p/%p)",
429 lsa->name, lsa, lsa->header);
paul718e3742002-12-13 20:15:29 +0000430
431 return lsa;
432}
433
434struct ospf6_lsa *
hasso508e53e2004-05-18 18:57:06 +0000435ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header)
paul718e3742002-12-13 20:15:29 +0000436{
437 struct ospf6_lsa *lsa = NULL;
hasso508e53e2004-05-18 18:57:06 +0000438 struct ospf6_lsa_header *new_header = NULL;
paul718e3742002-12-13 20:15:29 +0000439
440 /* allocate memory for this LSA */
hasso508e53e2004-05-18 18:57:06 +0000441 new_header = (struct ospf6_lsa_header *)
442 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +0000443
hasso508e53e2004-05-18 18:57:06 +0000444 /* copy LSA from original header */
445 memcpy (new_header, header, sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +0000446
447 /* LSA information structure */
448 /* allocate memory */
449 lsa = (struct ospf6_lsa *)
hasso508e53e2004-05-18 18:57:06 +0000450 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
paul718e3742002-12-13 20:15:29 +0000451 memset (lsa, 0, sizeof (struct ospf6_lsa));
452
hasso508e53e2004-05-18 18:57:06 +0000453 lsa->header = (struct ospf6_lsa_header *) new_header;
hasso6452df02004-08-15 05:52:07 +0000454 SET_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY);
paul718e3742002-12-13 20:15:29 +0000455
456 /* dump string */
hasso508e53e2004-05-18 18:57:06 +0000457 ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
paul718e3742002-12-13 20:15:29 +0000458
459 /* calculate birth, expire and refresh of this lsa */
460 ospf6_lsa_age_set (lsa);
461
hasso508e53e2004-05-18 18:57:06 +0000462 if (IS_OSPF6_DEBUG_LSA (MEMORY))
463 zlog_info ("Create LSA (Header-only) Memory: %s (%p/%p)",
464 lsa->name, lsa, lsa->header);
paul718e3742002-12-13 20:15:29 +0000465
466 return lsa;
467}
468
469void
470ospf6_lsa_delete (struct ospf6_lsa *lsa)
471{
hasso508e53e2004-05-18 18:57:06 +0000472 assert (lsa->lock == 0);
paul718e3742002-12-13 20:15:29 +0000473
474 /* cancel threads */
hasso508e53e2004-05-18 18:57:06 +0000475 THREAD_OFF (lsa->expire);
476 THREAD_OFF (lsa->refresh);
paul718e3742002-12-13 20:15:29 +0000477
hasso508e53e2004-05-18 18:57:06 +0000478 if (IS_OSPF6_DEBUG_LSA (MEMORY))
479 zlog_info ("Delete LSA %s Memory: %s (%p/%p)",
hasso6452df02004-08-15 05:52:07 +0000480 (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY) ?
481 "(Header-only) " : ""), lsa->name, lsa, lsa->header);
paul718e3742002-12-13 20:15:29 +0000482
483 /* do free */
hasso508e53e2004-05-18 18:57:06 +0000484 XFREE (MTYPE_OSPF6_LSA, lsa->header);
485 XFREE (MTYPE_OSPF6_LSA, lsa);
paul718e3742002-12-13 20:15:29 +0000486}
487
hasso508e53e2004-05-18 18:57:06 +0000488struct ospf6_lsa *
489ospf6_lsa_copy (struct ospf6_lsa *lsa)
490{
491 struct ospf6_lsa *copy = NULL;
492
493 if (IS_OSPF6_DEBUG_LSA (MEMORY))
494 zlog_info ("Create LSA Copy from %s", lsa->name);
495
496 ospf6_lsa_age_current (lsa);
hasso6452df02004-08-15 05:52:07 +0000497 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
hasso508e53e2004-05-18 18:57:06 +0000498 copy = ospf6_lsa_create_headeronly (lsa->header);
499 else
500 copy = ospf6_lsa_create (lsa->header);
501 assert (copy->lock == 0);
502
503 copy->installed = lsa->installed;
504 copy->originated = lsa->originated;
hasso6452df02004-08-15 05:52:07 +0000505 copy->lsdb = lsa->lsdb;
hasso508e53e2004-05-18 18:57:06 +0000506
hasso508e53e2004-05-18 18:57:06 +0000507 return copy;
508}
509
510/* increment reference counter of struct ospf6_lsa */
paul718e3742002-12-13 20:15:29 +0000511void
512ospf6_lsa_lock (struct ospf6_lsa *lsa)
513{
514 lsa->lock++;
515 return;
516}
517
hasso508e53e2004-05-18 18:57:06 +0000518/* decrement reference counter of struct ospf6_lsa */
paul718e3742002-12-13 20:15:29 +0000519void
520ospf6_lsa_unlock (struct ospf6_lsa *lsa)
521{
522 /* decrement reference counter */
hasso508e53e2004-05-18 18:57:06 +0000523 assert (lsa->lock > 0);
524 lsa->lock--;
paul718e3742002-12-13 20:15:29 +0000525
hasso508e53e2004-05-18 18:57:06 +0000526 if (lsa->lock != 0)
527 return;
528
hasso508e53e2004-05-18 18:57:06 +0000529 ospf6_lsa_delete (lsa);
paul718e3742002-12-13 20:15:29 +0000530}
531
paul718e3742002-12-13 20:15:29 +0000532
hasso508e53e2004-05-18 18:57:06 +0000533/* ospf6 lsa expiry */
paul718e3742002-12-13 20:15:29 +0000534int
535ospf6_lsa_expire (struct thread *thread)
536{
537 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000538
539 lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +0000540
hasso508e53e2004-05-18 18:57:06 +0000541 assert (lsa && lsa->header);
542 assert (OSPF6_LSA_IS_MAXAGE (lsa));
543 assert (! lsa->refresh);
paul718e3742002-12-13 20:15:29 +0000544
545 lsa->expire = (struct thread *) NULL;
546
hasso508e53e2004-05-18 18:57:06 +0000547 if (IS_OSPF6_DEBUG_LSA (TIMER))
paul718e3742002-12-13 20:15:29 +0000548 {
hasso508e53e2004-05-18 18:57:06 +0000549 zlog_info ("LSA Expire:");
550 ospf6_lsa_header_print (lsa);
paul718e3742002-12-13 20:15:29 +0000551 }
552
hasso6452df02004-08-15 05:52:07 +0000553 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
hasso508e53e2004-05-18 18:57:06 +0000554 return 0; /* dbexchange will do something ... */
555
556 /* reflood lsa */
hasso6452df02004-08-15 05:52:07 +0000557 ospf6_flood (NULL, lsa);
hasso508e53e2004-05-18 18:57:06 +0000558
559 /* reinstall lsa */
hasso508e53e2004-05-18 18:57:06 +0000560 if (IS_OSPF6_DEBUG_LSA (DATABASE))
561 zlog_info ("Reinstall MaxAge %s", lsa->name);
hasso6452df02004-08-15 05:52:07 +0000562 ospf6_lsdb_add (lsa, lsa->lsdb);
hasso508e53e2004-05-18 18:57:06 +0000563
564 /* schedule maxage remover */
565 ospf6_maxage_remove (ospf6);
566
paul718e3742002-12-13 20:15:29 +0000567 return 0;
568}
569
570int
571ospf6_lsa_refresh (struct thread *thread)
572{
hasso6452df02004-08-15 05:52:07 +0000573 struct ospf6_lsa *old, *self, *new;
574 struct ospf6_lsdb *lsdb_self;
paul718e3742002-12-13 20:15:29 +0000575
576 assert (thread);
hasso6452df02004-08-15 05:52:07 +0000577 old = (struct ospf6_lsa *) THREAD_ARG (thread);
578 assert (old && old->header);
paul718e3742002-12-13 20:15:29 +0000579
hasso6452df02004-08-15 05:52:07 +0000580 old->refresh = (struct thread *) NULL;
paul718e3742002-12-13 20:15:29 +0000581
hasso6452df02004-08-15 05:52:07 +0000582 lsdb_self = ospf6_get_scoped_lsdb_self (old);
583 self = ospf6_lsdb_lookup (old->header->type, old->header->id,
584 old->header->adv_router, lsdb_self);
585 if (self == NULL)
586 {
587 ospf6_lsa_premature_aging (old);
588 return 0;
589 }
590
591 /* Reset age, increment LS sequence number. */
592 self->header->age = htons (0);
593 self->header->seqnum =
594 ospf6_new_ls_seqnum (self->header->type, self->header->id,
595 self->header->adv_router, old->lsdb);
596 ospf6_lsa_checksum (self->header);
597
598 new = ospf6_lsa_create (self->header);
599 new->lsdb = old->lsdb;
600 new->refresh = thread_add_timer (master, ospf6_lsa_refresh, new,
601 LS_REFRESH_TIME);
602
603 /* store it in the LSDB for self-originated LSAs */
604 ospf6_lsdb_add (ospf6_lsa_copy (new), lsdb_self);
paul718e3742002-12-13 20:15:29 +0000605
hasso508e53e2004-05-18 18:57:06 +0000606 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
paul718e3742002-12-13 20:15:29 +0000607 {
hasso508e53e2004-05-18 18:57:06 +0000608 zlog_info ("LSA Refresh:");
hasso6452df02004-08-15 05:52:07 +0000609 ospf6_lsa_header_print (new);
paul718e3742002-12-13 20:15:29 +0000610 }
611
hasso6452df02004-08-15 05:52:07 +0000612 ospf6_flood_clear (old);
613 ospf6_flood (NULL, new);
614 ospf6_install_lsa (new);
615
hasso508e53e2004-05-18 18:57:06 +0000616 return 0;
paul718e3742002-12-13 20:15:29 +0000617}
618
619
620
621/* enhanced Fletcher checksum algorithm, RFC1008 7.2 */
622#define MODX 4102
623#define LSA_CHECKSUM_OFFSET 15
624
625unsigned short
626ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header)
627{
628 u_char *sp, *ep, *p, *q;
629 int c0 = 0, c1 = 0;
630 int x, y;
631 u_int16_t length;
632
633 lsa_header->checksum = 0;
634 length = ntohs (lsa_header->length) - 2;
635 sp = (char *) &lsa_header->type;
636
637 for (ep = sp + length; sp < ep; sp = q)
638 {
639 q = sp + MODX;
640 if (q > ep)
641 q = ep;
642 for (p = sp; p < q; p++)
643 {
644 c0 += *p;
645 c1 += c0;
646 }
647 c0 %= 255;
648 c1 %= 255;
649 }
650
651 /* r = (c1 << 8) + c0; */
652 x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255;
653 if (x <= 0)
654 x += 255;
655 y = 510 - c0 - x;
656 if (y > 255)
657 y -= 255;
658
659 lsa_header->checksum = htons ((x << 8) + y);
660
661 return (lsa_header->checksum);
662}
663
664int
hasso6452df02004-08-15 05:52:07 +0000665ospf6_unknown_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000666{
hasso508e53e2004-05-18 18:57:06 +0000667 u_char *start, *end, *current;
668 char byte[4];
paul718e3742002-12-13 20:15:29 +0000669
hasso508e53e2004-05-18 18:57:06 +0000670 start = (char *) lsa->header + sizeof (struct ospf6_lsa_header);
paul718e3742002-12-13 20:15:29 +0000671 end = (char *) lsa->header + ntohs (lsa->header->length);
hasso508e53e2004-05-18 18:57:06 +0000672
hasso049207c2004-08-04 20:02:13 +0000673 vty_out (vty, " Unknown contents:%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000674 for (current = start; current < end; current ++)
paul718e3742002-12-13 20:15:29 +0000675 {
hasso508e53e2004-05-18 18:57:06 +0000676 if ((current - start) % 16 == 0)
hasso049207c2004-08-04 20:02:13 +0000677 vty_out (vty, "%s ", VNL);
hasso508e53e2004-05-18 18:57:06 +0000678 else if ((current - start) % 4 == 0)
679 vty_out (vty, " ");
paul718e3742002-12-13 20:15:29 +0000680
hasso508e53e2004-05-18 18:57:06 +0000681 snprintf (byte, sizeof (byte), "%02x", *current);
682 vty_out (vty, "%s", byte);
paul718e3742002-12-13 20:15:29 +0000683 }
hasso508e53e2004-05-18 18:57:06 +0000684
hasso049207c2004-08-04 20:02:13 +0000685 vty_out (vty, "%s%s", VNL, VNL);
paul718e3742002-12-13 20:15:29 +0000686 return 0;
687}
688
paul718e3742002-12-13 20:15:29 +0000689void
hasso6452df02004-08-15 05:52:07 +0000690ospf6_install_lsa_handler (struct ospf6_lsa_handler *handler)
691{
692 /* might need to adjust dynamic array length ... */
693 int index = OSPF6_LSTYPE_INDEX (htons (handler->type));
694 ospf6_lsa_handler[index] = handler;
695}
696
697struct ospf6_lsa_handler unknown_handler =
698{
699 OSPF6_LSTYPE_UNKNOWN,
700 "Unknown",
701 ospf6_unknown_lsa_show
702};
703
704void
paul718e3742002-12-13 20:15:29 +0000705ospf6_lsa_init ()
706{
hasso6452df02004-08-15 05:52:07 +0000707 memset (ospf6_lsa_handler, 0, sizeof (ospf6_lsa_handler));
708 ospf6_install_lsa_handler (&unknown_handler);
paul718e3742002-12-13 20:15:29 +0000709}
710
hasso508e53e2004-05-18 18:57:06 +0000711
712
713DEFUN (debug_ospf6_lsa_sendrecv,
714 debug_ospf6_lsa_sendrecv_cmd,
715 "debug ospf6 lsa (send|recv|originate|timer|database|memory|all)",
716 DEBUG_STR
717 OSPF6_STR
718 "Debug Link State Advertisements (LSAs)\n"
719 "Debug Sending LSAs\n"
720 "Debug Receiving LSAs\n"
721 "Debug Originating LSAs\n"
722 "Debug Timer Event of LSAs\n"
723 "Debug LSA Database\n"
724 "Debug Memory of LSAs\n"
725 "Debug LSAs all\n"
726 )
727{
728 unsigned char level = 0;
729
730 if (argc)
731 {
732 if (! strncmp (argv[0], "s", 1))
733 level = OSPF6_DEBUG_LSA_SEND;
734 else if (! strncmp (argv[0], "r", 1))
735 level = OSPF6_DEBUG_LSA_RECV;
736 else if (! strncmp (argv[0], "o", 1))
737 level = OSPF6_DEBUG_LSA_ORIGINATE;
738 else if (! strncmp (argv[0], "t", 1))
739 level = OSPF6_DEBUG_LSA_TIMER;
740 else if (! strncmp (argv[0], "d", 1))
741 level = OSPF6_DEBUG_LSA_DATABASE;
742 else if (! strncmp (argv[0], "m", 1))
743 level = OSPF6_DEBUG_LSA_MEMORY;
744 else if (! strncmp (argv[0], "a", 1))
745 {
746 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
747 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER |
748 OSPF6_DEBUG_LSA_DATABASE | OSPF6_DEBUG_LSA_MEMORY;
749 }
750 }
751 else
752 {
753 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
754 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER;
755 }
756
757 OSPF6_DEBUG_LSA_ON (level);
758 return CMD_SUCCESS;
759}
760
761ALIAS (debug_ospf6_lsa_sendrecv,
762 debug_ospf6_lsa_cmd,
763 "debug ospf6 lsa",
764 NO_STR
765 DEBUG_STR
766 OSPF6_STR
767 "Debug Link State Advertisements (LSAs)\n"
768 );
769
770DEFUN (no_debug_ospf6_lsa_sendrecv,
771 no_debug_ospf6_lsa_sendrecv_cmd,
772 "no debug ospf6 lsa (send|recv|originate|timer|database|memory|all)",
773 NO_STR
774 DEBUG_STR
775 OSPF6_STR
776 "Debug Link State Advertisements (LSAs)\n"
777 "Debug Sending LSAs\n"
778 "Debug Receiving LSAs\n"
779 "Debug Originating LSAs\n"
780 "Debug Timer Event of LSAs\n"
781 "Debug LSA Database\n"
782 "Debug Memory of LSAs\n"
783 "Debug LSAs all\n"
784 )
785{
786 unsigned char level = 0;
787
788 if (argc)
789 {
790 if (! strncmp (argv[0], "s", 1))
791 level = OSPF6_DEBUG_LSA_SEND;
792 else if (! strncmp (argv[0], "r", 1))
793 level = OSPF6_DEBUG_LSA_RECV;
794 else if (! strncmp (argv[0], "o", 1))
795 level = OSPF6_DEBUG_LSA_ORIGINATE;
796 else if (! strncmp (argv[0], "t", 1))
797 level = OSPF6_DEBUG_LSA_TIMER;
798 else if (! strncmp (argv[0], "d", 1))
799 level = OSPF6_DEBUG_LSA_DATABASE;
800 else if (! strncmp (argv[0], "m", 1))
801 level = OSPF6_DEBUG_LSA_MEMORY;
802 else if (! strncmp (argv[0], "a", 1))
803 {
804 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
805 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER |
806 OSPF6_DEBUG_LSA_DATABASE | OSPF6_DEBUG_LSA_MEMORY;
807 }
808 }
809 else
810 {
811 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
812 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER;
813 }
814
815 OSPF6_DEBUG_LSA_OFF (level);
816 return CMD_SUCCESS;
817}
818
819ALIAS (no_debug_ospf6_lsa_sendrecv,
820 no_debug_ospf6_lsa_cmd,
821 "no debug ospf6 lsa",
822 NO_STR
823 DEBUG_STR
824 OSPF6_STR
825 "Debug Link State Advertisements (LSAs)\n"
826 );
827
828int
829config_write_ospf6_debug_lsa (struct vty *vty)
830{
831 if (conf_debug_ospf6_lsa == OSPF6_DEBUG_LSA_ALL)
hasso049207c2004-08-04 20:02:13 +0000832 vty_out (vty, "debug ospf6 lsa all%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000833 else
834 {
835 if (conf_debug_ospf6_lsa == OSPF6_DEBUG_LSA_DEFAULT)
hasso049207c2004-08-04 20:02:13 +0000836 vty_out (vty, "debug ospf6 lsa%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000837 else
838 {
839 if (IS_OSPF6_DEBUG_LSA (SEND))
hasso049207c2004-08-04 20:02:13 +0000840 vty_out (vty, "debug ospf6 lsa send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000841 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso049207c2004-08-04 20:02:13 +0000842 vty_out (vty, "debug ospf6 lsa recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000843 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
hasso049207c2004-08-04 20:02:13 +0000844 vty_out (vty, "debug ospf6 lsa originate%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000845 if (IS_OSPF6_DEBUG_LSA (TIMER))
hasso049207c2004-08-04 20:02:13 +0000846 vty_out (vty, "debug ospf6 lsa timer%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000847 }
848
849 if (IS_OSPF6_DEBUG_LSA (DATABASE))
hasso049207c2004-08-04 20:02:13 +0000850 vty_out (vty, "debug ospf6 lsa database%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000851 if (IS_OSPF6_DEBUG_LSA (MEMORY))
hasso049207c2004-08-04 20:02:13 +0000852 vty_out (vty, "debug ospf6 lsa memory%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000853 }
854
855 return 0;
856}
857
858void
859install_element_ospf6_debug_lsa ()
860{
861 install_element (ENABLE_NODE, &debug_ospf6_lsa_cmd);
862 install_element (ENABLE_NODE, &debug_ospf6_lsa_sendrecv_cmd);
863 install_element (ENABLE_NODE, &no_debug_ospf6_lsa_cmd);
864 install_element (ENABLE_NODE, &no_debug_ospf6_lsa_sendrecv_cmd);
865 install_element (CONFIG_NODE, &debug_ospf6_lsa_cmd);
866 install_element (CONFIG_NODE, &debug_ospf6_lsa_sendrecv_cmd);
867 install_element (CONFIG_NODE, &no_debug_ospf6_lsa_cmd);
868 install_element (CONFIG_NODE, &no_debug_ospf6_lsa_sendrecv_cmd);
869}
870
871