blob: 47cbd39daf2f858ebba0df611f8060d7169e993c [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
hasso508e53e2004-05-18 18:57:06 +000022#include <zebra.h>
23
24#include "log.h"
25#include "linklist.h"
26#include "thread.h"
27#include "memory.h"
28#include "if.h"
29#include "prefix.h"
30#include "table.h"
31#include "vty.h"
32#include "command.h"
33
paul718e3742002-12-13 20:15:29 +000034#include "ospf6d.h"
hasso508e53e2004-05-18 18:57:06 +000035#include "ospf6_proto.h"
36#include "ospf6_message.h"
37#include "ospf6_route.h"
38#include "ospf6_lsa.h"
39#include "ospf6_lsdb.h"
paul718e3742002-12-13 20:15:29 +000040
hasso508e53e2004-05-18 18:57:06 +000041#include "ospf6_top.h"
42#include "ospf6_area.h"
43#include "ospf6_interface.h"
44#include "ospf6_neighbor.h"
45#include "ospf6_intra.h"
46#include "ospf6_asbr.h"
paul718e3742002-12-13 20:15:29 +000047
hasso508e53e2004-05-18 18:57:06 +000048/******************************/
49/* RFC2740 3.4.3.1 Router-LSA */
50/******************************/
paul718e3742002-12-13 20:15:29 +000051
hasso508e53e2004-05-18 18:57:06 +000052int
53ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +000054{
hasso508e53e2004-05-18 18:57:06 +000055 char *start, *end, *current;
56 char buf[32], name[32], bits[16], options[32];
57 struct ospf6_router_lsa *router_lsa;
58 struct ospf6_router_lsdesc *lsdesc;
paul718e3742002-12-13 20:15:29 +000059
hasso508e53e2004-05-18 18:57:06 +000060 router_lsa = (struct ospf6_router_lsa *)
61 ((char *) lsa->header + sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +000062
hasso508e53e2004-05-18 18:57:06 +000063 ospf6_capability_printbuf (router_lsa->bits, bits, sizeof (bits));
64 ospf6_options_printbuf (router_lsa->options, options, sizeof (options));
65 vty_out (vty, " Bits: %s Options: %s%s", bits, options, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +000066
hasso508e53e2004-05-18 18:57:06 +000067 start = (char *) router_lsa + sizeof (struct ospf6_router_lsa);
paul718e3742002-12-13 20:15:29 +000068 end = (char *) lsa->header + ntohs (lsa->header->length);
hasso508e53e2004-05-18 18:57:06 +000069 for (current = start; current + sizeof (struct ospf6_router_lsdesc) <= end;
70 current += sizeof (struct ospf6_router_lsdesc))
paul718e3742002-12-13 20:15:29 +000071 {
hasso508e53e2004-05-18 18:57:06 +000072 lsdesc = (struct ospf6_router_lsdesc *) current;
paul718e3742002-12-13 20:15:29 +000073
hasso508e53e2004-05-18 18:57:06 +000074 if (lsdesc->type == OSPF6_ROUTER_LSDESC_POINTTOPOINT)
75 snprintf (name, sizeof (name), "Point-To-Point");
76 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK)
77 snprintf (name, sizeof (name), "Transit-Network");
78 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_STUB_NETWORK)
79 snprintf (name, sizeof (name), "Stub-Network");
80 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_VIRTUAL_LINK)
81 snprintf (name, sizeof (name), "Virtual-Link");
paul718e3742002-12-13 20:15:29 +000082 else
hasso508e53e2004-05-18 18:57:06 +000083 snprintf (name, sizeof (name), "Unknown (%#x)", lsdesc->type);
paul718e3742002-12-13 20:15:29 +000084
hasso508e53e2004-05-18 18:57:06 +000085 vty_out (vty, " Type: %s Metric: %d%s",
86 name, ntohs (lsdesc->metric), VTY_NEWLINE);
87 vty_out (vty, " Interface ID: %s%s",
88 inet_ntop (AF_INET, &lsdesc->interface_id,
89 buf, sizeof (buf)), VTY_NEWLINE);
90 vty_out (vty, " Neighbor Interface ID: %s%s",
91 inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
92 buf, sizeof (buf)), VTY_NEWLINE);
93 vty_out (vty, " Neighbor Router ID: %s%s",
94 inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
95 buf, sizeof (buf)), VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +000096 }
97 return 0;
98}
99
100void
hasso508e53e2004-05-18 18:57:06 +0000101ospf6_router_lsa_originate_sub (struct ospf6_area *oa, int force)
paul718e3742002-12-13 20:15:29 +0000102{
hasso508e53e2004-05-18 18:57:06 +0000103 char buffer [OSPF6_MAX_LSASIZE];
104 struct ospf6_lsa_header *lsa_header;
105 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000106
hasso508e53e2004-05-18 18:57:06 +0000107 u_int32_t link_state_id = 0;
108 listnode i, j;
109 struct ospf6_interface *oi;
110 struct ospf6_neighbor *on, *drouter = NULL;
111 struct ospf6_router_lsa *router_lsa;
112 struct ospf6_router_lsdesc *lsdesc;
113 u_int16_t type;
114 u_int32_t router;
115 int count;
paul718e3742002-12-13 20:15:29 +0000116
hasso508e53e2004-05-18 18:57:06 +0000117 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
118 zlog_info ("Originate Router-LSA for Area %s", oa->name);
paul718e3742002-12-13 20:15:29 +0000119
hasso508e53e2004-05-18 18:57:06 +0000120 memset (buffer, 0, sizeof (buffer));
121 lsa_header = (struct ospf6_lsa_header *) buffer;
122 router_lsa = (struct ospf6_router_lsa *)
123 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
124
125 OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_V6);
126 OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_E);
127 OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_MC);
128 OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_N);
129 OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_R);
130 OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_DC);
131
132 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
133 if (ospf6_asbr_is_asbr (ospf6))
134 SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
135 else
136 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
137 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_V);
138 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_W);
139
140 /* describe links for each interfaces */
141 lsdesc = (struct ospf6_router_lsdesc *)
142 ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa));
143
144 for (i = listhead (oa->if_list); i; nextnode (i))
paul718e3742002-12-13 20:15:29 +0000145 {
hasso508e53e2004-05-18 18:57:06 +0000146 oi = (struct ospf6_interface *) getdata (i);
147
148 /* Interfaces in state Down or Loopback are not described */
149 if (oi->state == OSPF6_INTERFACE_DOWN ||
150 oi->state == OSPF6_INTERFACE_LOOPBACK)
paul718e3742002-12-13 20:15:29 +0000151 continue;
152
hasso508e53e2004-05-18 18:57:06 +0000153 /* Nor are interfaces without any full adjacencies described */
154 count = 0;
155 for (j = listhead (oi->neighbor_list); j; nextnode (j))
paul718e3742002-12-13 20:15:29 +0000156 {
hasso508e53e2004-05-18 18:57:06 +0000157 on = (struct ospf6_neighbor *) getdata (j);
158 if (on->state == OSPF6_NEIGHBOR_FULL)
159 count++;
160 }
161 if (count == 0)
162 continue;
163
164 /* Multiple Router-LSA instance according to size limit setting */
165 if (oa->router_lsa_size_limit != 0 &&
166 (caddr_t) lsdesc + sizeof (struct ospf6_router_lsdesc) -
167 (caddr_t) buffer > oa->router_lsa_size_limit)
168 {
169 if ((caddr_t) lsdesc == (caddr_t) router_lsa +
170 sizeof (struct ospf6_router_lsa))
171 {
172 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
173 zlog_info ("Size limit setting for Router-LSA too short");
174 return;
175 }
176
177 /* Fill LSA Header */
178 lsa_header->age = 0;
179 lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
180 lsa_header->id = htonl (link_state_id);
181 lsa_header->adv_router = oa->ospf6->router_id;
182 lsa_header->seqnum =
183 ospf6_lsa_new_seqnum (lsa_header->type, lsa_header->id,
184 lsa_header->adv_router, oa);
185 lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
186
187 /* LSA checksum */
188 ospf6_lsa_checksum (lsa_header);
189
190 /* create LSA */
191 lsa = ospf6_lsa_create (lsa_header);
192 lsa->scope = oa;
193 if (force)
194 SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
195
196 /* Originate */
197 ospf6_lsa_originate (lsa);
198
199 /* Reset setting for consecutive origination */
200 memset ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa),
201 0, (caddr_t) lsdesc - (caddr_t) router_lsa);
202 lsdesc = (struct ospf6_router_lsdesc *)
203 ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa));
204 link_state_id ++;
paul718e3742002-12-13 20:15:29 +0000205 }
206
hasso508e53e2004-05-18 18:57:06 +0000207 /* Point-to-Point interfaces */
208 if (if_is_pointopoint (oi->interface))
209 {
210 for (j = listhead (oi->neighbor_list); j; nextnode (j))
211 {
212 on = (struct ospf6_neighbor *) getdata (j);
213 if (on->state != OSPF6_NEIGHBOR_FULL)
214 continue;
paul718e3742002-12-13 20:15:29 +0000215
hasso508e53e2004-05-18 18:57:06 +0000216 lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT;
217 lsdesc->metric = htons (oi->cost);
218 lsdesc->interface_id = htonl (oi->interface->ifindex);
219 lsdesc->neighbor_interface_id = htonl (on->ifindex);
220 lsdesc->neighbor_router_id = on->router_id;
221
222 lsdesc++;
223 }
224 }
225
226 /* Broadcast and NBMA interfaces */
227 if (if_is_broadcast (oi->interface))
228 {
229 /* If this router is not DR,
230 and If this router not fully adjacent with DR,
231 this interface is not transit yet: ignore. */
232 if (oi->state != OSPF6_INTERFACE_DR)
233 {
234 drouter = ospf6_neighbor_lookup (oi->drouter, oi);
235 if (drouter == NULL || drouter->state != OSPF6_NEIGHBOR_FULL)
236 continue;
237 }
238
239 lsdesc->type = OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK;
240 lsdesc->metric = htons (oi->cost);
241 lsdesc->interface_id = htonl (oi->interface->ifindex);
242 if (oi->state != OSPF6_INTERFACE_DR)
243 {
244 lsdesc->neighbor_interface_id = htonl (drouter->ifindex);
245 lsdesc->neighbor_router_id = drouter->router_id;
246 }
247 else
248 {
249 lsdesc->neighbor_interface_id = htonl (oi->interface->ifindex);
250 lsdesc->neighbor_router_id = oi->area->ospf6->router_id;
251 }
252
253 lsdesc++;
254 }
255
256 /* Virtual links */
257 /* xxx */
258 /* Point-to-Multipoint interfaces */
259 /* xxx */
paul718e3742002-12-13 20:15:29 +0000260 }
hasso508e53e2004-05-18 18:57:06 +0000261
262 if ((caddr_t) lsdesc != (caddr_t) router_lsa +
263 sizeof (struct ospf6_router_lsa))
264 {
265 /* Fill LSA Header */
266 lsa_header->age = 0;
267 lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
268 lsa_header->id = htonl (link_state_id);
269 lsa_header->adv_router = oa->ospf6->router_id;
270 lsa_header->seqnum =
271 ospf6_lsa_new_seqnum (lsa_header->type, lsa_header->id,
272 lsa_header->adv_router, oa);
273 lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
274
275 /* LSA checksum */
276 ospf6_lsa_checksum (lsa_header);
277
278 /* create LSA */
279 lsa = ospf6_lsa_create (lsa_header);
280 lsa->scope = oa;
281 if (force)
282 SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
283
284 /* Originate */
285 ospf6_lsa_originate (lsa);
286
287 link_state_id ++;
288 }
289
290 /* Do premature-aging of rest, undesired Router-LSAs */
291 type = ntohs (OSPF6_LSTYPE_ROUTER);
292 router = oa->ospf6->router_id;
293 for (lsa = ospf6_lsdb_type_router_head (type, router, oa->lsdb); lsa;
294 lsa = ospf6_lsdb_type_router_next (type, router, lsa))
295 {
296 if (ntohl (lsa->header->id) < link_state_id)
297 continue;
298 ospf6_lsa_premature_aging (lsa);
299 }
300}
301
302int
303ospf6_router_lsa_originate (struct thread *thread)
304{
305 struct ospf6_area *oa;
306 int force = 0;
307
308 oa = (struct ospf6_area *) THREAD_ARG (thread);
309 oa->thread_router_lsa = NULL;
310 ospf6_router_lsa_originate_sub (oa, force);
311
312 return 0;
313}
314
315int
316ospf6_router_lsa_reoriginate (struct ospf6_lsa *lsa)
317{
318 struct ospf6_area *oa;
319 int force = 1;
320
321 oa = (struct ospf6_area *) lsa->scope;
322 ospf6_router_lsa_originate_sub (oa, force);
323
324 return 0;
325}
326
327
328/*******************************/
329/* RFC2740 3.4.3.2 Network-LSA */
330/*******************************/
331
332int
333ospf6_network_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
334{
335 char *start, *end, *current;
336 struct ospf6_network_lsa *network_lsa;
337 struct ospf6_network_lsdesc *lsdesc;
338 char buf[128], options[32];
339
340 network_lsa = (struct ospf6_network_lsa *)
341 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
342
343 ospf6_options_printbuf (network_lsa->options, options, sizeof (options));
344 vty_out (vty, " Options: %s%s", options, VTY_NEWLINE);
345
346 start = (char *) network_lsa + sizeof (struct ospf6_network_lsa);
347 end = (char *) lsa->header + ntohs (lsa->header->length);
348 for (current = start; current + sizeof (struct ospf6_network_lsdesc) <= end;
349 current += sizeof (struct ospf6_network_lsdesc))
350 {
351 lsdesc = (struct ospf6_network_lsdesc *) current;
352 inet_ntop (AF_INET, &lsdesc->router_id, buf, sizeof (buf));
353 vty_out (vty, " Attached Router: %s%s", buf, VTY_NEWLINE);
354 }
355 return 0;
paul718e3742002-12-13 20:15:29 +0000356}
357
358void
hasso508e53e2004-05-18 18:57:06 +0000359ospf6_network_lsa_originate_sub (struct ospf6_interface *oi, int force)
paul718e3742002-12-13 20:15:29 +0000360{
hasso508e53e2004-05-18 18:57:06 +0000361 char buffer [OSPF6_MAX_LSASIZE];
362 struct ospf6_lsa_header *lsa_header;
paul718e3742002-12-13 20:15:29 +0000363
hasso508e53e2004-05-18 18:57:06 +0000364 int count;
365 struct ospf6_lsa *old, *lsa;
366 struct ospf6_network_lsa *network_lsa;
367 struct ospf6_network_lsdesc *lsdesc;
368 struct ospf6_neighbor *on;
369 struct ospf6_link_lsa *link_lsa;
370 listnode i;
371 u_int16_t type;
372
373 /* If self-originated Network-LSA for currently unenabled I/F
374 (but was once enabled, so other routers send it to this router),
375 we can't find oi->area for ospf6_lsdb_lookup (), and so can't
376 do premature aging of the Network-LSA. Just let the LSA flow
377 in network (other routers LSDB) for maximum duration of
378 MaxAge. The contents of this router's Router-LSA will preclude
379 the stale Network-LSA to be involved in routing calculation. */
380 if (oi->area == NULL)
paul718e3742002-12-13 20:15:29 +0000381 return;
382
hasso508e53e2004-05-18 18:57:06 +0000383 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_NETWORK),
384 htonl (oi->interface->ifindex),
385 oi->area->ospf6->router_id, oi->area->lsdb);
paul718e3742002-12-13 20:15:29 +0000386
hasso508e53e2004-05-18 18:57:06 +0000387 /* Do not originate Network-LSA if not DR */
388 if (oi->state != OSPF6_INTERFACE_DR)
paul718e3742002-12-13 20:15:29 +0000389 {
hasso508e53e2004-05-18 18:57:06 +0000390 if (old)
391 ospf6_lsa_premature_aging (old);
392 return;
paul718e3742002-12-13 20:15:29 +0000393 }
hasso508e53e2004-05-18 18:57:06 +0000394
395 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
396 zlog_info ("Originate Network-LSA for Interface %s", oi->interface->name);
397
398 /* If none of neighbor is adjacent to us */
399 count = 0;
400 for (i = listhead (oi->neighbor_list); i; nextnode (i))
401 {
402 on = (struct ospf6_neighbor *) getdata (i);
403 if (on->state == OSPF6_NEIGHBOR_FULL)
404 count++;
405 }
406 if (count == 0)
407 {
408 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
409 zlog_info ("Interface stub, ignore");
410 if (old)
411 ospf6_lsa_premature_aging (old);
412 return;
413 }
414
415 /* prepare buffer */
416 memset (buffer, 0, sizeof (buffer));
417 lsa_header = (struct ospf6_lsa_header *) buffer;
418 network_lsa = (struct ospf6_network_lsa *)
419 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
420
421 /* Collect the interface's Link-LSAs to describe
422 network's optional capabilities */
423 type = htons (OSPF6_LSTYPE_LINK);
424 for (lsa = ospf6_lsdb_type_head (type, oi->lsdb); lsa;
425 lsa = ospf6_lsdb_type_next (type, lsa))
426 {
427 link_lsa = (struct ospf6_link_lsa *)
428 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
429 network_lsa->options[0] |= link_lsa->options[0];
430 network_lsa->options[1] |= link_lsa->options[1];
431 network_lsa->options[2] |= link_lsa->options[2];
432 }
433
434 lsdesc = (struct ospf6_network_lsdesc *)
435 ((caddr_t) network_lsa + sizeof (struct ospf6_network_lsa));
436
437 /* set Link Description to the router itself */
438 lsdesc->router_id = oi->area->ospf6->router_id;
439 lsdesc++;
440
441 /* Walk through the neighbors */
442 for (i = listhead (oi->neighbor_list); i; nextnode (i))
443 {
444 on = (struct ospf6_neighbor *) getdata (i);
445
446 if (on->state != OSPF6_NEIGHBOR_FULL)
447 continue;
448
449 /* set this neighbor's Router-ID to LSA */
450 lsdesc->router_id = on->router_id;
451 lsdesc++;
452 }
453
454 /* Fill LSA Header */
455 lsa_header->age = 0;
456 lsa_header->type = htons (OSPF6_LSTYPE_NETWORK);
457 lsa_header->id = htonl (oi->interface->ifindex);
458 lsa_header->adv_router = oi->area->ospf6->router_id;
459 lsa_header->seqnum =
460 ospf6_lsa_new_seqnum (lsa_header->type, lsa_header->id,
461 lsa_header->adv_router, oi->area);
462 lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
463
464 /* LSA checksum */
465 ospf6_lsa_checksum (lsa_header);
466
467 /* create LSA */
468 lsa = ospf6_lsa_create (lsa_header);
469 lsa->scope = oi->area;
470 if (force)
471 SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
472
473 /* Originate */
474 ospf6_lsa_originate (lsa);
paul718e3742002-12-13 20:15:29 +0000475}
476
hasso508e53e2004-05-18 18:57:06 +0000477int
478ospf6_network_lsa_originate (struct thread *thread)
479{
480 struct ospf6_interface *oi;
481 int force = 0;
paul718e3742002-12-13 20:15:29 +0000482
hasso508e53e2004-05-18 18:57:06 +0000483 oi = (struct ospf6_interface *) THREAD_ARG (thread);
484 oi->thread_network_lsa = NULL;
485 ospf6_network_lsa_originate_sub (oi, force);
paul718e3742002-12-13 20:15:29 +0000486
hasso508e53e2004-05-18 18:57:06 +0000487 return 0;
488}
paul718e3742002-12-13 20:15:29 +0000489
490int
hasso508e53e2004-05-18 18:57:06 +0000491ospf6_network_lsa_reoriginate (struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +0000492{
hasso508e53e2004-05-18 18:57:06 +0000493 struct ospf6_interface *oi;
494 int force = 1;
495
496 oi = ospf6_interface_lookup_by_ifindex (ntohl (lsa->header->id));
497 ospf6_network_lsa_originate_sub (oi, force);
498
499 return 0;
500}
501
502
503/****************************/
504/* RFC2740 3.4.3.6 Link-LSA */
505/****************************/
506
507int
508ospf6_link_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
509{
paul718e3742002-12-13 20:15:29 +0000510 char *start, *end, *current;
hasso508e53e2004-05-18 18:57:06 +0000511 struct ospf6_link_lsa *link_lsa;
512 int prefixnum;
513 char buf[128], options[32];
514 struct ospf6_prefix *prefix;
515 char *p, *mc, *la, *nu;
516 struct in6_addr in6;
paul718e3742002-12-13 20:15:29 +0000517
hasso508e53e2004-05-18 18:57:06 +0000518 link_lsa = (struct ospf6_link_lsa *)
519 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +0000520
hasso508e53e2004-05-18 18:57:06 +0000521 ospf6_options_printbuf (link_lsa->options, options, sizeof (options));
522 inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));
523 prefixnum = ntohl (link_lsa->prefix_num);
paul718e3742002-12-13 20:15:29 +0000524
hasso508e53e2004-05-18 18:57:06 +0000525 vty_out (vty, " Priority: %d Options: %s%s",
526 link_lsa->priority, options, VTY_NEWLINE);
527 vty_out (vty, " LinkLocal Address: %s%s", buf, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000528 vty_out (vty, " Number of Prefix: %d%s", prefixnum, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000529
hasso508e53e2004-05-18 18:57:06 +0000530 start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
531 end = (char *) lsa->header + ntohs (lsa->header->length);
paul718e3742002-12-13 20:15:29 +0000532 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
533 {
534 prefix = (struct ospf6_prefix *) current;
hasso508e53e2004-05-18 18:57:06 +0000535 if (prefix->prefix_length == 0 ||
536 current + OSPF6_PREFIX_SIZE (prefix) > end)
537 break;
paul718e3742002-12-13 20:15:29 +0000538
hasso508e53e2004-05-18 18:57:06 +0000539 p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ?
540 "P" : "--");
541 mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ?
542 "MC" : "--");
543 la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ?
544 "LA" : "--");
545 nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ?
546 "NU" : "--");
547 vty_out (vty, " Prefix Options: %s|%s|%s|%s%s",
548 p, mc, la, nu, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +0000549
hasso508e53e2004-05-18 18:57:06 +0000550 memset (&in6, 0, sizeof (in6));
551 memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
552 OSPF6_PREFIX_SPACE (prefix->prefix_length));
paul718e3742002-12-13 20:15:29 +0000553 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
554 vty_out (vty, " Prefix: %s/%d%s",
555 buf, prefix->prefix_length, VTY_NEWLINE);
556 }
557
558 return 0;
559}
560
561void
hasso508e53e2004-05-18 18:57:06 +0000562ospf6_link_lsa_originate_sub (struct ospf6_interface *oi, int force)
paul718e3742002-12-13 20:15:29 +0000563{
hasso508e53e2004-05-18 18:57:06 +0000564 char buffer[OSPF6_MAX_LSASIZE];
565 struct ospf6_lsa_header *lsa_header;
566 struct ospf6_lsa *old, *lsa;
paul718e3742002-12-13 20:15:29 +0000567
hasso508e53e2004-05-18 18:57:06 +0000568 struct ospf6_link_lsa *link_lsa;
569 struct ospf6_route *route;
570 struct ospf6_prefix *op;
paul718e3742002-12-13 20:15:29 +0000571
hasso508e53e2004-05-18 18:57:06 +0000572 if (oi->area == NULL)
573 return;
paul718e3742002-12-13 20:15:29 +0000574
575 /* find previous LSA */
hasso508e53e2004-05-18 18:57:06 +0000576 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_LINK),
577 htonl (oi->interface->ifindex),
578 oi->area->ospf6->router_id, oi->lsdb);
paul718e3742002-12-13 20:15:29 +0000579
hasso508e53e2004-05-18 18:57:06 +0000580 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
paul718e3742002-12-13 20:15:29 +0000581 {
582 if (old)
paul718e3742002-12-13 20:15:29 +0000583 ospf6_lsa_premature_aging (old);
584 return;
585 }
586
hasso508e53e2004-05-18 18:57:06 +0000587 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
588 zlog_info ("Originate Link-LSA for Interface %s", oi->interface->name);
paul718e3742002-12-13 20:15:29 +0000589
hasso508e53e2004-05-18 18:57:06 +0000590 /* can't make Link-LSA if linklocal address not set */
591 if (oi->linklocal_addr == NULL)
paul718e3742002-12-13 20:15:29 +0000592 {
hasso508e53e2004-05-18 18:57:06 +0000593 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
594 zlog_info ("No Linklocal address on %s, defer originating",
595 oi->interface->name);
596 if (old)
597 ospf6_lsa_premature_aging (old);
598 return;
599 }
600
601 /* prepare buffer */
602 memset (buffer, 0, sizeof (buffer));
603 lsa_header = (struct ospf6_lsa_header *) buffer;
604 link_lsa = (struct ospf6_link_lsa *)
605 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
606
607 /* Fill Link-LSA */
608 link_lsa->priority = oi->priority;
609 memcpy (link_lsa->options, oi->area->options, 3);
610 memcpy (&link_lsa->linklocal_addr, oi->linklocal_addr,
611 sizeof (struct in6_addr));
612 link_lsa->prefix_num = htonl (oi->route_connected->count);
613
614 op = (struct ospf6_prefix *)
615 ((caddr_t) link_lsa + sizeof (struct ospf6_link_lsa));
616
617 /* connected prefix to advertise */
618 for (route = ospf6_route_head (oi->route_connected); route;
619 route = ospf6_route_next (route))
620 {
621 op->prefix_length = route->prefix.prefixlen;
622 op->prefix_options = route->path.prefix_options;
623 op->prefix_metric = htons (0);
624 memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
625 OSPF6_PREFIX_SPACE (op->prefix_length));
626 op = OSPF6_PREFIX_NEXT (op);
627 }
628
629 /* Fill LSA Header */
630 lsa_header->age = 0;
631 lsa_header->type = htons (OSPF6_LSTYPE_LINK);
632 lsa_header->id = htonl (oi->interface->ifindex);
633 lsa_header->adv_router = oi->area->ospf6->router_id;
634 lsa_header->seqnum =
635 ospf6_lsa_new_seqnum (lsa_header->type, lsa_header->id,
636 lsa_header->adv_router, oi);
637 lsa_header->length = htons ((caddr_t) op - (caddr_t) buffer);
638
639 /* LSA checksum */
640 ospf6_lsa_checksum (lsa_header);
641
642 /* create LSA */
643 lsa = ospf6_lsa_create (lsa_header);
644 lsa->scope = oi;
645 if (force)
646 SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
647
648 /* Originate */
649 ospf6_lsa_originate (lsa);
650}
651
652int
653ospf6_link_lsa_originate (struct thread *thread)
654{
655 struct ospf6_interface *oi;
656 int force = 0;
657
658 oi = (struct ospf6_interface *) THREAD_ARG (thread);
659 oi->thread_link_lsa = NULL;
660 ospf6_link_lsa_originate_sub (oi, force);
661
662 return 0;
663}
664
665int
666ospf6_link_lsa_reoriginate (struct ospf6_lsa *lsa)
667{
668 struct ospf6_interface *oi;
669 int force = 1;
670
671 oi = ospf6_interface_lookup_by_ifindex (ntohl (lsa->header->id));
672 ospf6_link_lsa_originate_sub (oi, force);
673
674 return 0;
675}
676
677
678/*****************************************/
679/* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
680/*****************************************/
681
682int
683ospf6_intra_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
684{
685 char *start, *end, *current;
686 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
687 int prefixnum;
688 char buf[128];
689 struct ospf6_prefix *prefix;
690 char id[16], adv_router[16];
691 char *p, *mc, *la, *nu;
692 struct in6_addr in6;
693
694 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
695 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
696
697 prefixnum = ntohs (intra_prefix_lsa->prefix_num);
698
699 vty_out (vty, " Number of Prefix: %d%s", prefixnum, VTY_NEWLINE);
700
701 inet_ntop (AF_INET, &intra_prefix_lsa->ref_id, id, sizeof (id));
702 inet_ntop (AF_INET, &intra_prefix_lsa->ref_adv_router,
703 adv_router, sizeof (adv_router));
704 vty_out (vty, " Reference: %s Id: %s Adv: %s%s",
705 OSPF6_LSTYPE_NAME (intra_prefix_lsa->ref_type), id, adv_router,
706 VTY_NEWLINE);
707
708 start = (char *) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa);
709 end = (char *) lsa->header + ntohs (lsa->header->length);
710 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
711 {
712 prefix = (struct ospf6_prefix *) current;
713 if (prefix->prefix_length == 0 ||
714 current + OSPF6_PREFIX_SIZE (prefix) > end)
715 break;
716
717 p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ?
718 "P" : "--");
719 mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ?
720 "MC" : "--");
721 la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ?
722 "LA" : "--");
723 nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ?
724 "NU" : "--");
725 vty_out (vty, " Prefix Options: %s|%s|%s|%s%s",
726 p, mc, la, nu, VTY_NEWLINE);
727
728 memset (&in6, 0, sizeof (in6));
729 memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
730 OSPF6_PREFIX_SPACE (prefix->prefix_length));
731 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
732 vty_out (vty, " Prefix: %s/%d%s",
733 buf, prefix->prefix_length, VTY_NEWLINE);
734 }
735
736 return 0;
737}
738
739void
740ospf6_intra_prefix_lsa_originate_stub_sub (struct ospf6_area *oa,
741 int force)
742{
743 char buffer[OSPF6_MAX_LSASIZE];
744 struct ospf6_lsa_header *lsa_header;
745 struct ospf6_lsa *old, *lsa;
746
747 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
748 struct ospf6_interface *oi;
749 struct ospf6_neighbor *on;
750 struct ospf6_route *route;
751 struct ospf6_prefix *op;
752 listnode i, j;
753 int full_count = 0;
754 unsigned short prefix_num = 0;
755 char buf[BUFSIZ];
756 struct ospf6_route_table *route_advertise;
757
758 /* find previous LSA */
759 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
760 htonl (0), oa->ospf6->router_id, oa->lsdb);
761
762 if (CHECK_FLAG (oa->flag, OSPF6_AREA_DISABLE))
763 {
764 if (old)
765 ospf6_lsa_premature_aging (old);
766 return;
767 }
768
769 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
770 zlog_info ("Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
771 oa->name);
772
773 /* prepare buffer */
774 memset (buffer, 0, sizeof (buffer));
775 lsa_header = (struct ospf6_lsa_header *) buffer;
776 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
777 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
778
779 /* Fill Intra-Area-Prefix-LSA */
780 intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_ROUTER);
781 intra_prefix_lsa->ref_id = htonl (0);
782 intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id;
783
784 route_advertise = ospf6_route_table_create ();
785
786 for (i = listhead (oa->if_list); i; nextnode (i))
787 {
788 oi = (struct ospf6_interface *) getdata (i);
789
790 if (oi->state == OSPF6_INTERFACE_DOWN)
791 {
792 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
793 zlog_info (" Interface %s is down, ignore", oi->interface->name);
794 continue;
795 }
796
797 full_count = 0;
798 for (j = listhead (oi->neighbor_list); j; nextnode (j))
799 {
800 on = (struct ospf6_neighbor *) getdata (j);
801 if (on->state == OSPF6_NEIGHBOR_FULL)
802 full_count++;
803 }
804 if (oi->state != OSPF6_INTERFACE_LOOPBACK &&
805 oi->state != OSPF6_INTERFACE_POINTTOPOINT &&
806 full_count != 0)
807 {
808 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
809 zlog_info (" Interface %s is not stub, ignore",
810 oi->interface->name);
811 continue;
812 }
813
814 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
815 zlog_info (" Interface %s:", oi->interface->name);
816
817 /* connected prefix to advertise */
818 for (route = ospf6_route_head (oi->route_connected); route;
819 route = ospf6_route_best_next (route))
820 {
821 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
822 {
823 prefix2str (&route->prefix, buf, sizeof (buf));
824 zlog_info (" include %s", buf);
825 }
826 ospf6_route_add (ospf6_route_copy (route), route_advertise);
827 }
828 }
829
830 if (route_advertise->count == 0)
831 {
832 if (old)
833 ospf6_lsa_premature_aging (old);
834 ospf6_route_table_delete (route_advertise);
835 return;
836 }
837
838 /* put prefixes to advertise */
839 prefix_num = 0;
840 op = (struct ospf6_prefix *)
841 ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa));
842 for (route = ospf6_route_head (route_advertise); route;
843 route = ospf6_route_best_next (route))
844 {
845 op->prefix_length = route->prefix.prefixlen;
846 op->prefix_options = route->path.prefix_options;
847 op->prefix_metric = htons (route->path.cost);
848 memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
849 OSPF6_PREFIX_SPACE (op->prefix_length));
850 op = OSPF6_PREFIX_NEXT (op);
851 prefix_num++;
852 }
853
854 ospf6_route_table_delete (route_advertise);
855
856 if (prefix_num == 0)
857 {
858 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
859 zlog_info ("Quit to Advertise Intra-Prefix: no route to advertise");
860 return;
861 }
862
863 intra_prefix_lsa->prefix_num = htons (prefix_num);
864
865 /* Fill LSA Header */
866 lsa_header->age = 0;
867 lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
868 lsa_header->id = htonl (0);
869 lsa_header->adv_router = oa->ospf6->router_id;
870 lsa_header->seqnum =
871 ospf6_lsa_new_seqnum (lsa_header->type, lsa_header->id,
872 lsa_header->adv_router, oa);
873 lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
874
875 /* LSA checksum */
876 ospf6_lsa_checksum (lsa_header);
877
878 /* create LSA */
879 lsa = ospf6_lsa_create (lsa_header);
880 lsa->scope = oa;
881 if (force)
882 SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
883
884 /* Originate */
885 ospf6_lsa_originate (lsa);
886}
887
888void
889ospf6_intra_prefix_lsa_originate_transit_sub (struct ospf6_interface *oi,
890 int force)
891{
892 char buffer[OSPF6_MAX_LSASIZE];
893 struct ospf6_lsa_header *lsa_header;
894 struct ospf6_lsa *old, *lsa;
895
896 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
897 struct ospf6_neighbor *on;
898 struct ospf6_route *route;
899 struct ospf6_prefix *op;
900 listnode i;
901 int full_count = 0;
902 unsigned short prefix_num = 0;
903 struct ospf6_route_table *route_advertise;
904 struct ospf6_link_lsa *link_lsa;
905 char *start, *end, *current;
906 u_int16_t type;
907 char buf[BUFSIZ];
908
909 if (oi->area == NULL)
910 return;
911
912 /* find previous LSA */
913 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
914 htonl (oi->interface->ifindex),
915 oi->area->ospf6->router_id, oi->area->lsdb);
916
917 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
918 {
919 if (old)
920 ospf6_lsa_premature_aging (old);
921 return;
922 }
923
924 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
925 zlog_info ("Originate Intra-Area-Prefix-LSA for interface %s's prefix",
926 oi->interface->name);
927
928 /* prepare buffer */
929 memset (buffer, 0, sizeof (buffer));
930 lsa_header = (struct ospf6_lsa_header *) buffer;
931 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
932 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
933
934 /* Fill Intra-Area-Prefix-LSA */
935 intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_NETWORK);
936 intra_prefix_lsa->ref_id = htonl (oi->interface->ifindex);
937 intra_prefix_lsa->ref_adv_router = oi->area->ospf6->router_id;
938
939 if (oi->state != OSPF6_INTERFACE_DR)
940 {
941 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
942 zlog_info (" Interface is not DR");
943 if (old)
944 ospf6_lsa_premature_aging (old);
945 return;
946 }
947
948 full_count = 0;
949 for (i = listhead (oi->neighbor_list); i; nextnode (i))
950 {
951 on = (struct ospf6_neighbor *) getdata (i);
952 if (on->state == OSPF6_NEIGHBOR_FULL)
953 full_count++;
954 }
955 if (full_count == 0)
956 {
957 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
958 zlog_info (" Interface is stub");
959 if (old)
960 ospf6_lsa_premature_aging (old);
961 return;
962 }
963
964 /* connected prefix to advertise */
965 route_advertise = ospf6_route_table_create ();
966
967 type = ntohs (OSPF6_LSTYPE_LINK);
968 for (lsa = ospf6_lsdb_type_head (type, oi->lsdb); lsa;
969 lsa = ospf6_lsdb_type_next (type, lsa))
970 {
971 if (OSPF6_LSA_IS_MAXAGE (lsa))
paul718e3742002-12-13 20:15:29 +0000972 continue;
973
hasso508e53e2004-05-18 18:57:06 +0000974 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
975 zlog_info (" include prefix from %s", lsa->name);
paul718e3742002-12-13 20:15:29 +0000976
hasso508e53e2004-05-18 18:57:06 +0000977 if (lsa->header->adv_router != oi->area->ospf6->router_id)
paul718e3742002-12-13 20:15:29 +0000978 {
hasso508e53e2004-05-18 18:57:06 +0000979 on = ospf6_neighbor_lookup (lsa->header->adv_router, oi);
980 if (on == NULL || on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000981 {
hasso508e53e2004-05-18 18:57:06 +0000982 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
983 zlog_info (" Neighbor not found or not Full, ignore");
paul718e3742002-12-13 20:15:29 +0000984 continue;
985 }
986 }
987
hasso508e53e2004-05-18 18:57:06 +0000988 link_lsa = (struct ospf6_link_lsa *)
989 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +0000990
hasso508e53e2004-05-18 18:57:06 +0000991 prefix_num = (unsigned short) ntohl (link_lsa->prefix_num);
992 start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
993 end = (char *) lsa->header + ntohs (lsa->header->length);
994 for (current = start; current < end && prefix_num;
995 current += OSPF6_PREFIX_SIZE (op))
paul718e3742002-12-13 20:15:29 +0000996 {
hasso508e53e2004-05-18 18:57:06 +0000997 op = (struct ospf6_prefix *) current;
998 if (op->prefix_length == 0 ||
999 current + OSPF6_PREFIX_SIZE (op) > end)
1000 break;
paul718e3742002-12-13 20:15:29 +00001001
hasso508e53e2004-05-18 18:57:06 +00001002 route = ospf6_route_create ();
1003
1004 route->type = OSPF6_DEST_TYPE_NETWORK;
1005 route->prefix.family = AF_INET6;
1006 route->prefix.prefixlen = op->prefix_length;
1007 memset (&route->prefix.u.prefix6, 0, sizeof (struct in6_addr));
1008 memcpy (&route->prefix.u.prefix6, OSPF6_PREFIX_BODY (op),
1009 OSPF6_PREFIX_SPACE (op->prefix_length));
1010
1011 route->path.origin.type = lsa->header->type;
1012 route->path.origin.id = lsa->header->id;
1013 route->path.origin.adv_router = lsa->header->adv_router;
1014 route->path.options[0] = link_lsa->options[0];
1015 route->path.options[1] = link_lsa->options[1];
1016 route->path.options[2] = link_lsa->options[2];
1017 route->path.prefix_options = op->prefix_options;
1018 route->path.area_id = oi->area->area_id;
1019 route->path.type = OSPF6_PATH_TYPE_INTRA;
1020
1021 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
paul718e3742002-12-13 20:15:29 +00001022 {
hasso508e53e2004-05-18 18:57:06 +00001023 prefix2str (&route->prefix, buf, sizeof (buf));
1024 zlog_info (" include %s", buf);
paul718e3742002-12-13 20:15:29 +00001025 }
1026
hasso508e53e2004-05-18 18:57:06 +00001027 ospf6_route_add (route, route_advertise);
1028 prefix_num--;
paul718e3742002-12-13 20:15:29 +00001029 }
hasso508e53e2004-05-18 18:57:06 +00001030 if (current != end && IS_OSPF6_DEBUG_LSA (ORIGINATE))
1031 zlog_info ("Trailing garbage in %s", lsa->name);
paul718e3742002-12-13 20:15:29 +00001032 }
1033
hasso508e53e2004-05-18 18:57:06 +00001034 op = (struct ospf6_prefix *)
1035 ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa));
1036
1037 prefix_num = 0;
1038 for (route = ospf6_route_head (route_advertise); route;
1039 route = ospf6_route_best_next (route))
paul718e3742002-12-13 20:15:29 +00001040 {
hasso508e53e2004-05-18 18:57:06 +00001041 op->prefix_length = route->prefix.prefixlen;
1042 op->prefix_options = route->path.prefix_options;
1043 op->prefix_metric = htons (0);
1044 memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
1045 OSPF6_PREFIX_SPACE (op->prefix_length));
1046 op = OSPF6_PREFIX_NEXT (op);
1047 prefix_num++;
1048 }
1049
1050 ospf6_route_table_delete (route_advertise);
1051
1052 if (prefix_num == 0)
1053 {
1054 if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
1055 zlog_info ("Quit to Advertise Intra-Prefix: no route to advertise");
paul718e3742002-12-13 20:15:29 +00001056 return;
1057 }
1058
hasso508e53e2004-05-18 18:57:06 +00001059 intra_prefix_lsa->prefix_num = htons (prefix_num);
paul718e3742002-12-13 20:15:29 +00001060
hasso508e53e2004-05-18 18:57:06 +00001061 /* Fill LSA Header */
1062 lsa_header->age = 0;
1063 lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
1064 lsa_header->id = htonl (oi->interface->ifindex);
1065 lsa_header->adv_router = oi->area->ospf6->router_id;
1066 lsa_header->seqnum =
1067 ospf6_lsa_new_seqnum (lsa_header->type, lsa_header->id,
1068 lsa_header->adv_router, oi->area);
1069 lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
paul718e3742002-12-13 20:15:29 +00001070
hasso508e53e2004-05-18 18:57:06 +00001071 /* LSA checksum */
1072 ospf6_lsa_checksum (lsa_header);
paul718e3742002-12-13 20:15:29 +00001073
hasso508e53e2004-05-18 18:57:06 +00001074 /* create LSA */
1075 lsa = ospf6_lsa_create (lsa_header);
1076 lsa->scope = oi->area;
1077 if (force)
1078 SET_FLAG (lsa->flag, OSPF6_LSA_REFRESH);
paul718e3742002-12-13 20:15:29 +00001079
hasso508e53e2004-05-18 18:57:06 +00001080 /* Originate */
1081 ospf6_lsa_originate (lsa);
paul718e3742002-12-13 20:15:29 +00001082}
1083
1084int
hasso508e53e2004-05-18 18:57:06 +00001085ospf6_intra_prefix_lsa_originate_stub (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001086{
hasso508e53e2004-05-18 18:57:06 +00001087 struct ospf6_area *oa;
1088 int force = 0;
1089
1090 oa = (struct ospf6_area *) THREAD_ARG (thread);
1091 oa->thread_intra_prefix_lsa = NULL;
1092 ospf6_intra_prefix_lsa_originate_stub_sub (oa, force);
1093
paul718e3742002-12-13 20:15:29 +00001094 return 0;
1095}
1096
1097int
hasso508e53e2004-05-18 18:57:06 +00001098ospf6_intra_prefix_lsa_originate_transit (struct thread *thread)
paul718e3742002-12-13 20:15:29 +00001099{
hasso508e53e2004-05-18 18:57:06 +00001100 struct ospf6_interface *oi;
1101 int force = 0;
1102
1103 oi = (struct ospf6_interface *) THREAD_ARG (thread);
1104 oi->thread_intra_prefix_lsa = NULL;
1105 ospf6_intra_prefix_lsa_originate_transit_sub (oi, force);
1106
paul718e3742002-12-13 20:15:29 +00001107 return 0;
1108}
1109
1110int
hasso508e53e2004-05-18 18:57:06 +00001111ospf6_intra_prefix_lsa_reoriginate (struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00001112{
hasso508e53e2004-05-18 18:57:06 +00001113 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1114 u_int16_t type;
paul718e3742002-12-13 20:15:29 +00001115 u_int32_t id;
hasso508e53e2004-05-18 18:57:06 +00001116 struct ospf6_area *oa;
1117 struct ospf6_interface *oi;
1118 int force = 1;
paul718e3742002-12-13 20:15:29 +00001119
hasso508e53e2004-05-18 18:57:06 +00001120 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
1121 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
1122 type = ntohs (intra_prefix_lsa->ref_type);
1123 id = ntohl (intra_prefix_lsa->ref_id);
1124
1125 if (type == OSPF6_LSTYPE_ROUTER && id == 0)
paul718e3742002-12-13 20:15:29 +00001126 {
hasso508e53e2004-05-18 18:57:06 +00001127 oa = (struct ospf6_area *) lsa->scope;
1128 ospf6_intra_prefix_lsa_originate_stub_sub (oa, force);
1129 }
1130 else if (type == OSPF6_LSTYPE_NETWORK && id != 0)
1131 {
1132 if (intra_prefix_lsa->ref_id != lsa->header->id)
paul718e3742002-12-13 20:15:29 +00001133 ospf6_lsa_premature_aging (lsa);
hasso508e53e2004-05-18 18:57:06 +00001134 oi = ospf6_interface_lookup_by_ifindex (id);
1135 ospf6_intra_prefix_lsa_originate_transit_sub (oi, force);
paul718e3742002-12-13 20:15:29 +00001136 }
1137 else
hasso508e53e2004-05-18 18:57:06 +00001138 ospf6_lsa_premature_aging (lsa);
paul718e3742002-12-13 20:15:29 +00001139
1140 return 0;
1141}
1142
1143void
hasso508e53e2004-05-18 18:57:06 +00001144ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00001145{
hasso508e53e2004-05-18 18:57:06 +00001146 struct ospf6_area *oa;
1147 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1148 struct prefix ls_prefix;
1149 struct ospf6_route *route, *ls_entry;
1150 int i, prefix_num;
1151 struct ospf6_prefix *op;
1152 char *start, *current, *end;
1153 char buf[64];
paul718e3742002-12-13 20:15:29 +00001154
hasso508e53e2004-05-18 18:57:06 +00001155 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
1156 zlog_info ("%s found", lsa->name);
paul718e3742002-12-13 20:15:29 +00001157
hasso508e53e2004-05-18 18:57:06 +00001158 oa = (struct ospf6_area *) lsa->scope;
1159 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
1160 OSPF6_LSA_HEADER_END (lsa->header);
1161 if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_ROUTER))
1162 ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
1163 htonl (0), &ls_prefix);
1164 else if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_NETWORK))
1165 ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
1166 intra_prefix_lsa->ref_id, &ls_prefix);
1167 else
1168 {
1169 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
1170 zlog_info ("Unknown reference LS-type: %#hx",
1171 ntohs (intra_prefix_lsa->ref_type));
1172 return;
1173 }
paul718e3742002-12-13 20:15:29 +00001174
hasso508e53e2004-05-18 18:57:06 +00001175 ls_entry = ospf6_route_lookup (&ls_prefix, oa->spf_table);
1176 if (ls_entry == NULL)
1177 {
1178 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
1179 {
1180 ospf6_linkstate_prefix2str (&ls_prefix, buf, sizeof (buf));
1181 zlog_info ("LS entry does not exist: %s", buf);
1182 }
1183 return;
1184 }
paul718e3742002-12-13 20:15:29 +00001185
hasso508e53e2004-05-18 18:57:06 +00001186 prefix_num = ntohs (intra_prefix_lsa->prefix_num);
1187 start = (caddr_t) intra_prefix_lsa +
1188 sizeof (struct ospf6_intra_prefix_lsa);
1189 end = OSPF6_LSA_END (lsa->header);
1190 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
1191 {
1192 op = (struct ospf6_prefix *) current;
1193 if (prefix_num == 0)
1194 break;
1195 if (end < current + OSPF6_PREFIX_SIZE (op))
1196 break;
1197
1198 route = ospf6_route_create ();
1199 route->prefix.prefixlen = op->prefix_length;
1200 route->prefix.family = AF_INET6;
1201 memcpy (&route->prefix.u.prefix6, OSPF6_PREFIX_BODY (op),
1202 OSPF6_PREFIX_SPACE (op->prefix_length));
1203 route->type = OSPF6_DEST_TYPE_NETWORK;
1204 route->path.origin.type = lsa->header->type;
1205 route->path.origin.id = lsa->header->id;
1206 route->path.origin.adv_router = lsa->header->adv_router;
1207 route->path.prefix_options = op->prefix_options;
1208 route->path.area_id = oa->area_id;
1209 route->path.type = OSPF6_PATH_TYPE_INTRA;
1210 route->path.metric_type = 1;
1211 route->path.cost = ls_entry->path.cost +
1212 ntohs (op->prefix_metric);
1213
1214 for (i = 0; ospf6_nexthop_is_set (&ls_entry->nexthop[i]) &&
1215 i < OSPF6_MULTI_PATH_LIMIT; i++)
1216 ospf6_nexthop_copy (&route->nexthop[i], &ls_entry->nexthop[i]);
1217
1218 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
1219 {
1220 prefix2str (&route->prefix, buf, sizeof (buf));
1221 zlog_info (" add %s", buf);
1222 }
1223
1224 ospf6_route_add (route, oa->route_table);
1225 prefix_num--;
1226 }
1227
1228 if (current != end && IS_OSPF6_DEBUG_ROUTE (INTRA))
1229 zlog_info ("Trailing garbage ignored");
paul718e3742002-12-13 20:15:29 +00001230}
1231
1232void
hasso508e53e2004-05-18 18:57:06 +00001233ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00001234{
hasso508e53e2004-05-18 18:57:06 +00001235 struct ospf6_area *oa;
1236 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1237 struct prefix prefix;
1238 struct ospf6_route *route;
1239 int prefix_num;
1240 struct ospf6_prefix *op;
1241 char *start, *current, *end;
1242 char buf[64];
1243
1244 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
1245 zlog_info ("%s disappearing", lsa->name);
1246
1247 oa = (struct ospf6_area *) lsa->scope;
1248 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
1249 OSPF6_LSA_HEADER_END (lsa->header);
1250
1251 prefix_num = ntohs (intra_prefix_lsa->prefix_num);
1252 start = (caddr_t) intra_prefix_lsa +
1253 sizeof (struct ospf6_intra_prefix_lsa);
1254 end = OSPF6_LSA_END (lsa->header);
1255 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
1256 {
1257 op = (struct ospf6_prefix *) current;
1258 if (prefix_num == 0)
1259 break;
1260 if (end < current + OSPF6_PREFIX_SIZE (op))
1261 break;
1262 prefix_num--;
1263
1264 prefix.family = AF_INET6;
1265 prefix.prefixlen = op->prefix_length;
1266 ospf6_prefix_in6_addr (&prefix.u.prefix6, op);
1267
1268 route = ospf6_route_lookup (&prefix, oa->route_table);
1269 if (route == NULL)
1270 continue;
1271
1272 for (ospf6_route_lock (route);
1273 route && ospf6_route_is_prefix (&prefix, route);
1274 route = ospf6_route_next (route))
1275 {
1276 if (route->type != OSPF6_DEST_TYPE_NETWORK)
1277 continue;
1278 if (route->path.area_id != oa->area_id)
1279 continue;
1280 if (route->path.type != OSPF6_PATH_TYPE_INTRA)
1281 continue;
1282 if (route->path.origin.type != lsa->header->type ||
1283 route->path.origin.id != lsa->header->id ||
1284 route->path.origin.adv_router != lsa->header->adv_router)
1285 continue;
1286
1287 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
1288 {
1289 prefix2str (&route->prefix, buf, sizeof (buf));
1290 zlog_info ("remove %s", buf);
1291 }
1292 ospf6_route_remove (route, oa->route_table);
1293 }
1294 }
1295
1296 if (current != end && IS_OSPF6_DEBUG_ROUTE (INTRA))
1297 zlog_info ("Trailing garbage ignored");
paul718e3742002-12-13 20:15:29 +00001298}
1299
1300void
hasso508e53e2004-05-18 18:57:06 +00001301ospf6_intra_route_calculation (struct ospf6_area *oa)
paul718e3742002-12-13 20:15:29 +00001302{
hasso508e53e2004-05-18 18:57:06 +00001303 struct ospf6_route *route;
1304 u_int16_t type;
1305 struct ospf6_lsa *lsa;
1306 void (*hook_add) (struct ospf6_route *) = NULL;
1307 void (*hook_remove) (struct ospf6_route *) = NULL;
1308
1309 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
1310 zlog_info ("Intra-area routing table calculation for area %s",
1311 oa->name);
1312
1313 hook_add = oa->route_table->hook_add;
1314 hook_remove = oa->route_table->hook_remove;
1315 oa->route_table->hook_add = NULL;
1316 oa->route_table->hook_remove = NULL;
1317
1318 for (route = ospf6_route_head (oa->route_table); route;
1319 route = ospf6_route_next (route))
1320 route->flag = OSPF6_ROUTE_REMOVE;
1321
1322 type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
1323 for (lsa = ospf6_lsdb_type_head (type, oa->lsdb); lsa;
1324 lsa = ospf6_lsdb_type_next (type, lsa))
1325 ospf6_intra_prefix_lsa_add (lsa);
1326
1327 oa->route_table->hook_add = hook_add;
1328 oa->route_table->hook_remove = hook_remove;
1329
1330 for (route = ospf6_route_head (oa->route_table); route;
1331 route = ospf6_route_next (route))
1332 {
1333 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) &&
1334 CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD))
1335 {
1336 UNSET_FLAG (route->flag, OSPF6_ROUTE_REMOVE);
1337 UNSET_FLAG (route->flag, OSPF6_ROUTE_ADD);
1338 }
1339
1340 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE))
1341 ospf6_route_remove (route, oa->route_table);
1342 else if (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ||
1343 CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE))
1344 {
1345 if (hook_add)
1346 (*hook_add) (route);
1347 }
1348
1349 route->flag = 0;
1350 }
1351
1352 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
1353 zlog_info ("Intra-area routing table calculation for area %s: Done",
1354 oa->name);
1355}
1356
1357void
1358ospf6_intra_asbr_calculation (struct ospf6_area *oa)
1359{
1360 struct ospf6_route *lsentry, *copy;
1361 void (*hook_add) (struct ospf6_route *) = NULL;
1362 void (*hook_remove) (struct ospf6_route *) = NULL;
1363
1364 if (IS_OSPF6_DEBUG_ASBR)
1365 zlog_info ("Intra-area ASBR calculation for area %s", oa->name);
1366
1367 hook_add = oa->ospf6->asbr_table->hook_add;
1368 hook_remove = oa->ospf6->asbr_table->hook_remove;
1369 oa->ospf6->asbr_table->hook_add = NULL;
1370 oa->ospf6->asbr_table->hook_remove = NULL;
1371
1372 for (lsentry = ospf6_route_head (oa->ospf6->asbr_table); lsentry;
1373 lsentry = ospf6_route_next (lsentry))
1374 {
1375 if (lsentry->path.area_id != oa->area_id)
1376 continue;
1377 lsentry->flag = OSPF6_ROUTE_REMOVE;
1378 }
1379
1380 for (lsentry = ospf6_route_head (oa->spf_table); lsentry;
1381 lsentry = ospf6_route_next (lsentry))
1382 {
1383 if (lsentry->type != OSPF6_DEST_TYPE_LINKSTATE)
1384 continue;
1385 if (ospf6_linkstate_prefix_id (&lsentry->prefix) != htonl (0))
1386 continue;
1387 if (! CHECK_FLAG (lsentry->path.router_bits, OSPF6_ROUTER_BIT_E))
1388 continue;
1389
1390 copy = ospf6_route_copy (lsentry);
1391 copy->type = OSPF6_DEST_TYPE_ROUTER;
1392 copy->prefix.family = AF_INET;
1393 copy->prefix.prefixlen = 32;
1394 ospf6_route_add (copy, oa->ospf6->asbr_table);
1395 }
1396
1397 oa->ospf6->asbr_table->hook_add = hook_add;
1398 oa->ospf6->asbr_table->hook_remove = hook_remove;
1399
1400 for (lsentry = ospf6_route_head (oa->ospf6->asbr_table); lsentry;
1401 lsentry = ospf6_route_next (lsentry))
1402 {
1403 if (lsentry->path.area_id != oa->area_id)
1404 continue;
1405
1406 if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_REMOVE) &&
1407 CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_ADD))
1408 {
1409 UNSET_FLAG (lsentry->flag, OSPF6_ROUTE_REMOVE);
1410 UNSET_FLAG (lsentry->flag, OSPF6_ROUTE_ADD);
1411 }
1412
1413 if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_REMOVE))
1414 ospf6_route_remove (lsentry, oa->ospf6->asbr_table);
1415 else if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_ADD) ||
1416 CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_CHANGE))
1417 {
1418 if (hook_add)
1419 (*hook_add) (lsentry);
1420 }
1421
1422 lsentry->flag = 0;
1423 }
1424
1425 if (IS_OSPF6_DEBUG_ASBR)
1426 zlog_info ("Intra-area ASBR calculation for area %s: Done", oa->name);
paul718e3742002-12-13 20:15:29 +00001427}
1428
1429void
1430ospf6_intra_init ()
1431{
hasso508e53e2004-05-18 18:57:06 +00001432 ospf6_lstype[1].name = "Router";
1433 ospf6_lstype[2].name = "Network";
1434 ospf6_lstype[8].name = "Link";
1435 ospf6_lstype[9].name = "Intra-Prefix";
paul718e3742002-12-13 20:15:29 +00001436
hasso508e53e2004-05-18 18:57:06 +00001437 ospf6_lstype[1].reoriginate = ospf6_router_lsa_reoriginate;
1438 ospf6_lstype[2].reoriginate = ospf6_network_lsa_reoriginate;
1439 ospf6_lstype[8].reoriginate = ospf6_link_lsa_reoriginate;
1440 ospf6_lstype[9].reoriginate = ospf6_intra_prefix_lsa_reoriginate;
1441
1442 ospf6_lstype[1].show = ospf6_router_lsa_show;
1443 ospf6_lstype[2].show = ospf6_network_lsa_show;
1444 ospf6_lstype[8].show = ospf6_link_lsa_show;
1445 ospf6_lstype[9].show = ospf6_intra_prefix_lsa_show;
paul718e3742002-12-13 20:15:29 +00001446}
1447
1448