source: src/router/quagga/ospf6d/ospf6_intra.c @ 18797

Last change on this file since 18797 was 18797, checked in by BrainSlayer, 14 months ago

update quagga

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