blob: 6c8341f7cf02947eb0448623f7b295cf0e82f847 [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->originated = lsa->originated;
hassoccb59b12004-08-25 09:10:37 +0000501 copy->received = lsa->received;
502 copy->installed = lsa->installed;
hasso6452df02004-08-15 05:52:07 +0000503 copy->lsdb = lsa->lsdb;
hasso508e53e2004-05-18 18:57:06 +0000504
hasso508e53e2004-05-18 18:57:06 +0000505 return copy;
506}
507
508/* increment reference counter of struct ospf6_lsa */
paul718e3742002-12-13 20:15:29 +0000509void
510ospf6_lsa_lock (struct ospf6_lsa *lsa)
511{
512 lsa->lock++;
513 return;
514}
515
hasso508e53e2004-05-18 18:57:06 +0000516/* decrement reference counter of struct ospf6_lsa */
paul718e3742002-12-13 20:15:29 +0000517void
518ospf6_lsa_unlock (struct ospf6_lsa *lsa)
519{
520 /* decrement reference counter */
hasso508e53e2004-05-18 18:57:06 +0000521 assert (lsa->lock > 0);
522 lsa->lock--;
paul718e3742002-12-13 20:15:29 +0000523
hasso508e53e2004-05-18 18:57:06 +0000524 if (lsa->lock != 0)
525 return;
526
hasso508e53e2004-05-18 18:57:06 +0000527 ospf6_lsa_delete (lsa);
paul718e3742002-12-13 20:15:29 +0000528}
529
paul718e3742002-12-13 20:15:29 +0000530
hasso508e53e2004-05-18 18:57:06 +0000531/* ospf6 lsa expiry */
paul718e3742002-12-13 20:15:29 +0000532int
533ospf6_lsa_expire (struct thread *thread)
534{
535 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000536
537 lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +0000538
hasso508e53e2004-05-18 18:57:06 +0000539 assert (lsa && lsa->header);
540 assert (OSPF6_LSA_IS_MAXAGE (lsa));
541 assert (! lsa->refresh);
paul718e3742002-12-13 20:15:29 +0000542
543 lsa->expire = (struct thread *) NULL;
544
hasso508e53e2004-05-18 18:57:06 +0000545 if (IS_OSPF6_DEBUG_LSA (TIMER))
paul718e3742002-12-13 20:15:29 +0000546 {
hasso508e53e2004-05-18 18:57:06 +0000547 zlog_info ("LSA Expire:");
548 ospf6_lsa_header_print (lsa);
paul718e3742002-12-13 20:15:29 +0000549 }
550
hasso6452df02004-08-15 05:52:07 +0000551 if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
hasso508e53e2004-05-18 18:57:06 +0000552 return 0; /* dbexchange will do something ... */
553
554 /* reflood lsa */
hasso6452df02004-08-15 05:52:07 +0000555 ospf6_flood (NULL, lsa);
hasso508e53e2004-05-18 18:57:06 +0000556
557 /* reinstall lsa */
hasso508e53e2004-05-18 18:57:06 +0000558 if (IS_OSPF6_DEBUG_LSA (DATABASE))
559 zlog_info ("Reinstall MaxAge %s", lsa->name);
hasso3b687352004-08-19 06:56:53 +0000560 ospf6_install_lsa (lsa);
hasso508e53e2004-05-18 18:57:06 +0000561
562 /* schedule maxage remover */
563 ospf6_maxage_remove (ospf6);
564
paul718e3742002-12-13 20:15:29 +0000565 return 0;
566}
567
568int
569ospf6_lsa_refresh (struct thread *thread)
570{
hasso6452df02004-08-15 05:52:07 +0000571 struct ospf6_lsa *old, *self, *new;
572 struct ospf6_lsdb *lsdb_self;
paul718e3742002-12-13 20:15:29 +0000573
574 assert (thread);
hasso6452df02004-08-15 05:52:07 +0000575 old = (struct ospf6_lsa *) THREAD_ARG (thread);
576 assert (old && old->header);
paul718e3742002-12-13 20:15:29 +0000577
hasso6452df02004-08-15 05:52:07 +0000578 old->refresh = (struct thread *) NULL;
paul718e3742002-12-13 20:15:29 +0000579
hasso6452df02004-08-15 05:52:07 +0000580 lsdb_self = ospf6_get_scoped_lsdb_self (old);
581 self = ospf6_lsdb_lookup (old->header->type, old->header->id,
582 old->header->adv_router, lsdb_self);
583 if (self == NULL)
584 {
hasso3b687352004-08-19 06:56:53 +0000585 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
586 zlog_info ("Refresh: could not find self LSA, flush %s", old->name);
hasso6452df02004-08-15 05:52:07 +0000587 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