blob: 56ed318d74fb98ba5ddb360731388843e190e94b [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
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
paul718e3742002-12-13 20:15:29 +0000286 vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
hasso049207c2004-08-04 20:02:13 +0000287 OSPF6_LSTYPE_NAME (lsa->header->type), VNL);
288 vty_out (vty, "Link State ID: %s%s", id, VNL);
289 vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
hasso508e53e2004-05-18 18:57:06 +0000290 vty_out (vty, "LS Sequence Number: %#010lx%s",
hasso049207c2004-08-04 20:02:13 +0000291 (u_long) ntohl (lsa->header->seqnum), VNL);
hasso508e53e2004-05-18 18:57:06 +0000292 vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
293 ntohs (lsa->header->checksum),
hasso049207c2004-08-04 20:02:13 +0000294 ntohs (lsa->header->length), VNL);
paul718e3742002-12-13 20:15:29 +0000295
hasso508e53e2004-05-18 18:57:06 +0000296 index = OSPF6_LSTYPE_INDEX (ntohs (lsa->header->type));
297 if (ospf6_lstype[index].show)
298 (*ospf6_lstype[index].show) (vty, lsa);
299 else
hasso049207c2004-08-04 20:02:13 +0000300 vty_out (vty, "%sUnknown LSA type ...%s", VNL, VNL);
paul718e3742002-12-13 20:15:29 +0000301
hasso049207c2004-08-04 20:02:13 +0000302 vty_out (vty, "%s", VNL);
paul718e3742002-12-13 20:15:29 +0000303}
304
305void
306ospf6_lsa_show_summary_header (struct vty *vty)
307{
308 vty_out (vty, "%-12s %-15s %-15s %4s %8s %4s %4s %-8s%s",
309 "Type", "LSId", "AdvRouter", "Age", "SeqNum",
hasso049207c2004-08-04 20:02:13 +0000310 "Cksm", "Len", "Duration", VNL);
paul718e3742002-12-13 20:15:29 +0000311}
312
313void
314ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa)
315{
hasso508e53e2004-05-18 18:57:06 +0000316 char adv_router[16], id[16];
paul718e3742002-12-13 20:15:29 +0000317 struct timeval now, res;
318 char duration[16];
319
320 assert (lsa);
321 assert (lsa->header);
322
paul718e3742002-12-13 20:15:29 +0000323 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
324 inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
325 sizeof (adv_router));
326
327 gettimeofday (&now, NULL);
hasso508e53e2004-05-18 18:57:06 +0000328 timersub (&now, &lsa->installed, &res);
329 timerstring (&res, duration, sizeof (duration));
paul718e3742002-12-13 20:15:29 +0000330
331 vty_out (vty, "%-12s %-15s %-15s %4hu %8lx %04hx %4hu %8s%s",
hasso508e53e2004-05-18 18:57:06 +0000332 OSPF6_LSTYPE_NAME (lsa->header->type),
333 id, adv_router, ospf6_lsa_age_current (lsa),
paul718e3742002-12-13 20:15:29 +0000334 (u_long) ntohl (lsa->header->seqnum),
335 ntohs (lsa->header->checksum), ntohs (lsa->header->length),
hasso049207c2004-08-04 20:02:13 +0000336 duration, VNL);
paul718e3742002-12-13 20:15:29 +0000337}
338
339void
340ospf6_lsa_show_dump (struct vty *vty, struct ospf6_lsa *lsa)
341{
342 u_char *start, *end, *current;
343 char byte[4];
344
345 start = (char *) lsa->header;
346 end = (char *) lsa->header + ntohs (lsa->header->length);
347
hasso049207c2004-08-04 20:02:13 +0000348 vty_out (vty, "%s", VNL);
349 vty_out (vty, "%s:%s", lsa->name, VNL);
paul718e3742002-12-13 20:15:29 +0000350
351 for (current = start; current < end; current ++)
352 {
353 if ((current - start) % 16 == 0)
hasso049207c2004-08-04 20:02:13 +0000354 vty_out (vty, "%s ", VNL);
paul718e3742002-12-13 20:15:29 +0000355 else if ((current - start) % 4 == 0)
356 vty_out (vty, " ");
357
358 snprintf (byte, sizeof (byte), "%02x", *current);
359 vty_out (vty, "%s", byte);
360 }
361
hasso049207c2004-08-04 20:02:13 +0000362 vty_out (vty, "%s%s", VNL, VNL);
paul718e3742002-12-13 20:15:29 +0000363}
364
hasso508e53e2004-05-18 18:57:06 +0000365void
366ospf6_lsa_show_internal (struct vty *vty, struct ospf6_lsa *lsa)
367{
368 char adv_router[64], id[64];
369
370 assert (lsa && lsa->header);
371
372 inet_ntop (AF_INET, &lsa->header->id, id, sizeof (id));
373 inet_ntop (AF_INET, &lsa->header->adv_router,
374 adv_router, sizeof (adv_router));
375
hasso049207c2004-08-04 20:02:13 +0000376 vty_out (vty, "%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000377 vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
hasso049207c2004-08-04 20:02:13 +0000378 OSPF6_LSTYPE_NAME (lsa->header->type), VNL);
379 vty_out (vty, "Link State ID: %s%s", id, VNL);
380 vty_out (vty, "Advertising Router: %s%s", adv_router, VNL);
hasso508e53e2004-05-18 18:57:06 +0000381 vty_out (vty, "LS Sequence Number: %#010lx%s",
hasso049207c2004-08-04 20:02:13 +0000382 (u_long) ntohl (lsa->header->seqnum), VNL);
hasso508e53e2004-05-18 18:57:06 +0000383 vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
384 ntohs (lsa->header->checksum),
hasso049207c2004-08-04 20:02:13 +0000385 ntohs (lsa->header->length), VNL);
hasso508e53e2004-05-18 18:57:06 +0000386 vty_out (vty, " Prev: %p This: %p Next: %p%s",
hasso049207c2004-08-04 20:02:13 +0000387 lsa->prev, lsa, lsa->next, VNL);
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 */
392
paul718e3742002-12-13 20:15:29 +0000393struct ospf6_lsa *
hasso508e53e2004-05-18 18:57:06 +0000394ospf6_lsa_create (struct ospf6_lsa_header *header)
paul718e3742002-12-13 20:15:29 +0000395{
396 struct ospf6_lsa *lsa = NULL;
hasso508e53e2004-05-18 18:57:06 +0000397 struct ospf6_lsa_header *new_header = NULL;
paul718e3742002-12-13 20:15:29 +0000398 u_int16_t lsa_size = 0;
paul718e3742002-12-13 20:15:29 +0000399
hasso508e53e2004-05-18 18:57:06 +0000400 /* size of the entire LSA */
401 lsa_size = ntohs (header->length); /* XXX vulnerable */
paul718e3742002-12-13 20:15:29 +0000402
403 /* allocate memory for this LSA */
hasso508e53e2004-05-18 18:57:06 +0000404 new_header = (struct ospf6_lsa_header *)
paul718e3742002-12-13 20:15:29 +0000405 XMALLOC (MTYPE_OSPF6_LSA, lsa_size);
paul718e3742002-12-13 20:15:29 +0000406
hasso508e53e2004-05-18 18:57:06 +0000407 /* copy LSA from original header */
408 memcpy (new_header, header, lsa_size);
paul718e3742002-12-13 20:15:29 +0000409
410 /* LSA information structure */
411 /* allocate memory */
412 lsa = (struct ospf6_lsa *)
hasso508e53e2004-05-18 18:57:06 +0000413 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
paul718e3742002-12-13 20:15:29 +0000414 memset (lsa, 0, sizeof (struct ospf6_lsa));
415
hasso508e53e2004-05-18 18:57:06 +0000416 lsa->header = (struct ospf6_lsa_header *) new_header;
417 lsa->headeronly = 0; /* this is not header only */
paul718e3742002-12-13 20:15:29 +0000418
419 /* dump string */
hasso508e53e2004-05-18 18:57:06 +0000420 ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
paul718e3742002-12-13 20:15:29 +0000421
422 /* calculate birth, expire and refresh of this lsa */
423 ospf6_lsa_age_set (lsa);
424
hasso508e53e2004-05-18 18:57:06 +0000425 if (IS_OSPF6_DEBUG_LSA (MEMORY))
426 zlog_info ("Create LSA Memory: %s (%p/%p)",
427 lsa->name, lsa, lsa->header);
paul718e3742002-12-13 20:15:29 +0000428
429 return lsa;
430}
431
432struct ospf6_lsa *
hasso508e53e2004-05-18 18:57:06 +0000433ospf6_lsa_create_headeronly (struct ospf6_lsa_header *header)
paul718e3742002-12-13 20:15:29 +0000434{
435 struct ospf6_lsa *lsa = NULL;
hasso508e53e2004-05-18 18:57:06 +0000436 struct ospf6_lsa_header *new_header = NULL;
paul718e3742002-12-13 20:15:29 +0000437
438 /* allocate memory for this LSA */
hasso508e53e2004-05-18 18:57:06 +0000439 new_header = (struct ospf6_lsa_header *)
440 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +0000441
hasso508e53e2004-05-18 18:57:06 +0000442 /* copy LSA from original header */
443 memcpy (new_header, header, sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +0000444
445 /* LSA information structure */
446 /* allocate memory */
447 lsa = (struct ospf6_lsa *)
hasso508e53e2004-05-18 18:57:06 +0000448 XMALLOC (MTYPE_OSPF6_LSA, sizeof (struct ospf6_lsa));
paul718e3742002-12-13 20:15:29 +0000449 memset (lsa, 0, sizeof (struct ospf6_lsa));
450
hasso508e53e2004-05-18 18:57:06 +0000451 lsa->header = (struct ospf6_lsa_header *) new_header;
452 lsa->headeronly = 1; /* this is header only */
paul718e3742002-12-13 20:15:29 +0000453
454 /* dump string */
hasso508e53e2004-05-18 18:57:06 +0000455 ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
paul718e3742002-12-13 20:15:29 +0000456
457 /* calculate birth, expire and refresh of this lsa */
458 ospf6_lsa_age_set (lsa);
459
hasso508e53e2004-05-18 18:57:06 +0000460 if (IS_OSPF6_DEBUG_LSA (MEMORY))
461 zlog_info ("Create LSA (Header-only) Memory: %s (%p/%p)",
462 lsa->name, lsa, lsa->header);
paul718e3742002-12-13 20:15:29 +0000463
464 return lsa;
465}
466
467void
468ospf6_lsa_delete (struct ospf6_lsa *lsa)
469{
hasso508e53e2004-05-18 18:57:06 +0000470 assert (lsa->lock == 0);
paul718e3742002-12-13 20:15:29 +0000471
472 /* cancel threads */
hasso508e53e2004-05-18 18:57:06 +0000473 THREAD_OFF (lsa->expire);
474 THREAD_OFF (lsa->refresh);
paul718e3742002-12-13 20:15:29 +0000475
hasso508e53e2004-05-18 18:57:06 +0000476 if (IS_OSPF6_DEBUG_LSA (MEMORY))
477 zlog_info ("Delete LSA %s Memory: %s (%p/%p)",
478 (lsa->headeronly ? "(Header-only) " : ""),
479 lsa->name, lsa, lsa->header);
paul718e3742002-12-13 20:15:29 +0000480
481 /* do free */
hasso508e53e2004-05-18 18:57:06 +0000482 XFREE (MTYPE_OSPF6_LSA, lsa->header);
483 XFREE (MTYPE_OSPF6_LSA, lsa);
paul718e3742002-12-13 20:15:29 +0000484}
485
hasso508e53e2004-05-18 18:57:06 +0000486struct ospf6_lsa *
487ospf6_lsa_copy (struct ospf6_lsa *lsa)
488{
489 struct ospf6_lsa *copy = NULL;
490
491 if (IS_OSPF6_DEBUG_LSA (MEMORY))
492 zlog_info ("Create LSA Copy from %s", lsa->name);
493
494 ospf6_lsa_age_current (lsa);
495 if (lsa->headeronly)
496 copy = ospf6_lsa_create_headeronly (lsa->header);
497 else
498 copy = ospf6_lsa_create (lsa->header);
499 assert (copy->lock == 0);
500
501 copy->installed = lsa->installed;
502 copy->originated = lsa->originated;
503 copy->scope = lsa->scope;
504
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
530void
hasso508e53e2004-05-18 18:57:06 +0000531ospf6_lsa_originate (struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000532{
paul718e3742002-12-13 20:15:29 +0000533 struct ospf6_lsa *old;
hasso508e53e2004-05-18 18:57:06 +0000534 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000535
536 /* find previous LSA */
hasso508e53e2004-05-18 18:57:06 +0000537 lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
538 if (lsdb == NULL)
539 {
540 zlog_warn ("Can't decide scoped LSDB");
541 ospf6_lsa_delete (lsa);
542 return;
543 }
544
paul718e3742002-12-13 20:15:29 +0000545 old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
hasso508e53e2004-05-18 18:57:06 +0000546 lsa->header->adv_router, lsdb);
paul718e3742002-12-13 20:15:29 +0000547 if (old)
548 {
hasso508e53e2004-05-18 18:57:06 +0000549 /* If this origination is neither different instance nor refresh,
550 suppress this origination */
551 if (! CHECK_FLAG (old->flag, OSPF6_LSA_REFRESH) &&
552 ! OSPF6_LSA_IS_DIFFER (lsa, old))
paul718e3742002-12-13 20:15:29 +0000553 {
hasso508e53e2004-05-18 18:57:06 +0000554 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
555 zlog_info ("Suppress updating LSA: %s", lsa->name);
paul718e3742002-12-13 20:15:29 +0000556 ospf6_lsa_delete (lsa);
557 return;
558 }
559 }
560
561 lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
hasso508e53e2004-05-18 18:57:06 +0000562 LS_REFRESH_TIME);
paul718e3742002-12-13 20:15:29 +0000563
hasso508e53e2004-05-18 18:57:06 +0000564 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
565 {
566 zlog_info ("LSA Originate:");
567 ospf6_lsa_header_print (lsa);
568 }
paul718e3742002-12-13 20:15:29 +0000569
hasso508e53e2004-05-18 18:57:06 +0000570 if (old)
571 ospf6_flood_clear (old);
572 ospf6_flood_lsa (lsa, NULL);
573 ospf6_install_lsa (lsa, lsdb);
574}
575
576void
577ospf6_lsa_re_originate (struct ospf6_lsa *lsa)
578{
579 u_int16_t index;
580
581 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
582 {
583 zlog_info ("LSA Reoriginate:");
584 ospf6_lsa_header_print (lsa);
585 }
586
587 index = OSPF6_LSTYPE_INDEX (ntohs (lsa->header->type));
588 if (ospf6_lstype[index].reoriginate)
589 (*ospf6_lstype[index].reoriginate) (lsa);
590 else
591 ospf6_lsa_premature_aging (lsa);
paul718e3742002-12-13 20:15:29 +0000592}
593
594
hasso508e53e2004-05-18 18:57:06 +0000595/* ospf6 lsa expiry */
paul718e3742002-12-13 20:15:29 +0000596int
597ospf6_lsa_expire (struct thread *thread)
598{
599 struct ospf6_lsa *lsa;
600 struct ospf6_lsdb *lsdb = NULL;
paul718e3742002-12-13 20:15:29 +0000601
602 lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
paul718e3742002-12-13 20:15:29 +0000603
hasso508e53e2004-05-18 18:57:06 +0000604 assert (lsa && lsa->header);
605 assert (OSPF6_LSA_IS_MAXAGE (lsa));
606 assert (! lsa->refresh);
paul718e3742002-12-13 20:15:29 +0000607
608 lsa->expire = (struct thread *) NULL;
609
hasso508e53e2004-05-18 18:57:06 +0000610 if (IS_OSPF6_DEBUG_LSA (TIMER))
paul718e3742002-12-13 20:15:29 +0000611 {
hasso508e53e2004-05-18 18:57:06 +0000612 zlog_info ("LSA Expire:");
613 ospf6_lsa_header_print (lsa);
paul718e3742002-12-13 20:15:29 +0000614 }
615
hasso508e53e2004-05-18 18:57:06 +0000616 if (lsa->headeronly)
617 return 0; /* dbexchange will do something ... */
618
619 /* reflood lsa */
620 ospf6_flood_lsa (lsa, NULL);
621
622 /* reinstall lsa */
623 lsdb = ospf6_get_scoped_lsdb (lsa->header->type, lsa->scope);
624 if (lsdb == NULL)
625 {
626 zlog_warn ("Can't decide scoped LSDB: %s", lsa->name);
627 return 0;
628 }
629 if (IS_OSPF6_DEBUG_LSA (DATABASE))
630 zlog_info ("Reinstall MaxAge %s", lsa->name);
631 ospf6_lsdb_add (lsa, lsdb);
632
633 /* schedule maxage remover */
634 ospf6_maxage_remove (ospf6);
635
paul718e3742002-12-13 20:15:29 +0000636 return 0;
637}
638
hasso508e53e2004-05-18 18:57:06 +0000639/* Below will become dummy thread.
640 refresh function must be set individually per each LSAs */
paul718e3742002-12-13 20:15:29 +0000641int
642ospf6_lsa_refresh (struct thread *thread)
643{
644 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000645
646 assert (thread);
hasso508e53e2004-05-18 18:57:06 +0000647 lsa = (struct ospf6_lsa *) THREAD_ARG (thread);
648 assert (lsa && lsa->header);
paul718e3742002-12-13 20:15:29 +0000649
paul718e3742002-12-13 20:15:29 +0000650 lsa->refresh = (struct thread *) NULL;
paul718e3742002-12-13 20:15:29 +0000651
hasso508e53e2004-05-18 18:57:06 +0000652 /* this will be used later to decide really originate or not */
653 SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
paul718e3742002-12-13 20:15:29 +0000654
hasso508e53e2004-05-18 18:57:06 +0000655 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
paul718e3742002-12-13 20:15:29 +0000656 {
hasso508e53e2004-05-18 18:57:06 +0000657 zlog_info ("LSA Refresh:");
658 ospf6_lsa_header_print (lsa);
paul718e3742002-12-13 20:15:29 +0000659 }
660
hasso508e53e2004-05-18 18:57:06 +0000661 ospf6_lsa_re_originate (lsa);
662 return 0;
paul718e3742002-12-13 20:15:29 +0000663}
664
665
666
667/* enhanced Fletcher checksum algorithm, RFC1008 7.2 */
668#define MODX 4102
669#define LSA_CHECKSUM_OFFSET 15
670
671unsigned short
672ospf6_lsa_checksum (struct ospf6_lsa_header *lsa_header)
673{
674 u_char *sp, *ep, *p, *q;
675 int c0 = 0, c1 = 0;
676 int x, y;
677 u_int16_t length;
678
679 lsa_header->checksum = 0;
680 length = ntohs (lsa_header->length) - 2;
681 sp = (char *) &lsa_header->type;
682
683 for (ep = sp + length; sp < ep; sp = q)
684 {
685 q = sp + MODX;
686 if (q > ep)
687 q = ep;
688 for (p = sp; p < q; p++)
689 {
690 c0 += *p;
691 c1 += c0;
692 }
693 c0 %= 255;
694 c1 %= 255;
695 }
696
697 /* r = (c1 << 8) + c0; */
698 x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255;
699 if (x <= 0)
700 x += 255;
701 y = 510 - c0 - x;
702 if (y > 255)
703 y -= 255;
704
705 lsa_header->checksum = htons ((x << 8) + y);
706
707 return (lsa_header->checksum);
708}
709
710int
hasso508e53e2004-05-18 18:57:06 +0000711ospf6_unknown_reoriginate (struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000712{
hasso508e53e2004-05-18 18:57:06 +0000713 ospf6_lsa_premature_aging (lsa);
paul718e3742002-12-13 20:15:29 +0000714 return 0;
715}
716
717int
hasso508e53e2004-05-18 18:57:06 +0000718ospf6_unknown_show (struct vty *vty, struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000719{
hasso508e53e2004-05-18 18:57:06 +0000720 u_char *start, *end, *current;
721 char byte[4];
paul718e3742002-12-13 20:15:29 +0000722
hasso508e53e2004-05-18 18:57:06 +0000723 start = (char *) lsa->header + sizeof (struct ospf6_lsa_header);
paul718e3742002-12-13 20:15:29 +0000724 end = (char *) lsa->header + ntohs (lsa->header->length);
hasso508e53e2004-05-18 18:57:06 +0000725
hasso049207c2004-08-04 20:02:13 +0000726 vty_out (vty, " Unknown contents:%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000727 for (current = start; current < end; current ++)
paul718e3742002-12-13 20:15:29 +0000728 {
hasso508e53e2004-05-18 18:57:06 +0000729 if ((current - start) % 16 == 0)
hasso049207c2004-08-04 20:02:13 +0000730 vty_out (vty, "%s ", VNL);
hasso508e53e2004-05-18 18:57:06 +0000731 else if ((current - start) % 4 == 0)
732 vty_out (vty, " ");
paul718e3742002-12-13 20:15:29 +0000733
hasso508e53e2004-05-18 18:57:06 +0000734 snprintf (byte, sizeof (byte), "%02x", *current);
735 vty_out (vty, "%s", byte);
paul718e3742002-12-13 20:15:29 +0000736 }
hasso508e53e2004-05-18 18:57:06 +0000737
hasso049207c2004-08-04 20:02:13 +0000738 vty_out (vty, "%s%s", VNL, VNL);
paul718e3742002-12-13 20:15:29 +0000739 return 0;
740}
741
paul718e3742002-12-13 20:15:29 +0000742void
743ospf6_lsa_init ()
744{
hasso508e53e2004-05-18 18:57:06 +0000745 memset (ospf6_lstype, 0, sizeof (ospf6_lstype));
paul718e3742002-12-13 20:15:29 +0000746
hasso508e53e2004-05-18 18:57:06 +0000747 ospf6_lstype[0].name = "Unknown";
748 ospf6_lstype[0].reoriginate = ospf6_unknown_reoriginate;
749 ospf6_lstype[0].show = ospf6_unknown_show;
paul718e3742002-12-13 20:15:29 +0000750}
751
hasso508e53e2004-05-18 18:57:06 +0000752
753
754DEFUN (debug_ospf6_lsa_sendrecv,
755 debug_ospf6_lsa_sendrecv_cmd,
756 "debug ospf6 lsa (send|recv|originate|timer|database|memory|all)",
757 DEBUG_STR
758 OSPF6_STR
759 "Debug Link State Advertisements (LSAs)\n"
760 "Debug Sending LSAs\n"
761 "Debug Receiving LSAs\n"
762 "Debug Originating LSAs\n"
763 "Debug Timer Event of LSAs\n"
764 "Debug LSA Database\n"
765 "Debug Memory of LSAs\n"
766 "Debug LSAs all\n"
767 )
768{
769 unsigned char level = 0;
770
771 if (argc)
772 {
773 if (! strncmp (argv[0], "s", 1))
774 level = OSPF6_DEBUG_LSA_SEND;
775 else if (! strncmp (argv[0], "r", 1))
776 level = OSPF6_DEBUG_LSA_RECV;
777 else if (! strncmp (argv[0], "o", 1))
778 level = OSPF6_DEBUG_LSA_ORIGINATE;
779 else if (! strncmp (argv[0], "t", 1))
780 level = OSPF6_DEBUG_LSA_TIMER;
781 else if (! strncmp (argv[0], "d", 1))
782 level = OSPF6_DEBUG_LSA_DATABASE;
783 else if (! strncmp (argv[0], "m", 1))
784 level = OSPF6_DEBUG_LSA_MEMORY;
785 else if (! strncmp (argv[0], "a", 1))
786 {
787 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
788 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER |
789 OSPF6_DEBUG_LSA_DATABASE | OSPF6_DEBUG_LSA_MEMORY;
790 }
791 }
792 else
793 {
794 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
795 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER;
796 }
797
798 OSPF6_DEBUG_LSA_ON (level);
799 return CMD_SUCCESS;
800}
801
802ALIAS (debug_ospf6_lsa_sendrecv,
803 debug_ospf6_lsa_cmd,
804 "debug ospf6 lsa",
805 NO_STR
806 DEBUG_STR
807 OSPF6_STR
808 "Debug Link State Advertisements (LSAs)\n"
809 );
810
811DEFUN (no_debug_ospf6_lsa_sendrecv,
812 no_debug_ospf6_lsa_sendrecv_cmd,
813 "no debug ospf6 lsa (send|recv|originate|timer|database|memory|all)",
814 NO_STR
815 DEBUG_STR
816 OSPF6_STR
817 "Debug Link State Advertisements (LSAs)\n"
818 "Debug Sending LSAs\n"
819 "Debug Receiving LSAs\n"
820 "Debug Originating LSAs\n"
821 "Debug Timer Event of LSAs\n"
822 "Debug LSA Database\n"
823 "Debug Memory of LSAs\n"
824 "Debug LSAs all\n"
825 )
826{
827 unsigned char level = 0;
828
829 if (argc)
830 {
831 if (! strncmp (argv[0], "s", 1))
832 level = OSPF6_DEBUG_LSA_SEND;
833 else if (! strncmp (argv[0], "r", 1))
834 level = OSPF6_DEBUG_LSA_RECV;
835 else if (! strncmp (argv[0], "o", 1))
836 level = OSPF6_DEBUG_LSA_ORIGINATE;
837 else if (! strncmp (argv[0], "t", 1))
838 level = OSPF6_DEBUG_LSA_TIMER;
839 else if (! strncmp (argv[0], "d", 1))
840 level = OSPF6_DEBUG_LSA_DATABASE;
841 else if (! strncmp (argv[0], "m", 1))
842 level = OSPF6_DEBUG_LSA_MEMORY;
843 else if (! strncmp (argv[0], "a", 1))
844 {
845 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
846 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER |
847 OSPF6_DEBUG_LSA_DATABASE | OSPF6_DEBUG_LSA_MEMORY;
848 }
849 }
850 else
851 {
852 level = OSPF6_DEBUG_LSA_SEND | OSPF6_DEBUG_LSA_RECV |
853 OSPF6_DEBUG_LSA_ORIGINATE | OSPF6_DEBUG_LSA_TIMER;
854 }
855
856 OSPF6_DEBUG_LSA_OFF (level);
857 return CMD_SUCCESS;
858}
859
860ALIAS (no_debug_ospf6_lsa_sendrecv,
861 no_debug_ospf6_lsa_cmd,
862 "no debug ospf6 lsa",
863 NO_STR
864 DEBUG_STR
865 OSPF6_STR
866 "Debug Link State Advertisements (LSAs)\n"
867 );
868
869int
870config_write_ospf6_debug_lsa (struct vty *vty)
871{
872 if (conf_debug_ospf6_lsa == OSPF6_DEBUG_LSA_ALL)
hasso049207c2004-08-04 20:02:13 +0000873 vty_out (vty, "debug ospf6 lsa all%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000874 else
875 {
876 if (conf_debug_ospf6_lsa == OSPF6_DEBUG_LSA_DEFAULT)
hasso049207c2004-08-04 20:02:13 +0000877 vty_out (vty, "debug ospf6 lsa%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000878 else
879 {
880 if (IS_OSPF6_DEBUG_LSA (SEND))
hasso049207c2004-08-04 20:02:13 +0000881 vty_out (vty, "debug ospf6 lsa send%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000882 if (IS_OSPF6_DEBUG_LSA (RECV))
hasso049207c2004-08-04 20:02:13 +0000883 vty_out (vty, "debug ospf6 lsa recv%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000884 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
hasso049207c2004-08-04 20:02:13 +0000885 vty_out (vty, "debug ospf6 lsa originate%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000886 if (IS_OSPF6_DEBUG_LSA (TIMER))
hasso049207c2004-08-04 20:02:13 +0000887 vty_out (vty, "debug ospf6 lsa timer%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000888 }
889
890 if (IS_OSPF6_DEBUG_LSA (DATABASE))
hasso049207c2004-08-04 20:02:13 +0000891 vty_out (vty, "debug ospf6 lsa database%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000892 if (IS_OSPF6_DEBUG_LSA (MEMORY))
hasso049207c2004-08-04 20:02:13 +0000893 vty_out (vty, "debug ospf6 lsa memory%s", VNL);
hasso508e53e2004-05-18 18:57:06 +0000894 }
895
896 return 0;
897}
898
899void
900install_element_ospf6_debug_lsa ()
901{
902 install_element (ENABLE_NODE, &debug_ospf6_lsa_cmd);
903 install_element (ENABLE_NODE, &debug_ospf6_lsa_sendrecv_cmd);
904 install_element (ENABLE_NODE, &no_debug_ospf6_lsa_cmd);
905 install_element (ENABLE_NODE, &no_debug_ospf6_lsa_sendrecv_cmd);
906 install_element (CONFIG_NODE, &debug_ospf6_lsa_cmd);
907 install_element (CONFIG_NODE, &debug_ospf6_lsa_sendrecv_cmd);
908 install_element (CONFIG_NODE, &no_debug_ospf6_lsa_cmd);
909 install_element (CONFIG_NODE, &no_debug_ospf6_lsa_sendrecv_cmd);
910}
911
912