blob: 13e9a0736f9c6352a4344325d07b58ed949da600 [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);
389 vty_out (vty, " Reference count: %ld%s", lsa->refcnt, VTY_NEWLINE);
390 vty_out (vty, " Reference source: %s (%p) %s",
391 (lsa->refsrc ? lsa->refsrc->name : "None"),
392 lsa->refsrc, VTY_NEWLINE);
393 vty_out (vty, "%s", VTY_NEWLINE);
394}
395
paul718e3742002-12-13 20:15:29 +0000396/* OSPFv3 LSA creation/deletion function */
397
398/* calculate LS sequence number for my new LSA.
399 return value is network byte order */
hasso508e53e2004-05-18 18:57:06 +0000400u_int32_t
401ospf6_lsa_new_seqnum (u_int16_t type, u_int32_t id, u_int32_t adv_router,
paul718e3742002-12-13 20:15:29 +0000402 void *scope)
403{
hasso508e53e2004-05-18 18:57:06 +0000404 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000405 struct ospf6_lsa *lsa;
hasso508e53e2004-05-18 18:57:06 +0000406 signed long seqnum = 0;
paul718e3742002-12-13 20:15:29 +0000407
408 /* get current database copy */
hasso508e53e2004-05-18 18:57:06 +0000409 lsdb = ospf6_get_scoped_lsdb (type, scope);
410 if (lsdb == NULL)
411 {
412 zlog_warn ("Can't decide scoped LSDB");
413 return ((u_int32_t) htonl (INITIAL_SEQUENCE_NUMBER));
414 }
paul718e3742002-12-13 20:15:29 +0000415
416 /* if current database copy not found, return InitialSequenceNumber */
hasso508e53e2004-05-18 18:57:06 +0000417 lsa = ospf6_lsdb_lookup (type, id, adv_router, lsdb);
418 if (lsa == NULL)
paul718e3742002-12-13 20:15:29 +0000419 seqnum = INITIAL_SEQUENCE_NUMBER;
420 else
421 seqnum = (signed long) ntohl (lsa->header->seqnum) + 1;
422
hasso508e53e2004-05-18 18:57:06 +0000423 return ((u_int32_t) htonl (seqnum));
paul718e3742002-12-13 20:15:29 +0000424}
425
paul718e3742002-12-13 20:15:29 +0000426struct ospf6_lsa *
hasso508e53e2004-05-18 18:57:06 +0000427ospf6_lsa_create (struct ospf6_lsa_header *header)
paul718e3742002-12-13 20:15:29 +0000428{
429 struct ospf6_lsa *lsa = NULL;
hasso508e53e2004-05-18 18:57:06 +0000430 struct ospf6_lsa_header *new_header = NULL;
paul718e3742002-12-13 20:15:29 +0000431 u_int16_t lsa_size = 0;
paul718e3742002-12-13 20:15:29 +0000432
hasso508e53e2004-05-18 18:57:06 +0000433 /* size of the entire LSA */
434 lsa_size = ntohs (header->length); /* XXX vulnerable */
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 *)
paul718e3742002-12-13 20:15:29 +0000438 XMALLOC (MTYPE_OSPF6_LSA, lsa_size);
paul718e3742002-12-13 20:15:29 +0000439
hasso508e53e2004-05-18 18:57:06 +0000440 /* copy LSA from original header */
441 memcpy (new_header, header, lsa_size);
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;
450 lsa->headeronly = 0; /* this is not header only */
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
455 /* calculate birth, expire and refresh of this lsa */
456 ospf6_lsa_age_set (lsa);
457
hasso508e53e2004-05-18 18:57:06 +0000458 if (IS_OSPF6_DEBUG_LSA (MEMORY))
459 zlog_info ("Create LSA Memory: %s (%p/%p)",
460 lsa->name, lsa, lsa->header);
paul718e3742002-12-13 20:15:29 +0000461
462 return lsa;
463}
464
465struct ospf6_lsa *
hasso508e53e2004-05-18 18:57:06 +0000466ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header)
paul718e3742002-12-13 20:15:29 +0000467{
468 struct ospf6_lsa *lsa = NULL;
hasso508e53e2004-05-18 18:57:06 +0000469 struct ospf6_lsa_header *new_header = NULL;
paul718e3742002-12-13 20:15:29 +0000470
471 /* allocate memory for this LSA */
hasso508e53e2004-05-18 18:57:06 +0000472 new_header = (struct ospf6_lsa_header *)
473 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +0000474
hasso508e53e2004-05-18 18:57:06 +0000475 /* copy LSA from original header */
476 memcpy (new_header, header, sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +0000477
478 /* LSA information structure */
479 /* allocate memory */
480 lsa = (struct ospf6_lsa *)
hasso508e53e2004-05-18 18:57:06 +0000481 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
paul718e3742002-12-13 20:15:29 +0000482 memset (lsa, 0, sizeof (struct ospf6_lsa));
483
hasso508e53e2004-05-18 18:57:06 +0000484 lsa->header = (struct ospf6_lsa_header *) new_header;
485 lsa->headeronly = 1; /* this is header only */
paul718e3742002-12-13 20:15:29 +0000486
487 /* dump string */
hasso508e53e2004-05-18 18:57:06 +0000488 ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
paul718e3742002-12-13 20:15:29 +0000489
490 /* calculate birth, expire and refresh of this lsa */
491 ospf6_lsa_age_set (lsa);
492
hasso508e53e2004-05-18 18:57:06 +0000493 if (IS_OSPF6_DEBUG_LSA (MEMORY))
494 zlog_info ("Create LSA (Header-only) Memory: %s (%p/%p)",
495 lsa->name, lsa, lsa->header);
paul718e3742002-12-13 20:15:29 +0000496
497 return lsa;
498}
499
500void
501ospf6_lsa_delete (struct ospf6_lsa *lsa)
502{
hasso508e53e2004-05-18 18:57:06 +0000503 assert (lsa->lock == 0);
paul718e3742002-12-13 20:15:29 +0000504
505 /* cancel threads */
hasso508e53e2004-05-18 18:57:06 +0000506 THREAD_OFF (lsa->expire);
507 THREAD_OFF (lsa->refresh);
paul718e3742002-12-13 20:15:29 +0000508
hasso508e53e2004-05-18 18:57:06 +0000509 if (IS_OSPF6_DEBUG_LSA (MEMORY))
510 zlog_info ("Delete LSA %s Memory: %s (%p/%p)",
511 (lsa->headeronly ? "(Header-only) " : ""),
512 lsa->name, lsa, lsa->header);
paul718e3742002-12-13 20:15:29 +0000513
514 /* do free */
hasso508e53e2004-05-18 18:57:06 +0000515 XFREE (MTYPE_OSPF6_LSA, lsa->header);
516 XFREE (MTYPE_OSPF6_LSA, lsa);
paul718e3742002-12-13 20:15:29 +0000517}
518
hasso508e53e2004-05-18 18:57:06 +0000519struct ospf6_lsa *
520ospf6_lsa_copy (struct ospf6_lsa *lsa)
521{
522 struct ospf6_lsa *copy = NULL;
523
524 if (IS_OSPF6_DEBUG_LSA (MEMORY))
525 zlog_info ("Create LSA Copy from %s", lsa->name);
526
527 ospf6_lsa_age_current (lsa);
528 if (lsa->headeronly)
529 copy = ospf6_lsa_create_headeronly (lsa->header);
530 else
531 copy = ospf6_lsa_create (lsa->header);
532 assert (copy->lock == 0);
533
534 copy->installed = lsa->installed;
535 copy->originated = lsa->originated;
536 copy->scope = lsa->scope;
537
538 copy->refsrc = lsa;
539 copy->refsrc->refcnt++;
540
541 return copy;
542}
543
544/* increment reference counter of struct ospf6_lsa */
paul718e3742002-12-13 20:15:29 +0000545void
546ospf6_lsa_lock (struct ospf6_lsa *lsa)
547{
548 lsa->lock++;
549 return;
550}
551
hasso508e53e2004-05-18 18:57:06 +0000552/* decrement reference counter of struct ospf6_lsa */
paul718e3742002-12-13 20:15:29 +0000553void
554ospf6_lsa_unlock (struct ospf6_lsa *lsa)
555{
556 /* decrement reference counter */
hasso508e53e2004-05-18 18:57:06 +0000557 assert (lsa->lock > 0);
558 lsa->lock--;
paul718e3742002-12-13 20:15:29 +0000559
hasso508e53e2004-05-18 18:57:06 +0000560 if (lsa->lock != 0)
561 return;
562
563 if (lsa->refsrc)
564 lsa->refsrc->refcnt--;
565
566 ospf6_lsa_delete (lsa);
paul718e3742002-12-13 20:15:29 +0000567}
568
569void
hasso508e53e2004-05-18 18:57:06 +0000570ospf6_lsa_originate (struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000571{
paul718e3742002-12-13 20:15:29 +0000572 struct ospf6_lsa *old;
hasso508e53e2004-05-18 18:57:06 +0000573 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000574
575 /* find previous LSA */
hasso508e53e2004-05-18 18:57:06 +0000576 lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
577 if (lsdb == NULL)
578 {
579 zlog_warn ("Can't decide scoped LSDB");
580 ospf6_lsa_delete (lsa);
581 return;
582 }
583
paul718e3742002-12-13 20:15:29 +0000584 old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
hasso508e53e2004-05-18 18:57:06 +0000585 lsa->header->adv_router, lsdb);
paul718e3742002-12-13 20:15:29 +0000586 if (old)
587 {
hasso508e53e2004-05-18 18:57:06 +0000588 /* If this origination is neither different instance nor refresh,
589 suppress this origination */
590 if (! CHECK_FLAG (old->flag, OSPF6_LSA_REFRESH) &&
591 ! OSPF6_LSA_IS_DIFFER (lsa, old))
paul718e3742002-12-13 20:15:29 +0000592 {
hasso508e53e2004-05-18 18:57:06 +0000593 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
594 zlog_info ("Suppress updating LSA: %s", lsa->name);
paul718e3742002-12-13 20:15:29 +0000595 ospf6_lsa_delete (lsa);
596 return;
597 }
598 }
599
600 lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
hasso508e53e2004-05-18 18:57:06 +0000601 LS_REFRESH_TIME);
paul718e3742002-12-13 20:15:29 +0000602
hasso508e53e2004-05-18 18:57:06 +0000603 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
604 {
605 zlog_info ("LSA Originate:");
606 ospf6_lsa_header_print (lsa);
607 }
paul718e3742002-12-13 20:15:29 +0000608
hasso508e53e2004-05-18 18:57:06 +0000609 if (old)
610 ospf6_flood_clear (old);
611 ospf6_flood_lsa (lsa, NULL);
612 ospf6_install_lsa (lsa, lsdb);
613}
614
615void
616ospf6_lsa_re_originate (struct ospf6_lsa *lsa)
617{
618 u_int16_t index;
619
620 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
621 {
622 zlog_info ("LSA Reoriginate:");
623 ospf6_lsa_header_print (lsa);
624 }
625
626 index = OSPF6_LSTYPE_INDEX (ntohs (lsa->header->type));
627 if (ospf6_lstype[index].reoriginate)
628 (*ospf6_lstype[index].reoriginate) (lsa);
629 else
630 ospf6_lsa_premature_aging (lsa);
paul718e3742002-12-13 20:15:29 +0000631}
632
633
hasso508e53e2004-05-18 18:57:06 +0000634/* ospf6 lsa expiry */
paul718e3742002-12-13 20:15:29 +0000635int
636ospf6_lsa_expire (struct thread *thread)
637{
638 struct ospf6_lsa *lsa;
639 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000640
641 lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +0000642
hasso508e53e2004-05-18 18:57:06 +0000643 assert (lsa && lsa->header);
644 assert (OSPF6_LSA_IS_MAXAGE (lsa));
645 assert (! lsa->refresh);
paul718e3742002-12-13 20:15:29 +0000646
647 lsa->expire = (struct thread *) NULL;
648
hasso508e53e2004-05-18 18:57:06 +0000649 if (IS_OSPF6_DEBUG_LSA (TIMER))
paul718e3742002-12-13 20:15:29 +0000650 {
hasso508e53e2004-05-18 18:57:06 +0000651 zlog_info ("LSA Expire:");
652 ospf6_lsa_header_print (lsa);
paul718e3742002-12-13 20:15:29 +0000653 }
654
hasso508e53e2004-05-18 18:57:06 +0000655 if (lsa->headeronly)
656 return 0; /* dbexchange will do something ... */
657
658 /* reflood lsa */
659 ospf6_flood_lsa (lsa, NULL);
660
661 /* reinstall lsa */
662 lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
663 if (lsdb == NULL)
664 {
665 zlog_warn ("Can't decide scoped LSDB: %s", lsa->name);
666 return 0;
667 }
668 if (IS_OSPF6_DEBUG_LSA (DATABASE))
669 zlog_info ("Reinstall MaxAge %s", lsa->name);
670 ospf6_lsdb_add (lsa, lsdb);
671
672 /* schedule maxage remover */
673 ospf6_maxage_remove (ospf6);
674
paul718e3742002-12-13 20:15:29 +0000675 return 0;
676}
677
hasso508e53e2004-05-18 18:57:06 +0000678/* Below will become dummy thread.
679 refresh function must be set individually per each LSAs */
paul718e3742002-12-13 20:15:29 +0000680int
681ospf6_lsa_refresh (struct thread *thread)
682{
683 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000684
685 assert (thread);
hasso508e53e2004-05-18 18:57:06 +0000686 lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
687 assert (lsa && lsa->header);
paul718e3742002-12-13 20:15:29 +0000688
paul718e3742002-12-13 20:15:29 +0000689 lsa->refresh = (struct thread *) NULL;
paul718e3742002-12-13 20:15:29 +0000690
hasso508e53e2004-05-18 18:57:06 +0000691 /* this will be used later to decide really originate or not */
692 SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
paul718e3742002-12-13 20:15:29 +0000693
hasso508e53e2004-05-18 18:57:06 +0000694 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
paul718e3742002-12-13 20:15:29 +0000695 {
hasso508e53e2004-05-18 18:57:06 +0000696 zlog_info ("LSA Refresh:");
697 ospf6_lsa_header_print (lsa);
paul718e3742002-12-13 20:15:29 +0000698 }
699
hasso508e53e2004-05-18 18:57:06 +0000700 ospf6_lsa_re_originate (lsa);
701 return 0;
paul718e3742002-12-13 20:15:29 +0000702}
703
704
705
706/* enhanced Fletcher checksum algorithm, RFC1008 7.2 */
707#define MODX 4102
708#define LSA_CHECKSUM_OFFSET 15
709
710unsigned short
711ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header)
712{
713 u_char *sp, *ep, *p, *q;
714 int c0 = 0, c1 = 0;
715 int x, y;
716 u_int16_t length;
717
718 lsa_header->checksum = 0;
719 length = ntohs (lsa_header->length) - 2;
720 sp = (char *) &lsa_header->type;
721
722 for (ep = sp + length; sp < ep; sp = q)
723 {
724 q = sp + MODX;
725 if (q > ep)
726 q = ep;
727 for (p = sp; p < q; p++)
728 {
729 c0 += *p;
730 c1 += c0;
731 }
732 c0 %= 255;
733 c1 %= 255;
734 }
735
736 /* r = (c1 << 8) + c0; */
737 x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255;
738 if (x <= 0)
739 x += 255;
740 y = 510 - c0 - x;
741 if (y > 255)
742 y -= 255;
743
744 lsa_header->checksum = htons ((x << 8) + y);
745
746 return (lsa_header->checksum);
747}
748
749int
hasso508e53e2004-05-18 18:57:06 +0000750ospf6_unknown_reoriginate (struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000751{
hasso508e53e2004-05-18 18:57:06 +0000752 ospf6_lsa_premature_aging (lsa);
paul718e3742002-12-13 20:15:29 +0000753 return 0;
754}
755
756int
hasso508e53e2004-05-18 18:57:06 +0000757ospf6_unknown_show (struct vty *vty, struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000758{
hasso508e53e2004-05-18 18:57:06 +0000759 u_char *start, *end, *current;
760 char byte[4];
paul718e3742002-12-13 20:15:29 +0000761
hasso508e53e2004-05-18 18:57:06 +0000762 start = (char *) lsa->header + sizeof (struct ospf6_lsa_header);
paul718e3742002-12-13 20:15:29 +0000763 end = (char *) lsa->header + ntohs (lsa->header->length);
hasso508e53e2004-05-18 18:57:06 +0000764
765 vty_out (vty, " Unknown contents:%s", VTY_NEWLINE);
766 for (current = start; current < end; current ++)
paul718e3742002-12-13 20:15:29 +0000767 {
hasso508e53e2004-05-18 18:57:06 +0000768 if ((current - start) % 16 == 0)
769 vty_out (vty, "%s ", VTY_NEWLINE);
770 else if ((current - start) % 4 == 0)
771 vty_out (vty, " ");
paul718e3742002-12-13 20:15:29 +0000772
hasso508e53e2004-05-18 18:57:06 +0000773 snprintf (byte, sizeof (byte), "%02x", *current);
774 vty_out (vty, "%s", byte);
paul718e3742002-12-13 20:15:29 +0000775 }
hasso508e53e2004-05-18 18:57:06 +0000776
777 vty_out (vty, "%s%s", VTY_NEWLINE, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000778 return 0;
779}
780
paul718e3742002-12-13 20:15:29 +0000781void
782ospf6_lsa_init ()
783{
hasso508e53e2004-05-18 18:57:06 +0000784 memset (ospf6_lstype, 0, sizeof (ospf6_lstype));
paul718e3742002-12-13 20:15:29 +0000785
hasso508e53e2004-05-18 18:57:06 +0000786 ospf6_lstype[0].name = "Unknown";
787 ospf6_lstype[0].reoriginate = ospf6_unknown_reoriginate;
788 ospf6_lstype[0].show = ospf6_unknown_show;
paul718e3742002-12-13 20:15:29 +0000789}
790
hasso508e53e2004-05-18 18:57:06 +0000791
792
793DEFUN (debug_ospf6_lsa_sendrecv,
794 debug_ospf6_lsa_sendrecv_cmd,
795 "debug ospf6 lsa (send|recv|originate|timer|database|memory|all)",
796 DEBUG_STR
797 OSPF6_STR
798 "Debug Link State Advertisements (LSAs)\n"
799 "Debug Sending LSAs\n"
800 "Debug Receiving LSAs\n"
801 "Debug Originating LSAs\n"
802 "Debug Timer Event of LSAs\n"
803 "Debug LSA Database\n"
804 "Debug Memory of LSAs\n"
805 "Debug LSAs all\n"
806 )
807{
808 unsigned char level = 0;
809
810 if (argc)
811 {
812 if (! strncmp (argv[0], "s", 1))
813 level = OSPF6_DEBUG_LSA_SEND;
814 else if (! strncmp (argv[0], "r", 1))
815 level = OSPF6_DEBUG_LSA_RECV;
816 else if (! strncmp (argv[0], "o", 1))
817 level = OSPF6_DEBUG_LSA_ORIGINATE;
818 else if (! strncmp (argv[0], "t", 1))
819 level = OSPF6_DEBUG_LSA_TIMER;
820 else if (! strncmp (argv[0], "d", 1))
821 level = OSPF6_DEBUG_LSA_DATABASE;
822 else if (! strncmp (argv[0], "m", 1))
823 level = OSPF6_DEBUG_LSA_MEMORY;
824 else if (! strncmp (argv[0], "a", 1))
825 {
826 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
827 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER |
828 OSPF6_DEBUG_LSA_DATABASE | OSPF6_DEBUG_LSA_MEMORY;
829 }
830 }
831 else
832 {
833 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
834 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER;
835 }
836
837 OSPF6_DEBUG_LSA_ON (level);
838 return CMD_SUCCESS;
839}
840
841ALIAS (debug_ospf6_lsa_sendrecv,
842 debug_ospf6_lsa_cmd,
843 "debug ospf6 lsa",
844 NO_STR
845 DEBUG_STR
846 OSPF6_STR
847 "Debug Link State Advertisements (LSAs)\n"
848 );
849
850DEFUN (no_debug_ospf6_lsa_sendrecv,
851 no_debug_ospf6_lsa_sendrecv_cmd,
852 "no debug ospf6 lsa (send|recv|originate|timer|database|memory|all)",
853 NO_STR
854 DEBUG_STR
855 OSPF6_STR
856 "Debug Link State Advertisements (LSAs)\n"
857 "Debug Sending LSAs\n"
858 "Debug Receiving LSAs\n"
859 "Debug Originating LSAs\n"
860 "Debug Timer Event of LSAs\n"
861 "Debug LSA Database\n"
862 "Debug Memory of LSAs\n"
863 "Debug LSAs all\n"
864 )
865{
866 unsigned char level = 0;
867
868 if (argc)
869 {
870 if (! strncmp (argv[0], "s", 1))
871 level = OSPF6_DEBUG_LSA_SEND;
872 else if (! strncmp (argv[0], "r", 1))
873 level = OSPF6_DEBUG_LSA_RECV;
874 else if (! strncmp (argv[0], "o", 1))
875 level = OSPF6_DEBUG_LSA_ORIGINATE;
876 else if (! strncmp (argv[0], "t", 1))
877 level = OSPF6_DEBUG_LSA_TIMER;
878 else if (! strncmp (argv[0], "d", 1))
879 level = OSPF6_DEBUG_LSA_DATABASE;
880 else if (! strncmp (argv[0], "m", 1))
881 level = OSPF6_DEBUG_LSA_MEMORY;
882 else if (! strncmp (argv[0], "a", 1))
883 {
884 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
885 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER |
886 OSPF6_DEBUG_LSA_DATABASE | OSPF6_DEBUG_LSA_MEMORY;
887 }
888 }
889 else
890 {
891 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
892 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER;
893 }
894
895 OSPF6_DEBUG_LSA_OFF (level);
896 return CMD_SUCCESS;
897}
898
899ALIAS (no_debug_ospf6_lsa_sendrecv,
900 no_debug_ospf6_lsa_cmd,
901 "no debug ospf6 lsa",
902 NO_STR
903 DEBUG_STR
904 OSPF6_STR
905 "Debug Link State Advertisements (LSAs)\n"
906 );
907
908int
909config_write_ospf6_debug_lsa (struct vty *vty)
910{
911 if (conf_debug_ospf6_lsa == OSPF6_DEBUG_LSA_ALL)
912 vty_out (vty, "debug ospf6 lsa all%s", VTY_NEWLINE);
913 else
914 {
915 if (conf_debug_ospf6_lsa == OSPF6_DEBUG_LSA_DEFAULT)
916 vty_out (vty, "debug ospf6 lsa%s", VTY_NEWLINE);
917 else
918 {
919 if (IS_OSPF6_DEBUG_LSA (SEND))
920 vty_out (vty, "debug ospf6 lsa send%s", VTY_NEWLINE);
921 if (IS_OSPF6_DEBUG_LSA (RECV))
922 vty_out (vty, "debug ospf6 lsa recv%s", VTY_NEWLINE);
923 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
924 vty_out (vty, "debug ospf6 lsa originate%s", VTY_NEWLINE);
925 if (IS_OSPF6_DEBUG_LSA (TIMER))
926 vty_out (vty, "debug ospf6 lsa timer%s", VTY_NEWLINE);
927 }
928
929 if (IS_OSPF6_DEBUG_LSA (DATABASE))
930 vty_out (vty, "debug ospf6 lsa database%s", VTY_NEWLINE);
931 if (IS_OSPF6_DEBUG_LSA (MEMORY))
932 vty_out (vty, "debug ospf6 lsa memory%s", VTY_NEWLINE);
933 }
934
935 return 0;
936}
937
938void
939install_element_ospf6_debug_lsa ()
940{
941 install_element (ENABLE_NODE, &debug_ospf6_lsa_cmd);
942 install_element (ENABLE_NODE, &debug_ospf6_lsa_sendrecv_cmd);
943 install_element (ENABLE_NODE, &no_debug_ospf6_lsa_cmd);
944 install_element (ENABLE_NODE, &no_debug_ospf6_lsa_sendrecv_cmd);
945 install_element (CONFIG_NODE, &debug_ospf6_lsa_cmd);
946 install_element (CONFIG_NODE, &debug_ospf6_lsa_sendrecv_cmd);
947 install_element (CONFIG_NODE, &no_debug_ospf6_lsa_cmd);
948 install_element (CONFIG_NODE, &no_debug_ospf6_lsa_sendrecv_cmd);
949}
950
951