blob: c08a6ae640d9e96e869d93e8f60391aee27d5061 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
hasso508e53e2004-05-18 18:57:06 +00002 * Copyright (C) 2003 Yasuhiro Ohara
paul718e3742002-12-13 20:15:29 +00003 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
hasso508e53e2004-05-18 18:57:06 +000022#include <zebra.h>
23
24#include "log.h"
25#include "linklist.h"
26#include "thread.h"
27#include "memory.h"
28#include "if.h"
29#include "prefix.h"
30#include "table.h"
31#include "vty.h"
32#include "command.h"
33
hasso508e53e2004-05-18 18:57:06 +000034#include "ospf6_proto.h"
35#include "ospf6_message.h"
36#include "ospf6_route.h"
37#include "ospf6_lsa.h"
38#include "ospf6_lsdb.h"
paul718e3742002-12-13 20:15:29 +000039
hasso508e53e2004-05-18 18:57:06 +000040#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"
hasso6452df02004-08-15 05:52:07 +000046#include "ospf6_abr.h"
47#include "ospf6_flood.h"
hasso049207c2004-08-04 20:02:13 +000048#include "ospf6d.h"
paul718e3742002-12-13 20:15:29 +000049
Paul Jakmacb4b8842006-05-15 10:39:30 +000050
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
hasso508e53e2004-05-18 18:57:06 +000055/******************************/
56/* RFC2740 3.4.3.1 Router-LSA */
57/******************************/
paul718e3742002-12-13 20:15:29 +000058
Paul Jakma6ac29a52008-08-15 13:45:30 +010059static int
hasso508e53e2004-05-18 18:57:06 +000060ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +000061{
hasso508e53e2004-05-18 18:57:06 +000062 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;
paul718e3742002-12-13 20:15:29 +000066
hasso508e53e2004-05-18 18:57:06 +000067 router_lsa = (struct ospf6_router_lsa *)
68 ((char *) lsa->header + sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +000069
hasso508e53e2004-05-18 18:57:06 +000070 ospf6_capability_printbuf (router_lsa->bits, bits, sizeof (bits));
71 ospf6_options_printbuf (router_lsa->options, options, sizeof (options));
hasso049207c2004-08-04 20:02:13 +000072 vty_out (vty, " Bits: %s Options: %s%s", bits, options, VNL);
paul718e3742002-12-13 20:15:29 +000073
hasso508e53e2004-05-18 18:57:06 +000074 start = (char *) router_lsa + sizeof (struct ospf6_router_lsa);
paul718e3742002-12-13 20:15:29 +000075 end = (char *) lsa->header + ntohs (lsa->header->length);
hasso508e53e2004-05-18 18:57:06 +000076 for (current = start; current + sizeof (struct ospf6_router_lsdesc) <= end;
77 current += sizeof (struct ospf6_router_lsdesc))
paul718e3742002-12-13 20:15:29 +000078 {
hasso508e53e2004-05-18 18:57:06 +000079 lsdesc = (struct ospf6_router_lsdesc *) current;
paul718e3742002-12-13 20:15:29 +000080
hasso508e53e2004-05-18 18:57:06 +000081 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");
paul718e3742002-12-13 20:15:29 +000089 else
hasso508e53e2004-05-18 18:57:06 +000090 snprintf (name, sizeof (name), "Unknown (%#x)", lsdesc->type);
paul718e3742002-12-13 20:15:29 +000091
hasso508e53e2004-05-18 18:57:06 +000092 vty_out (vty, " Type: %s Metric: %d%s",
hasso049207c2004-08-04 20:02:13 +000093 name, ntohs (lsdesc->metric), VNL);
hasso508e53e2004-05-18 18:57:06 +000094 vty_out (vty, " Interface ID: %s%s",
95 inet_ntop (AF_INET, &lsdesc->interface_id,
hasso049207c2004-08-04 20:02:13 +000096 buf, sizeof (buf)), VNL);
hasso508e53e2004-05-18 18:57:06 +000097 vty_out (vty, " Neighbor Interface ID: %s%s",
98 inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
hasso049207c2004-08-04 20:02:13 +000099 buf, sizeof (buf)), VNL);
hasso508e53e2004-05-18 18:57:06 +0000100 vty_out (vty, " Neighbor Router ID: %s%s",
101 inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
hasso049207c2004-08-04 20:02:13 +0000102 buf, sizeof (buf)), VNL);
paul718e3742002-12-13 20:15:29 +0000103 }
104 return 0;
105}
106
hasso6452df02004-08-15 05:52:07 +0000107int
108ospf6_router_lsa_originate (struct thread *thread)
paul718e3742002-12-13 20:15:29 +0000109{
hasso6452df02004-08-15 05:52:07 +0000110 struct ospf6_area *oa;
111
hasso508e53e2004-05-18 18:57:06 +0000112 char buffer [OSPF6_MAX_LSASIZE];
113 struct ospf6_lsa_header *lsa_header;
114 struct ospf6_lsa *lsa;
paul718e3742002-12-13 20:15:29 +0000115
hasso508e53e2004-05-18 18:57:06 +0000116 u_int32_t link_state_id = 0;
paul1eb8ef22005-04-07 07:30:20 +0000117 struct listnode *node, *nnode;
118 struct listnode *j;
hasso508e53e2004-05-18 18:57:06 +0000119 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;
paul718e3742002-12-13 20:15:29 +0000126
hasso6452df02004-08-15 05:52:07 +0000127 oa = (struct ospf6_area *) THREAD_ARG (thread);
128 oa->thread_router_lsa = NULL;
129
hasso1e058382004-09-01 21:36:14 +0000130 if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
hassoc6487d62004-12-24 06:00:11 +0000131 zlog_debug ("Originate Router-LSA for Area %s", oa->name);
paul718e3742002-12-13 20:15:29 +0000132
hasso508e53e2004-05-18 18:57:06 +0000133 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
hasso6452df02004-08-15 05:52:07 +0000145 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);
hasso508e53e2004-05-18 18:57:06 +0000149 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
paul1eb8ef22005-04-07 07:30:20 +0000160 for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
paul718e3742002-12-13 20:15:29 +0000161 {
hasso508e53e2004-05-18 18:57:06 +0000162 /* Interfaces in state Down or Loopback are not described */
163 if (oi->state == OSPF6_INTERFACE_DOWN ||
164 oi->state == OSPF6_INTERFACE_LOOPBACK)
paul718e3742002-12-13 20:15:29 +0000165 continue;
166
hasso508e53e2004-05-18 18:57:06 +0000167 /* Nor are interfaces without any full adjacencies described */
168 count = 0;
paul1eb8ef22005-04-07 07:30:20 +0000169 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
170 if (on->state == OSPF6_NEIGHBOR_FULL)
171 count++;
172
hasso508e53e2004-05-18 18:57:06 +0000173 if (count == 0)
174 continue;
175
176 /* Multiple Router-LSA instance according to size limit setting */
paul0c083ee2004-10-10 12:54:58 +0000177 if ( (oa->router_lsa_size_limit != 0)
178 && ((caddr_t) lsdesc + sizeof (struct ospf6_router_lsdesc) -
gdt1686f932004-12-09 14:47:09 +0000179 /* XXX warning: comparison between signed and unsigned */
paul0c083ee2004-10-10 12:54:58 +0000180 (caddr_t) buffer > oa->router_lsa_size_limit))
hasso508e53e2004-05-18 18:57:06 +0000181 {
182 if ((caddr_t) lsdesc == (caddr_t) router_lsa +
183 sizeof (struct ospf6_router_lsa))
184 {
hasso1e058382004-09-01 21:36:14 +0000185 if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
hassoc6487d62004-12-24 06:00:11 +0000186 zlog_debug ("Size limit setting for Router-LSA too short");
hasso6452df02004-08-15 05:52:07 +0000187 return 0;
hasso508e53e2004-05-18 18:57:06 +0000188 }
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 =
hasso049207c2004-08-04 20:02:13 +0000196 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
197 lsa_header->adv_router, oa->lsdb);
hasso508e53e2004-05-18 18:57:06 +0000198 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);
hasso508e53e2004-05-18 18:57:06 +0000205
206 /* Originate */
hasso6452df02004-08-15 05:52:07 +0000207 ospf6_lsa_originate_area (lsa, oa);
hasso508e53e2004-05-18 18:57:06 +0000208
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 ++;
paul718e3742002-12-13 20:15:29 +0000215 }
216
hasso508e53e2004-05-18 18:57:06 +0000217 /* Point-to-Point interfaces */
Dinesh Duttc5926a92013-08-24 07:55:00 +0000218 if (oi->type == OSPF_IFTYPE_POINTOPOINT)
hasso508e53e2004-05-18 18:57:06 +0000219 {
paul1eb8ef22005-04-07 07:30:20 +0000220 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
hasso508e53e2004-05-18 18:57:06 +0000221 {
hasso508e53e2004-05-18 18:57:06 +0000222 if (on->state != OSPF6_NEIGHBOR_FULL)
223 continue;
paul718e3742002-12-13 20:15:29 +0000224
hasso508e53e2004-05-18 18:57:06 +0000225 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 */
Dinesh Duttc5926a92013-08-24 07:55:00 +0000236 else if (oi->type == OSPF_IFTYPE_BROADCAST)
hasso508e53e2004-05-18 18:57:06 +0000237 {
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 }
Dinesh Duttc5926a92013-08-24 07:55:00 +0000264 else
265 {
266 assert (0); /* Unknown interface type */
267 }
hasso508e53e2004-05-18 18:57:06 +0000268
269 /* Virtual links */
270 /* xxx */
271 /* Point-to-Multipoint interfaces */
272 /* xxx */
paul718e3742002-12-13 20:15:29 +0000273 }
hasso508e53e2004-05-18 18:57:06 +0000274
Dinesh Dutt17d003d2013-08-24 07:55:43 +0000275 /* Fill LSA Header */
276 lsa_header->age = 0;
277 lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
278 lsa_header->id = htonl (link_state_id);
279 lsa_header->adv_router = oa->ospf6->router_id;
280 lsa_header->seqnum =
281 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
282 lsa_header->adv_router, oa->lsdb);
283 lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
hasso508e53e2004-05-18 18:57:06 +0000284
Dinesh Dutt17d003d2013-08-24 07:55:43 +0000285 /* LSA checksum */
286 ospf6_lsa_checksum (lsa_header);
hasso508e53e2004-05-18 18:57:06 +0000287
Dinesh Dutt17d003d2013-08-24 07:55:43 +0000288 /* create LSA */
289 lsa = ospf6_lsa_create (lsa_header);
hasso508e53e2004-05-18 18:57:06 +0000290
Dinesh Dutt17d003d2013-08-24 07:55:43 +0000291 /* Originate */
292 ospf6_lsa_originate_area (lsa, oa);
hasso508e53e2004-05-18 18:57:06 +0000293
Dinesh Dutt17d003d2013-08-24 07:55:43 +0000294 link_state_id ++;
hasso508e53e2004-05-18 18:57:06 +0000295
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))
301 {
302 if (ntohl (lsa->header->id) < link_state_id)
303 continue;
hasso6452df02004-08-15 05:52:07 +0000304 ospf6_lsa_purge (lsa);
hasso508e53e2004-05-18 18:57:06 +0000305 }
hasso508e53e2004-05-18 18:57:06 +0000306
307 return 0;
308}
309
hasso508e53e2004-05-18 18:57:06 +0000310/*******************************/
311/* RFC2740 3.4.3.2 Network-LSA */
312/*******************************/
313
Paul Jakma6ac29a52008-08-15 13:45:30 +0100314static int
hasso508e53e2004-05-18 18:57:06 +0000315ospf6_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));
hasso049207c2004-08-04 20:02:13 +0000326 vty_out (vty, " Options: %s%s", options, VNL);
hasso508e53e2004-05-18 18:57:06 +0000327
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))
332 {
333 lsdesc = (struct ospf6_network_lsdesc *) current;
334 inet_ntop (AF_INET, &lsdesc->router_id, buf, sizeof (buf));
hasso049207c2004-08-04 20:02:13 +0000335 vty_out (vty, " Attached Router: %s%s", buf, VNL);
hasso508e53e2004-05-18 18:57:06 +0000336 }
337 return 0;
paul718e3742002-12-13 20:15:29 +0000338}
339
hasso6452df02004-08-15 05:52:07 +0000340int
341ospf6_network_lsa_originate (struct thread *thread)
paul718e3742002-12-13 20:15:29 +0000342{
hasso6452df02004-08-15 05:52:07 +0000343 struct ospf6_interface *oi;
344
hasso508e53e2004-05-18 18:57:06 +0000345 char buffer [OSPF6_MAX_LSASIZE];
346 struct ospf6_lsa_header *lsa_header;
paul718e3742002-12-13 20:15:29 +0000347
hasso508e53e2004-05-18 18:57:06 +0000348 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;
hasso52dc7ee2004-09-23 19:18:23 +0000354 struct listnode *i;
hasso508e53e2004-05-18 18:57:06 +0000355 u_int16_t type;
356
hasso6452df02004-08-15 05:52:07 +0000357 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);
paul718e3742002-12-13 20:15:29 +0000364
hasso508e53e2004-05-18 18:57:06 +0000365 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_NETWORK),
366 htonl (oi->interface->ifindex),
367 oi->area->ospf6->router_id, oi->area->lsdb);
paul718e3742002-12-13 20:15:29 +0000368
hasso508e53e2004-05-18 18:57:06 +0000369 /* Do not originate Network-LSA if not DR */
370 if (oi->state != OSPF6_INTERFACE_DR)
paul718e3742002-12-13 20:15:29 +0000371 {
hasso508e53e2004-05-18 18:57:06 +0000372 if (old)
hasso6452df02004-08-15 05:52:07 +0000373 ospf6_lsa_purge (old);
374 return 0;
paul718e3742002-12-13 20:15:29 +0000375 }
hasso508e53e2004-05-18 18:57:06 +0000376
hasso1e058382004-09-01 21:36:14 +0000377 if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK))
hassoc6487d62004-12-24 06:00:11 +0000378 zlog_debug ("Originate Network-LSA for Interface %s", oi->interface->name);
hasso508e53e2004-05-18 18:57:06 +0000379
380 /* If none of neighbor is adjacent to us */
381 count = 0;
paul1eb8ef22005-04-07 07:30:20 +0000382
383 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
384 if (on->state == OSPF6_NEIGHBOR_FULL)
385 count++;
386
hasso508e53e2004-05-18 18:57:06 +0000387 if (count == 0)
388 {
hasso1e058382004-09-01 21:36:14 +0000389 if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK))
hassoc6487d62004-12-24 06:00:11 +0000390 zlog_debug ("Interface stub, ignore");
hasso508e53e2004-05-18 18:57:06 +0000391 if (old)
hasso6452df02004-08-15 05:52:07 +0000392 ospf6_lsa_purge (old);
393 return 0;
hasso508e53e2004-05-18 18:57:06 +0000394 }
395
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 }
414
415 lsdesc = (struct ospf6_network_lsdesc *)
416 ((caddr_t) network_lsa + sizeof (struct ospf6_network_lsa));
417
418 /* set Link Description to the router itself */
419 lsdesc->router_id = oi->area->ospf6->router_id;
420 lsdesc++;
421
422 /* Walk through the neighbors */
paul1eb8ef22005-04-07 07:30:20 +0000423 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
hasso508e53e2004-05-18 18:57:06 +0000424 {
hasso508e53e2004-05-18 18:57:06 +0000425 if (on->state != OSPF6_NEIGHBOR_FULL)
426 continue;
427
428 /* set this neighbor's Router-ID to LSA */
429 lsdesc->router_id = on->router_id;
430 lsdesc++;
431 }
432
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 =
hasso049207c2004-08-04 20:02:13 +0000439 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
440 lsa_header->adv_router, oi->area->lsdb);
hasso508e53e2004-05-18 18:57:06 +0000441 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);
hasso508e53e2004-05-18 18:57:06 +0000448
449 /* Originate */
hasso6452df02004-08-15 05:52:07 +0000450 ospf6_lsa_originate_area (lsa, oi->area);
hasso508e53e2004-05-18 18:57:06 +0000451
452 return 0;
453}
454
455
456/****************************/
457/* RFC2740 3.4.3.6 Link-LSA */
458/****************************/
459
Paul Jakma6ac29a52008-08-15 13:45:30 +0100460static int
hasso508e53e2004-05-18 18:57:06 +0000461ospf6_link_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
462{
paul718e3742002-12-13 20:15:29 +0000463 char *start, *end, *current;
hasso508e53e2004-05-18 18:57:06 +0000464 struct ospf6_link_lsa *link_lsa;
465 int prefixnum;
466 char buf[128], options[32];
467 struct ospf6_prefix *prefix;
paul0c083ee2004-10-10 12:54:58 +0000468 const char *p, *mc, *la, *nu;
hasso508e53e2004-05-18 18:57:06 +0000469 struct in6_addr in6;
paul718e3742002-12-13 20:15:29 +0000470
hasso508e53e2004-05-18 18:57:06 +0000471 link_lsa = (struct ospf6_link_lsa *)
472 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +0000473
hasso508e53e2004-05-18 18:57:06 +0000474 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);
paul718e3742002-12-13 20:15:29 +0000477
hasso508e53e2004-05-18 18:57:06 +0000478 vty_out (vty, " Priority: %d Options: %s%s",
hasso049207c2004-08-04 20:02:13 +0000479 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);
paul718e3742002-12-13 20:15:29 +0000482
hasso508e53e2004-05-18 18:57:06 +0000483 start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
484 end = (char *) lsa->header + ntohs (lsa->header->length);
paul718e3742002-12-13 20:15:29 +0000485 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
486 {
487 prefix = (struct ospf6_prefix *) current;
hasso508e53e2004-05-18 18:57:06 +0000488 if (prefix->prefix_length == 0 ||
489 current + OSPF6_PREFIX_SIZE (prefix) > end)
490 break;
paul718e3742002-12-13 20:15:29 +0000491
hasso508e53e2004-05-18 18:57:06 +0000492 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",
hasso049207c2004-08-04 20:02:13 +0000501 p, mc, la, nu, VNL);
paul718e3742002-12-13 20:15:29 +0000502
hasso508e53e2004-05-18 18:57:06 +0000503 memset (&in6, 0, sizeof (in6));
504 memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
505 OSPF6_PREFIX_SPACE (prefix->prefix_length));
paul718e3742002-12-13 20:15:29 +0000506 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
507 vty_out (vty, " Prefix: %s/%d%s",
hasso049207c2004-08-04 20:02:13 +0000508 buf, prefix->prefix_length, VNL);
paul718e3742002-12-13 20:15:29 +0000509 }
510
511 return 0;
512}
513
hasso6452df02004-08-15 05:52:07 +0000514int
515ospf6_link_lsa_originate (struct thread *thread)
paul718e3742002-12-13 20:15:29 +0000516{
hasso6452df02004-08-15 05:52:07 +0000517 struct ospf6_interface *oi;
518
hasso508e53e2004-05-18 18:57:06 +0000519 char buffer[OSPF6_MAX_LSASIZE];
520 struct ospf6_lsa_header *lsa_header;
521 struct ospf6_lsa *old, *lsa;
paul718e3742002-12-13 20:15:29 +0000522
hasso508e53e2004-05-18 18:57:06 +0000523 struct ospf6_link_lsa *link_lsa;
524 struct ospf6_route *route;
525 struct ospf6_prefix *op;
paul718e3742002-12-13 20:15:29 +0000526
hasso6452df02004-08-15 05:52:07 +0000527 oi = (struct ospf6_interface *) THREAD_ARG (thread);
528 oi->thread_link_lsa = NULL;
529
530 assert (oi->area);
paul718e3742002-12-13 20:15:29 +0000531
532 /* find previous LSA */
hasso508e53e2004-05-18 18:57:06 +0000533 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_LINK),
534 htonl (oi->interface->ifindex),
535 oi->area->ospf6->router_id, oi->lsdb);
paul718e3742002-12-13 20:15:29 +0000536
hasso508e53e2004-05-18 18:57:06 +0000537 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
paul718e3742002-12-13 20:15:29 +0000538 {
539 if (old)
hasso6452df02004-08-15 05:52:07 +0000540 ospf6_lsa_purge (old);
541 return 0;
paul718e3742002-12-13 20:15:29 +0000542 }
543
hasso1e058382004-09-01 21:36:14 +0000544 if (IS_OSPF6_DEBUG_ORIGINATE (LINK))
hassoc6487d62004-12-24 06:00:11 +0000545 zlog_debug ("Originate Link-LSA for Interface %s", oi->interface->name);
paul718e3742002-12-13 20:15:29 +0000546
hasso508e53e2004-05-18 18:57:06 +0000547 /* can't make Link-LSA if linklocal address not set */
548 if (oi->linklocal_addr == NULL)
paul718e3742002-12-13 20:15:29 +0000549 {
hasso1e058382004-09-01 21:36:14 +0000550 if (IS_OSPF6_DEBUG_ORIGINATE (LINK))
hassoc6487d62004-12-24 06:00:11 +0000551 zlog_debug ("No Linklocal address on %s, defer originating",
hasso508e53e2004-05-18 18:57:06 +0000552 oi->interface->name);
553 if (old)
hasso6452df02004-08-15 05:52:07 +0000554 ospf6_lsa_purge (old);
555 return 0;
hasso508e53e2004-05-18 18:57:06 +0000556 }
557
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))
577 {
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 }
585
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 =
hasso049207c2004-08-04 20:02:13 +0000592 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
593 lsa_header->adv_router, oi->lsdb);
hasso508e53e2004-05-18 18:57:06 +0000594 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);
hasso508e53e2004-05-18 18:57:06 +0000601
602 /* Originate */
hasso6452df02004-08-15 05:52:07 +0000603 ospf6_lsa_originate_interface (lsa, oi);
hasso508e53e2004-05-18 18:57:06 +0000604
605 return 0;
606}
607
608
609/*****************************************/
610/* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
611/*****************************************/
612
Paul Jakma6ac29a52008-08-15 13:45:30 +0100613static int
hasso508e53e2004-05-18 18:57:06 +0000614ospf6_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];
paul0c083ee2004-10-10 12:54:58 +0000622 const char *p, *mc, *la, *nu;
hasso508e53e2004-05-18 18:57:06 +0000623 struct in6_addr in6;
624
625 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
626 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
627
628 prefixnum = ntohs (intra_prefix_lsa->prefix_num);
629
hasso049207c2004-08-04 20:02:13 +0000630 vty_out (vty, " Number of Prefix: %d%s", prefixnum, VNL);
hasso508e53e2004-05-18 18:57:06 +0000631
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",
hasso1e058382004-09-01 21:36:14 +0000636 ospf6_lstype_name (intra_prefix_lsa->ref_type), id, adv_router,
hasso049207c2004-08-04 20:02:13 +0000637 VNL);
hasso508e53e2004-05-18 18:57:06 +0000638
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))
642 {
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",
hasso049207c2004-08-04 20:02:13 +0000657 p, mc, la, nu, VNL);
hasso508e53e2004-05-18 18:57:06 +0000658
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",
hasso049207c2004-08-04 20:02:13 +0000664 buf, prefix->prefix_length, VNL);
hasso508e53e2004-05-18 18:57:06 +0000665 }
666
667 return 0;
668}
669
hasso6452df02004-08-15 05:52:07 +0000670int
671ospf6_intra_prefix_lsa_originate_stub (struct thread *thread)
hasso508e53e2004-05-18 18:57:06 +0000672{
hasso6452df02004-08-15 05:52:07 +0000673 struct ospf6_area *oa;
674
hasso508e53e2004-05-18 18:57:06 +0000675 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;
hasso52dc7ee2004-09-23 19:18:23 +0000684 struct listnode *i, *j;
hasso508e53e2004-05-18 18:57:06 +0000685 int full_count = 0;
686 unsigned short prefix_num = 0;
687 char buf[BUFSIZ];
688 struct ospf6_route_table *route_advertise;
689
hasso6452df02004-08-15 05:52:07 +0000690 oa = (struct ospf6_area *) THREAD_ARG (thread);
691 oa->thread_intra_prefix_lsa = NULL;
692
hasso508e53e2004-05-18 18:57:06 +0000693 /* find previous LSA */
694 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
695 htonl (0), oa->ospf6->router_id, oa->lsdb);
696
hasso6452df02004-08-15 05:52:07 +0000697 if (! IS_AREA_ENABLED (oa))
hasso508e53e2004-05-18 18:57:06 +0000698 {
699 if (old)
hasso6452df02004-08-15 05:52:07 +0000700 ospf6_lsa_purge (old);
701 return 0;
hasso508e53e2004-05-18 18:57:06 +0000702 }
703
hasso1e058382004-09-01 21:36:14 +0000704 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000705 zlog_debug ("Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
hasso508e53e2004-05-18 18:57:06 +0000706 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;
718
Paul Jakmacf1ce252006-05-15 10:46:07 +0000719 route_advertise = ospf6_route_table_create (0, 0);
hasso508e53e2004-05-18 18:57:06 +0000720
paul1eb8ef22005-04-07 07:30:20 +0000721 for (ALL_LIST_ELEMENTS_RO (oa->if_list, i, oi))
hasso508e53e2004-05-18 18:57:06 +0000722 {
hasso508e53e2004-05-18 18:57:06 +0000723 if (oi->state == OSPF6_INTERFACE_DOWN)
724 {
hasso1e058382004-09-01 21:36:14 +0000725 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000726 zlog_debug (" Interface %s is down, ignore", oi->interface->name);
hasso508e53e2004-05-18 18:57:06 +0000727 continue;
728 }
729
730 full_count = 0;
paul1eb8ef22005-04-07 07:30:20 +0000731
732 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
733 if (on->state == OSPF6_NEIGHBOR_FULL)
734 full_count++;
735
hasso508e53e2004-05-18 18:57:06 +0000736 if (oi->state != OSPF6_INTERFACE_LOOPBACK &&
737 oi->state != OSPF6_INTERFACE_POINTTOPOINT &&
738 full_count != 0)
739 {
hasso1e058382004-09-01 21:36:14 +0000740 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000741 zlog_debug (" Interface %s is not stub, ignore",
hasso508e53e2004-05-18 18:57:06 +0000742 oi->interface->name);
743 continue;
744 }
745
hasso1e058382004-09-01 21:36:14 +0000746 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000747 zlog_debug (" Interface %s:", oi->interface->name);
hasso508e53e2004-05-18 18:57:06 +0000748
749 /* connected prefix to advertise */
750 for (route = ospf6_route_head (oi->route_connected); route;
751 route = ospf6_route_best_next (route))
752 {
hasso1e058382004-09-01 21:36:14 +0000753 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hasso508e53e2004-05-18 18:57:06 +0000754 {
755 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000756 zlog_debug (" include %s", buf);
hasso508e53e2004-05-18 18:57:06 +0000757 }
758 ospf6_route_add (ospf6_route_copy (route), route_advertise);
759 }
760 }
761
762 if (route_advertise->count == 0)
763 {
764 if (old)
hasso6452df02004-08-15 05:52:07 +0000765 ospf6_lsa_purge (old);
hasso508e53e2004-05-18 18:57:06 +0000766 ospf6_route_table_delete (route_advertise);
hasso6452df02004-08-15 05:52:07 +0000767 return 0;
hasso508e53e2004-05-18 18:57:06 +0000768 }
769
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 }
785
786 ospf6_route_table_delete (route_advertise);
787
788 if (prefix_num == 0)
789 {
hasso1e058382004-09-01 21:36:14 +0000790 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000791 zlog_debug ("Quit to Advertise Intra-Prefix: no route to advertise");
hasso6452df02004-08-15 05:52:07 +0000792 return 0;
hasso508e53e2004-05-18 18:57:06 +0000793 }
794
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 =
hasso049207c2004-08-04 20:02:13 +0000803 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
804 lsa_header->adv_router, oa->lsdb);
hasso508e53e2004-05-18 18:57:06 +0000805 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);
hasso508e53e2004-05-18 18:57:06 +0000812
813 /* Originate */
hasso6452df02004-08-15 05:52:07 +0000814 ospf6_lsa_originate_area (lsa, oa);
815
816 return 0;
hasso508e53e2004-05-18 18:57:06 +0000817}
818
hasso6452df02004-08-15 05:52:07 +0000819
820int
821ospf6_intra_prefix_lsa_originate_transit (struct thread *thread)
hasso508e53e2004-05-18 18:57:06 +0000822{
hasso6452df02004-08-15 05:52:07 +0000823 struct ospf6_interface *oi;
824
hasso508e53e2004-05-18 18:57:06 +0000825 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;
hasso52dc7ee2004-09-23 19:18:23 +0000833 struct listnode *i;
hasso508e53e2004-05-18 18:57:06 +0000834 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];
841
hasso6452df02004-08-15 05:52:07 +0000842 oi = (struct ospf6_interface *) THREAD_ARG (thread);
843 oi->thread_intra_prefix_lsa = NULL;
844
845 assert (oi->area);
hasso508e53e2004-05-18 18:57:06 +0000846
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);
851
852 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
853 {
854 if (old)
hasso6452df02004-08-15 05:52:07 +0000855 ospf6_lsa_purge (old);
856 return 0;
hasso508e53e2004-05-18 18:57:06 +0000857 }
858
hasso1e058382004-09-01 21:36:14 +0000859 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000860 zlog_debug ("Originate Intra-Area-Prefix-LSA for interface %s's prefix",
hasso508e53e2004-05-18 18:57:06 +0000861 oi->interface->name);
862
863 /* prepare buffer */
864 memset (buffer, 0, sizeof (buffer));
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));
868
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;
873
874 if (oi->state != OSPF6_INTERFACE_DR)
875 {
hasso1e058382004-09-01 21:36:14 +0000876 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000877 zlog_debug (" Interface is not DR");
hasso508e53e2004-05-18 18:57:06 +0000878 if (old)
hasso6452df02004-08-15 05:52:07 +0000879 ospf6_lsa_purge (old);
880 return 0;
hasso508e53e2004-05-18 18:57:06 +0000881 }
882
883 full_count = 0;
paul1eb8ef22005-04-07 07:30:20 +0000884 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
885 if (on->state == OSPF6_NEIGHBOR_FULL)
886 full_count++;
887
hasso508e53e2004-05-18 18:57:06 +0000888 if (full_count == 0)
889 {
hasso1e058382004-09-01 21:36:14 +0000890 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000891 zlog_debug (" Interface is stub");
hasso508e53e2004-05-18 18:57:06 +0000892 if (old)
hasso6452df02004-08-15 05:52:07 +0000893 ospf6_lsa_purge (old);
894 return 0;
hasso508e53e2004-05-18 18:57:06 +0000895 }
896
897 /* connected prefix to advertise */
Paul Jakmacf1ce252006-05-15 10:46:07 +0000898 route_advertise = ospf6_route_table_create (0, 0);
hasso508e53e2004-05-18 18:57:06 +0000899
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))
paul718e3742002-12-13 20:15:29 +0000905 continue;
906
hasso1e058382004-09-01 21:36:14 +0000907 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000908 zlog_debug (" include prefix from %s", lsa->name);
paul718e3742002-12-13 20:15:29 +0000909
hasso508e53e2004-05-18 18:57:06 +0000910 if (lsa->header->adv_router != oi->area->ospf6->router_id)
paul718e3742002-12-13 20:15:29 +0000911 {
hasso508e53e2004-05-18 18:57:06 +0000912 on = ospf6_neighbor_lookup (lsa->header->adv_router, oi);
913 if (on == NULL || on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000914 {
hasso1e058382004-09-01 21:36:14 +0000915 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000916 zlog_debug (" Neighbor not found or not Full, ignore");
paul718e3742002-12-13 20:15:29 +0000917 continue;
918 }
919 }
920
hasso508e53e2004-05-18 18:57:06 +0000921 link_lsa = (struct ospf6_link_lsa *)
922 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +0000923
hasso508e53e2004-05-18 18:57:06 +0000924 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))
paul718e3742002-12-13 20:15:29 +0000929 {
hasso508e53e2004-05-18 18:57:06 +0000930 op = (struct ospf6_prefix *) current;
931 if (op->prefix_length == 0 ||
932 current + OSPF6_PREFIX_SIZE (op) > end)
933 break;
paul718e3742002-12-13 20:15:29 +0000934
hasso508e53e2004-05-18 18:57:06 +0000935 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
hasso1e058382004-09-01 21:36:14 +0000954 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
paul718e3742002-12-13 20:15:29 +0000955 {
hasso508e53e2004-05-18 18:57:06 +0000956 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000957 zlog_debug (" include %s", buf);
paul718e3742002-12-13 20:15:29 +0000958 }
959
hasso508e53e2004-05-18 18:57:06 +0000960 ospf6_route_add (route, route_advertise);
961 prefix_num--;
paul718e3742002-12-13 20:15:29 +0000962 }
hasso1e058382004-09-01 21:36:14 +0000963 if (current != end && IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000964 zlog_debug ("Trailing garbage in %s", lsa->name);
paul718e3742002-12-13 20:15:29 +0000965 }
966
hasso508e53e2004-05-18 18:57:06 +0000967 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))
paul718e3742002-12-13 20:15:29 +0000973 {
hasso508e53e2004-05-18 18:57:06 +0000974 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++;
981 }
982
983 ospf6_route_table_delete (route_advertise);
984
985 if (prefix_num == 0)
986 {
hasso1e058382004-09-01 21:36:14 +0000987 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000988 zlog_debug ("Quit to Advertise Intra-Prefix: no route to advertise");
hasso6452df02004-08-15 05:52:07 +0000989 return 0;
paul718e3742002-12-13 20:15:29 +0000990 }
991
hasso508e53e2004-05-18 18:57:06 +0000992 intra_prefix_lsa->prefix_num = htons (prefix_num);
paul718e3742002-12-13 20:15:29 +0000993
hasso508e53e2004-05-18 18:57:06 +0000994 /* 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 =
hasso049207c2004-08-04 20:02:13 +00001000 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
1001 lsa_header->adv_router, oi->area->lsdb);
hasso508e53e2004-05-18 18:57:06 +00001002 lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
paul718e3742002-12-13 20:15:29 +00001003
hasso508e53e2004-05-18 18:57:06 +00001004 /* LSA checksum */
1005 ospf6_lsa_checksum (lsa_header);
paul718e3742002-12-13 20:15:29 +00001006
hasso508e53e2004-05-18 18:57:06 +00001007 /* create LSA */
1008 lsa = ospf6_lsa_create (lsa_header);
paul718e3742002-12-13 20:15:29 +00001009
hasso508e53e2004-05-18 18:57:06 +00001010 /* Originate */
hasso6452df02004-08-15 05:52:07 +00001011 ospf6_lsa_originate_area (lsa, oi->area);
paul718e3742002-12-13 20:15:29 +00001012
1013 return 0;
1014}
1015
1016void
hasso508e53e2004-05-18 18:57:06 +00001017ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00001018{
hasso508e53e2004-05-18 18:57:06 +00001019 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];
Dinesh Duttb81e97a2013-08-24 07:55:50 +00001027 struct interface *ifp;
1028 int direct_connect = 0;
paul718e3742002-12-13 20:15:29 +00001029
hassoccb59b12004-08-25 09:10:37 +00001030 if (OSPF6_LSA_IS_MAXAGE (lsa))
1031 return;
1032
hasso1e058382004-09-01 21:36:14 +00001033 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +00001034 zlog_debug ("%s found", lsa->name);
paul718e3742002-12-13 20:15:29 +00001035
hasso6452df02004-08-15 05:52:07 +00001036 oa = OSPF6_AREA (lsa->lsdb->data);
1037
hasso508e53e2004-05-18 18:57:06 +00001038 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
1039 OSPF6_LSA_HEADER_END (lsa->header);
1040 if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_ROUTER))
1041 ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
1042 htonl (0), &ls_prefix);
1043 else if (intra_prefix_lsa->ref_type == htons (OSPF6_LSTYPE_NETWORK))
1044 ospf6_linkstate_prefix (intra_prefix_lsa->ref_adv_router,
1045 intra_prefix_lsa->ref_id, &ls_prefix);
1046 else
1047 {
hasso1e058382004-09-01 21:36:14 +00001048 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +00001049 zlog_debug ("Unknown reference LS-type: %#hx",
1050 ntohs (intra_prefix_lsa->ref_type));
hasso508e53e2004-05-18 18:57:06 +00001051 return;
1052 }
paul718e3742002-12-13 20:15:29 +00001053
hasso508e53e2004-05-18 18:57:06 +00001054 ls_entry = ospf6_route_lookup (&ls_prefix, oa->spf_table);
1055 if (ls_entry == NULL)
1056 {
hasso1e058382004-09-01 21:36:14 +00001057 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hasso508e53e2004-05-18 18:57:06 +00001058 {
1059 ospf6_linkstate_prefix2str (&ls_prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +00001060 zlog_debug ("LS entry does not exist: %s", buf);
hasso508e53e2004-05-18 18:57:06 +00001061 }
1062 return;
1063 }
paul718e3742002-12-13 20:15:29 +00001064
Dinesh Duttb81e97a2013-08-24 07:55:50 +00001065 if (intra_prefix_lsa->ref_adv_router == oa->ospf6->router_id)
1066 {
1067 /* the intra-prefix are directly connected */
1068 direct_connect = 1;
1069 }
1070
hasso508e53e2004-05-18 18:57:06 +00001071 prefix_num = ntohs (intra_prefix_lsa->prefix_num);
1072 start = (caddr_t) intra_prefix_lsa +
1073 sizeof (struct ospf6_intra_prefix_lsa);
1074 end = OSPF6_LSA_END (lsa->header);
1075 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
1076 {
1077 op = (struct ospf6_prefix *) current;
1078 if (prefix_num == 0)
1079 break;
1080 if (end < current + OSPF6_PREFIX_SIZE (op))
1081 break;
1082
1083 route = ospf6_route_create ();
hassoccb59b12004-08-25 09:10:37 +00001084
1085 memset (&route->prefix, 0, sizeof (struct prefix));
hasso508e53e2004-05-18 18:57:06 +00001086 route->prefix.family = AF_INET6;
hassoccb59b12004-08-25 09:10:37 +00001087 route->prefix.prefixlen = op->prefix_length;
1088 ospf6_prefix_in6_addr (&route->prefix.u.prefix6, op);
1089
hasso508e53e2004-05-18 18:57:06 +00001090 route->type = OSPF6_DEST_TYPE_NETWORK;
1091 route->path.origin.type = lsa->header->type;
1092 route->path.origin.id = lsa->header->id;
1093 route->path.origin.adv_router = lsa->header->adv_router;
1094 route->path.prefix_options = op->prefix_options;
1095 route->path.area_id = oa->area_id;
1096 route->path.type = OSPF6_PATH_TYPE_INTRA;
1097 route->path.metric_type = 1;
1098 route->path.cost = ls_entry->path.cost +
1099 ntohs (op->prefix_metric);
1100
Dinesh Duttb81e97a2013-08-24 07:55:50 +00001101 if (direct_connect)
1102 {
1103 ifp = if_lookup_prefix(&route->prefix);
1104 if (ifp)
1105 route->nexthop[0].ifindex = ifp->ifindex;
1106 }
1107 else
1108 {
1109 for (i = 0; ospf6_nexthop_is_set (&ls_entry->nexthop[i]) &&
1110 i < OSPF6_MULTI_PATH_LIMIT; i++)
1111 ospf6_nexthop_copy (&route->nexthop[i], &ls_entry->nexthop[i]);
1112 }
hasso508e53e2004-05-18 18:57:06 +00001113
hasso1e058382004-09-01 21:36:14 +00001114 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hasso508e53e2004-05-18 18:57:06 +00001115 {
1116 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +00001117 zlog_debug (" add %s", buf);
hasso508e53e2004-05-18 18:57:06 +00001118 }
1119
1120 ospf6_route_add (route, oa->route_table);
1121 prefix_num--;
1122 }
1123
hasso1e058382004-09-01 21:36:14 +00001124 if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +00001125 zlog_debug ("Trailing garbage ignored");
paul718e3742002-12-13 20:15:29 +00001126}
1127
1128void
hasso508e53e2004-05-18 18:57:06 +00001129ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00001130{
hasso508e53e2004-05-18 18:57:06 +00001131 struct ospf6_area *oa;
1132 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1133 struct prefix prefix;
1134 struct ospf6_route *route;
1135 int prefix_num;
1136 struct ospf6_prefix *op;
1137 char *start, *current, *end;
1138 char buf[64];
1139
hasso1e058382004-09-01 21:36:14 +00001140 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +00001141 zlog_debug ("%s disappearing", lsa->name);
hasso508e53e2004-05-18 18:57:06 +00001142
hasso6452df02004-08-15 05:52:07 +00001143 oa = OSPF6_AREA (lsa->lsdb->data);
1144
hasso508e53e2004-05-18 18:57:06 +00001145 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
1146 OSPF6_LSA_HEADER_END (lsa->header);
1147
1148 prefix_num = ntohs (intra_prefix_lsa->prefix_num);
1149 start = (caddr_t) intra_prefix_lsa +
1150 sizeof (struct ospf6_intra_prefix_lsa);
1151 end = OSPF6_LSA_END (lsa->header);
1152 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (op))
1153 {
1154 op = (struct ospf6_prefix *) current;
1155 if (prefix_num == 0)
1156 break;
1157 if (end < current + OSPF6_PREFIX_SIZE (op))
1158 break;
1159 prefix_num--;
1160
hassoccb59b12004-08-25 09:10:37 +00001161 memset (&prefix, 0, sizeof (struct prefix));
hasso508e53e2004-05-18 18:57:06 +00001162 prefix.family = AF_INET6;
1163 prefix.prefixlen = op->prefix_length;
1164 ospf6_prefix_in6_addr (&prefix.u.prefix6, op);
1165
1166 route = ospf6_route_lookup (&prefix, oa->route_table);
1167 if (route == NULL)
1168 continue;
1169
1170 for (ospf6_route_lock (route);
1171 route && ospf6_route_is_prefix (&prefix, route);
1172 route = ospf6_route_next (route))
1173 {
1174 if (route->type != OSPF6_DEST_TYPE_NETWORK)
1175 continue;
1176 if (route->path.area_id != oa->area_id)
1177 continue;
1178 if (route->path.type != OSPF6_PATH_TYPE_INTRA)
1179 continue;
1180 if (route->path.origin.type != lsa->header->type ||
1181 route->path.origin.id != lsa->header->id ||
1182 route->path.origin.adv_router != lsa->header->adv_router)
1183 continue;
1184
hasso1e058382004-09-01 21:36:14 +00001185 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hasso508e53e2004-05-18 18:57:06 +00001186 {
1187 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +00001188 zlog_debug ("remove %s", buf);
hasso508e53e2004-05-18 18:57:06 +00001189 }
1190 ospf6_route_remove (route, oa->route_table);
1191 }
Tom Goffe7a6d802010-11-10 13:03:02 -08001192 if (route)
1193 ospf6_route_unlock (route);
hasso508e53e2004-05-18 18:57:06 +00001194 }
1195
hasso1e058382004-09-01 21:36:14 +00001196 if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +00001197 zlog_debug ("Trailing garbage ignored");
paul718e3742002-12-13 20:15:29 +00001198}
1199
1200void
hasso508e53e2004-05-18 18:57:06 +00001201ospf6_intra_route_calculation (struct ospf6_area *oa)
paul718e3742002-12-13 20:15:29 +00001202{
hasso508e53e2004-05-18 18:57:06 +00001203 struct ospf6_route *route;
1204 u_int16_t type;
1205 struct ospf6_lsa *lsa;
1206 void (*hook_add) (struct ospf6_route *) = NULL;
1207 void (*hook_remove) (struct ospf6_route *) = NULL;
1208
hasso1e058382004-09-01 21:36:14 +00001209 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +00001210 zlog_debug ("Re-examin intra-routes for area %s", oa->name);
hasso508e53e2004-05-18 18:57:06 +00001211
1212 hook_add = oa->route_table->hook_add;
1213 hook_remove = oa->route_table->hook_remove;
1214 oa->route_table->hook_add = NULL;
1215 oa->route_table->hook_remove = NULL;
1216
1217 for (route = ospf6_route_head (oa->route_table); route;
1218 route = ospf6_route_next (route))
1219 route->flag = OSPF6_ROUTE_REMOVE;
1220
1221 type = htons (OSPF6_LSTYPE_INTRA_PREFIX);
1222 for (lsa = ospf6_lsdb_type_head (type, oa->lsdb); lsa;
1223 lsa = ospf6_lsdb_type_next (type, lsa))
1224 ospf6_intra_prefix_lsa_add (lsa);
1225
1226 oa->route_table->hook_add = hook_add;
1227 oa->route_table->hook_remove = hook_remove;
1228
1229 for (route = ospf6_route_head (oa->route_table); route;
1230 route = ospf6_route_next (route))
1231 {
1232 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE) &&
1233 CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD))
1234 {
1235 UNSET_FLAG (route->flag, OSPF6_ROUTE_REMOVE);
1236 UNSET_FLAG (route->flag, OSPF6_ROUTE_ADD);
1237 }
1238
1239 if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE))
1240 ospf6_route_remove (route, oa->route_table);
1241 else if (CHECK_FLAG (route->flag, OSPF6_ROUTE_ADD) ||
1242 CHECK_FLAG (route->flag, OSPF6_ROUTE_CHANGE))
1243 {
1244 if (hook_add)
1245 (*hook_add) (route);
1246 }
1247
1248 route->flag = 0;
1249 }
1250
hasso1e058382004-09-01 21:36:14 +00001251 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +00001252 zlog_debug ("Re-examin intra-routes for area %s: Done", oa->name);
hasso508e53e2004-05-18 18:57:06 +00001253}
1254
Paul Jakma6ac29a52008-08-15 13:45:30 +01001255static void
Paul Jakmacf1ce252006-05-15 10:46:07 +00001256ospf6_brouter_debug_print (struct ospf6_route *brouter)
1257{
1258 u_int32_t brouter_id;
1259 char brouter_name[16];
1260 char area_name[16];
1261 char destination[64];
1262 char installed[16], changed[16];
1263 struct timeval now, res;
1264 char id[16], adv_router[16];
1265 char capa[16], options[16];
1266
1267 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1268 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
1269 inet_ntop (AF_INET, &brouter->path.area_id, area_name, sizeof (area_name));
1270 ospf6_linkstate_prefix2str (&brouter->prefix, destination,
1271 sizeof (destination));
1272
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001273 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001274 timersub (&now, &brouter->installed, &res);
1275 timerstring (&res, installed, sizeof (installed));
1276
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001277 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001278 timersub (&now, &brouter->changed, &res);
1279 timerstring (&res, changed, sizeof (changed));
1280
1281 inet_ntop (AF_INET, &brouter->path.origin.id, id, sizeof (id));
1282 inet_ntop (AF_INET, &brouter->path.origin.adv_router, adv_router,
1283 sizeof (adv_router));
1284
1285 ospf6_options_printbuf (brouter->path.options, options, sizeof (options));
1286 ospf6_capability_printbuf (brouter->path.router_bits, capa, sizeof (capa));
1287
1288 zlog_info ("Brouter: %s via area %s", brouter_name, area_name);
1289 zlog_info (" memory: prev: %p this: %p next: %p parent rnode: %p",
1290 brouter->prev, brouter, brouter->next, brouter->rnode);
1291 zlog_info (" type: %d prefix: %s installed: %s changed: %s",
1292 brouter->type, destination, installed, changed);
1293 zlog_info (" lock: %d flags: %s%s%s%s", brouter->lock,
1294 (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
1295 (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
1296 (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
1297 (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"));
1298 zlog_info (" path type: %s ls-origin %s id: %s adv-router %s",
1299 OSPF6_PATH_TYPE_NAME (brouter->path.type),
1300 ospf6_lstype_name (brouter->path.origin.type),
1301 id, adv_router);
1302 zlog_info (" options: %s router-bits: %s metric-type: %d metric: %d/%d",
1303 options, capa, brouter->path.metric_type,
1304 brouter->path.cost, brouter->path.cost_e2);
1305}
1306
1307void
hasso6452df02004-08-15 05:52:07 +00001308ospf6_intra_brouter_calculation (struct ospf6_area *oa)
hasso508e53e2004-05-18 18:57:06 +00001309{
Paul Jakmacb4b8842006-05-15 10:39:30 +00001310 struct ospf6_route *brouter, *copy;
hasso508e53e2004-05-18 18:57:06 +00001311 void (*hook_add) (struct ospf6_route *) = NULL;
1312 void (*hook_remove) (struct ospf6_route *) = NULL;
Paul Jakmacb4b8842006-05-15 10:39:30 +00001313 u_int32_t brouter_id;
1314 char brouter_name[16];
1315
1316 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1317 zlog_info ("border-router calculation for area %s", oa->name);
1318
hasso6452df02004-08-15 05:52:07 +00001319 hook_add = oa->ospf6->brouter_table->hook_add;
1320 hook_remove = oa->ospf6->brouter_table->hook_remove;
1321 oa->ospf6->brouter_table->hook_add = NULL;
1322 oa->ospf6->brouter_table->hook_remove = NULL;
hasso508e53e2004-05-18 18:57:06 +00001323
hasso6452df02004-08-15 05:52:07 +00001324 /* withdraw the previous router entries for the area */
Paul Jakmacb4b8842006-05-15 10:39:30 +00001325 for (brouter = ospf6_route_head (oa->ospf6->brouter_table); brouter;
1326 brouter = ospf6_route_next (brouter))
hasso508e53e2004-05-18 18:57:06 +00001327 {
Paul Jakmacf1ce252006-05-15 10:46:07 +00001328 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1329 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
Paul Jakmacb4b8842006-05-15 10:39:30 +00001330 if (brouter->path.area_id != oa->area_id)
hasso508e53e2004-05-18 18:57:06 +00001331 continue;
Paul Jakmacb4b8842006-05-15 10:39:30 +00001332 brouter->flag = OSPF6_ROUTE_REMOVE;
Paul Jakmacf1ce252006-05-15 10:46:07 +00001333
1334 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1335 IS_OSPF6_DEBUG_ROUTE (MEMORY))
1336 {
1337 zlog_info ("%p: mark as removing: area %s brouter %s",
1338 brouter, oa->name, brouter_name);
1339 ospf6_brouter_debug_print (brouter);
1340 }
hasso508e53e2004-05-18 18:57:06 +00001341 }
1342
Paul Jakmacb4b8842006-05-15 10:39:30 +00001343 for (brouter = ospf6_route_head (oa->spf_table); brouter;
1344 brouter = ospf6_route_next (brouter))
hasso508e53e2004-05-18 18:57:06 +00001345 {
Paul Jakmacf1ce252006-05-15 10:46:07 +00001346 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1347 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
1348
Paul Jakmacb4b8842006-05-15 10:39:30 +00001349 if (brouter->type != OSPF6_DEST_TYPE_LINKSTATE)
hasso508e53e2004-05-18 18:57:06 +00001350 continue;
Paul Jakmacb4b8842006-05-15 10:39:30 +00001351 if (ospf6_linkstate_prefix_id (&brouter->prefix) != htonl (0))
hasso508e53e2004-05-18 18:57:06 +00001352 continue;
Paul Jakmacb4b8842006-05-15 10:39:30 +00001353 if (! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_E) &&
1354 ! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_B))
hasso508e53e2004-05-18 18:57:06 +00001355 continue;
1356
Paul Jakmacb4b8842006-05-15 10:39:30 +00001357 copy = ospf6_route_copy (brouter);
hasso508e53e2004-05-18 18:57:06 +00001358 copy->type = OSPF6_DEST_TYPE_ROUTER;
hassoccb59b12004-08-25 09:10:37 +00001359 copy->path.area_id = oa->area_id;
hasso6452df02004-08-15 05:52:07 +00001360 ospf6_route_add (copy, oa->ospf6->brouter_table);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001361
1362 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1363 IS_OSPF6_DEBUG_ROUTE (MEMORY))
1364 {
1365 zlog_info ("%p: transfer: area %s brouter %s",
1366 brouter, oa->name, brouter_name);
1367 ospf6_brouter_debug_print (brouter);
1368 }
hasso508e53e2004-05-18 18:57:06 +00001369 }
1370
hasso6452df02004-08-15 05:52:07 +00001371 oa->ospf6->brouter_table->hook_add = hook_add;
1372 oa->ospf6->brouter_table->hook_remove = hook_remove;
hasso508e53e2004-05-18 18:57:06 +00001373
Paul Jakmacb4b8842006-05-15 10:39:30 +00001374 for (brouter = ospf6_route_head (oa->ospf6->brouter_table); brouter;
1375 brouter = ospf6_route_next (brouter))
hasso508e53e2004-05-18 18:57:06 +00001376 {
Paul Jakmacb4b8842006-05-15 10:39:30 +00001377 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1378 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
1379
1380 if (brouter->path.area_id != oa->area_id)
hasso508e53e2004-05-18 18:57:06 +00001381 continue;
1382
Paul Jakmacb4b8842006-05-15 10:39:30 +00001383 if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_WAS_REMOVED))
hasso9428f2d2004-09-13 14:01:12 +00001384 continue;
1385
Paul Jakmacb4b8842006-05-15 10:39:30 +00001386 if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE) &&
1387 CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD))
hasso508e53e2004-05-18 18:57:06 +00001388 {
Paul Jakmacb4b8842006-05-15 10:39:30 +00001389 UNSET_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE);
1390 UNSET_FLAG (brouter->flag, OSPF6_ROUTE_ADD);
hasso508e53e2004-05-18 18:57:06 +00001391 }
1392
Paul Jakmacb4b8842006-05-15 10:39:30 +00001393 if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE))
hasso508e53e2004-05-18 18:57:06 +00001394 {
Paul Jakmacb4b8842006-05-15 10:39:30 +00001395 if (IS_OSPF6_DEBUG_BROUTER ||
1396 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1397 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1398 zlog_info ("brouter %s disappears via area %s",
1399 brouter_name, oa->name);
1400 ospf6_route_remove (brouter, oa->ospf6->brouter_table);
1401 }
1402 else if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD) ||
1403 CHECK_FLAG (brouter->flag, OSPF6_ROUTE_CHANGE))
1404 {
1405 if (IS_OSPF6_DEBUG_BROUTER ||
1406 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1407 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1408 zlog_info ("brouter %s appears via area %s",
1409 brouter_name, oa->name);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001410
Paul Jakmacb4b8842006-05-15 10:39:30 +00001411 /* newly added */
hasso508e53e2004-05-18 18:57:06 +00001412 if (hook_add)
Paul Jakmacb4b8842006-05-15 10:39:30 +00001413 (*hook_add) (brouter);
1414 }
1415 else
1416 {
1417 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID (brouter_id) ||
1418 IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1419 zlog_info ("brouter %s still exists via area %s",
1420 brouter_name, oa->name);
hasso508e53e2004-05-18 18:57:06 +00001421 }
1422
Paul Jakmacb4b8842006-05-15 10:39:30 +00001423 brouter->flag = 0;
hasso508e53e2004-05-18 18:57:06 +00001424 }
1425
Paul Jakmacb4b8842006-05-15 10:39:30 +00001426 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1427 zlog_info ("border-router calculation for area %s: done", oa->name);
paul718e3742002-12-13 20:15:29 +00001428}
1429
hasso6452df02004-08-15 05:52:07 +00001430struct ospf6_lsa_handler router_handler =
1431{
1432 OSPF6_LSTYPE_ROUTER,
1433 "Router",
1434 ospf6_router_lsa_show
1435};
1436
1437struct ospf6_lsa_handler network_handler =
1438{
1439 OSPF6_LSTYPE_NETWORK,
1440 "Network",
1441 ospf6_network_lsa_show
1442};
1443
1444struct ospf6_lsa_handler link_handler =
1445{
1446 OSPF6_LSTYPE_LINK,
1447 "Link",
1448 ospf6_link_lsa_show
1449};
1450
1451struct ospf6_lsa_handler intra_prefix_handler =
1452{
1453 OSPF6_LSTYPE_INTRA_PREFIX,
1454 "Intra-Prefix",
1455 ospf6_intra_prefix_lsa_show
1456};
1457
paul718e3742002-12-13 20:15:29 +00001458void
Paul Jakmacb4b8842006-05-15 10:39:30 +00001459ospf6_intra_init (void)
paul718e3742002-12-13 20:15:29 +00001460{
hasso6452df02004-08-15 05:52:07 +00001461 ospf6_install_lsa_handler (&router_handler);
1462 ospf6_install_lsa_handler (&network_handler);
1463 ospf6_install_lsa_handler (&link_handler);
1464 ospf6_install_lsa_handler (&intra_prefix_handler);
paul718e3742002-12-13 20:15:29 +00001465}
1466
Paul Jakmacb4b8842006-05-15 10:39:30 +00001467DEFUN (debug_ospf6_brouter,
1468 debug_ospf6_brouter_cmd,
1469 "debug ospf6 border-routers",
1470 DEBUG_STR
1471 OSPF6_STR
1472 "Debug border router\n"
1473 )
1474{
1475 OSPF6_DEBUG_BROUTER_ON ();
1476 return CMD_SUCCESS;
1477}
1478
1479DEFUN (no_debug_ospf6_brouter,
1480 no_debug_ospf6_brouter_cmd,
1481 "no debug ospf6 border-routers",
1482 NO_STR
1483 DEBUG_STR
1484 OSPF6_STR
1485 "Debug border router\n"
1486 )
1487{
1488 OSPF6_DEBUG_BROUTER_OFF ();
1489 return CMD_SUCCESS;
1490}
1491
1492DEFUN (debug_ospf6_brouter_router,
1493 debug_ospf6_brouter_router_cmd,
1494 "debug ospf6 border-routers router-id A.B.C.D",
1495 DEBUG_STR
1496 OSPF6_STR
1497 "Debug border router\n"
1498 "Debug specific border router\n"
1499 "Specify border-router's router-id\n"
1500 )
1501{
1502 u_int32_t router_id;
1503 inet_pton (AF_INET, argv[0], &router_id);
1504 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON (router_id);
1505 return CMD_SUCCESS;
1506}
1507
1508DEFUN (no_debug_ospf6_brouter_router,
1509 no_debug_ospf6_brouter_router_cmd,
1510 "no debug ospf6 border-routers router-id",
1511 NO_STR
1512 DEBUG_STR
1513 OSPF6_STR
1514 "Debug border router\n"
1515 "Debug specific border router\n"
1516 )
1517{
1518 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF ();
1519 return CMD_SUCCESS;
1520}
1521
1522DEFUN (debug_ospf6_brouter_area,
1523 debug_ospf6_brouter_area_cmd,
1524 "debug ospf6 border-routers area-id A.B.C.D",
1525 DEBUG_STR
1526 OSPF6_STR
1527 "Debug border router\n"
1528 "Debug border routers in specific Area\n"
1529 "Specify Area-ID\n"
1530 )
1531{
1532 u_int32_t area_id;
1533 inet_pton (AF_INET, argv[0], &area_id);
1534 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON (area_id);
1535 return CMD_SUCCESS;
1536}
1537
1538DEFUN (no_debug_ospf6_brouter_area,
1539 no_debug_ospf6_brouter_area_cmd,
1540 "no debug ospf6 border-routers area-id",
1541 NO_STR
1542 DEBUG_STR
1543 OSPF6_STR
1544 "Debug border router\n"
1545 "Debug border routers in specific Area\n"
1546 )
1547{
1548 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF ();
1549 return CMD_SUCCESS;
1550}
1551
1552int
1553config_write_ospf6_debug_brouter (struct vty *vty)
1554{
1555 char buf[16];
1556 if (IS_OSPF6_DEBUG_BROUTER)
1557 vty_out (vty, "debug ospf6 border-routers%s", VNL);
1558 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER)
1559 {
1560 inet_ntop (AF_INET, &conf_debug_ospf6_brouter_specific_router_id,
1561 buf, sizeof (buf));
1562 vty_out (vty, "debug ospf6 border-routers router-id %s%s", buf, VNL);
1563 }
1564 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA)
1565 {
1566 inet_ntop (AF_INET, &conf_debug_ospf6_brouter_specific_area_id,
1567 buf, sizeof (buf));
1568 vty_out (vty, "debug ospf6 border-routers area-id %s%s", buf, VNL);
1569 }
1570 return 0;
1571}
1572
1573void
1574install_element_ospf6_debug_brouter (void)
1575{
1576 install_element (ENABLE_NODE, &debug_ospf6_brouter_cmd);
1577 install_element (ENABLE_NODE, &debug_ospf6_brouter_router_cmd);
1578 install_element (ENABLE_NODE, &debug_ospf6_brouter_area_cmd);
1579 install_element (ENABLE_NODE, &no_debug_ospf6_brouter_cmd);
1580 install_element (ENABLE_NODE, &no_debug_ospf6_brouter_router_cmd);
1581 install_element (ENABLE_NODE, &no_debug_ospf6_brouter_area_cmd);
1582 install_element (CONFIG_NODE, &debug_ospf6_brouter_cmd);
1583 install_element (CONFIG_NODE, &debug_ospf6_brouter_router_cmd);
1584 install_element (CONFIG_NODE, &debug_ospf6_brouter_area_cmd);
1585 install_element (CONFIG_NODE, &no_debug_ospf6_brouter_cmd);
1586 install_element (CONFIG_NODE, &no_debug_ospf6_brouter_router_cmd);
1587 install_element (CONFIG_NODE, &no_debug_ospf6_brouter_area_cmd);
1588}
1589
paul718e3742002-12-13 20:15:29 +00001590