blob: 5204c23346ab909919a6f205f6dd5e77dbe39b39 [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
hasso508e53e2004-05-18 18:57:06 +000031#include "ospf6d.h"
paul718e3742002-12-13 20:15:29 +000032#include "ospf6_proto.h"
paul718e3742002-12-13 20:15:29 +000033#include "ospf6_lsa.h"
34#include "ospf6_lsdb.h"
35#include "ospf6_message.h"
paul718e3742002-12-13 20:15:29 +000036
37#include "ospf6_top.h"
38#include "ospf6_area.h"
39#include "ospf6_interface.h"
40#include "ospf6_neighbor.h"
paul718e3742002-12-13 20:15:29 +000041
hasso508e53e2004-05-18 18:57:06 +000042#include "ospf6_flood.h"
paul718e3742002-12-13 20:15:29 +000043
hasso508e53e2004-05-18 18:57:06 +000044unsigned char conf_debug_ospf6_lsa = 0;
45
46struct ospf6_lstype ospf6_lstype[OSPF6_LSTYPE_SIZE];
47
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];
56 int index = ntohs (type) & OSPF6_LSTYPE_FCODE_MASK;
paul718e3742002-12-13 20:15:29 +000057
hasso508e53e2004-05-18 18:57:06 +000058 if (index < OSPF6_LSTYPE_SIZE && ospf6_lstype_str[index])
59 return ospf6_lstype_str[index];
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,
hasso508e53e2004-05-18 18:57:06 +0000128 MAXAGE + lsa->birth.tv_sec
129 - now.tv_sec);
paul718e3742002-12-13 20:15:29 +0000130 else
131 lsa->expire = NULL;
132 return;
133}
134
135/* this function calculates current age from its birth,
136 then update age field of LSA header. return value is current age */
137u_int16_t
138ospf6_lsa_age_current (struct ospf6_lsa *lsa)
139{
140 struct timeval now;
141 u_int32_t ulage;
142 u_int16_t age;
143
144 assert (lsa);
145 assert (lsa->header);
146
147 /* current time */
148 if (gettimeofday (&now, (struct timezone *)NULL) < 0)
hasso508e53e2004-05-18 18:57:06 +0000149 zlog_warn ("LSA: gettimeofday failed, may fail LSA AGEs: %s",
paul718e3742002-12-13 20:15:29 +0000150 strerror (errno));
151
152 /* calculate age */
153 ulage = now.tv_sec - lsa->birth.tv_sec;
154
155 /* if over MAXAGE, set to it */
hasso508e53e2004-05-18 18:57:06 +0000156 age = (ulage > MAXAGE ? MAXAGE : ulage);
paul718e3742002-12-13 20:15:29 +0000157
158 lsa->header->age = htons (age);
159 return age;
160}
161
162/* update age field of LSA header with adding InfTransDelay */
163void
164ospf6_lsa_age_update_to_send (struct ospf6_lsa *lsa, u_int32_t transdelay)
165{
166 unsigned short age;
167
168 age = ospf6_lsa_age_current (lsa) + transdelay;
169 if (age > MAXAGE)
170 age = MAXAGE;
171 lsa->header->age = htons (age);
paul718e3742002-12-13 20:15:29 +0000172}
173
174void
175ospf6_lsa_premature_aging (struct ospf6_lsa *lsa)
176{
177 /* log */
hasso508e53e2004-05-18 18:57:06 +0000178 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
179 zlog_info ("LSA: Premature aging: %s", lsa->name);
paul718e3742002-12-13 20:15:29 +0000180
hasso508e53e2004-05-18 18:57:06 +0000181 THREAD_OFF (lsa->expire);
182 THREAD_OFF (lsa->refresh);
paul718e3742002-12-13 20:15:29 +0000183
184 memset (&lsa->birth, 0, sizeof (struct timeval));
185 thread_execute (master, ospf6_lsa_expire, lsa, 0);
186}
187
188/* check which is more recent. if a is more recent, return -1;
189 if the same, return 0; otherwise(b is more recent), return 1 */
190int
hasso508e53e2004-05-18 18:57:06 +0000191ospf6_lsa_compare (struct ospf6_lsa *a, struct ospf6_lsa *b)
paul718e3742002-12-13 20:15:29 +0000192{
193 signed long seqnuma, seqnumb;
194 u_int16_t cksuma, cksumb;
195 u_int16_t agea, ageb;
196
197 assert (a && a->header);
198 assert (b && b->header);
hasso508e53e2004-05-18 18:57:06 +0000199 assert (OSPF6_LSA_IS_SAME (a, b));
paul718e3742002-12-13 20:15:29 +0000200
201 seqnuma = ((signed long) ntohl (a->header->seqnum))
202 - (signed long) INITIAL_SEQUENCE_NUMBER;
203 seqnumb = ((signed long) ntohl (b->header->seqnum))
204 - (signed long) INITIAL_SEQUENCE_NUMBER;
205
206 /* compare by sequence number */
hasso508e53e2004-05-18 18:57:06 +0000207 /* XXX, LS sequence number wrapping */
paul718e3742002-12-13 20:15:29 +0000208 if (seqnuma > seqnumb)
209 return -1;
210 else if (seqnuma < seqnumb)
211 return 1;
212
213 /* Checksum */
214 cksuma = ntohs (a->header->checksum);
215 cksumb = ntohs (b->header->checksum);
216 if (cksuma > cksumb)
217 return -1;
218 if (cksuma < cksumb)
219 return 0;
220
hasso508e53e2004-05-18 18:57:06 +0000221 /* Update Age */
paul718e3742002-12-13 20:15:29 +0000222 agea = ospf6_lsa_age_current (a);
223 ageb = ospf6_lsa_age_current (b);
224
hasso508e53e2004-05-18 18:57:06 +0000225 /* MaxAge check */
226 if (agea == MAXAGE && ageb != MAXAGE)
paul718e3742002-12-13 20:15:29 +0000227 return -1;
hasso508e53e2004-05-18 18:57:06 +0000228 else if (agea != MAXAGE && ageb == MAXAGE)
paul718e3742002-12-13 20:15:29 +0000229 return 1;
230
hasso508e53e2004-05-18 18:57:06 +0000231 /* Age check */
232 if (agea > ageb && agea - ageb >= MAX_AGE_DIFF)
paul718e3742002-12-13 20:15:29 +0000233 return 1;
hasso508e53e2004-05-18 18:57:06 +0000234 else if (agea < ageb && ageb - agea >= MAX_AGE_DIFF)
paul718e3742002-12-13 20:15:29 +0000235 return -1;
236
237 /* neither recent */
paul718e3742002-12-13 20:15:29 +0000238 return 0;
239}
240
hasso508e53e2004-05-18 18:57:06 +0000241char *
242ospf6_lsa_printbuf (struct ospf6_lsa *lsa, char *buf, int size)
paul718e3742002-12-13 20:15:29 +0000243{
hasso508e53e2004-05-18 18:57:06 +0000244 char id[16], adv_router[16];
245 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
246 inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
247 sizeof (adv_router));
248 snprintf (buf, size, "[%s Id:%s Adv:%s]",
249 OSPF6_LSTYPE_NAME (lsa->header->type), id, adv_router);
250 return buf;
paul718e3742002-12-13 20:15:29 +0000251}
252
hasso508e53e2004-05-18 18:57:06 +0000253void
254ospf6_lsa_header_print_raw (struct ospf6_lsa_header *header)
paul718e3742002-12-13 20:15:29 +0000255{
hasso508e53e2004-05-18 18:57:06 +0000256 char id[16], adv_router[16];
257 inet_ntop (AF_INET, &header->id, id, sizeof (id));
258 inet_ntop (AF_INET, &header->adv_router, adv_router,
259 sizeof (adv_router));
260 zlog_info (" [%s Id:%s Adv:%s]",
261 OSPF6_LSTYPE_NAME (header->type), id, adv_router);
262 zlog_info (" Age: %4hu SeqNum: %#08lx Cksum: %04hx Len: %d",
263 ntohs (header->age), (u_long) ntohl (header->seqnum),
264 ntohs (header->checksum), ntohs (header->length));
paul718e3742002-12-13 20:15:29 +0000265}
266
hasso508e53e2004-05-18 18:57:06 +0000267void
268ospf6_lsa_header_print (struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000269{
hasso508e53e2004-05-18 18:57:06 +0000270 ospf6_lsa_age_current (lsa);
271 ospf6_lsa_header_print_raw (lsa->header);
paul718e3742002-12-13 20:15:29 +0000272}
273
274void
275ospf6_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
276{
hasso508e53e2004-05-18 18:57:06 +0000277 char adv_router[64], id[64];
278 int index;
paul718e3742002-12-13 20:15:29 +0000279
hasso508e53e2004-05-18 18:57:06 +0000280 assert (lsa && lsa->header);
paul718e3742002-12-13 20:15:29 +0000281
paul718e3742002-12-13 20:15:29 +0000282 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
283 inet_ntop (AF_INET, &lsa->header->adv_router,
284 adv_router, sizeof (adv_router));
285
286 vty_out (vty, "%s", VTY_NEWLINE);
287 vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
hasso508e53e2004-05-18 18:57:06 +0000288 OSPF6_LSTYPE_NAME (lsa->header->type), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000289 vty_out (vty, "Link State ID: %s%s", id, VTY_NEWLINE);
290 vty_out (vty, "Advertising Router: %s%s", adv_router, VTY_NEWLINE);
hasso508e53e2004-05-18 18:57:06 +0000291 vty_out (vty, "LS Sequence Number: %#010lx%s",
292 (u_long) ntohl (lsa->header->seqnum), VTY_NEWLINE);
293 vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
294 ntohs (lsa->header->checksum),
paul718e3742002-12-13 20:15:29 +0000295 ntohs (lsa->header->length), VTY_NEWLINE);
296
hasso508e53e2004-05-18 18:57:06 +0000297 index = OSPF6_LSTYPE_INDEX (ntohs (lsa->header->type));
298 if (ospf6_lstype[index].show)
299 (*ospf6_lstype[index].show) (vty, lsa);
300 else
301 vty_out (vty, "%sUnknown LSA type ...%s", VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000302
hasso508e53e2004-05-18 18:57:06 +0000303 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000304}
305
306void
307ospf6_lsa_show_summary_header (struct vty *vty)
308{
309 vty_out (vty, "%-12s %-15s %-15s %4s %8s %4s %4s %-8s%s",
310 "Type", "LSId", "AdvRouter", "Age", "SeqNum",
311 "Cksm", "Len", "Duration", VTY_NEWLINE);
312}
313
314void
315ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa)
316{
hasso508e53e2004-05-18 18:57:06 +0000317 char adv_router[16], id[16];
paul718e3742002-12-13 20:15:29 +0000318 struct timeval now, res;
319 char duration[16];
320
321 assert (lsa);
322 assert (lsa->header);
323
paul718e3742002-12-13 20:15:29 +0000324 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
325 inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
326 sizeof (adv_router));
327
328 gettimeofday (&now, NULL);
hasso508e53e2004-05-18 18:57:06 +0000329 timersub (&now, &lsa->installed, &res);
330 timerstring (&res, duration, sizeof (duration));
paul718e3742002-12-13 20:15:29 +0000331
332 vty_out (vty, "%-12s %-15s %-15s %4hu %8lx %04hx %4hu %8s%s",
hasso508e53e2004-05-18 18:57:06 +0000333 OSPF6_LSTYPE_NAME (lsa->header->type),
334 id, adv_router, ospf6_lsa_age_current (lsa),
paul718e3742002-12-13 20:15:29 +0000335 (u_long) ntohl (lsa->header->seqnum),
336 ntohs (lsa->header->checksum), ntohs (lsa->header->length),
337 duration, VTY_NEWLINE);
338}
339
340void
341ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa)
342{
343 u_char *start, *end, *current;
344 char byte[4];
345
346 start = (char *) lsa->header;
347 end = (char *) lsa->header + ntohs (lsa->header->length);
348
349 vty_out (vty, "%s", VTY_NEWLINE);
hasso508e53e2004-05-18 18:57:06 +0000350 vty_out (vty, "%s:%s", lsa->name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000351
352 for (current = start; current < end; current ++)
353 {
354 if ((current - start) % 16 == 0)
355 vty_out (vty, "%s ", VTY_NEWLINE);
356 else if ((current - start) % 4 == 0)
357 vty_out (vty, " ");
358
359 snprintf (byte, sizeof (byte), "%02x", *current);
360 vty_out (vty, "%s", byte);
361 }
362
363 vty_out (vty, "%s%s", VTY_NEWLINE, VTY_NEWLINE);
364}
365
hasso508e53e2004-05-18 18:57:06 +0000366void
367ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa)
368{
369 char adv_router[64], id[64];
370
371 assert (lsa && lsa->header);
372
373 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
374 inet_ntop (AF_INET, &lsa->header->adv_router,
375 adv_router, sizeof (adv_router));
376
377 vty_out (vty, "%s", VTY_NEWLINE);
378 vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
379 OSPF6_LSTYPE_NAME (lsa->header->type), VTY_NEWLINE);
380 vty_out (vty, "Link State ID: %s%s", id, VTY_NEWLINE);
381 vty_out (vty, "Advertising Router: %s%s", adv_router, VTY_NEWLINE);
382 vty_out (vty, "LS Sequence Number: %#010lx%s",
383 (u_long) ntohl (lsa->header->seqnum), VTY_NEWLINE);
384 vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
385 ntohs (lsa->header->checksum),
386 ntohs (lsa->header->length), VTY_NEWLINE);
387 vty_out (vty, " Prev: %p This: %p Next: %p%s",
388 lsa->prev, lsa, lsa->next, VTY_NEWLINE);
hasso508e53e2004-05-18 18:57:06 +0000389 vty_out (vty, "%s", VTY_NEWLINE);
390}
391
paul718e3742002-12-13 20:15:29 +0000392/* OSPFv3 LSA creation/deletion function */
393
394/* calculate LS sequence number for my new LSA.
395 return value is network byte order */
hasso508e53e2004-05-18 18:57:06 +0000396u_int32_t
397ospf6_lsa_new_seqnum (u_int16_t type, u_int32_t id, u_int32_t adv_router,
paul718e3742002-12-13 20:15:29 +0000398 void *scope)
399{
hasso508e53e2004-05-18 18:57:06 +0000400 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000401 struct ospf6_lsa *lsa;
hasso508e53e2004-05-18 18:57:06 +0000402 signed long seqnum = 0;
paul718e3742002-12-13 20:15:29 +0000403
404 /* get current database copy */
hasso508e53e2004-05-18 18:57:06 +0000405 lsdb = ospf6_get_scoped_lsdb (type, scope);
406 if (lsdb == NULL)
407 {
408 zlog_warn ("Can't decide scoped LSDB");
409 return ((u_int32_t) htonl (INITIAL_SEQUENCE_NUMBER));
410 }
paul718e3742002-12-13 20:15:29 +0000411
412 /* if current database copy not found, return InitialSequenceNumber */
hasso508e53e2004-05-18 18:57:06 +0000413 lsa = ospf6_lsdb_lookup (type, id, adv_router, lsdb);
414 if (lsa == NULL)
paul718e3742002-12-13 20:15:29 +0000415 seqnum = INITIAL_SEQUENCE_NUMBER;
416 else
417 seqnum = (signed long) ntohl (lsa->header->seqnum) + 1;
418
hasso508e53e2004-05-18 18:57:06 +0000419 return ((u_int32_t) htonl (seqnum));
paul718e3742002-12-13 20:15:29 +0000420}
421
paul718e3742002-12-13 20:15:29 +0000422struct ospf6_lsa *
hasso508e53e2004-05-18 18:57:06 +0000423ospf6_lsa_create (struct ospf6_lsa_header *header)
paul718e3742002-12-13 20:15:29 +0000424{
425 struct ospf6_lsa *lsa = NULL;
hasso508e53e2004-05-18 18:57:06 +0000426 struct ospf6_lsa_header *new_header = NULL;
paul718e3742002-12-13 20:15:29 +0000427 u_int16_t lsa_size = 0;
paul718e3742002-12-13 20:15:29 +0000428
hasso508e53e2004-05-18 18:57:06 +0000429 /* size of the entire LSA */
430 lsa_size = ntohs (header->length); /* XXX vulnerable */
paul718e3742002-12-13 20:15:29 +0000431
432 /* allocate memory for this LSA */
hasso508e53e2004-05-18 18:57:06 +0000433 new_header = (struct ospf6_lsa_header *)
paul718e3742002-12-13 20:15:29 +0000434 XMALLOC (MTYPE_OSPF6_LSA, lsa_size);
paul718e3742002-12-13 20:15:29 +0000435
hasso508e53e2004-05-18 18:57:06 +0000436 /* copy LSA from original header */
437 memcpy (new_header, header, lsa_size);
paul718e3742002-12-13 20:15:29 +0000438
439 /* LSA information structure */
440 /* allocate memory */
441 lsa = (struct ospf6_lsa *)
hasso508e53e2004-05-18 18:57:06 +0000442 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
paul718e3742002-12-13 20:15:29 +0000443 memset (lsa, 0, sizeof (struct ospf6_lsa));
444
hasso508e53e2004-05-18 18:57:06 +0000445 lsa->header = (struct ospf6_lsa_header *) new_header;
446 lsa->headeronly = 0; /* this is not header only */
paul718e3742002-12-13 20:15:29 +0000447
448 /* dump string */
hasso508e53e2004-05-18 18:57:06 +0000449 ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
paul718e3742002-12-13 20:15:29 +0000450
451 /* calculate birth, expire and refresh of this lsa */
452 ospf6_lsa_age_set (lsa);
453
hasso508e53e2004-05-18 18:57:06 +0000454 if (IS_OSPF6_DEBUG_LSA (MEMORY))
455 zlog_info ("Create LSA Memory: %s (%p/%p)",
456 lsa->name, lsa, lsa->header);
paul718e3742002-12-13 20:15:29 +0000457
458 return lsa;
459}
460
461struct ospf6_lsa *
hasso508e53e2004-05-18 18:57:06 +0000462ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header)
paul718e3742002-12-13 20:15:29 +0000463{
464 struct ospf6_lsa *lsa = NULL;
hasso508e53e2004-05-18 18:57:06 +0000465 struct ospf6_lsa_header *new_header = NULL;
paul718e3742002-12-13 20:15:29 +0000466
467 /* allocate memory for this LSA */
hasso508e53e2004-05-18 18:57:06 +0000468 new_header = (struct ospf6_lsa_header *)
469 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +0000470
hasso508e53e2004-05-18 18:57:06 +0000471 /* copy LSA from original header */
472 memcpy (new_header, header, sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +0000473
474 /* LSA information structure */
475 /* allocate memory */
476 lsa = (struct ospf6_lsa *)
hasso508e53e2004-05-18 18:57:06 +0000477 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
paul718e3742002-12-13 20:15:29 +0000478 memset (lsa, 0, sizeof (struct ospf6_lsa));
479
hasso508e53e2004-05-18 18:57:06 +0000480 lsa->header = (struct ospf6_lsa_header *) new_header;
481 lsa->headeronly = 1; /* this is header only */
paul718e3742002-12-13 20:15:29 +0000482
483 /* dump string */
hasso508e53e2004-05-18 18:57:06 +0000484 ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
paul718e3742002-12-13 20:15:29 +0000485
486 /* calculate birth, expire and refresh of this lsa */
487 ospf6_lsa_age_set (lsa);
488
hasso508e53e2004-05-18 18:57:06 +0000489 if (IS_OSPF6_DEBUG_LSA (MEMORY))
490 zlog_info ("Create LSA (Header-only) Memory: %s (%p/%p)",
491 lsa->name, lsa, lsa->header);
paul718e3742002-12-13 20:15:29 +0000492
493 return lsa;
494}
495
496void
497ospf6_lsa_delete (struct ospf6_lsa *lsa)
498{
hasso508e53e2004-05-18 18:57:06 +0000499 assert (lsa->lock == 0);
paul718e3742002-12-13 20:15:29 +0000500
501 /* cancel threads */
hasso508e53e2004-05-18 18:57:06 +0000502 THREAD_OFF (lsa->expire);
503 THREAD_OFF (lsa->refresh);
paul718e3742002-12-13 20:15:29 +0000504
hasso508e53e2004-05-18 18:57:06 +0000505 if (IS_OSPF6_DEBUG_LSA (MEMORY))
506 zlog_info ("Delete LSA %s Memory: %s (%p/%p)",
507 (lsa->headeronly ? "(Header-only) " : ""),
508 lsa->name, lsa, lsa->header);
paul718e3742002-12-13 20:15:29 +0000509
510 /* do free */
hasso508e53e2004-05-18 18:57:06 +0000511 XFREE (MTYPE_OSPF6_LSA, lsa->header);
512 XFREE (MTYPE_OSPF6_LSA, lsa);
paul718e3742002-12-13 20:15:29 +0000513}
514
hasso508e53e2004-05-18 18:57:06 +0000515struct ospf6_lsa *
516ospf6_lsa_copy (struct ospf6_lsa *lsa)
517{
518 struct ospf6_lsa *copy = NULL;
519
520 if (IS_OSPF6_DEBUG_LSA (MEMORY))
521 zlog_info ("Create LSA Copy from %s", lsa->name);
522
523 ospf6_lsa_age_current (lsa);
524 if (lsa->headeronly)
525 copy = ospf6_lsa_create_headeronly (lsa->header);
526 else
527 copy = ospf6_lsa_create (lsa->header);
528 assert (copy->lock == 0);
529
530 copy->installed = lsa->installed;
531 copy->originated = lsa->originated;
532 copy->scope = lsa->scope;
533
hasso508e53e2004-05-18 18:57:06 +0000534 return copy;
535}
536
537/* increment reference counter of struct ospf6_lsa */
paul718e3742002-12-13 20:15:29 +0000538void
539ospf6_lsa_lock (struct ospf6_lsa *lsa)
540{
541 lsa->lock++;
542 return;
543}
544
hasso508e53e2004-05-18 18:57:06 +0000545/* decrement reference counter of struct ospf6_lsa */
paul718e3742002-12-13 20:15:29 +0000546void
547ospf6_lsa_unlock (struct ospf6_lsa *lsa)
548{
549 /* decrement reference counter */
hasso508e53e2004-05-18 18:57:06 +0000550 assert (lsa->lock > 0);
551 lsa->lock--;
paul718e3742002-12-13 20:15:29 +0000552
hasso508e53e2004-05-18 18:57:06 +0000553 if (lsa->lock != 0)
554 return;
555
hasso508e53e2004-05-18 18:57:06 +0000556 ospf6_lsa_delete (lsa);
paul718e3742002-12-13 20:15:29 +0000557}
558
559void
hasso508e53e2004-05-18 18:57:06 +0000560ospf6_lsa_originate (struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000561{
paul718e3742002-12-13 20:15:29 +0000562 struct ospf6_lsa *old;
hasso508e53e2004-05-18 18:57:06 +0000563 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000564
565 /* find previous LSA */
hasso508e53e2004-05-18 18:57:06 +0000566 lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
567 if (lsdb == NULL)
568 {
569 zlog_warn ("Can't decide scoped LSDB");
570 ospf6_lsa_delete (lsa);
571 return;
572 }
573
paul718e3742002-12-13 20:15:29 +0000574 old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
hasso508e53e2004-05-18 18:57:06 +0000575 lsa->header->adv_router, lsdb);
paul718e3742002-12-13 20:15:29 +0000576 if (old)
577 {
hasso508e53e2004-05-18 18:57:06 +0000578 /* If this origination is neither different instance nor refresh,
579 suppress this origination */
580 if (! CHECK_FLAG (old->flag, OSPF6_LSA_REFRESH) &&
581 ! OSPF6_LSA_IS_DIFFER (lsa, old))
paul718e3742002-12-13 20:15:29 +0000582 {
hasso508e53e2004-05-18 18:57:06 +0000583 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
584 zlog_info ("Suppress updating LSA: %s", lsa->name);
paul718e3742002-12-13 20:15:29 +0000585 ospf6_lsa_delete (lsa);
586 return;
587 }
588 }
589
590 lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
hasso508e53e2004-05-18 18:57:06 +0000591 LS_REFRESH_TIME);
paul718e3742002-12-13 20:15:29 +0000592
hasso508e53e2004-05-18 18:57:06 +0000593 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
594 {
595 zlog_info ("LSA Originate:");
596 ospf6_lsa_header_print (lsa);
597 }
paul718e3742002-12-13 20:15:29 +0000598
hasso508e53e2004-05-18 18:57:06 +0000599 if (old)
600 ospf6_flood_clear (old);
601 ospf6_flood_lsa (lsa, NULL);
602 ospf6_install_lsa (lsa, lsdb);
603}
604
605void
606ospf6_lsa_re_originate (struct ospf6_lsa *lsa)
607{
608 u_int16_t index;
609
610 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
611 {
612 zlog_info ("LSA Reoriginate:");
613 ospf6_lsa_header_print (lsa);
614 }
615
616 index = OSPF6_LSTYPE_INDEX (ntohs (lsa->header->type));
617 if (ospf6_lstype[index].reoriginate)
618 (*ospf6_lstype[index].reoriginate) (lsa);
619 else
620 ospf6_lsa_premature_aging (lsa);
paul718e3742002-12-13 20:15:29 +0000621}
622
623
hasso508e53e2004-05-18 18:57:06 +0000624/* ospf6 lsa expiry */
paul718e3742002-12-13 20:15:29 +0000625int
626ospf6_lsa_expire (struct thread *thread)
627{
628 struct ospf6_lsa *lsa;
629 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000630
631 lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +0000632
hasso508e53e2004-05-18 18:57:06 +0000633 assert (lsa && lsa->header);
634 assert (OSPF6_LSA_IS_MAXAGE (lsa));
635 assert (! lsa->refresh);
paul718e3742002-12-13 20:15:29 +0000636
637 lsa->expire = (struct thread *) NULL;
638
hasso508e53e2004-05-18 18:57:06 +0000639 if (IS_OSPF6_DEBUG_LSA (TIMER))
paul718e3742002-12-13 20:15:29 +0000640 {
hasso508e53e2004-05-18 18:57:06 +0000641 zlog_info ("LSA Expire:");
642 ospf6_lsa_header_print (lsa);
paul718e3742002-12-13 20:15:29 +0000643 }
644
hasso508e53e2004-05-18 18:57:06 +0000645 if (lsa->headeronly)
646 return 0; /* dbexchange will do something ... */
647
648 /* reflood lsa */
649 ospf6_flood_lsa (lsa, NULL);
650
651 /* reinstall lsa */
652 lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
653 if (lsdb == NULL)
654 {
655 zlog_warn ("Can't decide scoped LSDB: %s", lsa->name);
656 return 0;
657 }
658 if (IS_OSPF6_DEBUG_LSA (DATABASE))
659 zlog_info ("Reinstall MaxAge %s", lsa->name);
660 ospf6_lsdb_add (lsa, lsdb);
661
662 /* schedule maxage remover */
663 ospf6_maxage_remove (ospf6);
664
paul718e3742002-12-13 20:15:29 +0000665 return 0;
666}
667
hasso508e53e2004-05-18 18:57:06 +0000668/* Below will become dummy thread.
669 refresh function must be set individually per each LSAs */
paul718e3742002-12-13 20:15:29 +0000670int
671ospf6_lsa_refresh (struct thread *thread)
672{
673 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000674
675 assert (thread);
hasso508e53e2004-05-18 18:57:06 +0000676 lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
677 assert (lsa && lsa->header);
paul718e3742002-12-13 20:15:29 +0000678
paul718e3742002-12-13 20:15:29 +0000679 lsa->refresh = (struct thread *) NULL;
paul718e3742002-12-13 20:15:29 +0000680
hasso508e53e2004-05-18 18:57:06 +0000681 /* this will be used later to decide really originate or not */
682 SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
paul718e3742002-12-13 20:15:29 +0000683
hasso508e53e2004-05-18 18:57:06 +0000684 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
paul718e3742002-12-13 20:15:29 +0000685 {
hasso508e53e2004-05-18 18:57:06 +0000686 zlog_info ("LSA Refresh:");
687 ospf6_lsa_header_print (lsa);
paul718e3742002-12-13 20:15:29 +0000688 }
689
hasso508e53e2004-05-18 18:57:06 +0000690 ospf6_lsa_re_originate (lsa);
691 return 0;
paul718e3742002-12-13 20:15:29 +0000692}
693
694
695
696/* enhanced Fletcher checksum algorithm, RFC1008 7.2 */
697#define MODX 4102
698#define LSA_CHECKSUM_OFFSET 15
699
700unsigned short
701ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header)
702{
703 u_char *sp, *ep, *p, *q;
704 int c0 = 0, c1 = 0;
705 int x, y;
706 u_int16_t length;
707
708 lsa_header->checksum = 0;
709 length = ntohs (lsa_header->length) - 2;
710 sp = (char *) &lsa_header->type;
711
712 for (ep = sp + length; sp < ep; sp = q)
713 {
714 q = sp + MODX;
715 if (q > ep)
716 q = ep;
717 for (p = sp; p < q; p++)
718 {
719 c0 += *p;
720 c1 += c0;
721 }
722 c0 %= 255;
723 c1 %= 255;
724 }
725
726 /* r = (c1 << 8) + c0; */
727 x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255;
728 if (x <= 0)
729 x += 255;
730 y = 510 - c0 - x;
731 if (y > 255)
732 y -= 255;
733
734 lsa_header->checksum = htons ((x << 8) + y);
735
736 return (lsa_header->checksum);
737}
738
739int
hasso508e53e2004-05-18 18:57:06 +0000740ospf6_unknown_reoriginate (struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000741{
hasso508e53e2004-05-18 18:57:06 +0000742 ospf6_lsa_premature_aging (lsa);
paul718e3742002-12-13 20:15:29 +0000743 return 0;
744}
745
746int
hasso508e53e2004-05-18 18:57:06 +0000747ospf6_unknown_show (struct vty *vty, struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000748{
hasso508e53e2004-05-18 18:57:06 +0000749 u_char *start, *end, *current;
750 char byte[4];
paul718e3742002-12-13 20:15:29 +0000751
hasso508e53e2004-05-18 18:57:06 +0000752 start = (char *) lsa->header + sizeof (struct ospf6_lsa_header);
paul718e3742002-12-13 20:15:29 +0000753 end = (char *) lsa->header + ntohs (lsa->header->length);
hasso508e53e2004-05-18 18:57:06 +0000754
755 vty_out (vty, " Unknown contents:%s", VTY_NEWLINE);
756 for (current = start; current < end; current ++)
paul718e3742002-12-13 20:15:29 +0000757 {
hasso508e53e2004-05-18 18:57:06 +0000758 if ((current - start) % 16 == 0)
759 vty_out (vty, "%s ", VTY_NEWLINE);
760 else if ((current - start) % 4 == 0)
761 vty_out (vty, " ");
paul718e3742002-12-13 20:15:29 +0000762
hasso508e53e2004-05-18 18:57:06 +0000763 snprintf (byte, sizeof (byte), "%02x", *current);
764 vty_out (vty, "%s", byte);
paul718e3742002-12-13 20:15:29 +0000765 }
hasso508e53e2004-05-18 18:57:06 +0000766
767 vty_out (vty, "%s%s", VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000768 return 0;
769}
770
paul718e3742002-12-13 20:15:29 +0000771void
772ospf6_lsa_init ()
773{
hasso508e53e2004-05-18 18:57:06 +0000774 memset (ospf6_lstype, 0, sizeof (ospf6_lstype));
paul718e3742002-12-13 20:15:29 +0000775
hasso508e53e2004-05-18 18:57:06 +0000776 ospf6_lstype[0].name = "Unknown";
777 ospf6_lstype[0].reoriginate = ospf6_unknown_reoriginate;
778 ospf6_lstype[0].show = ospf6_unknown_show;
paul718e3742002-12-13 20:15:29 +0000779}
780
hasso508e53e2004-05-18 18:57:06 +0000781
782
783DEFUN (debug_ospf6_lsa_sendrecv,
784 debug_ospf6_lsa_sendrecv_cmd,
785 "debug ospf6 lsa (send|recv|originate|timer|database|memory|all)",
786 DEBUG_STR
787 OSPF6_STR
788 "Debug Link State Advertisements (LSAs)\n"
789 "Debug Sending LSAs\n"
790 "Debug Receiving LSAs\n"
791 "Debug Originating LSAs\n"
792 "Debug Timer Event of LSAs\n"
793 "Debug LSA Database\n"
794 "Debug Memory of LSAs\n"
795 "Debug LSAs all\n"
796 )
797{
798 unsigned char level = 0;
799
800 if (argc)
801 {
802 if (! strncmp (argv[0], "s", 1))
803 level = OSPF6_DEBUG_LSA_SEND;
804 else if (! strncmp (argv[0], "r", 1))
805 level = OSPF6_DEBUG_LSA_RECV;
806 else if (! strncmp (argv[0], "o", 1))
807 level = OSPF6_DEBUG_LSA_ORIGINATE;
808 else if (! strncmp (argv[0], "t", 1))
809 level = OSPF6_DEBUG_LSA_TIMER;
810 else if (! strncmp (argv[0], "d", 1))
811 level = OSPF6_DEBUG_LSA_DATABASE;
812 else if (! strncmp (argv[0], "m", 1))
813 level = OSPF6_DEBUG_LSA_MEMORY;
814 else if (! strncmp (argv[0], "a", 1))
815 {
816 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
817 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER |
818 OSPF6_DEBUG_LSA_DATABASE | OSPF6_DEBUG_LSA_MEMORY;
819 }
820 }
821 else
822 {
823 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
824 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER;
825 }
826
827 OSPF6_DEBUG_LSA_ON (level);
828 return CMD_SUCCESS;
829}
830
831ALIAS (debug_ospf6_lsa_sendrecv,
832 debug_ospf6_lsa_cmd,
833 "debug ospf6 lsa",
834 NO_STR
835 DEBUG_STR
836 OSPF6_STR
837 "Debug Link State Advertisements (LSAs)\n"
838 );
839
840DEFUN (no_debug_ospf6_lsa_sendrecv,
841 no_debug_ospf6_lsa_sendrecv_cmd,
842 "no debug ospf6 lsa (send|recv|originate|timer|database|memory|all)",
843 NO_STR
844 DEBUG_STR
845 OSPF6_STR
846 "Debug Link State Advertisements (LSAs)\n"
847 "Debug Sending LSAs\n"
848 "Debug Receiving LSAs\n"
849 "Debug Originating LSAs\n"
850 "Debug Timer Event of LSAs\n"
851 "Debug LSA Database\n"
852 "Debug Memory of LSAs\n"
853 "Debug LSAs all\n"
854 )
855{
856 unsigned char level = 0;
857
858 if (argc)
859 {
860 if (! strncmp (argv[0], "s", 1))
861 level = OSPF6_DEBUG_LSA_SEND;
862 else if (! strncmp (argv[0], "r", 1))
863 level = OSPF6_DEBUG_LSA_RECV;
864 else if (! strncmp (argv[0], "o", 1))
865 level = OSPF6_DEBUG_LSA_ORIGINATE;
866 else if (! strncmp (argv[0], "t", 1))
867 level = OSPF6_DEBUG_LSA_TIMER;
868 else if (! strncmp (argv[0], "d", 1))
869 level = OSPF6_DEBUG_LSA_DATABASE;
870 else if (! strncmp (argv[0], "m", 1))
871 level = OSPF6_DEBUG_LSA_MEMORY;
872 else if (! strncmp (argv[0], "a", 1))
873 {
874 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
875 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER |
876 OSPF6_DEBUG_LSA_DATABASE | OSPF6_DEBUG_LSA_MEMORY;
877 }
878 }
879 else
880 {
881 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
882 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER;
883 }
884
885 OSPF6_DEBUG_LSA_OFF (level);
886 return CMD_SUCCESS;
887}
888
889ALIAS (no_debug_ospf6_lsa_sendrecv,
890 no_debug_ospf6_lsa_cmd,
891 "no debug ospf6 lsa",
892 NO_STR
893 DEBUG_STR
894 OSPF6_STR
895 "Debug Link State Advertisements (LSAs)\n"
896 );
897
898int
899config_write_ospf6_debug_lsa (struct vty *vty)
900{
901 if (conf_debug_ospf6_lsa == OSPF6_DEBUG_LSA_ALL)
902 vty_out (vty, "debug ospf6 lsa all%s", VTY_NEWLINE);
903 else
904 {
905 if (conf_debug_ospf6_lsa == OSPF6_DEBUG_LSA_DEFAULT)
906 vty_out (vty, "debug ospf6 lsa%s", VTY_NEWLINE);
907 else
908 {
909 if (IS_OSPF6_DEBUG_LSA (SEND))
910 vty_out (vty, "debug ospf6 lsa send%s", VTY_NEWLINE);
911 if (IS_OSPF6_DEBUG_LSA (RECV))
912 vty_out (vty, "debug ospf6 lsa recv%s", VTY_NEWLINE);
913 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
914 vty_out (vty, "debug ospf6 lsa originate%s", VTY_NEWLINE);
915 if (IS_OSPF6_DEBUG_LSA (TIMER))
916 vty_out (vty, "debug ospf6 lsa timer%s", VTY_NEWLINE);
917 }
918
919 if (IS_OSPF6_DEBUG_LSA (DATABASE))
920 vty_out (vty, "debug ospf6 lsa database%s", VTY_NEWLINE);
921 if (IS_OSPF6_DEBUG_LSA (MEMORY))
922 vty_out (vty, "debug ospf6 lsa memory%s", VTY_NEWLINE);
923 }
924
925 return 0;
926}
927
928void
929install_element_ospf6_debug_lsa ()
930{
931 install_element (ENABLE_NODE, &debug_ospf6_lsa_cmd);
932 install_element (ENABLE_NODE, &debug_ospf6_lsa_sendrecv_cmd);
933 install_element (ENABLE_NODE, &no_debug_ospf6_lsa_cmd);
934 install_element (ENABLE_NODE, &no_debug_ospf6_lsa_sendrecv_cmd);
935 install_element (CONFIG_NODE, &debug_ospf6_lsa_cmd);
936 install_element (CONFIG_NODE, &debug_ospf6_lsa_sendrecv_cmd);
937 install_element (CONFIG_NODE, &no_debug_ospf6_lsa_cmd);
938 install_element (CONFIG_NODE, &no_debug_ospf6_lsa_sendrecv_cmd);
939}
940
941