blob: 8eea002ea5dfb7a1953101a6db7d414d08cb3150 [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 */
hasso3b687352004-08-19 06:56:53 +0000112/* calculate birth */
paul718e3742002-12-13 20:15:29 +0000113static 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;
hasso3b687352004-08-19 06:56:53 +0000126
paul718e3742002-12-13 20:15:29 +0000127 return;
128}
129
130/* this function calculates current age from its birth,
131 then update age field of LSA header. return value is current age */
132u_int16_t
133ospf6_lsa_age_current (struct ospf6_lsa *lsa)
134{
135 struct timeval now;
136 u_int32_t ulage;
137 u_int16_t age;
138
139 assert (lsa);
140 assert (lsa->header);
141
142 /* current time */
143 if (gettimeofday (&now, (struct timezone *)NULL) < 0)
hasso508e53e2004-05-18 18:57:06 +0000144 zlog_warn ("LSA: gettimeofday failed, may fail LSA AGEs: %s",
paul718e3742002-12-13 20:15:29 +0000145 strerror (errno));
146
147 /* calculate age */
148 ulage = now.tv_sec - lsa->birth.tv_sec;
149
150 /* if over MAXAGE, set to it */
hasso508e53e2004-05-18 18:57:06 +0000151 age = (ulage > MAXAGE ? MAXAGE : ulage);
paul718e3742002-12-13 20:15:29 +0000152
153 lsa->header->age = htons (age);
154 return age;
155}
156
157/* update age field of LSA header with adding InfTransDelay */
158void
159ospf6_lsa_age_update_to_send (struct ospf6_lsa *lsa, u_int32_t transdelay)
160{
161 unsigned short age;
162
163 age = ospf6_lsa_age_current (lsa) + transdelay;
164 if (age > MAXAGE)
165 age = MAXAGE;
166 lsa->header->age = htons (age);
paul718e3742002-12-13 20:15:29 +0000167}
168
169void
170ospf6_lsa_premature_aging (struct ospf6_lsa *lsa)
171{
172 /* log */
hasso508e53e2004-05-18 18:57:06 +0000173 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
174 zlog_info ("LSA: Premature aging: %s", lsa->name);
paul718e3742002-12-13 20:15:29 +0000175
hasso508e53e2004-05-18 18:57:06 +0000176 THREAD_OFF (lsa->expire);
177 THREAD_OFF (lsa->refresh);
paul718e3742002-12-13 20:15:29 +0000178
179 memset (&lsa->birth, 0, sizeof (struct timeval));
180 thread_execute (master, ospf6_lsa_expire, lsa, 0);
181}
182
183/* check which is more recent. if a is more recent, return -1;
184 if the same, return 0; otherwise(b is more recent), return 1 */
185int
hasso508e53e2004-05-18 18:57:06 +0000186ospf6_lsa_compare (struct ospf6_lsa *a, struct ospf6_lsa *b)
paul718e3742002-12-13 20:15:29 +0000187{
188 signed long seqnuma, seqnumb;
189 u_int16_t cksuma, cksumb;
190 u_int16_t agea, ageb;
191
192 assert (a && a->header);
193 assert (b && b->header);
hasso508e53e2004-05-18 18:57:06 +0000194 assert (OSPF6_LSA_IS_SAME (a, b));
paul718e3742002-12-13 20:15:29 +0000195
196 seqnuma = ((signed long) ntohl (a->header->seqnum))
197 - (signed long) INITIAL_SEQUENCE_NUMBER;
198 seqnumb = ((signed long) ntohl (b->header->seqnum))
199 - (signed long) INITIAL_SEQUENCE_NUMBER;
200
201 /* compare by sequence number */
hasso508e53e2004-05-18 18:57:06 +0000202 /* XXX, LS sequence number wrapping */
paul718e3742002-12-13 20:15:29 +0000203 if (seqnuma > seqnumb)
204 return -1;
205 else if (seqnuma < seqnumb)
206 return 1;
207
208 /* Checksum */
209 cksuma = ntohs (a->header->checksum);
210 cksumb = ntohs (b->header->checksum);
211 if (cksuma > cksumb)
212 return -1;
213 if (cksuma < cksumb)
214 return 0;
215
hasso508e53e2004-05-18 18:57:06 +0000216 /* Update Age */
paul718e3742002-12-13 20:15:29 +0000217 agea = ospf6_lsa_age_current (a);
218 ageb = ospf6_lsa_age_current (b);
219
hasso508e53e2004-05-18 18:57:06 +0000220 /* MaxAge check */
221 if (agea == MAXAGE && ageb != MAXAGE)
paul718e3742002-12-13 20:15:29 +0000222 return -1;
hasso508e53e2004-05-18 18:57:06 +0000223 else if (agea != MAXAGE && ageb == MAXAGE)
paul718e3742002-12-13 20:15:29 +0000224 return 1;
225
hasso508e53e2004-05-18 18:57:06 +0000226 /* Age check */
227 if (agea > ageb && agea - ageb >= MAX_AGE_DIFF)
paul718e3742002-12-13 20:15:29 +0000228 return 1;
hasso508e53e2004-05-18 18:57:06 +0000229 else if (agea < ageb && ageb - agea >= MAX_AGE_DIFF)
paul718e3742002-12-13 20:15:29 +0000230 return -1;
231
232 /* neither recent */
paul718e3742002-12-13 20:15:29 +0000233 return 0;
234}
235
hasso508e53e2004-05-18 18:57:06 +0000236char *
237ospf6_lsa_printbuf (struct ospf6_lsa *lsa, char *buf, int size)
paul718e3742002-12-13 20:15:29 +0000238{
hasso508e53e2004-05-18 18:57:06 +0000239 char id[16], adv_router[16];
240 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
241 inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
242 sizeof (adv_router));
243 snprintf (buf, size, "[%s Id:%s Adv:%s]",
244 OSPF6_LSTYPE_NAME (lsa->header->type), id, adv_router);
245 return buf;
paul718e3742002-12-13 20:15:29 +0000246}
247
hasso508e53e2004-05-18 18:57:06 +0000248void
249ospf6_lsa_header_print_raw (struct ospf6_lsa_header *header)
paul718e3742002-12-13 20:15:29 +0000250{
hasso508e53e2004-05-18 18:57:06 +0000251 char id[16], adv_router[16];
252 inet_ntop (AF_INET, &header->id, id, sizeof (id));
253 inet_ntop (AF_INET, &header->adv_router, adv_router,
254 sizeof (adv_router));
255 zlog_info (" [%s Id:%s Adv:%s]",
256 OSPF6_LSTYPE_NAME (header->type), id, adv_router);
257 zlog_info (" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
258 ntohs (header->age), (u_long) ntohl (header->seqnum),
259 ntohs (header->checksum), ntohs (header->length));
paul718e3742002-12-13 20:15:29 +0000260}
261
hasso508e53e2004-05-18 18:57:06 +0000262void
263ospf6_lsa_header_print (struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000264{
hasso508e53e2004-05-18 18:57:06 +0000265 ospf6_lsa_age_current (lsa);
266 ospf6_lsa_header_print_raw (lsa->header);
paul718e3742002-12-13 20:15:29 +0000267}
268
269void
paul718e3742002-12-13 20:15:29 +0000270ospf6_lsa_show_summary_header (struct vty *vty)
271{
272 vty_out (vty, "%-12s %-15s %-15s %4s %8s %4s %4s %-8s%s",
273 "Type", "LSId", "AdvRouter", "Age", "SeqNum",
hasso049207c2004-08-04 20:02:13 +0000274 "Cksm", "Len", "Duration", VNL);
paul718e3742002-12-13 20:15:29 +0000275}
276
277void
278ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa)
279{
hasso508e53e2004-05-18 18:57:06 +0000280 char adv_router[16], id[16];
paul718e3742002-12-13 20:15:29 +0000281 struct timeval now, res;
282 char duration[16];
283
284 assert (lsa);
285 assert (lsa->header);
286
paul718e3742002-12-13 20:15:29 +0000287 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
288 inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
289 sizeof (adv_router));
290
291 gettimeofday (&now, NULL);
hasso508e53e2004-05-18 18:57:06 +0000292 timersub (&now, &lsa->installed, &res);
293 timerstring (&res, duration, sizeof (duration));
paul718e3742002-12-13 20:15:29 +0000294
295 vty_out (vty, "%-12s %-15s %-15s %4hu %8lx %04hx %4hu %8s%s",
hasso508e53e2004-05-18 18:57:06 +0000296 OSPF6_LSTYPE_NAME (lsa->header->type),
297 id, adv_router, ospf6_lsa_age_current (lsa),
paul718e3742002-12-13 20:15:29 +0000298 (u_long) ntohl (lsa->header->seqnum),
299 ntohs (lsa->header->checksum), ntohs (lsa->header->length),
hasso049207c2004-08-04 20:02:13 +0000300 duration, VNL);
paul718e3742002-12-13 20:15:29 +0000301}
302
303void
304ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa)
305{
306 u_char *start, *end, *current;
307 char byte[4];
308
309 start = (char *) lsa->header;
310 end = (char *) lsa->header + ntohs (lsa->header->length);
311
hasso049207c2004-08-04 20:02:13 +0000312 vty_out (vty, "%s", VNL);
313 vty_out (vty, "%s:%s", lsa->name, VNL);
paul718e3742002-12-13 20:15:29 +0000314
315 for (current = start; current < end; current ++)
316 {
317 if ((current - start) % 16 == 0)
hasso049207c2004-08-04 20:02:13 +0000318 vty_out (vty, "%s ", VNL);
paul718e3742002-12-13 20:15:29 +0000319 else if ((current - start) % 4 == 0)
320 vty_out (vty, " ");
321
322 snprintf (byte, sizeof (byte), "%02x", *current);
323 vty_out (vty, "%s", byte);
324 }
325
hasso049207c2004-08-04 20:02:13 +0000326 vty_out (vty, "%s%s", VNL, VNL);
hasso6452df02004-08-15 05:52:07 +0000327 return;
paul718e3742002-12-13 20:15:29 +0000328}
329
hasso508e53e2004-05-18 18:57:06 +0000330void
331ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa)
332{
333 char adv_router[64], id[64];
334
335 assert (lsa && lsa->header);
336
337 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
338 inet_ntop (AF_INET, &lsa->header->adv_router,
339 adv_router, sizeof (adv_router));
340
hasso049207c2004-08-04 20:02:13 +0000341 vty_out (vty, "%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000342 vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
hasso049207c2004-08-04 20:02:13 +0000343 OSPF6_LSTYPE_NAME (lsa->header->type), VNL);
344 vty_out (vty, "Link State ID: %s%s", id, VNL);
345 vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
hasso508e53e2004-05-18 18:57:06 +0000346 vty_out (vty, "LS Sequence Number: %#010lx%s",
hasso049207c2004-08-04 20:02:13 +0000347 (u_long) ntohl (lsa->header->seqnum), VNL);
hasso508e53e2004-05-18 18:57:06 +0000348 vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
349 ntohs (lsa->header->checksum),
hasso049207c2004-08-04 20:02:13 +0000350 ntohs (lsa->header->length), VNL);
hasso508e53e2004-05-18 18:57:06 +0000351 vty_out (vty, " Prev: %p This: %p Next: %p%s",
hasso049207c2004-08-04 20:02:13 +0000352 lsa->prev, lsa, lsa->next, VNL);
353 vty_out (vty, "%s", VNL);
hasso6452df02004-08-15 05:52:07 +0000354 return;
355}
356
357void
358ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
359{
360 char adv_router[64], id[64];
361 int index;
362
363 assert (lsa && lsa->header);
364
365 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
366 inet_ntop (AF_INET, &lsa->header->adv_router,
367 adv_router, sizeof (adv_router));
368
369 vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
370 OSPF6_LSTYPE_NAME (lsa->header->type), VNL);
371 vty_out (vty, "Link State ID: %s%s", id, VNL);
372 vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
373 vty_out (vty, "LS Sequence Number: %#010lx%s",
374 (u_long) ntohl (lsa->header->seqnum), VNL);
375 vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
376 ntohs (lsa->header->checksum),
377 ntohs (lsa->header->length), VNL);
378
379 index = OSPF6_LSTYPE_INDEX (lsa->header->type);
380 if (ospf6_lsa_handler[index]->show)
381 (*ospf6_lsa_handler[index]->show) (vty, lsa);
382 else
383 {
384 ospf6_lsa_show_dump (vty, lsa);
385 vty_out (vty, "%sUnknown LSA type ...%s", VNL, VNL);
386 }
387
388 vty_out (vty, "%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000389}
390
paul718e3742002-12-13 20:15:29 +0000391/* OSPFv3 LSA creation/deletion function */
paul718e3742002-12-13 20:15:29 +0000392struct ospf6_lsa *
hasso508e53e2004-05-18 18:57:06 +0000393ospf6_lsa_create (struct ospf6_lsa_header *header)
paul718e3742002-12-13 20:15:29 +0000394{
395 struct ospf6_lsa *lsa = NULL;
hasso508e53e2004-05-18 18:57:06 +0000396 struct ospf6_lsa_header *new_header = NULL;
paul718e3742002-12-13 20:15:29 +0000397 u_int16_t lsa_size = 0;
paul718e3742002-12-13 20:15:29 +0000398
hasso508e53e2004-05-18 18:57:06 +0000399 /* size of the entire LSA */
400 lsa_size = ntohs (header->length); /* XXX vulnerable */
paul718e3742002-12-13 20:15:29 +0000401
402 /* allocate memory for this LSA */
hasso508e53e2004-05-18 18:57:06 +0000403 new_header = (struct ospf6_lsa_header *)
paul718e3742002-12-13 20:15:29 +0000404 XMALLOC (MTYPE_OSPF6_LSA, lsa_size);
paul718e3742002-12-13 20:15:29 +0000405
hasso508e53e2004-05-18 18:57:06 +0000406 /* copy LSA from original header */
407 memcpy (new_header, header, lsa_size);
paul718e3742002-12-13 20:15:29 +0000408
409 /* LSA information structure */
410 /* allocate memory */
411 lsa = (struct ospf6_lsa *)
hasso508e53e2004-05-18 18:57:06 +0000412 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
paul718e3742002-12-13 20:15:29 +0000413 memset (lsa, 0, sizeof (struct ospf6_lsa));
414
hasso508e53e2004-05-18 18:57:06 +0000415 lsa->header = (struct ospf6_lsa_header *) new_header;
paul718e3742002-12-13 20:15:29 +0000416
417 /* dump string */
hasso508e53e2004-05-18 18:57:06 +0000418 ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
paul718e3742002-12-13 20:15:29 +0000419
hasso3b687352004-08-19 06:56:53 +0000420 /* calculate birth of this lsa */
paul718e3742002-12-13 20:15:29 +0000421 ospf6_lsa_age_set (lsa);
422
hasso508e53e2004-05-18 18:57:06 +0000423 if (IS_OSPF6_DEBUG_LSA (MEMORY))
424 zlog_info ("Create LSA Memory: %s (%p/%p)",
425 lsa->name, lsa, lsa->header);
paul718e3742002-12-13 20:15:29 +0000426
427 return lsa;
428}
429
430struct ospf6_lsa *
hasso508e53e2004-05-18 18:57:06 +0000431ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header)
paul718e3742002-12-13 20:15:29 +0000432{
433 struct ospf6_lsa *lsa = NULL;
hasso508e53e2004-05-18 18:57:06 +0000434 struct ospf6_lsa_header *new_header = NULL;
paul718e3742002-12-13 20:15:29 +0000435
436 /* allocate memory for this LSA */
hasso508e53e2004-05-18 18:57:06 +0000437 new_header = (struct ospf6_lsa_header *)
438 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +0000439
hasso508e53e2004-05-18 18:57:06 +0000440 /* copy LSA from original header */
441 memcpy (new_header, header, sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +0000442
443 /* LSA information structure */
444 /* allocate memory */
445 lsa = (struct ospf6_lsa *)
hasso508e53e2004-05-18 18:57:06 +0000446 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
paul718e3742002-12-13 20:15:29 +0000447 memset (lsa, 0, sizeof (struct ospf6_lsa));
448
hasso508e53e2004-05-18 18:57:06 +0000449 lsa->header = (struct ospf6_lsa_header *) new_header;
hasso6452df02004-08-15 05:52:07 +0000450 SET_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY);
paul718e3742002-12-13 20:15:29 +0000451
452 /* dump string */
hasso508e53e2004-05-18 18:57:06 +0000453 ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
paul718e3742002-12-13 20:15:29 +0000454
hasso3b687352004-08-19 06:56:53 +0000455 /* calculate birth of this lsa */
paul718e3742002-12-13 20:15:29 +0000456 ospf6_lsa_age_set (lsa);
457
hasso508e53e2004-05-18 18:57:06 +0000458 if (IS_OSPF6_DEBUG_LSA (MEMORY))
459 zlog_info ("Create LSA (Header-only) Memory: %s (%p/%p)",
460 lsa->name, lsa, lsa->header);
paul718e3742002-12-13 20:15:29 +0000461
462 return lsa;
463}
464
465void
466ospf6_lsa_delete (struct ospf6_lsa *lsa)
467{
hasso508e53e2004-05-18 18:57:06 +0000468 assert (lsa->lock == 0);
paul718e3742002-12-13 20:15:29 +0000469
470 /* cancel threads */
hasso508e53e2004-05-18 18:57:06 +0000471 THREAD_OFF (lsa->expire);
472 THREAD_OFF (lsa->refresh);
paul718e3742002-12-13 20:15:29 +0000473
hasso508e53e2004-05-18 18:57:06 +0000474 if (IS_OSPF6_DEBUG_LSA (MEMORY))
475 zlog_info ("Delete LSA %s Memory: %s (%p/%p)",
hasso6452df02004-08-15 05:52:07 +0000476 (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY) ?
477 "(Header-only) " : ""), lsa->name, lsa, lsa->header);
paul718e3742002-12-13 20:15:29 +0000478
479 /* do free */
hasso508e53e2004-05-18 18:57:06 +0000480 XFREE (MTYPE_OSPF6_LSA, lsa->header);
481 XFREE (MTYPE_OSPF6_LSA, lsa);
paul718e3742002-12-13 20:15:29 +0000482}
483
hasso508e53e2004-05-18 18:57:06 +0000484struct ospf6_lsa *
485ospf6_lsa_copy (struct ospf6_lsa *lsa)
486{
487 struct ospf6_lsa *copy = NULL;
488
489 if (IS_OSPF6_DEBUG_LSA (MEMORY))
490 zlog_info ("Create LSA Copy from %s", lsa->name);
491
492 ospf6_lsa_age_current (lsa);
hasso6452df02004-08-15 05:52:07 +0000493 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
hasso508e53e2004-05-18 18:57:06 +0000494 copy = ospf6_lsa_create_headeronly (lsa->header);
495 else
496 copy = ospf6_lsa_create (lsa->header);
497 assert (copy->lock == 0);
498
hasso3b687352004-08-19 06:56:53 +0000499 copy->birth = lsa->birth;
hasso508e53e2004-05-18 18:57:06 +0000500 copy->installed = lsa->installed;
501 copy->originated = lsa->originated;
hasso6452df02004-08-15 05:52:07 +0000502 copy->lsdb = lsa->lsdb;
hasso508e53e2004-05-18 18:57:06 +0000503
hasso508e53e2004-05-18 18:57:06 +0000504 return copy;
505}
506
507/* increment reference counter of struct ospf6_lsa */
paul718e3742002-12-13 20:15:29 +0000508void
509ospf6_lsa_lock (struct ospf6_lsa *lsa)
510{
511 lsa->lock++;
512 return;
513}
514
hasso508e53e2004-05-18 18:57:06 +0000515/* decrement reference counter of struct ospf6_lsa */
paul718e3742002-12-13 20:15:29 +0000516void
517ospf6_lsa_unlock (struct ospf6_lsa *lsa)
518{
519 /* decrement reference counter */
hasso508e53e2004-05-18 18:57:06 +0000520 assert (lsa->lock > 0);
521 lsa->lock--;
paul718e3742002-12-13 20:15:29 +0000522
hasso508e53e2004-05-18 18:57:06 +0000523 if (lsa->lock != 0)
524 return;
525
hasso508e53e2004-05-18 18:57:06 +0000526 ospf6_lsa_delete (lsa);
paul718e3742002-12-13 20:15:29 +0000527}
528
paul718e3742002-12-13 20:15:29 +0000529
hasso508e53e2004-05-18 18:57:06 +0000530/* ospf6 lsa expiry */
paul718e3742002-12-13 20:15:29 +0000531int
532ospf6_lsa_expire (struct thread *thread)
533{
534 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000535
536 lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +0000537
hasso508e53e2004-05-18 18:57:06 +0000538 assert (lsa && lsa->header);
539 assert (OSPF6_LSA_IS_MAXAGE (lsa));
540 assert (! lsa->refresh);
paul718e3742002-12-13 20:15:29 +0000541
542 lsa->expire = (struct thread *) NULL;
543
hasso508e53e2004-05-18 18:57:06 +0000544 if (IS_OSPF6_DEBUG_LSA (TIMER))
paul718e3742002-12-13 20:15:29 +0000545 {
hasso508e53e2004-05-18 18:57:06 +0000546 zlog_info ("LSA Expire:");
547 ospf6_lsa_header_print (lsa);
paul718e3742002-12-13 20:15:29 +0000548 }
549
hasso6452df02004-08-15 05:52:07 +0000550 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
hasso508e53e2004-05-18 18:57:06 +0000551 return 0; /* dbexchange will do something ... */
552
553 /* reflood lsa */
hasso6452df02004-08-15 05:52:07 +0000554 ospf6_flood (NULL, lsa);
hasso508e53e2004-05-18 18:57:06 +0000555
556 /* reinstall lsa */
hasso508e53e2004-05-18 18:57:06 +0000557 if (IS_OSPF6_DEBUG_LSA (DATABASE))
558 zlog_info ("Reinstall MaxAge %s", lsa->name);
hasso3b687352004-08-19 06:56:53 +0000559 ospf6_install_lsa (lsa);
hasso508e53e2004-05-18 18:57:06 +0000560
561 /* schedule maxage remover */
562 ospf6_maxage_remove (ospf6);
563
paul718e3742002-12-13 20:15:29 +0000564 return 0;
565}
566
567int
568ospf6_lsa_refresh (struct thread *thread)
569{
hasso6452df02004-08-15 05:52:07 +0000570 struct ospf6_lsa *old, *self, *new;
571 struct ospf6_lsdb *lsdb_self;
paul718e3742002-12-13 20:15:29 +0000572
573 assert (thread);
hasso6452df02004-08-15 05:52:07 +0000574 old = (struct ospf6_lsa *) THREAD_ARG (thread);
575 assert (old && old->header);
paul718e3742002-12-13 20:15:29 +0000576
hasso6452df02004-08-15 05:52:07 +0000577 old->refresh = (struct thread *) NULL;
paul718e3742002-12-13 20:15:29 +0000578
hasso6452df02004-08-15 05:52:07 +0000579 lsdb_self = ospf6_get_scoped_lsdb_self (old);
580 self = ospf6_lsdb_lookup (old->header->type, old->header->id,
581 old->header->adv_router, lsdb_self);
582 if (self == NULL)
583 {
hasso3b687352004-08-19 06:56:53 +0000584 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
585 zlog_info ("Refresh: could not find self LSA, flush %s", old->name);
hasso6452df02004-08-15 05:52:07 +0000586 ospf6_lsa_premature_aging (old);
587 return 0;
588 }
589
590 /* Reset age, increment LS sequence number. */
591 self->header->age = htons (0);
592 self->header->seqnum =
593 ospf6_new_ls_seqnum (self->header->type, self->header->id,
594 self->header->adv_router, old->lsdb);
595 ospf6_lsa_checksum (self->header);
596
597 new = ospf6_lsa_create (self->header);
598 new->lsdb = old->lsdb;
599 new->refresh = thread_add_timer (master, ospf6_lsa_refresh, new,
600 LS_REFRESH_TIME);
601
602 /* store it in the LSDB for self-originated LSAs */
603 ospf6_lsdb_add (ospf6_lsa_copy (new), lsdb_self);
paul718e3742002-12-13 20:15:29 +0000604
hasso508e53e2004-05-18 18:57:06 +0000605 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
paul718e3742002-12-13 20:15:29 +0000606 {
hasso508e53e2004-05-18 18:57:06 +0000607 zlog_info ("LSA Refresh:");
hasso6452df02004-08-15 05:52:07 +0000608 ospf6_lsa_header_print (new);
paul718e3742002-12-13 20:15:29 +0000609 }
610
hasso6452df02004-08-15 05:52:07 +0000611 ospf6_flood_clear (old);
612 ospf6_flood (NULL, new);
613 ospf6_install_lsa (new);
614
hasso508e53e2004-05-18 18:57:06 +0000615 return 0;
paul718e3742002-12-13 20:15:29 +0000616}
617
618
619
620/* enhanced Fletcher checksum algorithm, RFC1008 7.2 */
621#define MODX 4102
622#define LSA_CHECKSUM_OFFSET 15
623
624unsigned short
625ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header)
626{
627 u_char *sp, *ep, *p, *q;
628 int c0 = 0, c1 = 0;
629 int x, y;
630 u_int16_t length;
631
632 lsa_header->checksum = 0;
633 length = ntohs (lsa_header->length) - 2;
634 sp = (char *) &lsa_header->type;
635
636 for (ep = sp + length; sp < ep; sp = q)
637 {
638 q = sp + MODX;
639 if (q > ep)
640 q = ep;
641 for (p = sp; p < q; p++)
642 {
643 c0 += *p;
644 c1 += c0;
645 }
646 c0 %= 255;
647 c1 %= 255;
648 }
649
650 /* r = (c1 << 8) + c0; */
651 x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255;
652 if (x <= 0)
653 x += 255;
654 y = 510 - c0 - x;
655 if (y > 255)
656 y -= 255;
657
658 lsa_header->checksum = htons ((x << 8) + y);
659
660 return (lsa_header->checksum);
661}
662
663int
hasso6452df02004-08-15 05:52:07 +0000664ospf6_unknown_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000665{
hasso508e53e2004-05-18 18:57:06 +0000666 u_char *start, *end, *current;
667 char byte[4];
paul718e3742002-12-13 20:15:29 +0000668
hasso508e53e2004-05-18 18:57:06 +0000669 start = (char *) lsa->header + sizeof (struct ospf6_lsa_header);
paul718e3742002-12-13 20:15:29 +0000670 end = (char *) lsa->header + ntohs (lsa->header->length);
hasso508e53e2004-05-18 18:57:06 +0000671
hasso049207c2004-08-04 20:02:13 +0000672 vty_out (vty, " Unknown contents:%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000673 for (current = start; current < end; current ++)
paul718e3742002-12-13 20:15:29 +0000674 {
hasso508e53e2004-05-18 18:57:06 +0000675 if ((current - start) % 16 == 0)
hasso049207c2004-08-04 20:02:13 +0000676 vty_out (vty, "%s ", VNL);
hasso508e53e2004-05-18 18:57:06 +0000677 else if ((current - start) % 4 == 0)
678 vty_out (vty, " ");
paul718e3742002-12-13 20:15:29 +0000679
hasso508e53e2004-05-18 18:57:06 +0000680 snprintf (byte, sizeof (byte), "%02x", *current);
681 vty_out (vty, "%s", byte);
paul718e3742002-12-13 20:15:29 +0000682 }
hasso508e53e2004-05-18 18:57:06 +0000683
hasso049207c2004-08-04 20:02:13 +0000684 vty_out (vty, "%s%s", VNL, VNL);
paul718e3742002-12-13 20:15:29 +0000685 return 0;
686}
687
paul718e3742002-12-13 20:15:29 +0000688void
hasso6452df02004-08-15 05:52:07 +0000689ospf6_install_lsa_handler (struct ospf6_lsa_handler *handler)
690{
691 /* might need to adjust dynamic array length ... */
692 int index = OSPF6_LSTYPE_INDEX (htons (handler->type));
693 ospf6_lsa_handler[index] = handler;
694}
695
696struct ospf6_lsa_handler unknown_handler =
697{
698 OSPF6_LSTYPE_UNKNOWN,
699 "Unknown",
700 ospf6_unknown_lsa_show
701};
702
703void
paul718e3742002-12-13 20:15:29 +0000704ospf6_lsa_init ()
705{
hasso6452df02004-08-15 05:52:07 +0000706 memset (ospf6_lsa_handler, 0, sizeof (ospf6_lsa_handler));
707 ospf6_install_lsa_handler (&unknown_handler);
paul718e3742002-12-13 20:15:29 +0000708}
709
hasso508e53e2004-05-18 18:57:06 +0000710
711
712DEFUN (debug_ospf6_lsa_sendrecv,
713 debug_ospf6_lsa_sendrecv_cmd,
714 "debug ospf6 lsa (send|recv|originate|timer|database|memory|all)",
715 DEBUG_STR
716 OSPF6_STR
717 "Debug Link State Advertisements (LSAs)\n"
718 "Debug Sending LSAs\n"
719 "Debug Receiving LSAs\n"
720 "Debug Originating LSAs\n"
721 "Debug Timer Event of LSAs\n"
722 "Debug LSA Database\n"
723 "Debug Memory of LSAs\n"
724 "Debug LSAs all\n"
725 )
726{
727 unsigned char level = 0;
728
729 if (argc)
730 {
731 if (! strncmp (argv[0], "s", 1))
732 level = OSPF6_DEBUG_LSA_SEND;
733 else if (! strncmp (argv[0], "r", 1))
734 level = OSPF6_DEBUG_LSA_RECV;
735 else if (! strncmp (argv[0], "o", 1))
736 level = OSPF6_DEBUG_LSA_ORIGINATE;
737 else if (! strncmp (argv[0], "t", 1))
738 level = OSPF6_DEBUG_LSA_TIMER;
739 else if (! strncmp (argv[0], "d", 1))
740 level = OSPF6_DEBUG_LSA_DATABASE;
741 else if (! strncmp (argv[0], "m", 1))
742 level = OSPF6_DEBUG_LSA_MEMORY;
743 else if (! strncmp (argv[0], "a", 1))
744 {
745 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
746 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER |
747 OSPF6_DEBUG_LSA_DATABASE | OSPF6_DEBUG_LSA_MEMORY;
748 }
749 }
750 else
751 {
752 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
753 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER;
754 }
755
756 OSPF6_DEBUG_LSA_ON (level);
757 return CMD_SUCCESS;
758}
759
760ALIAS (debug_ospf6_lsa_sendrecv,
761 debug_ospf6_lsa_cmd,
762 "debug ospf6 lsa",
763 NO_STR
764 DEBUG_STR
765 OSPF6_STR
766 "Debug Link State Advertisements (LSAs)\n"
767 );
768
769DEFUN (no_debug_ospf6_lsa_sendrecv,
770 no_debug_ospf6_lsa_sendrecv_cmd,
771 "no debug ospf6 lsa (send|recv|originate|timer|database|memory|all)",
772 NO_STR
773 DEBUG_STR
774 OSPF6_STR
775 "Debug Link State Advertisements (LSAs)\n"
776 "Debug Sending LSAs\n"
777 "Debug Receiving LSAs\n"
778 "Debug Originating LSAs\n"
779 "Debug Timer Event of LSAs\n"
780 "Debug LSA Database\n"
781 "Debug Memory of LSAs\n"
782 "Debug LSAs all\n"
783 )
784{
785 unsigned char level = 0;
786
787 if (argc)
788 {
789 if (! strncmp (argv[0], "s", 1))
790 level = OSPF6_DEBUG_LSA_SEND;
791 else if (! strncmp (argv[0], "r", 1))
792 level = OSPF6_DEBUG_LSA_RECV;
793 else if (! strncmp (argv[0], "o", 1))
794 level = OSPF6_DEBUG_LSA_ORIGINATE;
795 else if (! strncmp (argv[0], "t", 1))
796 level = OSPF6_DEBUG_LSA_TIMER;
797 else if (! strncmp (argv[0], "d", 1))
798 level = OSPF6_DEBUG_LSA_DATABASE;
799 else if (! strncmp (argv[0], "m", 1))
800 level = OSPF6_DEBUG_LSA_MEMORY;
801 else if (! strncmp (argv[0], "a", 1))
802 {
803 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
804 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER |
805 OSPF6_DEBUG_LSA_DATABASE | OSPF6_DEBUG_LSA_MEMORY;
806 }
807 }
808 else
809 {
810 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
811 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER;
812 }
813
814 OSPF6_DEBUG_LSA_OFF (level);
815 return CMD_SUCCESS;
816}
817
818ALIAS (no_debug_ospf6_lsa_sendrecv,
819 no_debug_ospf6_lsa_cmd,
820 "no debug ospf6 lsa",
821 NO_STR
822 DEBUG_STR
823 OSPF6_STR
824 "Debug Link State Advertisements (LSAs)\n"
825 );
826
827int
828config_write_ospf6_debug_lsa (struct vty *vty)
829{
830 if (conf_debug_ospf6_lsa == OSPF6_DEBUG_LSA_ALL)
hasso049207c2004-08-04 20:02:13 +0000831 vty_out (vty, "debug ospf6 lsa all%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000832 else
833 {
834 if (conf_debug_ospf6_lsa == OSPF6_DEBUG_LSA_DEFAULT)
hasso049207c2004-08-04 20:02:13 +0000835 vty_out (vty, "debug ospf6 lsa%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000836 else
837 {
838 if (IS_OSPF6_DEBUG_LSA (SEND))
hasso049207c2004-08-04 20:02:13 +0000839 vty_out (vty, "debug ospf6 lsa send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000840 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso049207c2004-08-04 20:02:13 +0000841 vty_out (vty, "debug ospf6 lsa recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000842 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
hasso049207c2004-08-04 20:02:13 +0000843 vty_out (vty, "debug ospf6 lsa originate%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000844 if (IS_OSPF6_DEBUG_LSA (TIMER))
hasso049207c2004-08-04 20:02:13 +0000845 vty_out (vty, "debug ospf6 lsa timer%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000846 }
847
848 if (IS_OSPF6_DEBUG_LSA (DATABASE))
hasso049207c2004-08-04 20:02:13 +0000849 vty_out (vty, "debug ospf6 lsa database%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000850 if (IS_OSPF6_DEBUG_LSA (MEMORY))
hasso049207c2004-08-04 20:02:13 +0000851 vty_out (vty, "debug ospf6 lsa memory%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000852 }
853
854 return 0;
855}
856
857void
858install_element_ospf6_debug_lsa ()
859{
860 install_element (ENABLE_NODE, &debug_ospf6_lsa_cmd);
861 install_element (ENABLE_NODE, &debug_ospf6_lsa_sendrecv_cmd);
862 install_element (ENABLE_NODE, &no_debug_ospf6_lsa_cmd);
863 install_element (ENABLE_NODE, &no_debug_ospf6_lsa_sendrecv_cmd);
864 install_element (CONFIG_NODE, &debug_ospf6_lsa_cmd);
865 install_element (CONFIG_NODE, &debug_ospf6_lsa_sendrecv_cmd);
866 install_element (CONFIG_NODE, &no_debug_ospf6_lsa_cmd);
867 install_element (CONFIG_NODE, &no_debug_ospf6_lsa_sendrecv_cmd);
868}
869
870