blob: 9bc603b307b5528acbf07e7cae2646d3fb3407b3 [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 */
218 if (if_is_pointopoint (oi->interface))
219 {
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 */
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 */
paul718e3742002-12-13 20:15:29 +0000269 }
hasso508e53e2004-05-18 18:57:06 +0000270
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 =
hasso049207c2004-08-04 20:02:13 +0000280 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
281 lsa_header->adv_router, oa->lsdb);
hasso508e53e2004-05-18 18:57:06 +0000282 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);
hasso508e53e2004-05-18 18:57:06 +0000289
290 /* Originate */
hasso6452df02004-08-15 05:52:07 +0000291 ospf6_lsa_originate_area (lsa, oa);
hasso508e53e2004-05-18 18:57:06 +0000292
293 link_state_id ++;
294 }
hasso6452df02004-08-15 05:52:07 +0000295 else
296 {
hasso1e058382004-09-01 21:36:14 +0000297 if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
hassoc6487d62004-12-24 06:00:11 +0000298 zlog_debug ("Nothing to describe in Router-LSA, suppress");
hasso6452df02004-08-15 05:52:07 +0000299 }
hasso508e53e2004-05-18 18:57:06 +0000300
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;
hasso6452df02004-08-15 05:52:07 +0000309 ospf6_lsa_purge (lsa);
hasso508e53e2004-05-18 18:57:06 +0000310 }
hasso508e53e2004-05-18 18:57:06 +0000311
312 return 0;
313}
314
hasso508e53e2004-05-18 18:57:06 +0000315/*******************************/
316/* RFC2740 3.4.3.2 Network-LSA */
317/*******************************/
318
Paul Jakma6ac29a52008-08-15 13:45:30 +0100319static int
hasso508e53e2004-05-18 18:57:06 +0000320ospf6_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));
hasso049207c2004-08-04 20:02:13 +0000331 vty_out (vty, " Options: %s%s", options, VNL);
hasso508e53e2004-05-18 18:57:06 +0000332
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));
hasso049207c2004-08-04 20:02:13 +0000340 vty_out (vty, " Attached Router: %s%s", buf, VNL);
hasso508e53e2004-05-18 18:57:06 +0000341 }
342 return 0;
paul718e3742002-12-13 20:15:29 +0000343}
344
hasso6452df02004-08-15 05:52:07 +0000345int
346ospf6_network_lsa_originate (struct thread *thread)
paul718e3742002-12-13 20:15:29 +0000347{
hasso6452df02004-08-15 05:52:07 +0000348 struct ospf6_interface *oi;
349
hasso508e53e2004-05-18 18:57:06 +0000350 char buffer [OSPF6_MAX_LSASIZE];
351 struct ospf6_lsa_header *lsa_header;
paul718e3742002-12-13 20:15:29 +0000352
hasso508e53e2004-05-18 18:57:06 +0000353 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;
hasso52dc7ee2004-09-23 19:18:23 +0000359 struct listnode *i;
hasso508e53e2004-05-18 18:57:06 +0000360 u_int16_t type;
361
hasso6452df02004-08-15 05:52:07 +0000362 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);
paul718e3742002-12-13 20:15:29 +0000369
hasso508e53e2004-05-18 18:57:06 +0000370 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_NETWORK),
371 htonl (oi->interface->ifindex),
372 oi->area->ospf6->router_id, oi->area->lsdb);
paul718e3742002-12-13 20:15:29 +0000373
hasso508e53e2004-05-18 18:57:06 +0000374 /* Do not originate Network-LSA if not DR */
375 if (oi->state != OSPF6_INTERFACE_DR)
paul718e3742002-12-13 20:15:29 +0000376 {
hasso508e53e2004-05-18 18:57:06 +0000377 if (old)
hasso6452df02004-08-15 05:52:07 +0000378 ospf6_lsa_purge (old);
379 return 0;
paul718e3742002-12-13 20:15:29 +0000380 }
hasso508e53e2004-05-18 18:57:06 +0000381
hasso1e058382004-09-01 21:36:14 +0000382 if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK))
hassoc6487d62004-12-24 06:00:11 +0000383 zlog_debug ("Originate Network-LSA for Interface %s", oi->interface->name);
hasso508e53e2004-05-18 18:57:06 +0000384
385 /* If none of neighbor is adjacent to us */
386 count = 0;
paul1eb8ef22005-04-07 07:30:20 +0000387
388 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
389 if (on->state == OSPF6_NEIGHBOR_FULL)
390 count++;
391
hasso508e53e2004-05-18 18:57:06 +0000392 if (count == 0)
393 {
hasso1e058382004-09-01 21:36:14 +0000394 if (IS_OSPF6_DEBUG_ORIGINATE (NETWORK))
hassoc6487d62004-12-24 06:00:11 +0000395 zlog_debug ("Interface stub, ignore");
hasso508e53e2004-05-18 18:57:06 +0000396 if (old)
hasso6452df02004-08-15 05:52:07 +0000397 ospf6_lsa_purge (old);
398 return 0;
hasso508e53e2004-05-18 18:57:06 +0000399 }
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 */
paul1eb8ef22005-04-07 07:30:20 +0000428 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
hasso508e53e2004-05-18 18:57:06 +0000429 {
hasso508e53e2004-05-18 18:57:06 +0000430 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 =
hasso049207c2004-08-04 20:02:13 +0000444 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
445 lsa_header->adv_router, oi->area->lsdb);
hasso508e53e2004-05-18 18:57:06 +0000446 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);
hasso508e53e2004-05-18 18:57:06 +0000453
454 /* Originate */
hasso6452df02004-08-15 05:52:07 +0000455 ospf6_lsa_originate_area (lsa, oi->area);
hasso508e53e2004-05-18 18:57:06 +0000456
457 return 0;
458}
459
460
461/****************************/
462/* RFC2740 3.4.3.6 Link-LSA */
463/****************************/
464
Paul Jakma6ac29a52008-08-15 13:45:30 +0100465static int
hasso508e53e2004-05-18 18:57:06 +0000466ospf6_link_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
467{
paul718e3742002-12-13 20:15:29 +0000468 char *start, *end, *current;
hasso508e53e2004-05-18 18:57:06 +0000469 struct ospf6_link_lsa *link_lsa;
470 int prefixnum;
471 char buf[128], options[32];
472 struct ospf6_prefix *prefix;
paul0c083ee2004-10-10 12:54:58 +0000473 const char *p, *mc, *la, *nu;
hasso508e53e2004-05-18 18:57:06 +0000474 struct in6_addr in6;
paul718e3742002-12-13 20:15:29 +0000475
hasso508e53e2004-05-18 18:57:06 +0000476 link_lsa = (struct ospf6_link_lsa *)
477 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +0000478
hasso508e53e2004-05-18 18:57:06 +0000479 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);
paul718e3742002-12-13 20:15:29 +0000482
hasso508e53e2004-05-18 18:57:06 +0000483 vty_out (vty, " Priority: %d Options: %s%s",
hasso049207c2004-08-04 20:02:13 +0000484 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);
paul718e3742002-12-13 20:15:29 +0000487
hasso508e53e2004-05-18 18:57:06 +0000488 start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
489 end = (char *) lsa->header + ntohs (lsa->header->length);
paul718e3742002-12-13 20:15:29 +0000490 for (current = start; current < end; current += OSPF6_PREFIX_SIZE (prefix))
491 {
492 prefix = (struct ospf6_prefix *) current;
hasso508e53e2004-05-18 18:57:06 +0000493 if (prefix->prefix_length == 0 ||
494 current + OSPF6_PREFIX_SIZE (prefix) > end)
495 break;
paul718e3742002-12-13 20:15:29 +0000496
hasso508e53e2004-05-18 18:57:06 +0000497 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",
hasso049207c2004-08-04 20:02:13 +0000506 p, mc, la, nu, VNL);
paul718e3742002-12-13 20:15:29 +0000507
hasso508e53e2004-05-18 18:57:06 +0000508 memset (&in6, 0, sizeof (in6));
509 memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
510 OSPF6_PREFIX_SPACE (prefix->prefix_length));
paul718e3742002-12-13 20:15:29 +0000511 inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
512 vty_out (vty, " Prefix: %s/%d%s",
hasso049207c2004-08-04 20:02:13 +0000513 buf, prefix->prefix_length, VNL);
paul718e3742002-12-13 20:15:29 +0000514 }
515
516 return 0;
517}
518
hasso6452df02004-08-15 05:52:07 +0000519int
520ospf6_link_lsa_originate (struct thread *thread)
paul718e3742002-12-13 20:15:29 +0000521{
hasso6452df02004-08-15 05:52:07 +0000522 struct ospf6_interface *oi;
523
hasso508e53e2004-05-18 18:57:06 +0000524 char buffer[OSPF6_MAX_LSASIZE];
525 struct ospf6_lsa_header *lsa_header;
526 struct ospf6_lsa *old, *lsa;
paul718e3742002-12-13 20:15:29 +0000527
hasso508e53e2004-05-18 18:57:06 +0000528 struct ospf6_link_lsa *link_lsa;
529 struct ospf6_route *route;
530 struct ospf6_prefix *op;
paul718e3742002-12-13 20:15:29 +0000531
hasso6452df02004-08-15 05:52:07 +0000532 oi = (struct ospf6_interface *) THREAD_ARG (thread);
533 oi->thread_link_lsa = NULL;
534
535 assert (oi->area);
paul718e3742002-12-13 20:15:29 +0000536
537 /* find previous LSA */
hasso508e53e2004-05-18 18:57:06 +0000538 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_LINK),
539 htonl (oi->interface->ifindex),
540 oi->area->ospf6->router_id, oi->lsdb);
paul718e3742002-12-13 20:15:29 +0000541
hasso508e53e2004-05-18 18:57:06 +0000542 if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
paul718e3742002-12-13 20:15:29 +0000543 {
544 if (old)
hasso6452df02004-08-15 05:52:07 +0000545 ospf6_lsa_purge (old);
546 return 0;
paul718e3742002-12-13 20:15:29 +0000547 }
548
hasso1e058382004-09-01 21:36:14 +0000549 if (IS_OSPF6_DEBUG_ORIGINATE (LINK))
hassoc6487d62004-12-24 06:00:11 +0000550 zlog_debug ("Originate Link-LSA for Interface %s", oi->interface->name);
paul718e3742002-12-13 20:15:29 +0000551
hasso508e53e2004-05-18 18:57:06 +0000552 /* can't make Link-LSA if linklocal address not set */
553 if (oi->linklocal_addr == NULL)
paul718e3742002-12-13 20:15:29 +0000554 {
hasso1e058382004-09-01 21:36:14 +0000555 if (IS_OSPF6_DEBUG_ORIGINATE (LINK))
hassoc6487d62004-12-24 06:00:11 +0000556 zlog_debug ("No Linklocal address on %s, defer originating",
hasso508e53e2004-05-18 18:57:06 +0000557 oi->interface->name);
558 if (old)
hasso6452df02004-08-15 05:52:07 +0000559 ospf6_lsa_purge (old);
560 return 0;
hasso508e53e2004-05-18 18:57:06 +0000561 }
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 =
hasso049207c2004-08-04 20:02:13 +0000597 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
598 lsa_header->adv_router, oi->lsdb);
hasso508e53e2004-05-18 18:57:06 +0000599 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);
hasso508e53e2004-05-18 18:57:06 +0000606
607 /* Originate */
hasso6452df02004-08-15 05:52:07 +0000608 ospf6_lsa_originate_interface (lsa, oi);
hasso508e53e2004-05-18 18:57:06 +0000609
610 return 0;
611}
612
613
614/*****************************************/
615/* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
616/*****************************************/
617
Paul Jakma6ac29a52008-08-15 13:45:30 +0100618static int
hasso508e53e2004-05-18 18:57:06 +0000619ospf6_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];
paul0c083ee2004-10-10 12:54:58 +0000627 const char *p, *mc, *la, *nu;
hasso508e53e2004-05-18 18:57:06 +0000628 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
hasso049207c2004-08-04 20:02:13 +0000635 vty_out (vty, " Number of Prefix: %d%s", prefixnum, VNL);
hasso508e53e2004-05-18 18:57:06 +0000636
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",
hasso1e058382004-09-01 21:36:14 +0000641 ospf6_lstype_name (intra_prefix_lsa->ref_type), id, adv_router,
hasso049207c2004-08-04 20:02:13 +0000642 VNL);
hasso508e53e2004-05-18 18:57:06 +0000643
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",
hasso049207c2004-08-04 20:02:13 +0000662 p, mc, la, nu, VNL);
hasso508e53e2004-05-18 18:57:06 +0000663
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",
hasso049207c2004-08-04 20:02:13 +0000669 buf, prefix->prefix_length, VNL);
hasso508e53e2004-05-18 18:57:06 +0000670 }
671
672 return 0;
673}
674
hasso6452df02004-08-15 05:52:07 +0000675int
676ospf6_intra_prefix_lsa_originate_stub (struct thread *thread)
hasso508e53e2004-05-18 18:57:06 +0000677{
hasso6452df02004-08-15 05:52:07 +0000678 struct ospf6_area *oa;
679
hasso508e53e2004-05-18 18:57:06 +0000680 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;
hasso52dc7ee2004-09-23 19:18:23 +0000689 struct listnode *i, *j;
hasso508e53e2004-05-18 18:57:06 +0000690 int full_count = 0;
691 unsigned short prefix_num = 0;
692 char buf[BUFSIZ];
693 struct ospf6_route_table *route_advertise;
694
hasso6452df02004-08-15 05:52:07 +0000695 oa = (struct ospf6_area *) THREAD_ARG (thread);
696 oa->thread_intra_prefix_lsa = NULL;
697
hasso508e53e2004-05-18 18:57:06 +0000698 /* find previous LSA */
699 old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_INTRA_PREFIX),
700 htonl (0), oa->ospf6->router_id, oa->lsdb);
701
hasso6452df02004-08-15 05:52:07 +0000702 if (! IS_AREA_ENABLED (oa))
hasso508e53e2004-05-18 18:57:06 +0000703 {
704 if (old)
hasso6452df02004-08-15 05:52:07 +0000705 ospf6_lsa_purge (old);
706 return 0;
hasso508e53e2004-05-18 18:57:06 +0000707 }
708
hasso1e058382004-09-01 21:36:14 +0000709 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000710 zlog_debug ("Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
hasso508e53e2004-05-18 18:57:06 +0000711 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
Paul Jakmacf1ce252006-05-15 10:46:07 +0000724 route_advertise = ospf6_route_table_create (0, 0);
hasso508e53e2004-05-18 18:57:06 +0000725
paul1eb8ef22005-04-07 07:30:20 +0000726 for (ALL_LIST_ELEMENTS_RO (oa->if_list, i, oi))
hasso508e53e2004-05-18 18:57:06 +0000727 {
hasso508e53e2004-05-18 18:57:06 +0000728 if (oi->state == OSPF6_INTERFACE_DOWN)
729 {
hasso1e058382004-09-01 21:36:14 +0000730 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000731 zlog_debug (" Interface %s is down, ignore", oi->interface->name);
hasso508e53e2004-05-18 18:57:06 +0000732 continue;
733 }
734
735 full_count = 0;
paul1eb8ef22005-04-07 07:30:20 +0000736
737 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
738 if (on->state == OSPF6_NEIGHBOR_FULL)
739 full_count++;
740
hasso508e53e2004-05-18 18:57:06 +0000741 if (oi->state != OSPF6_INTERFACE_LOOPBACK &&
742 oi->state != OSPF6_INTERFACE_POINTTOPOINT &&
743 full_count != 0)
744 {
hasso1e058382004-09-01 21:36:14 +0000745 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000746 zlog_debug (" Interface %s is not stub, ignore",
hasso508e53e2004-05-18 18:57:06 +0000747 oi->interface->name);
748 continue;
749 }
750
hasso1e058382004-09-01 21:36:14 +0000751 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000752 zlog_debug (" Interface %s:", oi->interface->name);
hasso508e53e2004-05-18 18:57:06 +0000753
754 /* connected prefix to advertise */
755 for (route = ospf6_route_head (oi->route_connected); route;
756 route = ospf6_route_best_next (route))
757 {
hasso1e058382004-09-01 21:36:14 +0000758 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hasso508e53e2004-05-18 18:57:06 +0000759 {
760 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000761 zlog_debug (" include %s", buf);
hasso508e53e2004-05-18 18:57:06 +0000762 }
763 ospf6_route_add (ospf6_route_copy (route), route_advertise);
764 }
765 }
766
767 if (route_advertise->count == 0)
768 {
769 if (old)
hasso6452df02004-08-15 05:52:07 +0000770 ospf6_lsa_purge (old);
hasso508e53e2004-05-18 18:57:06 +0000771 ospf6_route_table_delete (route_advertise);
hasso6452df02004-08-15 05:52:07 +0000772 return 0;
hasso508e53e2004-05-18 18:57:06 +0000773 }
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 {
hasso1e058382004-09-01 21:36:14 +0000795 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000796 zlog_debug ("Quit to Advertise Intra-Prefix: no route to advertise");
hasso6452df02004-08-15 05:52:07 +0000797 return 0;
hasso508e53e2004-05-18 18:57:06 +0000798 }
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 =
hasso049207c2004-08-04 20:02:13 +0000808 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
809 lsa_header->adv_router, oa->lsdb);
hasso508e53e2004-05-18 18:57:06 +0000810 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);
hasso508e53e2004-05-18 18:57:06 +0000817
818 /* Originate */
hasso6452df02004-08-15 05:52:07 +0000819 ospf6_lsa_originate_area (lsa, oa);
820
821 return 0;
hasso508e53e2004-05-18 18:57:06 +0000822}
823
hasso6452df02004-08-15 05:52:07 +0000824
825int
826ospf6_intra_prefix_lsa_originate_transit (struct thread *thread)
hasso508e53e2004-05-18 18:57:06 +0000827{
hasso6452df02004-08-15 05:52:07 +0000828 struct ospf6_interface *oi;
829
hasso508e53e2004-05-18 18:57:06 +0000830 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;
hasso52dc7ee2004-09-23 19:18:23 +0000838 struct listnode *i;
hasso508e53e2004-05-18 18:57:06 +0000839 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
hasso6452df02004-08-15 05:52:07 +0000847 oi = (struct ospf6_interface *) THREAD_ARG (thread);
848 oi->thread_intra_prefix_lsa = NULL;
849
850 assert (oi->area);
hasso508e53e2004-05-18 18:57:06 +0000851
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)
hasso6452df02004-08-15 05:52:07 +0000860 ospf6_lsa_purge (old);
861 return 0;
hasso508e53e2004-05-18 18:57:06 +0000862 }
863
hasso1e058382004-09-01 21:36:14 +0000864 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000865 zlog_debug ("Originate Intra-Area-Prefix-LSA for interface %s's prefix",
hasso508e53e2004-05-18 18:57:06 +0000866 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 {
hasso1e058382004-09-01 21:36:14 +0000881 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000882 zlog_debug (" Interface is not DR");
hasso508e53e2004-05-18 18:57:06 +0000883 if (old)
hasso6452df02004-08-15 05:52:07 +0000884 ospf6_lsa_purge (old);
885 return 0;
hasso508e53e2004-05-18 18:57:06 +0000886 }
887
888 full_count = 0;
paul1eb8ef22005-04-07 07:30:20 +0000889 for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, i, on))
890 if (on->state == OSPF6_NEIGHBOR_FULL)
891 full_count++;
892
hasso508e53e2004-05-18 18:57:06 +0000893 if (full_count == 0)
894 {
hasso1e058382004-09-01 21:36:14 +0000895 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000896 zlog_debug (" Interface is stub");
hasso508e53e2004-05-18 18:57:06 +0000897 if (old)
hasso6452df02004-08-15 05:52:07 +0000898 ospf6_lsa_purge (old);
899 return 0;
hasso508e53e2004-05-18 18:57:06 +0000900 }
901
902 /* connected prefix to advertise */
Paul Jakmacf1ce252006-05-15 10:46:07 +0000903 route_advertise = ospf6_route_table_create (0, 0);
hasso508e53e2004-05-18 18:57:06 +0000904
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))
paul718e3742002-12-13 20:15:29 +0000910 continue;
911
hasso1e058382004-09-01 21:36:14 +0000912 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000913 zlog_debug (" include prefix from %s", lsa->name);
paul718e3742002-12-13 20:15:29 +0000914
hasso508e53e2004-05-18 18:57:06 +0000915 if (lsa->header->adv_router != oi->area->ospf6->router_id)
paul718e3742002-12-13 20:15:29 +0000916 {
hasso508e53e2004-05-18 18:57:06 +0000917 on = ospf6_neighbor_lookup (lsa->header->adv_router, oi);
918 if (on == NULL || on->state != OSPF6_NEIGHBOR_FULL)
paul718e3742002-12-13 20:15:29 +0000919 {
hasso1e058382004-09-01 21:36:14 +0000920 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000921 zlog_debug (" Neighbor not found or not Full, ignore");
paul718e3742002-12-13 20:15:29 +0000922 continue;
923 }
924 }
925
hasso508e53e2004-05-18 18:57:06 +0000926 link_lsa = (struct ospf6_link_lsa *)
927 ((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
paul718e3742002-12-13 20:15:29 +0000928
hasso508e53e2004-05-18 18:57:06 +0000929 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))
paul718e3742002-12-13 20:15:29 +0000934 {
hasso508e53e2004-05-18 18:57:06 +0000935 op = (struct ospf6_prefix *) current;
936 if (op->prefix_length == 0 ||
937 current + OSPF6_PREFIX_SIZE (op) > end)
938 break;
paul718e3742002-12-13 20:15:29 +0000939
hasso508e53e2004-05-18 18:57:06 +0000940 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
hasso1e058382004-09-01 21:36:14 +0000959 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
paul718e3742002-12-13 20:15:29 +0000960 {
hasso508e53e2004-05-18 18:57:06 +0000961 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +0000962 zlog_debug (" include %s", buf);
paul718e3742002-12-13 20:15:29 +0000963 }
964
hasso508e53e2004-05-18 18:57:06 +0000965 ospf6_route_add (route, route_advertise);
966 prefix_num--;
paul718e3742002-12-13 20:15:29 +0000967 }
hasso1e058382004-09-01 21:36:14 +0000968 if (current != end && IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000969 zlog_debug ("Trailing garbage in %s", lsa->name);
paul718e3742002-12-13 20:15:29 +0000970 }
971
hasso508e53e2004-05-18 18:57:06 +0000972 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))
paul718e3742002-12-13 20:15:29 +0000978 {
hasso508e53e2004-05-18 18:57:06 +0000979 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 {
hasso1e058382004-09-01 21:36:14 +0000992 if (IS_OSPF6_DEBUG_ORIGINATE (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +0000993 zlog_debug ("Quit to Advertise Intra-Prefix: no route to advertise");
hasso6452df02004-08-15 05:52:07 +0000994 return 0;
paul718e3742002-12-13 20:15:29 +0000995 }
996
hasso508e53e2004-05-18 18:57:06 +0000997 intra_prefix_lsa->prefix_num = htons (prefix_num);
paul718e3742002-12-13 20:15:29 +0000998
hasso508e53e2004-05-18 18:57:06 +0000999 /* 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 =
hasso049207c2004-08-04 20:02:13 +00001005 ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
1006 lsa_header->adv_router, oi->area->lsdb);
hasso508e53e2004-05-18 18:57:06 +00001007 lsa_header->length = htons ((caddr_t) op - (caddr_t) lsa_header);
paul718e3742002-12-13 20:15:29 +00001008
hasso508e53e2004-05-18 18:57:06 +00001009 /* LSA checksum */
1010 ospf6_lsa_checksum (lsa_header);
paul718e3742002-12-13 20:15:29 +00001011
hasso508e53e2004-05-18 18:57:06 +00001012 /* create LSA */
1013 lsa = ospf6_lsa_create (lsa_header);
paul718e3742002-12-13 20:15:29 +00001014
hasso508e53e2004-05-18 18:57:06 +00001015 /* Originate */
hasso6452df02004-08-15 05:52:07 +00001016 ospf6_lsa_originate_area (lsa, oi->area);
paul718e3742002-12-13 20:15:29 +00001017
1018 return 0;
1019}
1020
1021void
hasso508e53e2004-05-18 18:57:06 +00001022ospf6_intra_prefix_lsa_add (struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00001023{
hasso508e53e2004-05-18 18:57:06 +00001024 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];
paul718e3742002-12-13 20:15:29 +00001032
hassoccb59b12004-08-25 09:10:37 +00001033 if (OSPF6_LSA_IS_MAXAGE (lsa))
1034 return;
1035
hasso1e058382004-09-01 21:36:14 +00001036 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +00001037 zlog_debug ("%s found", lsa->name);
paul718e3742002-12-13 20:15:29 +00001038
hasso6452df02004-08-15 05:52:07 +00001039 oa = OSPF6_AREA (lsa->lsdb->data);
1040
hasso508e53e2004-05-18 18:57:06 +00001041 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 {
hasso1e058382004-09-01 21:36:14 +00001051 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +00001052 zlog_debug ("Unknown reference LS-type: %#hx",
1053 ntohs (intra_prefix_lsa->ref_type));
hasso508e53e2004-05-18 18:57:06 +00001054 return;
1055 }
paul718e3742002-12-13 20:15:29 +00001056
hasso508e53e2004-05-18 18:57:06 +00001057 ls_entry = ospf6_route_lookup (&ls_prefix, oa->spf_table);
1058 if (ls_entry == NULL)
1059 {
hasso1e058382004-09-01 21:36:14 +00001060 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hasso508e53e2004-05-18 18:57:06 +00001061 {
1062 ospf6_linkstate_prefix2str (&ls_prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +00001063 zlog_debug ("LS entry does not exist: %s", buf);
hasso508e53e2004-05-18 18:57:06 +00001064 }
1065 return;
1066 }
paul718e3742002-12-13 20:15:29 +00001067
hasso508e53e2004-05-18 18:57:06 +00001068 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 ();
hassoccb59b12004-08-25 09:10:37 +00001081
1082 memset (&route->prefix, 0, sizeof (struct prefix));
hasso508e53e2004-05-18 18:57:06 +00001083 route->prefix.family = AF_INET6;
hassoccb59b12004-08-25 09:10:37 +00001084 route->prefix.prefixlen = op->prefix_length;
1085 ospf6_prefix_in6_addr (&route->prefix.u.prefix6, op);
1086
hasso508e53e2004-05-18 18:57:06 +00001087 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
hasso1e058382004-09-01 21:36:14 +00001102 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hasso508e53e2004-05-18 18:57:06 +00001103 {
1104 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +00001105 zlog_debug (" add %s", buf);
hasso508e53e2004-05-18 18:57:06 +00001106 }
1107
1108 ospf6_route_add (route, oa->route_table);
1109 prefix_num--;
1110 }
1111
hasso1e058382004-09-01 21:36:14 +00001112 if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +00001113 zlog_debug ("Trailing garbage ignored");
paul718e3742002-12-13 20:15:29 +00001114}
1115
1116void
hasso508e53e2004-05-18 18:57:06 +00001117ospf6_intra_prefix_lsa_remove (struct ospf6_lsa *lsa)
paul718e3742002-12-13 20:15:29 +00001118{
hasso508e53e2004-05-18 18:57:06 +00001119 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
hasso1e058382004-09-01 21:36:14 +00001128 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +00001129 zlog_debug ("%s disappearing", lsa->name);
hasso508e53e2004-05-18 18:57:06 +00001130
hasso6452df02004-08-15 05:52:07 +00001131 oa = OSPF6_AREA (lsa->lsdb->data);
1132
hasso508e53e2004-05-18 18:57:06 +00001133 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
hassoccb59b12004-08-25 09:10:37 +00001149 memset (&prefix, 0, sizeof (struct prefix));
hasso508e53e2004-05-18 18:57:06 +00001150 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
hasso1e058382004-09-01 21:36:14 +00001173 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hasso508e53e2004-05-18 18:57:06 +00001174 {
1175 prefix2str (&route->prefix, buf, sizeof (buf));
hassoc6487d62004-12-24 06:00:11 +00001176 zlog_debug ("remove %s", buf);
hasso508e53e2004-05-18 18:57:06 +00001177 }
1178 ospf6_route_remove (route, oa->route_table);
1179 }
Tom Goffe7a6d802010-11-10 13:03:02 -08001180 if (route)
1181 ospf6_route_unlock (route);
hasso508e53e2004-05-18 18:57:06 +00001182 }
1183
hasso1e058382004-09-01 21:36:14 +00001184 if (current != end && IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +00001185 zlog_debug ("Trailing garbage ignored");
paul718e3742002-12-13 20:15:29 +00001186}
1187
1188void
hasso508e53e2004-05-18 18:57:06 +00001189ospf6_intra_route_calculation (struct ospf6_area *oa)
paul718e3742002-12-13 20:15:29 +00001190{
hasso508e53e2004-05-18 18:57:06 +00001191 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
hasso1e058382004-09-01 21:36:14 +00001197 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +00001198 zlog_debug ("Re-examin intra-routes for area %s", oa->name);
hasso508e53e2004-05-18 18:57:06 +00001199
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
hasso1e058382004-09-01 21:36:14 +00001239 if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
hassoc6487d62004-12-24 06:00:11 +00001240 zlog_debug ("Re-examin intra-routes for area %s: Done", oa->name);
hasso508e53e2004-05-18 18:57:06 +00001241}
1242
Paul Jakma6ac29a52008-08-15 13:45:30 +01001243static void
Paul Jakmacf1ce252006-05-15 10:46:07 +00001244ospf6_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
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001261 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001262 timersub (&now, &brouter->installed, &res);
1263 timerstring (&res, installed, sizeof (installed));
1264
Takashi Sogabe86f72dc2009-06-22 13:07:02 +09001265 quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001266 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
hasso6452df02004-08-15 05:52:07 +00001296ospf6_intra_brouter_calculation (struct ospf6_area *oa)
hasso508e53e2004-05-18 18:57:06 +00001297{
Paul Jakmacb4b8842006-05-15 10:39:30 +00001298 struct ospf6_route *brouter, *copy;
hasso508e53e2004-05-18 18:57:06 +00001299 void (*hook_add) (struct ospf6_route *) = NULL;
1300 void (*hook_remove) (struct ospf6_route *) = NULL;
Paul Jakmacb4b8842006-05-15 10:39:30 +00001301 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
hasso6452df02004-08-15 05:52:07 +00001307 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;
hasso508e53e2004-05-18 18:57:06 +00001311
hasso6452df02004-08-15 05:52:07 +00001312 /* withdraw the previous router entries for the area */
Paul Jakmacb4b8842006-05-15 10:39:30 +00001313 for (brouter = ospf6_route_head (oa->ospf6->brouter_table); brouter;
1314 brouter = ospf6_route_next (brouter))
hasso508e53e2004-05-18 18:57:06 +00001315 {
Paul Jakmacf1ce252006-05-15 10:46:07 +00001316 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1317 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
Paul Jakmacb4b8842006-05-15 10:39:30 +00001318 if (brouter->path.area_id != oa->area_id)
hasso508e53e2004-05-18 18:57:06 +00001319 continue;
Paul Jakmacb4b8842006-05-15 10:39:30 +00001320 brouter->flag = OSPF6_ROUTE_REMOVE;
Paul Jakmacf1ce252006-05-15 10:46:07 +00001321
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 }
hasso508e53e2004-05-18 18:57:06 +00001329 }
1330
Paul Jakmacb4b8842006-05-15 10:39:30 +00001331 for (brouter = ospf6_route_head (oa->spf_table); brouter;
1332 brouter = ospf6_route_next (brouter))
hasso508e53e2004-05-18 18:57:06 +00001333 {
Paul Jakmacf1ce252006-05-15 10:46:07 +00001334 brouter_id = ADV_ROUTER_IN_PREFIX (&brouter->prefix);
1335 inet_ntop (AF_INET, &brouter_id, brouter_name, sizeof (brouter_name));
1336
Paul Jakmacb4b8842006-05-15 10:39:30 +00001337 if (brouter->type != OSPF6_DEST_TYPE_LINKSTATE)
hasso508e53e2004-05-18 18:57:06 +00001338 continue;
Paul Jakmacb4b8842006-05-15 10:39:30 +00001339 if (ospf6_linkstate_prefix_id (&brouter->prefix) != htonl (0))
hasso508e53e2004-05-18 18:57:06 +00001340 continue;
Paul Jakmacb4b8842006-05-15 10:39:30 +00001341 if (! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_E) &&
1342 ! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_B))
hasso508e53e2004-05-18 18:57:06 +00001343 continue;
1344
Paul Jakmacb4b8842006-05-15 10:39:30 +00001345 copy = ospf6_route_copy (brouter);
hasso508e53e2004-05-18 18:57:06 +00001346 copy->type = OSPF6_DEST_TYPE_ROUTER;
hassoccb59b12004-08-25 09:10:37 +00001347 copy->path.area_id = oa->area_id;
hasso6452df02004-08-15 05:52:07 +00001348 ospf6_route_add (copy, oa->ospf6->brouter_table);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001349
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 }
hasso508e53e2004-05-18 18:57:06 +00001357 }
1358
hasso6452df02004-08-15 05:52:07 +00001359 oa->ospf6->brouter_table->hook_add = hook_add;
1360 oa->ospf6->brouter_table->hook_remove = hook_remove;
hasso508e53e2004-05-18 18:57:06 +00001361
Paul Jakmacb4b8842006-05-15 10:39:30 +00001362 for (brouter = ospf6_route_head (oa->ospf6->brouter_table); brouter;
1363 brouter = ospf6_route_next (brouter))
hasso508e53e2004-05-18 18:57:06 +00001364 {
Paul Jakmacb4b8842006-05-15 10:39:30 +00001365 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)
hasso508e53e2004-05-18 18:57:06 +00001369 continue;
1370
Paul Jakmacb4b8842006-05-15 10:39:30 +00001371 if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_WAS_REMOVED))
hasso9428f2d2004-09-13 14:01:12 +00001372 continue;
1373
Paul Jakmacb4b8842006-05-15 10:39:30 +00001374 if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE) &&
1375 CHECK_FLAG (brouter->flag, OSPF6_ROUTE_ADD))
hasso508e53e2004-05-18 18:57:06 +00001376 {
Paul Jakmacb4b8842006-05-15 10:39:30 +00001377 UNSET_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE);
1378 UNSET_FLAG (brouter->flag, OSPF6_ROUTE_ADD);
hasso508e53e2004-05-18 18:57:06 +00001379 }
1380
Paul Jakmacb4b8842006-05-15 10:39:30 +00001381 if (CHECK_FLAG (brouter->flag, OSPF6_ROUTE_REMOVE))
hasso508e53e2004-05-18 18:57:06 +00001382 {
Paul Jakmacb4b8842006-05-15 10:39:30 +00001383 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);
Paul Jakmacf1ce252006-05-15 10:46:07 +00001398
Paul Jakmacb4b8842006-05-15 10:39:30 +00001399 /* newly added */
hasso508e53e2004-05-18 18:57:06 +00001400 if (hook_add)
Paul Jakmacb4b8842006-05-15 10:39:30 +00001401 (*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);
hasso508e53e2004-05-18 18:57:06 +00001409 }
1410
Paul Jakmacb4b8842006-05-15 10:39:30 +00001411 brouter->flag = 0;
hasso508e53e2004-05-18 18:57:06 +00001412 }
1413
Paul Jakmacb4b8842006-05-15 10:39:30 +00001414 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID (oa->area_id))
1415 zlog_info ("border-router calculation for area %s: done", oa->name);
paul718e3742002-12-13 20:15:29 +00001416}
1417
hasso6452df02004-08-15 05:52:07 +00001418struct 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
paul718e3742002-12-13 20:15:29 +00001446void
Paul Jakmacb4b8842006-05-15 10:39:30 +00001447ospf6_intra_init (void)
paul718e3742002-12-13 20:15:29 +00001448{
hasso6452df02004-08-15 05:52:07 +00001449 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);
paul718e3742002-12-13 20:15:29 +00001453}
1454
Paul Jakmacb4b8842006-05-15 10:39:30 +00001455DEFUN (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
paul718e3742002-12-13 20:15:29 +00001578