]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_intra.c
2005-04-07 Paul Jakma <paul.jakma@sun.com>
[mirror_frr.git] / ospf6d / ospf6_intra.c
CommitLineData
718e3744 1/*
508e53e2 2 * Copyright (C) 2003 Yasuhiro Ohara
718e3744 3 *
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
508e53e2 22#include <zebra.h>
718e3744 23
508e53e2 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"
718e3744 33
508e53e2 34#include "ospf6_proto.h"
35#include "ospf6_message.h"
36#include "ospf6_route.h"
37#include "ospf6_lsa.h"
38#include "ospf6_lsdb.h"
39
40#include "ospf6_top.h"
41#include "ospf6_area.h"
42#include "ospf6_interface.h"
43#include "ospf6_neighbor.h"
44#include "ospf6_intra.h"
45#include "ospf6_asbr.h"
6452df09 46#include "ospf6_abr.h"
47#include "ospf6_flood.h"
049207c3 48#include "ospf6d.h"
508e53e2 49
50/******************************/
51/* RFC2740 3.4.3.1 Router-LSA */
52/******************************/
718e3744 53
508e53e2 54int
55ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
718e3744 56{
508e53e2 57 char *start, *end, *current;
58 char buf[32], name[32], bits[16], options[32];
59 struct ospf6_router_lsa *router_lsa;
60 struct ospf6_router_lsdesc *lsdesc;
718e3744 61
508e53e2 62 router_lsa = (struct ospf6_router_lsa *)
63 ((char *) lsa->header + sizeof (struct ospf6_lsa_header));
718e3744 64
508e53e2 65 ospf6_capability_printbuf (router_lsa->bits, bits, sizeof (bits));
66 ospf6_options_printbuf (router_lsa->options, options, sizeof (options));
049207c3 67 vty_out (vty, " Bits: %s Options: %s%s", bits, options, VNL);
718e3744 68
508e53e2 69 start = (char *) router_lsa + sizeof (struct ospf6_router_lsa);
718e3744 70 end = (char *) lsa->header + ntohs (lsa->header->length);
508e53e2 71 for (current = start; current + sizeof (struct ospf6_router_lsdesc) <= end;
72 current += sizeof (struct ospf6_router_lsdesc))
73 {
74 lsdesc = (struct ospf6_router_lsdesc *) current;
75
76 if (lsdesc->type == OSPF6_ROUTER_LSDESC_POINTTOPOINT)
77 snprintf (name, sizeof (name), "Point-To-Point");
78 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK)
79 snprintf (name, sizeof (name), "Transit-Network");
80 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_STUB_NETWORK)
81 snprintf (name, sizeof (name), "Stub-Network");
82 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_VIRTUAL_LINK)
83 snprintf (name, sizeof (name), "Virtual-Link");
718e3744 84 else
508e53e2 85 snprintf (name, sizeof (name), "Unknown (%#x)", lsdesc->type);
86
87 vty_out (vty, " Type: %s Metric: %d%s",
049207c3 88 name, ntohs (lsdesc->metric), VNL);
508e53e2 89 vty_out (vty, " Interface ID: %s%s",
90 inet_ntop (AF_INET, &lsdesc->interface_id,
049207c3 91 buf, sizeof (buf)), VNL);
508e53e2 92 vty_out (vty, " Neighbor Interface ID: %s%s",
93 inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
049207c3 94 buf, sizeof (buf)), VNL);
508e53e2 95 vty_out (vty, " Neighbor Router ID: %s%s",
96 inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
049207c3 97 buf, sizeof (buf)), VNL);
718e3744 98 }
508e53e2 99 return 0;
718e3744 100}
101
6452df09 102int
103ospf6_router_lsa_originate (struct thread *thread)
718e3744 104{
6452df09 105 struct ospf6_area *oa;
106
508e53e2 107 char buffer [OSPF6_MAX_LSASIZE];
108 struct ospf6_lsa_header *lsa_header;
109 struct ospf6_lsa *lsa;
110
111 u_int32_t link_state_id = 0;
1eb8ef25 112 struct listnode *node, *nnode;
113 struct listnode *j;
508e53e2 114 struct ospf6_interface *oi;
115 struct ospf6_neighbor *on, *drouter = NULL;
116 struct ospf6_router_lsa *router_lsa;
117 struct ospf6_router_lsdesc *lsdesc;
118 u_int16_t type;
119 u_int32_t router;
120 int count;
718e3744 121
6452df09 122 oa = (struct ospf6_area *) THREAD_ARG (thread);
123 oa->thread_router_lsa = NULL;
124
1e05838a 125 if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
c6487d61 126 zlog_debug ("Originate Router-LSA for Area %s", oa->name);
718e3744 127
508e53e2 128 memset (buffer, 0, sizeof (buffer));
129 lsa_header = (struct ospf6_lsa_header *) buffer;
130 router_lsa = (struct ospf6_router_lsa *)
131 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
132
133 OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_V6);
134 OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_E);
135 OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_MC);
136 OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_N);
137 OSPF6_OPT_SET (router_lsa->options, OSPF6_OPT_R);
138 OSPF6_OPT_CLEAR (router_lsa->options, OSPF6_OPT_DC);
139
6452df09 140 if (ospf6_is_router_abr (ospf6))
141 SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
142 else
143 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_B);
508e53e2 144 if (ospf6_asbr_is_asbr (ospf6))
145 SET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
146 else
147 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_E);
148 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_V);
149 UNSET_FLAG (router_lsa->bits, OSPF6_ROUTER_BIT_W);
718e3744 150
508e53e2 151 /* describe links for each interfaces */
152 lsdesc = (struct ospf6_router_lsdesc *)
153 ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa));
718e3744 154
1eb8ef25 155 for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
718e3744 156 {
508e53e2 157 /* Interfaces in state Down or Loopback are not described */
158 if (oi->state == OSPF6_INTERFACE_DOWN ||
159 oi->state == OSPF6_INTERFACE_LOOPBACK)
160 continue;
161
162 /* Nor are interfaces without any full adjacencies described */
163 count = 0;
1eb8ef25 164 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
165 if (on->state == OSPF6_NEIGHBOR_FULL)
166 count++;
167
508e53e2 168 if (count == 0)
169 continue;
170
171 /* Multiple Router-LSA instance according to size limit setting */
0c083ee9 172 if ( (oa->router_lsa_size_limit != 0)
173 && ((caddr_t) lsdesc + sizeof (struct ospf6_router_lsdesc) -
1686f93f 174 /* XXX warning: comparison between signed and unsigned */
0c083ee9 175 (caddr_t) buffer > oa->router_lsa_size_limit))
508e53e2 176 {
177 if ((caddr_t) lsdesc == (caddr_t) router_lsa +
178 sizeof (struct ospf6_router_lsa))
179 {
1e05838a 180 if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
c6487d61 181 zlog_debug ("Size limit setting for Router-LSA too short");
6452df09 182 return 0;
508e53e2 183 }
184
185 /* Fill LSA Header */
186 lsa_header->age = 0;
187 lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
188 lsa_header->id = htonl (link_state_id);
189 lsa_header->adv_router = oa->ospf6->router_id;
190 lsa_header->seqnum =
049207c3 191 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
192 lsa_header->adv_router, oa->lsdb);
508e53e2 193 lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
194
195 /* LSA checksum */
196 ospf6_lsa_checksum (lsa_header);
197
198 /* create LSA */
199 lsa = ospf6_lsa_create (lsa_header);
508e53e2 200
201 /* Originate */
6452df09 202 ospf6_lsa_originate_area (lsa, oa);
508e53e2 203
204 /* Reset setting for consecutive origination */
205 memset ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa),
206 0, (caddr_t) lsdesc - (caddr_t) router_lsa);
207 lsdesc = (struct ospf6_router_lsdesc *)
208 ((caddr_t) router_lsa + sizeof (struct ospf6_router_lsa));
209 link_state_id ++;
210 }
211
212 /* Point-to-Point interfaces */
213 if (if_is_pointopoint (oi->interface))
214 {
1eb8ef25 215 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
508e53e2 216 {
508e53e2 217 if (on->state != OSPF6_NEIGHBOR_FULL)
218 continue;
219
220 lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT;
221 lsdesc->metric = htons (oi->cost);
222 lsdesc->interface_id = htonl (oi->interface->ifindex);
223 lsdesc->neighbor_interface_id = htonl (on->ifindex);
224 lsdesc->neighbor_router_id = on->router_id;
225
226 lsdesc++;
227 }
228 }
229
230 /* Broadcast and NBMA interfaces */
231 if (if_is_broadcast (oi->interface))
232 {
233 /* If this router is not DR,
234 and If this router not fully adjacent with DR,
235 this interface is not transit yet: ignore. */
236 if (oi->state != OSPF6_INTERFACE_DR)
237 {
238 drouter = ospf6_neighbor_lookup (oi->drouter, oi);
239 if (drouter == NULL || drouter->state != OSPF6_NEIGHBOR_FULL)
240 continue;
241 }
242
243 lsdesc->type = OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK;
244 lsdesc->metric = htons (oi->cost);
245 lsdesc->interface_id = htonl (oi->interface->ifindex);
246 if (oi->state != OSPF6_INTERFACE_DR)
247 {
248 lsdesc->neighbor_interface_id = htonl (drouter->ifindex);
249 lsdesc->neighbor_router_id = drouter->router_id;
250 }
251 else
252 {
253 lsdesc->neighbor_interface_id = htonl (oi->interface->ifindex);
254 lsdesc->neighbor_router_id = oi->area->ospf6->router_id;
255 }
256
257 lsdesc++;
258 }
259
260 /* Virtual links */
261 /* xxx */
262 /* Point-to-Multipoint interfaces */
263 /* xxx */
718e3744 264 }
265
508e53e2 266 if ((caddr_t) lsdesc != (caddr_t) router_lsa +
267 sizeof (struct ospf6_router_lsa))
268 {
269 /* Fill LSA Header */
270 lsa_header->age = 0;
271 lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
272 lsa_header->id = htonl (link_state_id);
273 lsa_header->adv_router = oa->ospf6->router_id;
274 lsa_header->seqnum =
049207c3 275 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
276 lsa_header->adv_router, oa->lsdb);
508e53e2 277 lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
278
279 /* LSA checksum */
280 ospf6_lsa_checksum (lsa_header);
281
282 /* create LSA */
283 lsa = ospf6_lsa_create (lsa_header);
508e53e2 284
285 /* Originate */
6452df09 286 ospf6_lsa_originate_area (lsa, oa);
508e53e2 287
288 link_state_id ++;
289 }
6452df09 290 else
291 {
1e05838a 292 if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
c6487d61 293 zlog_debug ("Nothing to describe in Router-LSA, suppress");
6452df09 294 }
718e3744 295
508e53e2 296 /* Do premature-aging of rest, undesired Router-LSAs */
297 type = ntohs (OSPF6_LSTYPE_ROUTER);
298 router = oa->ospf6->router_id;
299 for (lsa = ospf6_lsdb_type_router_head (type, router, oa->lsdb); lsa;
300 lsa = ospf6_lsdb_type_router_next (type, router, lsa))
718e3744 301 {
508e53e2 302 if (ntohl (lsa->header->id) < link_state_id)
303 continue;
6452df09 304 ospf6_lsa_purge (lsa);
718e3744 305 }
718e3744 306
508e53e2 307 return 0;
308}
718e3744 309
508e53e2 310/*******************************/
311/* RFC2740 3.4.3.2 Network-LSA */
312/*******************************/
718e3744 313
508e53e2 314int
315ospf6_network_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
316{
317 char *start, *end, *current;
318 struct ospf6_network_lsa *network_lsa;
319 struct ospf6_network_lsdesc *lsdesc;
320 char buf[128], options[32];
321
322 network_lsa = (struct ospf6_network_lsa *)
323 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
324
325 ospf6_options_printbuf (network_lsa->options, options, sizeof (options));
049207c3 326 vty_out (vty, " Options: %s%s", options, VNL);
718e3744 327
508e53e2 328 start = (char *) network_lsa + sizeof (struct ospf6_network_lsa);
329 end = (char *) lsa->header + ntohs (lsa->header->length);
330 for (current = start; current + sizeof (struct ospf6_network_lsdesc) <= end;
331 current += sizeof (struct ospf6_network_lsdesc))
718e3744 332 {
508e53e2 333 lsdesc = (struct ospf6_network_lsdesc *) current;
334 inet_ntop (AF_INET, &lsdesc->router_id, buf, sizeof (buf));
049207c3 335 vty_out (vty, " Attached Router: %s%s", buf, VNL);
718e3744 336 }
337 return 0;
338}
339
6452df09 340int
341ospf6_network_lsa_originate (struct thread *thread)
718e3744 342{
6452df09 343 struct ospf6_interface *oi;
344
508e53e2 345 char buffer [OSPF6_MAX_LSASIZE];
346 struct ospf6_lsa_header *lsa_header;
718e3744 347
508e53e2 348 int count;
349 struct ospf6_lsa *old, *lsa;
350 struct ospf6_network_lsa *network_lsa;
351 struct ospf6_network_lsdesc *lsdesc;
352 struct ospf6_neighbor *on;
353 struct ospf6_link_lsa *link_lsa;
52dc7ee6 354 struct listnode *i;
508e53e2 355 u_int16_t type;
356
6452df09 357 oi = (struct ospf6_interface *) THREAD_ARG (thread);
358 oi->thread_network_lsa = NULL;
359
360 /* The interface must be enabled until here. A Network-LSA of a
361 disabled interface (but was once enabled) should be flushed
362 by ospf6_lsa_refresh (), and does not come here. */
363 assert (oi->area);
718e3744 364
508e53e2 365 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_NETWORK),
366 htonl (oi->interface->ifindex),
367 oi->area->ospf6->router_id, oi->area->lsdb);
718e3744 368
508e53e2 369 /* Do not originate Network-LSA if not DR */
370 if (oi->state != OSPF6_INTERFACE_DR)
718e3744 371 {
508e53e2 372 if (old)
6452df09 373 ospf6_lsa_purge (old);
374 return 0;
508e53e2 375 }
718e3744 376
1e05838a 377 if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK))
c6487d61 378 zlog_debug ("Originate Network-LSA for Interface %s", oi->interface->name);
718e3744 379
508e53e2 380 /* If none of neighbor is adjacent to us */
381 count = 0;
1eb8ef25 382
383 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
384 if (on->state == OSPF6_NEIGHBOR_FULL)
385 count++;
386
508e53e2 387 if (count == 0)
388 {
1e05838a 389 if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK))
c6487d61 390 zlog_debug ("Interface stub, ignore");
508e53e2 391 if (old)
6452df09 392 ospf6_lsa_purge (old);
393 return 0;
718e3744 394 }
718e3744 395
508e53e2 396 /* prepare buffer */
397 memset (buffer, 0, sizeof (buffer));
398 lsa_header = (struct ospf6_lsa_header *) buffer;
399 network_lsa = (struct ospf6_network_lsa *)
400 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
401
402 /* Collect the interface's Link-LSAs to describe
403 network's optional capabilities */
404 type = htons (OSPF6_LSTYPE_LINK);
405 for (lsa = ospf6_lsdb_type_head (type, oi->lsdb); lsa;
406 lsa = ospf6_lsdb_type_next (type, lsa))
407 {
408 link_lsa = (struct ospf6_link_lsa *)
409 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
410 network_lsa->options[0] |= link_lsa->options[0];
411 network_lsa->options[1] |= link_lsa->options[1];
412 network_lsa->options[2] |= link_lsa->options[2];
413 }
718e3744 414
508e53e2 415 lsdesc = (struct ospf6_network_lsdesc *)
416 ((caddr_t) network_lsa + sizeof (struct ospf6_network_lsa));
718e3744 417
508e53e2 418 /* set Link Description to the router itself */
419 lsdesc->router_id = oi->area->ospf6->router_id;
420 lsdesc++;
718e3744 421
508e53e2 422 /* Walk through the neighbors */
1eb8ef25 423 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
718e3744 424 {
508e53e2 425 if (on->state != OSPF6_NEIGHBOR_FULL)
718e3744 426 continue;
427
508e53e2 428 /* set this neighbor's Router-ID to LSA */
429 lsdesc->router_id = on->router_id;
430 lsdesc++;
431 }
718e3744 432
508e53e2 433 /* Fill LSA Header */
434 lsa_header->age = 0;
435 lsa_header->type = htons (OSPF6_LSTYPE_NETWORK);
436 lsa_header->id = htonl (oi->interface->ifindex);
437 lsa_header->adv_router = oi->area->ospf6->router_id;
438 lsa_header->seqnum =
049207c3 439 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
440 lsa_header->adv_router, oi->area->lsdb);
508e53e2 441 lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
442
443 /* LSA checksum */
444 ospf6_lsa_checksum (lsa_header);
445
446 /* create LSA */
447 lsa = ospf6_lsa_create (lsa_header);
508e53e2 448
449 /* Originate */
6452df09 450 ospf6_lsa_originate_area (lsa, oi->area);
508e53e2 451
452 return 0;
453}
718e3744 454
455
508e53e2 456/****************************/
457/* RFC2740 3.4.3.6 Link-LSA */
458/****************************/
459
718e3744 460int
508e53e2 461ospf6_link_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
718e3744 462{
508e53e2 463 char *start, *end, *current;
464 struct ospf6_link_lsa *link_lsa;
465 int prefixnum;
466 char buf[128], options[32];
718e3744 467 struct ospf6_prefix *prefix;
0c083ee9 468 const char *p, *mc, *la, *nu;
718e3744 469 struct in6_addr in6;
718e3744 470
508e53e2 471 link_lsa = (struct ospf6_link_lsa *)
472 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
718e3744 473
508e53e2 474 ospf6_options_printbuf (link_lsa->options, options, sizeof (options));
475 inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));
476 prefixnum = ntohl (link_lsa->prefix_num);
718e3744 477
508e53e2 478 vty_out (vty, " Priority: %d Options: %s%s",
049207c3 479 link_lsa->priority, options, VNL);
480 vty_out (vty, " LinkLocal Address: %s%s", buf, VNL);
481 vty_out (vty, " Number of Prefix: %d%s", prefixnum, VNL);
718e3744 482
508e53e2 483 start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
484 end = (char *) lsa->header + ntohs (lsa->header->length);
718e3744 485 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
486 {
487 prefix = (struct ospf6_prefix *) current;
508e53e2 488 if (prefix->prefix_length == 0 ||
489 current + OSPF6_PREFIX_SIZE (prefix) > end)
490 break;
491
492 p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ?
493 "P" : "--");
494 mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ?
495 "MC" : "--");
496 la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ?
497 "LA" : "--");
498 nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ?
499 "NU" : "--");
500 vty_out (vty, " Prefix Options: %s|%s|%s|%s%s",
049207c3 501 p, mc, la, nu, VNL);
508e53e2 502
503 memset (&in6, 0, sizeof (in6));
504 memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
505 OSPF6_PREFIX_SPACE (prefix->prefix_length));
718e3744 506 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
507 vty_out (vty, " Prefix: %s/%d%s",
049207c3 508 buf, prefix->prefix_length, VNL);
718e3744 509 }
510
511 return 0;
512}
513
6452df09 514int
515ospf6_link_lsa_originate (struct thread *thread)
718e3744 516{
6452df09 517 struct ospf6_interface *oi;
518
508e53e2 519 char buffer[OSPF6_MAX_LSASIZE];
520 struct ospf6_lsa_header *lsa_header;
521 struct ospf6_lsa *old, *lsa;
718e3744 522
508e53e2 523 struct ospf6_link_lsa *link_lsa;
524 struct ospf6_route *route;
525 struct ospf6_prefix *op;
718e3744 526
6452df09 527 oi = (struct ospf6_interface *) THREAD_ARG (thread);
528 oi->thread_link_lsa = NULL;
529
530 assert (oi->area);
718e3744 531
532 /* find previous LSA */
508e53e2 533 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_LINK),
534 htonl (oi->interface->ifindex),
535 oi->area->ospf6->router_id, oi->lsdb);
718e3744 536
508e53e2 537 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
718e3744 538 {
539 if (old)
6452df09 540 ospf6_lsa_purge (old);
541 return 0;
718e3744 542 }
543
1e05838a 544 if (IS_OSPF6_DEBUG_ORIGINATE (LINK))
c6487d61 545 zlog_debug ("Originate Link-LSA for Interface %s", oi->interface->name);
508e53e2 546
547 /* can't make Link-LSA if linklocal address not set */
548 if (oi->linklocal_addr == NULL)
718e3744 549 {
1e05838a 550 if (IS_OSPF6_DEBUG_ORIGINATE (LINK))
c6487d61 551 zlog_debug ("No Linklocal address on %s, defer originating",
508e53e2 552 oi->interface->name);
718e3744 553 if (old)
6452df09 554 ospf6_lsa_purge (old);
555 return 0;
718e3744 556 }
557
508e53e2 558 /* prepare buffer */
559 memset (buffer, 0, sizeof (buffer));
560 lsa_header = (struct ospf6_lsa_header *) buffer;
561 link_lsa = (struct ospf6_link_lsa *)
562 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
563
564 /* Fill Link-LSA */
565 link_lsa->priority = oi->priority;
566 memcpy (link_lsa->options, oi->area->options, 3);
567 memcpy (&link_lsa->linklocal_addr, oi->linklocal_addr,
568 sizeof (struct in6_addr));
569 link_lsa->prefix_num = htonl (oi->route_connected->count);
570
571 op = (struct ospf6_prefix *)
572 ((caddr_t) link_lsa + sizeof (struct ospf6_link_lsa));
573
574 /* connected prefix to advertise */
575 for (route = ospf6_route_head (oi->route_connected); route;
576 route = ospf6_route_next (route))
718e3744 577 {
508e53e2 578 op->prefix_length = route->prefix.prefixlen;
579 op->prefix_options = route->path.prefix_options;
580 op->prefix_metric = htons (0);
581 memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
582 OSPF6_PREFIX_SPACE (op->prefix_length));
583 op = OSPF6_PREFIX_NEXT (op);
584 }
718e3744 585
508e53e2 586 /* Fill LSA Header */
587 lsa_header->age = 0;
588 lsa_header->type = htons (OSPF6_LSTYPE_LINK);
589 lsa_header->id = htonl (oi->interface->ifindex);
590 lsa_header->adv_router = oi->area->ospf6->router_id;
591 lsa_header->seqnum =
049207c3 592 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
593 lsa_header->adv_router, oi->lsdb);
508e53e2 594 lsa_header->length = htons ((caddr_t) op - (caddr_t) buffer);
595
596 /* LSA checksum */
597 ospf6_lsa_checksum (lsa_header);
598
599 /* create LSA */
600 lsa = ospf6_lsa_create (lsa_header);
508e53e2 601
602 /* Originate */
6452df09 603 ospf6_lsa_originate_interface (lsa, oi);
718e3744 604
508e53e2 605 return 0;
606}
718e3744 607
718e3744 608
508e53e2 609/*****************************************/
610/* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
611/*****************************************/
718e3744 612
508e53e2 613int
614ospf6_intra_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
615{
616 char *start, *end, *current;
617 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
618 int prefixnum;
619 char buf[128];
620 struct ospf6_prefix *prefix;
621 char id[16], adv_router[16];
0c083ee9 622 const char *p, *mc, *la, *nu;
508e53e2 623 struct in6_addr in6;
718e3744 624
508e53e2 625 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
626 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
718e3744 627
508e53e2 628 prefixnum = ntohs (intra_prefix_lsa->prefix_num);
718e3744 629
049207c3 630 vty_out (vty, " Number of Prefix: %d%s", prefixnum, VNL);
718e3744 631
508e53e2 632 inet_ntop (AF_INET, &intra_prefix_lsa->ref_id, id, sizeof (id));
633 inet_ntop (AF_INET, &intra_prefix_lsa->ref_adv_router,
634 adv_router, sizeof (adv_router));
635 vty_out (vty, " Reference: %s Id: %s Adv: %s%s",
1e05838a 636 ospf6_lstype_name (intra_prefix_lsa->ref_type), id, adv_router,
049207c3 637 VNL);
718e3744 638
508e53e2 639 start = (char *) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa);
640 end = (char *) lsa->header + ntohs (lsa->header->length);
641 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
718e3744 642 {
508e53e2 643 prefix = (struct ospf6_prefix *) current;
644 if (prefix->prefix_length == 0 ||
645 current + OSPF6_PREFIX_SIZE (prefix) > end)
646 break;
647
648 p = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_P) ?
649 "P" : "--");
650 mc = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_MC) ?
651 "MC" : "--");
652 la = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_LA) ?
653 "LA" : "--");
654 nu = (CHECK_FLAG (prefix->prefix_options, OSPF6_PREFIX_OPTION_NU) ?
655 "NU" : "--");
656 vty_out (vty, " Prefix Options: %s|%s|%s|%s%s",
049207c3 657 p, mc, la, nu, VNL);
508e53e2 658
659 memset (&in6, 0, sizeof (in6));
660 memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
661 OSPF6_PREFIX_SPACE (prefix->prefix_length));
662 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
663 vty_out (vty, " Prefix: %s/%d%s",
049207c3 664 buf, prefix->prefix_length, VNL);
718e3744 665 }
718e3744 666
508e53e2 667 return 0;
718e3744 668}
669
6452df09 670int
671ospf6_intra_prefix_lsa_originate_stub (struct thread *thread)
718e3744 672{
6452df09 673 struct ospf6_area *oa;
674
508e53e2 675 char buffer[OSPF6_MAX_LSASIZE];
676 struct ospf6_lsa_header *lsa_header;
677 struct ospf6_lsa *old, *lsa;
678
679 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
680 struct ospf6_interface *oi;
681 struct ospf6_neighbor *on;
682 struct ospf6_route *route;
683 struct ospf6_prefix *op;
52dc7ee6 684 struct listnode *i, *j;
508e53e2 685 int full_count = 0;
686 unsigned short prefix_num = 0;
687 char buf[BUFSIZ];
688 struct ospf6_route_table *route_advertise;
718e3744 689
6452df09 690 oa = (struct ospf6_area *) THREAD_ARG (thread);
691 oa->thread_intra_prefix_lsa = NULL;
692
508e53e2 693 /* find previous LSA */
694 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
695 htonl (0), oa->ospf6->router_id, oa->lsdb);
718e3744 696
6452df09 697 if (! IS_AREA_ENABLED (oa))
718e3744 698 {
508e53e2 699 if (old)
6452df09 700 ospf6_lsa_purge (old);
701 return 0;
718e3744 702 }
718e3744 703
1e05838a 704 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 705 zlog_debug ("Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
508e53e2 706 oa->name);
707
708 /* prepare buffer */
709 memset (buffer, 0, sizeof (buffer));
710 lsa_header = (struct ospf6_lsa_header *) buffer;
711 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
712 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
713
714 /* Fill Intra-Area-Prefix-LSA */
715 intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_ROUTER);
716 intra_prefix_lsa->ref_id = htonl (0);
717 intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id;
718e3744 718
508e53e2 719 route_advertise = ospf6_route_table_create ();
718e3744 720
1eb8ef25 721 for (ALL_LIST_ELEMENTS_RO (oa->if_list, i, oi))
718e3744 722 {
508e53e2 723 if (oi->state == OSPF6_INTERFACE_DOWN)
718e3744 724 {
1e05838a 725 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 726 zlog_debug (" Interface %s is down, ignore", oi->interface->name);
718e3744 727 continue;
728 }
729
508e53e2 730 full_count = 0;
1eb8ef25 731
732 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
733 if (on->state == OSPF6_NEIGHBOR_FULL)
734 full_count++;
735
508e53e2 736 if (oi->state != OSPF6_INTERFACE_LOOPBACK &&
737 oi->state != OSPF6_INTERFACE_POINTTOPOINT &&
738 full_count != 0)
718e3744 739 {
1e05838a 740 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 741 zlog_debug (" Interface %s is not stub, ignore",
508e53e2 742 oi->interface->name);
718e3744 743 continue;
744 }
745
1e05838a 746 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 747 zlog_debug (" Interface %s:", oi->interface->name);
718e3744 748
508e53e2 749 /* connected prefix to advertise */
750 for (route = ospf6_route_head (oi->route_connected); route;
751 route = ospf6_route_best_next (route))
718e3744 752 {
1e05838a 753 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
508e53e2 754 {
755 prefix2str (&route->prefix, buf, sizeof (buf));
c6487d61 756 zlog_debug (" include %s", buf);
508e53e2 757 }
758 ospf6_route_add (ospf6_route_copy (route), route_advertise);
759 }
760 }
718e3744 761
508e53e2 762 if (route_advertise->count == 0)
763 {
764 if (old)
6452df09 765 ospf6_lsa_purge (old);
508e53e2 766 ospf6_route_table_delete (route_advertise);
6452df09 767 return 0;
508e53e2 768 }
718e3744 769
508e53e2 770 /* put prefixes to advertise */
771 prefix_num = 0;
772 op = (struct ospf6_prefix *)
773 ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa));
774 for (route = ospf6_route_head (route_advertise); route;
775 route = ospf6_route_best_next (route))
776 {
777 op->prefix_length = route->prefix.prefixlen;
778 op->prefix_options = route->path.prefix_options;
779 op->prefix_metric = htons (route->path.cost);
780 memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
781 OSPF6_PREFIX_SPACE (op->prefix_length));
782 op = OSPF6_PREFIX_NEXT (op);
783 prefix_num++;
784 }
718e3744 785
508e53e2 786 ospf6_route_table_delete (route_advertise);
718e3744 787
508e53e2 788 if (prefix_num == 0)
789 {
1e05838a 790 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 791 zlog_debug ("Quit to Advertise Intra-Prefix: no route to advertise");
6452df09 792 return 0;
508e53e2 793 }
718e3744 794
508e53e2 795 intra_prefix_lsa->prefix_num = htons (prefix_num);
796
797 /* Fill LSA Header */
798 lsa_header->age = 0;
799 lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
800 lsa_header->id = htonl (0);
801 lsa_header->adv_router = oa->ospf6->router_id;
802 lsa_header->seqnum =
049207c3 803 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
804 lsa_header->adv_router, oa->lsdb);
508e53e2 805 lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
806
807 /* LSA checksum */
808 ospf6_lsa_checksum (lsa_header);
809
810 /* create LSA */
811 lsa = ospf6_lsa_create (lsa_header);
508e53e2 812
813 /* Originate */
6452df09 814 ospf6_lsa_originate_area (lsa, oa);
815
816 return 0;
508e53e2 817}
718e3744 818
6452df09 819
820int
821ospf6_intra_prefix_lsa_originate_transit (struct thread *thread)
508e53e2 822{
6452df09 823 struct ospf6_interface *oi;
824
508e53e2 825 char buffer[OSPF6_MAX_LSASIZE];
826 struct ospf6_lsa_header *lsa_header;
827 struct ospf6_lsa *old, *lsa;
828
829 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
830 struct ospf6_neighbor *on;
831 struct ospf6_route *route;
832 struct ospf6_prefix *op;
52dc7ee6 833 struct listnode *i;
508e53e2 834 int full_count = 0;
835 unsigned short prefix_num = 0;
836 struct ospf6_route_table *route_advertise;
837 struct ospf6_link_lsa *link_lsa;
838 char *start, *end, *current;
839 u_int16_t type;
840 char buf[BUFSIZ];
718e3744 841
6452df09 842 oi = (struct ospf6_interface *) THREAD_ARG (thread);
843 oi->thread_intra_prefix_lsa = NULL;
844
845 assert (oi->area);
718e3744 846
508e53e2 847 /* find previous LSA */
848 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
849 htonl (oi->interface->ifindex),
850 oi->area->ospf6->router_id, oi->area->lsdb);
718e3744 851
508e53e2 852 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
718e3744 853 {
718e3744 854 if (old)
6452df09 855 ospf6_lsa_purge (old);
856 return 0;
718e3744 857 }
858
1e05838a 859 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 860 zlog_debug ("Originate Intra-Area-Prefix-LSA for interface %s's prefix",
508e53e2 861 oi->interface->name);
862
718e3744 863 /* prepare buffer */
864 memset (buffer, 0, sizeof (buffer));
508e53e2 865 lsa_header = (struct ospf6_lsa_header *) buffer;
866 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
867 ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
718e3744 868
508e53e2 869 /* Fill Intra-Area-Prefix-LSA */
870 intra_prefix_lsa->ref_type = htons (OSPF6_LSTYPE_NETWORK);
871 intra_prefix_lsa->ref_id = htonl (oi->interface->ifindex);
872 intra_prefix_lsa->ref_adv_router = oi->area->ospf6->router_id;
718e3744 873
508e53e2 874 if (oi->state != OSPF6_INTERFACE_DR)
718e3744 875 {
1e05838a 876 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 877 zlog_debug (" Interface is not DR");
508e53e2 878 if (old)
6452df09 879 ospf6_lsa_purge (old);
880 return 0;
508e53e2 881 }
882
883 full_count = 0;
1eb8ef25 884 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
885 if (on->state == OSPF6_NEIGHBOR_FULL)
886 full_count++;
887
508e53e2 888 if (full_count == 0)
889 {
1e05838a 890 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 891 zlog_debug (" Interface is stub");
508e53e2 892 if (old)
6452df09 893 ospf6_lsa_purge (old);
894 return 0;
508e53e2 895 }
896
897 /* connected prefix to advertise */
898 route_advertise = ospf6_route_table_create ();
899
900 type = ntohs (OSPF6_LSTYPE_LINK);
901 for (lsa = ospf6_lsdb_type_head (type, oi->lsdb); lsa;
902 lsa = ospf6_lsdb_type_next (type, lsa))
903 {
904 if (OSPF6_LSA_IS_MAXAGE (lsa))
905 continue;
718e3744 906
1e05838a 907 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 908 zlog_debug (" include prefix from %s", lsa->name);
718e3744 909
508e53e2 910 if (lsa->header->adv_router != oi->area->ospf6->router_id)
911 {
912 on = ospf6_neighbor_lookup (lsa->header->adv_router, oi);
913 if (on == NULL || on->state != OSPF6_NEIGHBOR_FULL)
914 {
1e05838a 915 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 916 zlog_debug (" Neighbor not found or not Full, ignore");
508e53e2 917 continue;
918 }
919 }
920
921 link_lsa = (struct ospf6_link_lsa *)
922 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
923
924 prefix_num = (unsigned short) ntohl (link_lsa->prefix_num);
925 start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
926 end = (char *) lsa->header + ntohs (lsa->header->length);
927 for (current = start; current < end && prefix_num;
928 current += OSPF6_PREFIX_SIZE (op))
929 {
930 op = (struct ospf6_prefix *) current;
931 if (op->prefix_length == 0 ||
932 current + OSPF6_PREFIX_SIZE (op) > end)
933 break;
934
935 route = ospf6_route_create ();
936
937 route->type = OSPF6_DEST_TYPE_NETWORK;
938 route->prefix.family = AF_INET6;
939 route->prefix.prefixlen = op->prefix_length;
940 memset (&route->prefix.u.prefix6, 0, sizeof (struct in6_addr));
941 memcpy (&route->prefix.u.prefix6, OSPF6_PREFIX_BODY (op),
942 OSPF6_PREFIX_SPACE (op->prefix_length));
943
944 route->path.origin.type = lsa->header->type;
945 route->path.origin.id = lsa->header->id;
946 route->path.origin.adv_router = lsa->header->adv_router;
947 route->path.options[0] = link_lsa->options[0];
948 route->path.options[1] = link_lsa->options[1];
949 route->path.options[2] = link_lsa->options[2];
950 route->path.prefix_options = op->prefix_options;
951 route->path.area_id = oi->area->area_id;
952 route->path.type = OSPF6_PATH_TYPE_INTRA;
953
1e05838a 954 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
508e53e2 955 {
956 prefix2str (&route->prefix, buf, sizeof (buf));
c6487d61 957 zlog_debug (" include %s", buf);
508e53e2 958 }
959
960 ospf6_route_add (route, route_advertise);
961 prefix_num--;
962 }
1e05838a 963 if (current != end && IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 964 zlog_debug ("Trailing garbage in %s", lsa->name);
718e3744 965 }
718e3744 966
508e53e2 967 op = (struct ospf6_prefix *)
968 ((caddr_t) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa));
969
970 prefix_num = 0;
971 for (route = ospf6_route_head (route_advertise); route;
972 route = ospf6_route_best_next (route))
718e3744 973 {
508e53e2 974 op->prefix_length = route->prefix.prefixlen;
975 op->prefix_options = route->path.prefix_options;
976 op->prefix_metric = htons (0);
977 memcpy (OSPF6_PREFIX_BODY (op), &route->prefix.u.prefix6,
978 OSPF6_PREFIX_SPACE (op->prefix_length));
979 op = OSPF6_PREFIX_NEXT (op);
980 prefix_num++;
718e3744 981 }
718e3744 982
508e53e2 983 ospf6_route_table_delete (route_advertise);
718e3744 984
508e53e2 985 if (prefix_num == 0)
718e3744 986 {
1e05838a 987 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
c6487d61 988 zlog_debug ("Quit to Advertise Intra-Prefix: no route to advertise");
6452df09 989 return 0;
718e3744 990 }
508e53e2 991
992 intra_prefix_lsa->prefix_num = htons (prefix_num);
993
994 /* Fill LSA Header */
995 lsa_header->age = 0;
996 lsa_header->type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
997 lsa_header->id = htonl (oi->interface->ifindex);
998 lsa_header->adv_router = oi->area->ospf6->router_id;
999 lsa_header->seqnum =
049207c3 1000 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
1001 lsa_header->adv_router, oi->area->lsdb);
508e53e2 1002 lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
1003
1004 /* LSA checksum */
1005 ospf6_lsa_checksum (lsa_header);
1006
1007 /* create LSA */
1008 lsa = ospf6_lsa_create (lsa_header);
508e53e2 1009
1010 /* Originate */
6452df09 1011 ospf6_lsa_originate_area (lsa, oi->area);
508e53e2 1012
1013 return 0;
1014}
1015
1016void
1017ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
1018{
1019 struct ospf6_area *oa;
1020 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1021 struct prefix ls_prefix;
1022 struct ospf6_route *route, *ls_entry;
1023 int i, prefix_num;
1024 struct ospf6_prefix *op;
1025 char *start, *current, *end;
1026 char buf[64];
1027
ccb59b11 1028 if (OSPF6_LSA_IS_MAXAGE (lsa))
1029 return;
1030
1e05838a 1031 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
c6487d61 1032 zlog_debug ("%s found", lsa->name);
508e53e2 1033
6452df09 1034 oa = OSPF6_AREA (lsa->lsdb->data);
1035
508e53e2 1036 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
1037 OSPF6_LSA_HEADER_END (lsa->header);
1038 if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_ROUTER))
1039 ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
1040 htonl (0), &ls_prefix);
1041 else if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_NETWORK))
1042 ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
1043 intra_prefix_lsa->ref_id, &ls_prefix);
718e3744 1044 else
1045 {
1e05838a 1046 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
c6487d61 1047 zlog_debug ("Unknown reference LS-type: %#hx",
1048 ntohs (intra_prefix_lsa->ref_type));
508e53e2 1049 return;
718e3744 1050 }
1051
508e53e2 1052 ls_entry = ospf6_route_lookup (&ls_prefix, oa->spf_table);
1053 if (ls_entry == NULL)
1054 {
1e05838a 1055 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
508e53e2 1056 {
1057 ospf6_linkstate_prefix2str (&ls_prefix, buf, sizeof (buf));
c6487d61 1058 zlog_debug ("LS entry does not exist: %s", buf);
508e53e2 1059 }
1060 return;
1061 }
1062
1063 prefix_num = ntohs (intra_prefix_lsa->prefix_num);
1064 start = (caddr_t) intra_prefix_lsa +
1065 sizeof (struct ospf6_intra_prefix_lsa);
1066 end = OSPF6_LSA_END (lsa->header);
1067 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
1068 {
1069 op = (struct ospf6_prefix *) current;
1070 if (prefix_num == 0)
1071 break;
1072 if (end < current + OSPF6_PREFIX_SIZE (op))
1073 break;
1074
1075 route = ospf6_route_create ();
ccb59b11 1076
1077 memset (&route->prefix, 0, sizeof (struct prefix));
508e53e2 1078 route->prefix.family = AF_INET6;
ccb59b11 1079 route->prefix.prefixlen = op->prefix_length;
1080 ospf6_prefix_in6_addr (&route->prefix.u.prefix6, op);
1081
508e53e2 1082 route->type = OSPF6_DEST_TYPE_NETWORK;
1083 route->path.origin.type = lsa->header->type;
1084 route->path.origin.id = lsa->header->id;
1085 route->path.origin.adv_router = lsa->header->adv_router;
1086 route->path.prefix_options = op->prefix_options;
1087 route->path.area_id = oa->area_id;
1088 route->path.type = OSPF6_PATH_TYPE_INTRA;
1089 route->path.metric_type = 1;
1090 route->path.cost = ls_entry->path.cost +
1091 ntohs (op->prefix_metric);
1092
1093 for (i = 0; ospf6_nexthop_is_set (&ls_entry->nexthop[i]) &&
1094 i < OSPF6_MULTI_PATH_LIMIT; i++)
1095 ospf6_nexthop_copy (&route->nexthop[i], &ls_entry->nexthop[i]);
1096
1e05838a 1097 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
508e53e2 1098 {
1099 prefix2str (&route->prefix, buf, sizeof (buf));
c6487d61 1100 zlog_debug (" add %s", buf);
508e53e2 1101 }
1102
1103 ospf6_route_add (route, oa->route_table);
1104 prefix_num--;
1105 }
1106
1e05838a 1107 if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
c6487d61 1108 zlog_debug ("Trailing garbage ignored");
718e3744 1109}
1110
1111void
508e53e2 1112ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa)
718e3744 1113{
508e53e2 1114 struct ospf6_area *oa;
1115 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1116 struct prefix prefix;
1117 struct ospf6_route *route;
1118 int prefix_num;
1119 struct ospf6_prefix *op;
1120 char *start, *current, *end;
1121 char buf[64];
1122
1e05838a 1123 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
c6487d61 1124 zlog_debug ("%s disappearing", lsa->name);
508e53e2 1125
6452df09 1126 oa = OSPF6_AREA (lsa->lsdb->data);
1127
508e53e2 1128 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
1129 OSPF6_LSA_HEADER_END (lsa->header);
1130
1131 prefix_num = ntohs (intra_prefix_lsa->prefix_num);
1132 start = (caddr_t) intra_prefix_lsa +
1133 sizeof (struct ospf6_intra_prefix_lsa);
1134 end = OSPF6_LSA_END (lsa->header);
1135 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
1136 {
1137 op = (struct ospf6_prefix *) current;
1138 if (prefix_num == 0)
1139 break;
1140 if (end < current + OSPF6_PREFIX_SIZE (op))
1141 break;
1142 prefix_num--;
1143
ccb59b11 1144 memset (&prefix, 0, sizeof (struct prefix));
508e53e2 1145 prefix.family = AF_INET6;
1146 prefix.prefixlen = op->prefix_length;
1147 ospf6_prefix_in6_addr (&prefix.u.prefix6, op);
1148
1149 route = ospf6_route_lookup (&prefix, oa->route_table);
1150 if (route == NULL)
1151 continue;
1152
1153 for (ospf6_route_lock (route);
1154 route && ospf6_route_is_prefix (&prefix, route);
1155 route = ospf6_route_next (route))
1156 {
1157 if (route->type != OSPF6_DEST_TYPE_NETWORK)
1158 continue;
1159 if (route->path.area_id != oa->area_id)
1160 continue;
1161 if (route->path.type != OSPF6_PATH_TYPE_INTRA)
1162 continue;
1163 if (route->path.origin.type != lsa->header->type ||
1164 route->path.origin.id != lsa->header->id ||
1165 route->path.origin.adv_router != lsa->header->adv_router)
1166 continue;
1167
1e05838a 1168 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
508e53e2 1169 {
1170 prefix2str (&route->prefix, buf, sizeof (buf));
c6487d61 1171 zlog_debug ("remove %s", buf);
508e53e2 1172 }
1173 ospf6_route_remove (route, oa->route_table);
1174 }
1175 }
1176
1e05838a 1177 if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
c6487d61 1178 zlog_debug ("Trailing garbage ignored");
718e3744 1179}
1180
1181void
508e53e2 1182ospf6_intra_route_calculation (struct ospf6_area *oa)
718e3744 1183{
508e53e2 1184 struct ospf6_route *route;
1185 u_int16_t type;
1186 struct ospf6_lsa *lsa;
1187 void (*hook_add) (struct ospf6_route *) = NULL;
1188 void (*hook_remove) (struct ospf6_route *) = NULL;
1189
1e05838a 1190 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
c6487d61 1191 zlog_debug ("Re-examin intra-routes for area %s", oa->name);
508e53e2 1192
1193 hook_add = oa->route_table->hook_add;
1194 hook_remove = oa->route_table->hook_remove;
1195 oa->route_table->hook_add = NULL;
1196 oa->route_table->hook_remove = NULL;
1197
1198 for (route = ospf6_route_head (oa->route_table); route;
1199 route = ospf6_route_next (route))
1200 route->flag = OSPF6_ROUTE_REMOVE;
1201
1202 type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
1203 for (lsa = ospf6_lsdb_type_head (type, oa->lsdb); lsa;
1204 lsa = ospf6_lsdb_type_next (type, lsa))
1205 ospf6_intra_prefix_lsa_add (lsa);
1206
1207 oa->route_table->hook_add = hook_add;
1208 oa->route_table->hook_remove = hook_remove;
1209
1210 for (route = ospf6_route_head (oa->route_table); route;
1211 route = ospf6_route_next (route))
1212 {
1213 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) &&
1214 CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD))
1215 {
1216 UNSET_FLAG (route->flag, OSPF6_ROUTE_REMOVE);
1217 UNSET_FLAG (route->flag, OSPF6_ROUTE_ADD);
1218 }
1219
1220 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE))
1221 ospf6_route_remove (route, oa->route_table);
1222 else if (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ||
1223 CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE))
1224 {
1225 if (hook_add)
1226 (*hook_add) (route);
1227 }
1228
1229 route->flag = 0;
1230 }
1231
1e05838a 1232 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
c6487d61 1233 zlog_debug ("Re-examin intra-routes for area %s: Done", oa->name);
718e3744 1234}
1235
1236void
6452df09 1237ospf6_intra_brouter_calculation (struct ospf6_area *oa)
718e3744 1238{
508e53e2 1239 struct ospf6_route *lsentry, *copy;
1240 void (*hook_add) (struct ospf6_route *) = NULL;
1241 void (*hook_remove) (struct ospf6_route *) = NULL;
ccb59b11 1242 char buf[16];
508e53e2 1243
6452df09 1244 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
c6487d61 1245 zlog_debug ("Border-router calculation for area %s", oa->name);
508e53e2 1246
6452df09 1247 hook_add = oa->ospf6->brouter_table->hook_add;
1248 hook_remove = oa->ospf6->brouter_table->hook_remove;
1249 oa->ospf6->brouter_table->hook_add = NULL;
1250 oa->ospf6->brouter_table->hook_remove = NULL;
508e53e2 1251
6452df09 1252 /* withdraw the previous router entries for the area */
1253 for (lsentry = ospf6_route_head (oa->ospf6->brouter_table); lsentry;
508e53e2 1254 lsentry = ospf6_route_next (lsentry))
1255 {
1256 if (lsentry->path.area_id != oa->area_id)
1257 continue;
1258 lsentry->flag = OSPF6_ROUTE_REMOVE;
1259 }
1260
1261 for (lsentry = ospf6_route_head (oa->spf_table); lsentry;
1262 lsentry = ospf6_route_next (lsentry))
1263 {
1264 if (lsentry->type != OSPF6_DEST_TYPE_LINKSTATE)
1265 continue;
1266 if (ospf6_linkstate_prefix_id (&lsentry->prefix) != htonl (0))
1267 continue;
6452df09 1268 if (! CHECK_FLAG (lsentry->path.router_bits, OSPF6_ROUTER_BIT_E) &&
1269 ! CHECK_FLAG (lsentry->path.router_bits, OSPF6_ROUTER_BIT_B))
508e53e2 1270 continue;
1271
1272 copy = ospf6_route_copy (lsentry);
1273 copy->type = OSPF6_DEST_TYPE_ROUTER;
ccb59b11 1274 copy->path.area_id = oa->area_id;
6452df09 1275 ospf6_route_add (copy, oa->ospf6->brouter_table);
ccb59b11 1276
1277 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
1278 {
1279 inet_ntop (AF_INET, &ADV_ROUTER_IN_PREFIX (&copy->prefix),
1280 buf, sizeof (buf));
c6487d61 1281 zlog_debug ("Re-install router entry %s", buf);
ccb59b11 1282 }
508e53e2 1283 }
1284
6452df09 1285 oa->ospf6->brouter_table->hook_add = hook_add;
1286 oa->ospf6->brouter_table->hook_remove = hook_remove;
508e53e2 1287
6452df09 1288 for (lsentry = ospf6_route_head (oa->ospf6->brouter_table); lsentry;
508e53e2 1289 lsentry = ospf6_route_next (lsentry))
1290 {
1291 if (lsentry->path.area_id != oa->area_id)
1292 continue;
1293
9428f2dc 1294 if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_WAS_REMOVED))
1295 continue;
1296
508e53e2 1297 if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_REMOVE) &&
1298 CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_ADD))
1299 {
1300 UNSET_FLAG (lsentry->flag, OSPF6_ROUTE_REMOVE);
1301 UNSET_FLAG (lsentry->flag, OSPF6_ROUTE_ADD);
1302 }
1303
1304 if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_REMOVE))
6452df09 1305 ospf6_route_remove (lsentry, oa->ospf6->brouter_table);
508e53e2 1306 else if (CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_ADD) ||
1307 CHECK_FLAG (lsentry->flag, OSPF6_ROUTE_CHANGE))
1308 {
ccb59b11 1309 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
1310 {
1311 inet_ntop (AF_INET, &ADV_ROUTER_IN_PREFIX (&lsentry->prefix),
1312 buf, sizeof (buf));
c6487d61 1313 zlog_debug ("Call hook for router entry %s", buf);
ccb59b11 1314 }
508e53e2 1315 if (hook_add)
1316 (*hook_add) (lsentry);
1317 }
1318
1319 lsentry->flag = 0;
1320 }
1321
6452df09 1322 if (IS_OSPF6_DEBUG_ROUTE (INTRA))
c6487d61 1323 zlog_debug ("Border-router calculation for area %s: Done", oa->name);
718e3744 1324}
1325
6452df09 1326struct ospf6_lsa_handler router_handler =
1327{
1328 OSPF6_LSTYPE_ROUTER,
1329 "Router",
1330 ospf6_router_lsa_show
1331};
1332
1333struct ospf6_lsa_handler network_handler =
1334{
1335 OSPF6_LSTYPE_NETWORK,
1336 "Network",
1337 ospf6_network_lsa_show
1338};
1339
1340struct ospf6_lsa_handler link_handler =
1341{
1342 OSPF6_LSTYPE_LINK,
1343 "Link",
1344 ospf6_link_lsa_show
1345};
1346
1347struct ospf6_lsa_handler intra_prefix_handler =
1348{
1349 OSPF6_LSTYPE_INTRA_PREFIX,
1350 "Intra-Prefix",
1351 ospf6_intra_prefix_lsa_show
1352};
1353
718e3744 1354void
1355ospf6_intra_init ()
1356{
6452df09 1357 ospf6_install_lsa_handler (&router_handler);
1358 ospf6_install_lsa_handler (&network_handler);
1359 ospf6_install_lsa_handler (&link_handler);
1360 ospf6_install_lsa_handler (&intra_prefix_handler);
718e3744 1361}
1362
1363