]> git.proxmox.com Git - mirror_frr.git/blame - ospf6d/ospf6_intra.c
Revert "ospf6d: document the interface address limits for ospfv3"
[mirror_frr.git] / ospf6d / ospf6_intra.c
CommitLineData
718e3744 1/*
508e53e2 2 * Copyright (C) 2003 Yasuhiro Ohara
718e3744 3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
896014f4
DL
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
718e3744 19 */
20
508e53e2 21#include <zebra.h>
718e3744 22
508e53e2 23#include "log.h"
24#include "linklist.h"
25#include "thread.h"
26#include "memory.h"
27#include "if.h"
28#include "prefix.h"
29#include "table.h"
30#include "vty.h"
31#include "command.h"
a90607a4 32#include "vrf.h"
718e3744 33
508e53e2 34#include "ospf6_proto.h"
35#include "ospf6_message.h"
36#include "ospf6_route.h"
37#include "ospf6_lsa.h"
38#include "ospf6_lsdb.h"
39
40#include "ospf6_top.h"
41#include "ospf6_area.h"
42#include "ospf6_interface.h"
43#include "ospf6_neighbor.h"
44#include "ospf6_intra.h"
45#include "ospf6_asbr.h"
6452df09 46#include "ospf6_abr.h"
47#include "ospf6_flood.h"
049207c3 48#include "ospf6d.h"
a0edf674 49#include "ospf6_spf.h"
cb4b8845
PJ
50
51unsigned char conf_debug_ospf6_brouter = 0;
d7c0a89a
QY
52uint32_t conf_debug_ospf6_brouter_specific_router_id;
53uint32_t conf_debug_ospf6_brouter_specific_area_id;
cb4b8845 54
9a703f8d 55#define MAX_LSA_PAYLOAD (1024 + 256)
508e53e2 56/******************************/
57/* RFC2740 3.4.3.1 Router-LSA */
58/******************************/
718e3744 59
d62a17ae 60static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa *lsa, char *buf,
61 int buflen, int pos)
e68a6767 62{
d62a17ae 63 struct ospf6_router_lsa *router_lsa;
64 struct ospf6_router_lsdesc *lsdesc;
65 char *start, *end;
66 char buf1[INET_ADDRSTRLEN], buf2[INET_ADDRSTRLEN];
67
68 if (lsa) {
69 router_lsa = (struct ospf6_router_lsa
70 *)((char *)lsa->header
71 + sizeof(struct ospf6_lsa_header));
72 start = (char *)router_lsa + sizeof(struct ospf6_router_lsa);
73 end = (char *)lsa->header + ntohs(lsa->header->length);
74
75 lsdesc = (struct ospf6_router_lsdesc
76 *)(start
9d303b37
DL
77 + pos * (sizeof(struct
78 ospf6_router_lsdesc)));
100f2989
MB
79 if ((char *)lsdesc + sizeof(struct ospf6_router_lsdesc)
80 <= end) {
d62a17ae 81 if (buf && (buflen > INET_ADDRSTRLEN * 2)) {
82 inet_ntop(AF_INET,
83 &lsdesc->neighbor_interface_id, buf1,
84 sizeof(buf1));
85 inet_ntop(AF_INET, &lsdesc->neighbor_router_id,
86 buf2, sizeof(buf2));
7533cad7 87 snprintf(buf, buflen, "%s/%s", buf2, buf1);
8e04b88b
MB
88
89 return buf;
d62a17ae 90 }
8e04b88b 91 }
e68a6767 92 }
e68a6767 93
8e04b88b 94 return NULL;
e68a6767
DD
95}
96
e4bacbaa
YR
97static int ospf6_router_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
98 json_object *json_obj, bool use_json)
718e3744 99{
d62a17ae 100 char *start, *end, *current;
101 char buf[32], name[32], bits[16], options[32];
102 struct ospf6_router_lsa *router_lsa;
103 struct ospf6_router_lsdesc *lsdesc;
e4bacbaa
YR
104 json_object *json_arr;
105 json_object *json_loop;
d62a17ae 106
107 router_lsa =
108 (struct ospf6_router_lsa *)((char *)lsa->header
109 + sizeof(struct ospf6_lsa_header));
110
111 ospf6_capability_printbuf(router_lsa->bits, bits, sizeof(bits));
112 ospf6_options_printbuf(router_lsa->options, options, sizeof(options));
e4bacbaa
YR
113 if (use_json) {
114 json_object_string_add(json_obj, "bits", bits);
115 json_object_string_add(json_obj, "options", options);
116 json_arr = json_object_new_array();
117 } else
118 vty_out(vty, " Bits: %s Options: %s\n", bits, options);
d62a17ae 119
120 start = (char *)router_lsa + sizeof(struct ospf6_router_lsa);
121 end = (char *)lsa->header + ntohs(lsa->header->length);
122 for (current = start;
123 current + sizeof(struct ospf6_router_lsdesc) <= end;
124 current += sizeof(struct ospf6_router_lsdesc)) {
125 lsdesc = (struct ospf6_router_lsdesc *)current;
126
127 if (lsdesc->type == OSPF6_ROUTER_LSDESC_POINTTOPOINT)
128 snprintf(name, sizeof(name), "Point-To-Point");
129 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK)
130 snprintf(name, sizeof(name), "Transit-Network");
131 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_STUB_NETWORK)
132 snprintf(name, sizeof(name), "Stub-Network");
133 else if (lsdesc->type == OSPF6_ROUTER_LSDESC_VIRTUAL_LINK)
134 snprintf(name, sizeof(name), "Virtual-Link");
135 else
136 snprintf(name, sizeof(name), "Unknown (%#x)",
137 lsdesc->type);
138
e4bacbaa
YR
139 if (use_json) {
140 json_loop = json_object_new_object();
141 json_object_string_add(json_loop, "type", name);
142 json_object_int_add(json_loop, "metric",
143 ntohs(lsdesc->metric));
144 json_object_string_add(json_loop, "interfaceId",
145 inet_ntop(AF_INET,
146 &lsdesc->interface_id,
147 buf, sizeof(buf)));
148 json_object_string_add(
149 json_loop, "neighborInterfaceId",
150 inet_ntop(AF_INET,
151 &lsdesc->neighbor_interface_id, buf,
152 sizeof(buf)));
153 json_object_string_add(
154 json_loop, "neighborRouterId",
155 inet_ntop(AF_INET, &lsdesc->neighbor_router_id,
156 buf, sizeof(buf)));
157 json_object_array_add(json_arr, json_loop);
158 } else {
159 vty_out(vty, " Type: %s Metric: %d\n", name,
160 ntohs(lsdesc->metric));
161 vty_out(vty, " Interface ID: %s\n",
162 inet_ntop(AF_INET, &lsdesc->interface_id, buf,
163 sizeof(buf)));
164 vty_out(vty, " Neighbor Interface ID: %s\n",
165 inet_ntop(AF_INET,
166 &lsdesc->neighbor_interface_id, buf,
167 sizeof(buf)));
168 vty_out(vty, " Neighbor Router ID: %s\n",
169 inet_ntop(AF_INET, &lsdesc->neighbor_router_id,
170 buf, sizeof(buf)));
171 }
d62a17ae 172 }
e4bacbaa
YR
173 if (use_json)
174 json_object_object_add(json_obj, "lsaDescription", json_arr);
175
d62a17ae 176 return 0;
718e3744 177}
178
d62a17ae 179static void ospf6_router_lsa_options_set(struct ospf6_area *oa,
180 struct ospf6_router_lsa *router_lsa)
ca1f4309 181{
d62a17ae 182 OSPF6_OPT_CLEAR_ALL(router_lsa->options);
183 memcpy(router_lsa->options, oa->options, 3);
184
95b3f03d 185 if (ospf6_check_and_set_router_abr(oa->ospf6))
d62a17ae 186 SET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_B);
187 else
188 UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_B);
189
190 if (!IS_AREA_STUB(oa) && ospf6_asbr_is_asbr(oa->ospf6)) {
191 SET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_E);
192 } else {
193 UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_E);
194 }
195
ad500b22
K
196 /* If the router is ASBR and the area-type is NSSA set the
197 * translate bit in router LSA.
198 */
199 if (IS_AREA_NSSA(oa)
200 && (ospf6_asbr_is_asbr(oa->ospf6) || IS_OSPF6_ABR(oa->ospf6))) {
201 if (oa->NSSATranslatorRole == OSPF6_NSSA_ROLE_ALWAYS)
202 SET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_NT);
203 } else {
204 UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_NT);
205 }
206
d62a17ae 207 UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_V);
208 UNSET_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_W);
ca1f4309
DS
209}
210
d62a17ae 211int ospf6_router_is_stub_router(struct ospf6_lsa *lsa)
f41b4a02 212{
d62a17ae 213 struct ospf6_router_lsa *rtr_lsa;
214
215 if (lsa != NULL && OSPF6_LSA_IS_TYPE(ROUTER, lsa)) {
216 rtr_lsa = (struct ospf6_router_lsa
217 *)((caddr_t)lsa->header
218 + sizeof(struct ospf6_lsa_header));
219
220 if (!OSPF6_OPT_ISSET(rtr_lsa->options, OSPF6_OPT_R)) {
95f7965d 221 return OSPF6_IS_STUB_ROUTER;
d62a17ae 222 } else if (!OSPF6_OPT_ISSET(rtr_lsa->options, OSPF6_OPT_V6)) {
95f7965d 223 return OSPF6_IS_STUB_ROUTER_V6;
d62a17ae 224 }
f41b4a02 225 }
f41b4a02 226
95f7965d 227 return OSPF6_NOT_STUB_ROUTER;
f41b4a02
DD
228}
229
d62a17ae 230int ospf6_router_lsa_originate(struct thread *thread)
718e3744 231{
d62a17ae 232 struct ospf6_area *oa;
233
234 char buffer[OSPF6_MAX_LSASIZE];
235 struct ospf6_lsa_header *lsa_header;
236 struct ospf6_lsa *lsa;
237
d7c0a89a 238 uint32_t link_state_id = 0;
d62a17ae 239 struct listnode *node, *nnode;
240 struct listnode *j;
241 struct ospf6_interface *oi;
242 struct ospf6_neighbor *on, *drouter = NULL;
243 struct ospf6_router_lsa *router_lsa;
244 struct ospf6_router_lsdesc *lsdesc;
d7c0a89a
QY
245 uint16_t type;
246 uint32_t router;
d62a17ae 247 int count;
248
249 oa = (struct ospf6_area *)THREAD_ARG(thread);
250 oa->thread_router_lsa = NULL;
251
252 if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
253 zlog_debug("Originate Router-LSA for Area %s", oa->name);
254
255 memset(buffer, 0, sizeof(buffer));
256 lsa_header = (struct ospf6_lsa_header *)buffer;
257 router_lsa =
258 (struct ospf6_router_lsa *)((caddr_t)lsa_header
259 + sizeof(struct ospf6_lsa_header));
260
261 ospf6_router_lsa_options_set(oa, router_lsa);
262
263 /* describe links for each interfaces */
996c9314
LB
264 lsdesc = (struct ospf6_router_lsdesc
265 *)((caddr_t)router_lsa
d62a17ae 266 + sizeof(struct ospf6_router_lsa));
267
268 for (ALL_LIST_ELEMENTS(oa->if_list, node, nnode, oi)) {
269 /* Interfaces in state Down or Loopback are not described */
270 if (oi->state == OSPF6_INTERFACE_DOWN
271 || oi->state == OSPF6_INTERFACE_LOOPBACK)
272 continue;
273
274 /* Nor are interfaces without any full adjacencies described */
275 count = 0;
276 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on))
277 if (on->state == OSPF6_NEIGHBOR_FULL)
278 count++;
279
280 if (count == 0)
281 continue;
282
283 /* Multiple Router-LSA instance according to size limit setting
284 */
285 if ((oa->router_lsa_size_limit != 0)
286 && ((size_t)((char *)lsdesc - buffer)
287 + sizeof(struct ospf6_router_lsdesc)
288 > oa->router_lsa_size_limit)) {
289 if ((caddr_t)lsdesc
290 == (caddr_t)router_lsa
291 + sizeof(struct ospf6_router_lsa)) {
1b1f7b4f 292 zlog_warn(
293 "Size limit setting for Router-LSA too short");
d62a17ae 294 return 0;
295 }
296
9a703f8d
CS
297 /* Fill LSA Header */
298 lsa_header->age = 0;
299 lsa_header->type = htons(OSPF6_LSTYPE_ROUTER);
300 lsa_header->id = htonl(link_state_id);
301 lsa_header->adv_router = oa->ospf6->router_id;
996c9314
LB
302 lsa_header->seqnum = ospf6_new_ls_seqnum(
303 lsa_header->type, lsa_header->id,
304 lsa_header->adv_router, oa->lsdb);
9a703f8d
CS
305 lsa_header->length =
306 htons((caddr_t)lsdesc - (caddr_t)buffer);
307
308 /* LSA checksum */
309 ospf6_lsa_checksum(lsa_header);
310
311 /* create LSA */
312 lsa = ospf6_lsa_create(lsa_header);
313
314 /* Originate */
315 ospf6_lsa_originate_area(lsa, oa);
316
317 /* Reset Buffer to fill next Router LSA */
318 memset(buffer, 0, sizeof(buffer));
319 lsa_header = (struct ospf6_lsa_header *)buffer;
320 router_lsa =
996c9314
LB
321 (struct ospf6_router_lsa
322 *)((caddr_t)lsa_header
9a703f8d
CS
323 + sizeof(struct ospf6_lsa_header));
324
325 ospf6_router_lsa_options_set(oa, router_lsa);
326
327 /* describe links for each interfaces */
996c9314
LB
328 lsdesc = (struct ospf6_router_lsdesc
329 *)((caddr_t)router_lsa
330 + sizeof(struct ospf6_router_lsa));
9a703f8d 331
d62a17ae 332 link_state_id++;
333 }
334
335 /* Point-to-Point interfaces */
336 if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
337 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on)) {
338 if (on->state != OSPF6_NEIGHBOR_FULL)
339 continue;
340
341 lsdesc->type = OSPF6_ROUTER_LSDESC_POINTTOPOINT;
342 lsdesc->metric = htons(oi->cost);
343 lsdesc->interface_id =
344 htonl(oi->interface->ifindex);
345 lsdesc->neighbor_interface_id =
346 htonl(on->ifindex);
347 lsdesc->neighbor_router_id = on->router_id;
348
349 lsdesc++;
350 }
351 }
352
353 /* Broadcast and NBMA interfaces */
354 else if (oi->type == OSPF_IFTYPE_BROADCAST) {
355 /* If this router is not DR,
356 and If this router not fully adjacent with DR,
357 this interface is not transit yet: ignore. */
358 if (oi->state != OSPF6_INTERFACE_DR) {
359 drouter =
360 ospf6_neighbor_lookup(oi->drouter, oi);
361 if (drouter == NULL
362 || drouter->state != OSPF6_NEIGHBOR_FULL)
363 continue;
364 }
365
366 lsdesc->type = OSPF6_ROUTER_LSDESC_TRANSIT_NETWORK;
367 lsdesc->metric = htons(oi->cost);
368 lsdesc->interface_id = htonl(oi->interface->ifindex);
369 if (oi->state != OSPF6_INTERFACE_DR) {
370 lsdesc->neighbor_interface_id =
371 htonl(drouter->ifindex);
372 lsdesc->neighbor_router_id = drouter->router_id;
373 } else {
374 lsdesc->neighbor_interface_id =
375 htonl(oi->interface->ifindex);
376 lsdesc->neighbor_router_id =
377 oi->area->ospf6->router_id;
378 }
379
380 lsdesc++;
381 } else {
382 assert(0); /* Unknown interface type */
383 }
384
385 /* Virtual links */
386 /* xxx */
387 /* Point-to-Multipoint interfaces */
388 /* xxx */
389 }
390
391 /* Fill LSA Header */
392 lsa_header->age = 0;
393 lsa_header->type = htons(OSPF6_LSTYPE_ROUTER);
394 lsa_header->id = htonl(link_state_id);
395 lsa_header->adv_router = oa->ospf6->router_id;
396 lsa_header->seqnum =
397 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
398 lsa_header->adv_router, oa->lsdb);
399 lsa_header->length = htons((caddr_t)lsdesc - (caddr_t)buffer);
400
401 /* LSA checksum */
402 ospf6_lsa_checksum(lsa_header);
403
404 /* create LSA */
405 lsa = ospf6_lsa_create(lsa_header);
406
407 /* Originate */
408 ospf6_lsa_originate_area(lsa, oa);
409
410 link_state_id++;
411
412 /* Do premature-aging of rest, undesired Router-LSAs */
413 type = ntohs(OSPF6_LSTYPE_ROUTER);
414 router = oa->ospf6->router_id;
415 count = 0;
416 for (ALL_LSDB_TYPED_ADVRTR(oa->lsdb, type, router, lsa)) {
417 if (ntohl(lsa->header->id) < link_state_id)
418 continue;
419 ospf6_lsa_purge(lsa);
420 count++;
c5926a92 421 }
508e53e2 422
d62a17ae 423 /*
424 * Waiting till the LSA is actually removed from the database to trigger
425 * SPF delays network convergence. Unlike IPv4, for an ABR, when all
426 * interfaces associated with an area are gone, triggering an SPF right
427 * away
428 * helps convergence with inter-area routes.
429 */
430 if (count && !link_state_id)
431 ospf6_spf_schedule(oa->ospf6,
432 OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED);
433
434 return 0;
508e53e2 435}
718e3744 436
508e53e2 437/*******************************/
438/* RFC2740 3.4.3.2 Network-LSA */
439/*******************************/
718e3744 440
d62a17ae 441static char *ospf6_network_lsa_get_ar_id(struct ospf6_lsa *lsa, char *buf,
442 int buflen, int pos)
e68a6767 443{
d62a17ae 444 char *start, *end, *current;
445 struct ospf6_network_lsa *network_lsa;
446 struct ospf6_network_lsdesc *lsdesc;
447
448 if (lsa) {
449 network_lsa = (struct ospf6_network_lsa
450 *)((caddr_t)lsa->header
451 + sizeof(struct ospf6_lsa_header));
452
453 start = (char *)network_lsa + sizeof(struct ospf6_network_lsa);
454 end = (char *)lsa->header + ntohs(lsa->header->length);
455 current = start + pos * (sizeof(struct ospf6_network_lsdesc));
456
457 if ((current + sizeof(struct ospf6_network_lsdesc)) <= end) {
458 lsdesc = (struct ospf6_network_lsdesc *)current;
8e04b88b 459 if (buf) {
d62a17ae 460 inet_ntop(AF_INET, &lsdesc->router_id, buf,
461 buflen);
8e04b88b
MB
462 return buf;
463 }
464 }
e68a6767 465 }
e68a6767 466
8e04b88b 467 return NULL;
e68a6767
DD
468}
469
e4bacbaa
YR
470static int ospf6_network_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
471 json_object *json_obj, bool use_json)
508e53e2 472{
d62a17ae 473 char *start, *end, *current;
474 struct ospf6_network_lsa *network_lsa;
475 struct ospf6_network_lsdesc *lsdesc;
476 char buf[128], options[32];
e4bacbaa 477 json_object *json_arr;
d62a17ae 478
479 network_lsa =
480 (struct ospf6_network_lsa *)((caddr_t)lsa->header
481 + sizeof(struct ospf6_lsa_header));
482
483 ospf6_options_printbuf(network_lsa->options, options, sizeof(options));
e4bacbaa
YR
484 if (use_json)
485 json_object_string_add(json_obj, "options", options);
486 else
487 vty_out(vty, " Options: %s\n", options);
d62a17ae 488
489 start = (char *)network_lsa + sizeof(struct ospf6_network_lsa);
490 end = (char *)lsa->header + ntohs(lsa->header->length);
e4bacbaa
YR
491 if (use_json)
492 json_arr = json_object_new_array();
493
d62a17ae 494 for (current = start;
495 current + sizeof(struct ospf6_network_lsdesc) <= end;
496 current += sizeof(struct ospf6_network_lsdesc)) {
497 lsdesc = (struct ospf6_network_lsdesc *)current;
498 inet_ntop(AF_INET, &lsdesc->router_id, buf, sizeof(buf));
e4bacbaa
YR
499 if (use_json)
500 json_object_array_add(json_arr,
501 json_object_new_string(buf));
502 else
503 vty_out(vty, " Attached Router: %s\n", buf);
d62a17ae 504 }
e4bacbaa
YR
505 if (use_json)
506 json_object_object_add(json_obj, "attachedRouter", json_arr);
507
d62a17ae 508 return 0;
718e3744 509}
510
d62a17ae 511int ospf6_network_lsa_originate(struct thread *thread)
718e3744 512{
d62a17ae 513 struct ospf6_interface *oi;
514
515 char buffer[OSPF6_MAX_LSASIZE];
516 struct ospf6_lsa_header *lsa_header;
517
518 int count;
519 struct ospf6_lsa *old, *lsa;
520 struct ospf6_network_lsa *network_lsa;
521 struct ospf6_network_lsdesc *lsdesc;
522 struct ospf6_neighbor *on;
523 struct ospf6_link_lsa *link_lsa;
524 struct listnode *i;
d7c0a89a 525 uint16_t type;
d62a17ae 526
527 oi = (struct ospf6_interface *)THREAD_ARG(thread);
528 oi->thread_network_lsa = NULL;
529
530 /* The interface must be enabled until here. A Network-LSA of a
531 disabled interface (but was once enabled) should be flushed
532 by ospf6_lsa_refresh (), and does not come here. */
533 assert(oi->area);
534
535 old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_NETWORK),
536 htonl(oi->interface->ifindex),
537 oi->area->ospf6->router_id, oi->area->lsdb);
538
539 /* Do not originate Network-LSA if not DR */
540 if (oi->state != OSPF6_INTERFACE_DR) {
541 if (old) {
542 ospf6_lsa_purge(old);
543 /*
544 * Waiting till the LSA is actually removed from the
545 * database to
546 * trigger SPF delays network convergence.
547 */
548 ospf6_spf_schedule(
549 oi->area->ospf6,
550 OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED);
551 }
552 return 0;
553 }
554
555 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK))
556 zlog_debug("Originate Network-LSA for Interface %s",
557 oi->interface->name);
558
559 /* If none of neighbor is adjacent to us */
560 count = 0;
561
562 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, i, on))
563 if (on->state == OSPF6_NEIGHBOR_FULL)
564 count++;
565
566 if (count == 0) {
567 if (IS_OSPF6_DEBUG_ORIGINATE(NETWORK))
568 zlog_debug("Interface stub, ignore");
569 if (old)
570 ospf6_lsa_purge(old);
571 return 0;
c3c0ac83 572 }
d62a17ae 573
574 /* prepare buffer */
575 memset(buffer, 0, sizeof(buffer));
576 lsa_header = (struct ospf6_lsa_header *)buffer;
577 network_lsa =
578 (struct ospf6_network_lsa *)((caddr_t)lsa_header
579 + sizeof(struct ospf6_lsa_header));
580
581 /* Collect the interface's Link-LSAs to describe
582 network's optional capabilities */
583 type = htons(OSPF6_LSTYPE_LINK);
584 for (ALL_LSDB_TYPED(oi->lsdb, type, lsa)) {
585 link_lsa = (struct ospf6_link_lsa
586 *)((caddr_t)lsa->header
587 + sizeof(struct ospf6_lsa_header));
588 network_lsa->options[0] |= link_lsa->options[0];
589 network_lsa->options[1] |= link_lsa->options[1];
590 network_lsa->options[2] |= link_lsa->options[2];
591 }
592
593 lsdesc = (struct ospf6_network_lsdesc
594 *)((caddr_t)network_lsa
595 + sizeof(struct ospf6_network_lsa));
596
597 /* set Link Description to the router itself */
598 lsdesc->router_id = oi->area->ospf6->router_id;
599 lsdesc++;
600
601 /* Walk through the neighbors */
602 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, i, on)) {
603 if (on->state != OSPF6_NEIGHBOR_FULL)
604 continue;
605
606 /* set this neighbor's Router-ID to LSA */
607 lsdesc->router_id = on->router_id;
608 lsdesc++;
609 }
610
611 /* Fill LSA Header */
612 lsa_header->age = 0;
613 lsa_header->type = htons(OSPF6_LSTYPE_NETWORK);
614 lsa_header->id = htonl(oi->interface->ifindex);
615 lsa_header->adv_router = oi->area->ospf6->router_id;
616 lsa_header->seqnum =
617 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
618 lsa_header->adv_router, oi->area->lsdb);
619 lsa_header->length = htons((caddr_t)lsdesc - (caddr_t)buffer);
620
621 /* LSA checksum */
622 ospf6_lsa_checksum(lsa_header);
623
624 /* create LSA */
625 lsa = ospf6_lsa_create(lsa_header);
626
627 /* Originate */
628 ospf6_lsa_originate_area(lsa, oi->area);
629
630 return 0;
508e53e2 631}
718e3744 632
633
508e53e2 634/****************************/
635/* RFC2740 3.4.3.6 Link-LSA */
636/****************************/
637
d62a17ae 638static char *ospf6_link_lsa_get_prefix_str(struct ospf6_lsa *lsa, char *buf,
639 int buflen, int pos)
e68a6767 640{
d62a17ae 641 char *start, *end, *current;
642 struct ospf6_link_lsa *link_lsa;
643 struct in6_addr in6;
644 struct ospf6_prefix *prefix;
645 int cnt = 0, prefixnum;
646
647 if (lsa) {
648 link_lsa = (struct ospf6_link_lsa
649 *)((caddr_t)lsa->header
650 + sizeof(struct ospf6_lsa_header));
651
652 if (pos == 0) {
653 inet_ntop(AF_INET6, &link_lsa->linklocal_addr, buf,
654 buflen);
655 return (buf);
656 }
657
658 prefixnum = ntohl(link_lsa->prefix_num);
659 if (pos > prefixnum)
95f7965d 660 return NULL;
d62a17ae 661
662 start = (char *)link_lsa + sizeof(struct ospf6_link_lsa);
663 end = (char *)lsa->header + ntohs(lsa->header->length);
664 current = start;
665
100f2989 666 while (current + sizeof(struct ospf6_prefix) <= end) {
d62a17ae 667 prefix = (struct ospf6_prefix *)current;
668 if (prefix->prefix_length == 0
669 || current + OSPF6_PREFIX_SIZE(prefix) > end) {
95f7965d 670 return NULL;
d62a17ae 671 }
672
08d8fa45
YR
673 if (cnt < (pos - 1)) {
674 current += OSPF6_PREFIX_SIZE(prefix);
d62a17ae 675 cnt++;
676 } else {
677 memset(&in6, 0, sizeof(in6));
678 memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
679 OSPF6_PREFIX_SPACE(
680 prefix->prefix_length));
681 inet_ntop(AF_INET6, &in6, buf, buflen);
682 return (buf);
683 }
100f2989 684 }
d62a17ae 685 }
95f7965d 686 return NULL;
e68a6767
DD
687}
688
e4bacbaa
YR
689static int ospf6_link_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
690 json_object *json_obj, bool use_json)
718e3744 691{
d62a17ae 692 char *start, *end, *current;
693 struct ospf6_link_lsa *link_lsa;
694 int prefixnum;
695 char buf[128], options[32];
696 struct ospf6_prefix *prefix;
d62a17ae 697 struct in6_addr in6;
e4bacbaa
YR
698 json_object *json_loop;
699 json_object *json_arr = NULL;
e4bacbaa 700 char prefix_string[133];
d62a17ae 701
702 link_lsa = (struct ospf6_link_lsa *)((caddr_t)lsa->header
703 + sizeof(struct ospf6_lsa_header));
704
705 ospf6_options_printbuf(link_lsa->options, options, sizeof(options));
706 inet_ntop(AF_INET6, &link_lsa->linklocal_addr, buf, sizeof(buf));
707 prefixnum = ntohl(link_lsa->prefix_num);
708
e4bacbaa
YR
709 if (use_json) {
710 json_arr = json_object_new_array();
711 json_object_int_add(json_obj, "priority", link_lsa->priority);
712 json_object_string_add(json_obj, "options", options);
713 json_object_string_add(json_obj, "linkLocalAddress", buf);
714 json_object_int_add(json_obj, "numberOfPrefix", prefixnum);
715 } else {
716 vty_out(vty, " Priority: %d Options: %s\n",
717 link_lsa->priority, options);
718 vty_out(vty, " LinkLocal Address: %s\n", buf);
719 vty_out(vty, " Number of Prefix: %d\n", prefixnum);
720 }
d62a17ae 721
722 start = (char *)link_lsa + sizeof(struct ospf6_link_lsa);
723 end = (char *)lsa->header + ntohs(lsa->header->length);
724 for (current = start; current < end;
725 current += OSPF6_PREFIX_SIZE(prefix)) {
726 prefix = (struct ospf6_prefix *)current;
727 if (prefix->prefix_length == 0
728 || current + OSPF6_PREFIX_SIZE(prefix) > end)
729 break;
730
8ae79ff2 731 ospf6_prefix_options_printbuf(prefix->prefix_options, buf,
732 sizeof(buf));
e4bacbaa
YR
733 if (use_json) {
734 json_loop = json_object_new_object();
8ae79ff2 735 json_object_string_add(json_loop, "prefixOption", buf);
e4bacbaa 736 } else
8ae79ff2 737 vty_out(vty, " Prefix Options: %s\n", buf);
d62a17ae 738
739 memset(&in6, 0, sizeof(in6));
740 memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
741 OSPF6_PREFIX_SPACE(prefix->prefix_length));
742 inet_ntop(AF_INET6, &in6, buf, sizeof(buf));
e4bacbaa
YR
743 if (use_json) {
744 snprintf(prefix_string, sizeof(prefix_string), "%s/%d",
745 buf, prefix->prefix_length);
746 json_object_string_add(json_loop, "prefix",
747 prefix_string);
748 json_object_array_add(json_arr, json_loop);
749 } else
750 vty_out(vty, " Prefix: %s/%d\n", buf,
751 prefix->prefix_length);
d62a17ae 752 }
e4bacbaa
YR
753 if (use_json)
754 json_object_object_add(json_obj, "prefix", json_arr);
d62a17ae 755
756 return 0;
718e3744 757}
758
d62a17ae 759int ospf6_link_lsa_originate(struct thread *thread)
718e3744 760{
d62a17ae 761 struct ospf6_interface *oi;
762
763 char buffer[OSPF6_MAX_LSASIZE];
764 struct ospf6_lsa_header *lsa_header;
765 struct ospf6_lsa *old, *lsa;
766
767 struct ospf6_link_lsa *link_lsa;
768 struct ospf6_route *route;
769 struct ospf6_prefix *op;
f85b7619 770 int count, max_addr_count;
d62a17ae 771
772 oi = (struct ospf6_interface *)THREAD_ARG(thread);
773 oi->thread_link_lsa = NULL;
774
775 assert(oi->area);
776
777 /* find previous LSA */
778 old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_LINK),
779 htonl(oi->interface->ifindex),
780 oi->area->ospf6->router_id, oi->lsdb);
781
782 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
783 if (old)
784 ospf6_lsa_purge(old);
785 return 0;
786 }
787
788 if (IS_OSPF6_DEBUG_ORIGINATE(LINK))
789 zlog_debug("Originate Link-LSA for Interface %s",
790 oi->interface->name);
791
792 /* can't make Link-LSA if linklocal address not set */
793 if (oi->linklocal_addr == NULL) {
794 if (IS_OSPF6_DEBUG_ORIGINATE(LINK))
795 zlog_debug(
796 "No Linklocal address on %s, defer originating",
797 oi->interface->name);
798 if (old)
799 ospf6_lsa_purge(old);
800 return 0;
801 }
802
803 /* prepare buffer */
804 memset(buffer, 0, sizeof(buffer));
805 lsa_header = (struct ospf6_lsa_header *)buffer;
806 link_lsa = (struct ospf6_link_lsa *)((caddr_t)lsa_header
807 + sizeof(struct ospf6_lsa_header));
808
809 /* Fill Link-LSA */
810 link_lsa->priority = oi->priority;
811 memcpy(link_lsa->options, oi->area->options, 3);
812 memcpy(&link_lsa->linklocal_addr, oi->linklocal_addr,
813 sizeof(struct in6_addr));
d62a17ae 814
815 op = (struct ospf6_prefix *)((caddr_t)link_lsa
816 + sizeof(struct ospf6_link_lsa));
817
f85b7619 818 /* connected prefix to advertise, number of interface addresses
819 * supported is based on MTU size of OSPFv3 packets
820 */
821 if (oi->ifmtu >= OSPF6_JUMBO_MTU)
822 max_addr_count = OSPF6_MAX_IF_ADDRS_JUMBO;
823 else
824 max_addr_count = OSPF6_MAX_IF_ADDRS;
825 for (route = ospf6_route_head(oi->route_connected), count = 0;
826 route && count < max_addr_count;
827 route = ospf6_route_next(route), count++) {
d62a17ae 828 op->prefix_length = route->prefix.prefixlen;
829 op->prefix_options = route->path.prefix_options;
830 op->prefix_metric = htons(0);
831 memcpy(OSPF6_PREFIX_BODY(op), &route->prefix.u.prefix6,
832 OSPF6_PREFIX_SPACE(op->prefix_length));
833 op = OSPF6_PREFIX_NEXT(op);
834 }
835
f85b7619 836 link_lsa->prefix_num = htonl(count);
837
d62a17ae 838 /* Fill LSA Header */
839 lsa_header->age = 0;
840 lsa_header->type = htons(OSPF6_LSTYPE_LINK);
841 lsa_header->id = htonl(oi->interface->ifindex);
842 lsa_header->adv_router = oi->area->ospf6->router_id;
843 lsa_header->seqnum =
844 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
845 lsa_header->adv_router, oi->lsdb);
846 lsa_header->length = htons((caddr_t)op - (caddr_t)buffer);
847
848 /* LSA checksum */
849 ospf6_lsa_checksum(lsa_header);
850
851 /* create LSA */
852 lsa = ospf6_lsa_create(lsa_header);
853
854 /* Originate */
855 ospf6_lsa_originate_interface(lsa, oi);
856
857 return 0;
508e53e2 858}
718e3744 859
718e3744 860
508e53e2 861/*****************************************/
862/* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
863/*****************************************/
d62a17ae 864static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
865 char *buf, int buflen,
866 int pos)
e68a6767 867{
d62a17ae 868 char *start, *end, *current;
869 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
870 struct in6_addr in6;
871 int prefixnum, cnt = 0;
872 struct ospf6_prefix *prefix;
7533cad7 873 char tbuf[16];
d62a17ae 874
875 if (lsa) {
876 intra_prefix_lsa =
877 (struct ospf6_intra_prefix_lsa
878 *)((caddr_t)lsa->header
879 + sizeof(struct ospf6_lsa_header));
880
881 prefixnum = ntohs(intra_prefix_lsa->prefix_num);
8044f7aa 882 if ((pos + 1) > prefixnum)
95f7965d 883 return NULL;
d62a17ae 884
885 start = (char *)intra_prefix_lsa
886 + sizeof(struct ospf6_intra_prefix_lsa);
887 end = (char *)lsa->header + ntohs(lsa->header->length);
888 current = start;
889
100f2989 890 while (current + sizeof(struct ospf6_prefix) <= end) {
d62a17ae 891 prefix = (struct ospf6_prefix *)current;
892 if (prefix->prefix_length == 0
893 || current + OSPF6_PREFIX_SIZE(prefix) > end) {
894 return NULL;
895 }
896
897 if (cnt < pos) {
8044f7aa 898 current += OSPF6_PREFIX_SIZE(prefix);
d62a17ae 899 cnt++;
900 } else {
901 memset(&in6, 0, sizeof(in6));
902 memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
903 OSPF6_PREFIX_SPACE(
904 prefix->prefix_length));
905 inet_ntop(AF_INET6, &in6, buf, buflen);
7533cad7
QY
906 snprintf(tbuf, sizeof(tbuf), "/%d",
907 prefix->prefix_length);
908 strlcat(buf, tbuf, buflen);
d62a17ae 909 return (buf);
910 }
100f2989 911 }
d62a17ae 912 }
8e04b88b 913 return NULL;
e68a6767 914}
718e3744 915
e4bacbaa
YR
916static int ospf6_intra_prefix_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
917 json_object *json_obj, bool use_json)
508e53e2 918{
d62a17ae 919 char *start, *end, *current;
920 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
921 int prefixnum;
922 char buf[128];
923 struct ospf6_prefix *prefix;
924 char id[16], adv_router[16];
d62a17ae 925 struct in6_addr in6;
e4bacbaa
YR
926 json_object *json_loop;
927 json_object *json_arr = NULL;
e4bacbaa 928 char prefix_string[133];
d62a17ae 929
930 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa
931 *)((caddr_t)lsa->header
932 + sizeof(struct ospf6_lsa_header));
933
934 prefixnum = ntohs(intra_prefix_lsa->prefix_num);
935
e4bacbaa
YR
936 if (use_json) {
937 json_arr = json_object_new_array();
938 json_object_int_add(json_obj, "numberOfPrefix", prefixnum);
939 } else
940 vty_out(vty, " Number of Prefix: %d\n", prefixnum);
d62a17ae 941
942 inet_ntop(AF_INET, &intra_prefix_lsa->ref_id, id, sizeof(id));
943 inet_ntop(AF_INET, &intra_prefix_lsa->ref_adv_router, adv_router,
944 sizeof(adv_router));
e4bacbaa
YR
945 if (use_json) {
946 json_object_string_add(
947 json_obj, "reference",
948 ospf6_lstype_name(intra_prefix_lsa->ref_type));
949 json_object_string_add(json_obj, "referenceId", id);
950 json_object_string_add(json_obj, "referenceAdv", adv_router);
951 } else
952 vty_out(vty, " Reference: %s Id: %s Adv: %s\n",
953 ospf6_lstype_name(intra_prefix_lsa->ref_type), id,
954 adv_router);
d62a17ae 955
956 start = (char *)intra_prefix_lsa
957 + sizeof(struct ospf6_intra_prefix_lsa);
958 end = (char *)lsa->header + ntohs(lsa->header->length);
959 for (current = start; current < end;
960 current += OSPF6_PREFIX_SIZE(prefix)) {
961 prefix = (struct ospf6_prefix *)current;
962 if (prefix->prefix_length == 0
963 || current + OSPF6_PREFIX_SIZE(prefix) > end)
964 break;
965
8ae79ff2 966 ospf6_prefix_options_printbuf(prefix->prefix_options, buf,
967 sizeof(buf));
e4bacbaa
YR
968 if (use_json) {
969 json_loop = json_object_new_object();
8ae79ff2 970 json_object_string_add(json_loop, "prefixOption", buf);
e4bacbaa 971 } else
8ae79ff2 972 vty_out(vty, " Prefix Options: %s\n", buf);
d62a17ae 973
974 memset(&in6, 0, sizeof(in6));
975 memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
976 OSPF6_PREFIX_SPACE(prefix->prefix_length));
977 inet_ntop(AF_INET6, &in6, buf, sizeof(buf));
e4bacbaa
YR
978 if (use_json) {
979 snprintf(prefix_string, sizeof(prefix_string), "%s/%d",
980 buf, prefix->prefix_length);
981 json_object_string_add(json_loop, "prefix",
982 prefix_string);
2727b660
YR
983 json_object_int_add(json_loop, "metric",
984 ntohs(prefix->prefix_metric));
e4bacbaa 985 json_object_array_add(json_arr, json_loop);
2727b660 986 } else {
e4bacbaa
YR
987 vty_out(vty, " Prefix: %s/%d\n", buf,
988 prefix->prefix_length);
2727b660
YR
989 vty_out(vty, " Metric: %d\n",
990 ntohs(prefix->prefix_metric));
991 }
d62a17ae 992 }
e4bacbaa
YR
993 if (use_json)
994 json_object_object_add(json_obj, "prefix", json_arr);
d62a17ae 995
996 return 0;
718e3744 997}
998
d62a17ae 999int ospf6_intra_prefix_lsa_originate_stub(struct thread *thread)
718e3744 1000{
d62a17ae 1001 struct ospf6_area *oa;
1002
1003 char buffer[OSPF6_MAX_LSASIZE];
1004 struct ospf6_lsa_header *lsa_header;
9a703f8d 1005 struct ospf6_lsa *old, *lsa, *old_next = NULL;
d62a17ae 1006
1007 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1008 struct ospf6_interface *oi;
1009 struct ospf6_neighbor *on;
1010 struct ospf6_route *route;
1011 struct ospf6_prefix *op;
1012 struct listnode *i, *j;
1013 int full_count = 0;
1014 unsigned short prefix_num = 0;
d62a17ae 1015 struct ospf6_route_table *route_advertise;
9a703f8d 1016 int ls_id = 0;
f85b7619 1017 int count, max_addr_count;
d62a17ae 1018
1019 oa = (struct ospf6_area *)THREAD_ARG(thread);
1020 oa->thread_intra_prefix_lsa = NULL;
1021
1022 /* find previous LSA */
1023 old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX), htonl(0),
1024 oa->ospf6->router_id, oa->lsdb);
1025
1026 if (!IS_AREA_ENABLED(oa)) {
9a703f8d 1027 if (old) {
d62a17ae 1028 ospf6_lsa_purge(old);
9a703f8d
CS
1029 /* find previous LSA */
1030 old_next = ospf6_lsdb_lookup(
996c9314
LB
1031 htons(OSPF6_LSTYPE_INTRA_PREFIX),
1032 htonl(++ls_id), oa->ospf6->router_id, oa->lsdb);
9a703f8d
CS
1033
1034 while (old_next) {
1035 ospf6_lsa_purge(old_next);
1036 old_next = ospf6_lsdb_lookup(
1037 htons(OSPF6_LSTYPE_INTRA_PREFIX),
996c9314
LB
1038 htonl(++ls_id), oa->ospf6->router_id,
1039 oa->lsdb);
9a703f8d
CS
1040 }
1041 }
d62a17ae 1042 return 0;
1043 }
1044
1045 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1046 zlog_debug(
1047 "Originate Intra-Area-Prefix-LSA for area %s's stub prefix",
1048 oa->name);
1049
1050 /* prepare buffer */
1051 memset(buffer, 0, sizeof(buffer));
1052 lsa_header = (struct ospf6_lsa_header *)buffer;
996c9314
LB
1053 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa
1054 *)((caddr_t)lsa_header
d62a17ae 1055 + sizeof(struct ospf6_lsa_header));
1056
1057 /* Fill Intra-Area-Prefix-LSA */
1058 intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_ROUTER);
1059 intra_prefix_lsa->ref_id = htonl(0);
1060 intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id;
1061
1062 route_advertise = ospf6_route_table_create(0, 0);
f85b7619 1063 route_advertise->hook_add = NULL;
1064 route_advertise->hook_remove = NULL;
d62a17ae 1065
1066 for (ALL_LIST_ELEMENTS_RO(oa->if_list, i, oi)) {
1067 if (oi->state == OSPF6_INTERFACE_DOWN) {
1068 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1069 zlog_debug(" Interface %s is down, ignore",
1070 oi->interface->name);
1071 continue;
1072 }
1073
1074 full_count = 0;
1075
1076 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, j, on))
1077 if (on->state == OSPF6_NEIGHBOR_FULL)
1078 full_count++;
1079
1080 if (oi->state != OSPF6_INTERFACE_LOOPBACK
1081 && oi->state != OSPF6_INTERFACE_POINTTOPOINT
1082 && full_count != 0) {
1083 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1084 zlog_debug(" Interface %s is not stub, ignore",
1085 oi->interface->name);
1086 continue;
1087 }
1088
1089 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1090 zlog_debug(" Interface %s:", oi->interface->name);
1091
1092 /* connected prefix to advertise */
f85b7619 1093 if (oi->ifmtu >= OSPF6_JUMBO_MTU)
1094 max_addr_count = OSPF6_MAX_IF_ADDRS_JUMBO;
1095 else
1096 max_addr_count = OSPF6_MAX_IF_ADDRS;
1097
1098 for (route = ospf6_route_head(oi->route_connected), count = 0;
1099 route && count < max_addr_count;
1100 route = ospf6_route_best_next(route), count++) {
2dbe669b
DA
1101 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1102 zlog_debug(" include %pFX", &route->prefix);
d62a17ae 1103 ospf6_route_add(ospf6_route_copy(route),
e285b70d 1104 route_advertise);
d62a17ae 1105 }
1106 }
1107
1108 if (route_advertise->count == 0) {
9a703f8d
CS
1109 if (old) {
1110 ls_id = 0;
d62a17ae 1111 ospf6_lsa_purge(old);
9a703f8d
CS
1112 /* find previous LSA */
1113 old_next = ospf6_lsdb_lookup(
996c9314
LB
1114 htons(OSPF6_LSTYPE_INTRA_PREFIX),
1115 htonl(++ls_id), oa->ospf6->router_id, oa->lsdb);
9a703f8d
CS
1116
1117 while (old_next) {
1118 ospf6_lsa_purge(old_next);
1119 old_next = ospf6_lsdb_lookup(
1120 htons(OSPF6_LSTYPE_INTRA_PREFIX),
996c9314
LB
1121 htonl(++ls_id), oa->ospf6->router_id,
1122 oa->lsdb);
9a703f8d
CS
1123 }
1124 }
e285b70d 1125 ospf6_route_table_delete(route_advertise);
d62a17ae 1126 return 0;
1127 }
1128
690df177
CS
1129 /* Neighbor change to FULL, if INTRA-AREA-PREFIX LSA
1130 * has not change, Flush old LSA and Re-Originate INP,
1131 * as ospf6_flood() checks if LSA is same as DB,
1132 * it won't be updated to neighbor's DB.
1133 */
1134 if (oa->intra_prefix_originate) {
1135 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
5e81f5dd
DS
1136 zlog_debug(
1137 "%s: Re-originate intra prefix LSA, Current full nbrs %u",
1138 __func__, oa->full_nbrs);
690df177
CS
1139 if (old)
1140 ospf6_lsa_purge_multi_ls_id(oa, old);
1141 oa->intra_prefix_originate = 0;
1142 }
1143
d62a17ae 1144 /* put prefixes to advertise */
1145 prefix_num = 0;
1146 op = (struct ospf6_prefix *)((caddr_t)intra_prefix_lsa
1147 + sizeof(struct ospf6_intra_prefix_lsa));
1148 for (route = ospf6_route_head(route_advertise); route;
1149 route = ospf6_route_best_next(route)) {
9a703f8d
CS
1150 if (((caddr_t)op - (caddr_t)lsa_header) > MAX_LSA_PAYLOAD) {
1151
1152 intra_prefix_lsa->prefix_num = htons(prefix_num);
1153
1154 /* Fill LSA Header */
1155 lsa_header->age = 0;
1156 lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
1157 lsa_header->id = htonl(ls_id++);
1158 lsa_header->adv_router = oa->ospf6->router_id;
996c9314
LB
1159 lsa_header->seqnum = ospf6_new_ls_seqnum(
1160 lsa_header->type, lsa_header->id,
1161 lsa_header->adv_router, oa->lsdb);
1162 lsa_header->length =
1163 htons((caddr_t)op - (caddr_t)lsa_header);
9a703f8d
CS
1164
1165 /* LSA checksum */
1166 ospf6_lsa_checksum(lsa_header);
1167
1168 /* Create LSA */
1169 lsa = ospf6_lsa_create(lsa_header);
1170
1171 /* Originate */
1172 ospf6_lsa_originate_area(lsa, oa);
1173
1174 /* Prepare next buffer */
1175 memset(buffer, 0, sizeof(buffer));
1176 lsa_header = (struct ospf6_lsa_header *)buffer;
996c9314
LB
1177 intra_prefix_lsa =
1178 (struct ospf6_intra_prefix_lsa
1179 *)((caddr_t)lsa_header
1180 + sizeof(struct ospf6_lsa_header));
9a703f8d
CS
1181
1182 /* Fill Intra-Area-Prefix-LSA */
1183 intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_ROUTER);
1184 intra_prefix_lsa->ref_id = htonl(0);
1185 intra_prefix_lsa->ref_adv_router = oa->ospf6->router_id;
1186
1187 /* Put next set of prefixes to advertise */
1188 prefix_num = 0;
996c9314
LB
1189 op = (struct ospf6_prefix
1190 *)((caddr_t)intra_prefix_lsa
1191 + sizeof(struct
1192 ospf6_intra_prefix_lsa));
9a703f8d
CS
1193 }
1194
d62a17ae 1195 op->prefix_length = route->prefix.prefixlen;
1196 op->prefix_options = route->path.prefix_options;
1197 op->prefix_metric = htons(route->path.cost);
1198 memcpy(OSPF6_PREFIX_BODY(op), &route->prefix.u.prefix6,
1199 OSPF6_PREFIX_SPACE(op->prefix_length));
d62a17ae 1200 prefix_num++;
9a703f8d
CS
1201
1202 op = OSPF6_PREFIX_NEXT(op);
d62a17ae 1203 }
1204
e285b70d 1205 ospf6_route_table_delete(route_advertise);
d62a17ae 1206
1207 if (prefix_num == 0) {
1208 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1209 zlog_debug(
1210 "Quit to Advertise Intra-Prefix: no route to advertise");
1211 return 0;
1212 }
1213
1214 intra_prefix_lsa->prefix_num = htons(prefix_num);
1215
1216 /* Fill LSA Header */
1217 lsa_header->age = 0;
1218 lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
9a703f8d 1219 lsa_header->id = htonl(ls_id++);
d62a17ae 1220 lsa_header->adv_router = oa->ospf6->router_id;
1221 lsa_header->seqnum =
1222 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
1223 lsa_header->adv_router, oa->lsdb);
1224 lsa_header->length = htons((caddr_t)op - (caddr_t)lsa_header);
1225
1226 /* LSA checksum */
1227 ospf6_lsa_checksum(lsa_header);
1228
1229 /* create LSA */
1230 lsa = ospf6_lsa_create(lsa_header);
1231
1232 /* Originate */
1233 ospf6_lsa_originate_area(lsa, oa);
1234
1235 return 0;
508e53e2 1236}
718e3744 1237
6452df09 1238
d62a17ae 1239int ospf6_intra_prefix_lsa_originate_transit(struct thread *thread)
508e53e2 1240{
d62a17ae 1241 struct ospf6_interface *oi;
1242
1243 char buffer[OSPF6_MAX_LSASIZE];
1244 struct ospf6_lsa_header *lsa_header;
1245 struct ospf6_lsa *old, *lsa;
1246
1247 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1248 struct ospf6_neighbor *on;
1249 struct ospf6_route *route;
1250 struct ospf6_prefix *op;
1251 struct listnode *i;
1252 int full_count = 0;
1253 unsigned short prefix_num = 0;
1254 struct ospf6_route_table *route_advertise;
1255 struct ospf6_link_lsa *link_lsa;
1256 char *start, *end, *current;
d7c0a89a 1257 uint16_t type;
d62a17ae 1258
1259 oi = (struct ospf6_interface *)THREAD_ARG(thread);
1260 oi->thread_intra_prefix_lsa = NULL;
1261
1262 assert(oi->area);
1263
1264 /* find previous LSA */
1265 old = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_INTRA_PREFIX),
1266 htonl(oi->interface->ifindex),
1267 oi->area->ospf6->router_id, oi->area->lsdb);
1268
1269 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
1270 if (old)
1271 ospf6_lsa_purge(old);
1272 return 0;
1273 }
1274
1275 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1276 zlog_debug(
1277 "Originate Intra-Area-Prefix-LSA for interface %s's prefix",
1278 oi->interface->name);
1279
1280 /* prepare buffer */
1281 memset(buffer, 0, sizeof(buffer));
1282 lsa_header = (struct ospf6_lsa_header *)buffer;
1283 intra_prefix_lsa = (struct ospf6_intra_prefix_lsa
1284 *)((caddr_t)lsa_header
1285 + sizeof(struct ospf6_lsa_header));
1286
1287 /* Fill Intra-Area-Prefix-LSA */
1288 intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_NETWORK);
1289 intra_prefix_lsa->ref_id = htonl(oi->interface->ifindex);
1290 intra_prefix_lsa->ref_adv_router = oi->area->ospf6->router_id;
1291
1292 if (oi->state != OSPF6_INTERFACE_DR) {
1293 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1294 zlog_debug(" Interface is not DR");
1295 if (old)
1296 ospf6_lsa_purge(old);
1297 return 0;
1298 }
1299
1300 full_count = 0;
1301 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, i, on))
1302 if (on->state == OSPF6_NEIGHBOR_FULL)
1303 full_count++;
1304
1305 if (full_count == 0) {
1306 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1307 zlog_debug(" Interface is stub");
1308 if (old)
1309 ospf6_lsa_purge(old);
1310 return 0;
1311 }
1312
1313 /* connected prefix to advertise */
1314 route_advertise = ospf6_route_table_create(0, 0);
f85b7619 1315 route_advertise->hook_add = NULL;
1316 route_advertise->hook_remove = NULL;
d62a17ae 1317
1318 type = ntohs(OSPF6_LSTYPE_LINK);
1319 for (ALL_LSDB_TYPED(oi->lsdb, type, lsa)) {
1320 if (OSPF6_LSA_IS_MAXAGE(lsa))
1321 continue;
1322
1323 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1324 zlog_debug(" include prefix from %s", lsa->name);
1325
1326 if (lsa->header->adv_router != oi->area->ospf6->router_id) {
1327 on = ospf6_neighbor_lookup(lsa->header->adv_router, oi);
1328 if (on == NULL || on->state != OSPF6_NEIGHBOR_FULL) {
1329 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1330 zlog_debug(
1331 " Neighbor not found or not Full, ignore");
1332 continue;
1333 }
1334 }
1335
1336 link_lsa = (struct ospf6_link_lsa
1337 *)((caddr_t)lsa->header
1338 + sizeof(struct ospf6_lsa_header));
1339
1340 prefix_num = (unsigned short)ntohl(link_lsa->prefix_num);
1341 start = (char *)link_lsa + sizeof(struct ospf6_link_lsa);
1342 end = (char *)lsa->header + ntohs(lsa->header->length);
1343 for (current = start; current < end && prefix_num;
1344 current += OSPF6_PREFIX_SIZE(op)) {
1345 op = (struct ospf6_prefix *)current;
1346 if (op->prefix_length == 0
1347 || current + OSPF6_PREFIX_SIZE(op) > end)
1348 break;
1349
1350 route = ospf6_route_create();
1351
1352 route->type = OSPF6_DEST_TYPE_NETWORK;
1353 route->prefix.family = AF_INET6;
1354 route->prefix.prefixlen = op->prefix_length;
1355 memset(&route->prefix.u.prefix6, 0,
1356 sizeof(struct in6_addr));
1357 memcpy(&route->prefix.u.prefix6, OSPF6_PREFIX_BODY(op),
1358 OSPF6_PREFIX_SPACE(op->prefix_length));
1359
1360 route->path.origin.type = lsa->header->type;
1361 route->path.origin.id = lsa->header->id;
1362 route->path.origin.adv_router = lsa->header->adv_router;
1363 route->path.options[0] = link_lsa->options[0];
1364 route->path.options[1] = link_lsa->options[1];
1365 route->path.options[2] = link_lsa->options[2];
1366 route->path.prefix_options = op->prefix_options;
1367 route->path.area_id = oi->area->area_id;
1368 route->path.type = OSPF6_PATH_TYPE_INTRA;
1369
2dbe669b
DA
1370 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1371 zlog_debug(" include %pFX", &route->prefix);
d62a17ae 1372
e285b70d 1373 ospf6_route_add(route, route_advertise);
d62a17ae 1374 prefix_num--;
1375 }
1376 if (current != end && IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1377 zlog_debug("Trailing garbage in %s", lsa->name);
1378 }
1379
1380 op = (struct ospf6_prefix *)((caddr_t)intra_prefix_lsa
1381 + sizeof(struct ospf6_intra_prefix_lsa));
1382
1383 prefix_num = 0;
1384 for (route = ospf6_route_head(route_advertise); route;
1385 route = ospf6_route_best_next(route)) {
1386 op->prefix_length = route->prefix.prefixlen;
1387 op->prefix_options = route->path.prefix_options;
1388 op->prefix_metric = htons(0);
1389 memcpy(OSPF6_PREFIX_BODY(op), &route->prefix.u.prefix6,
1390 OSPF6_PREFIX_SPACE(op->prefix_length));
1391 op = OSPF6_PREFIX_NEXT(op);
1392 prefix_num++;
1393 }
1394
e285b70d 1395 ospf6_route_table_delete(route_advertise);
d62a17ae 1396
1397 if (prefix_num == 0) {
1398 if (IS_OSPF6_DEBUG_ORIGINATE(INTRA_PREFIX))
1399 zlog_debug(
1400 "Quit to Advertise Intra-Prefix: no route to advertise");
1401 return 0;
1402 }
1403
1404 intra_prefix_lsa->prefix_num = htons(prefix_num);
1405
1406 /* Fill LSA Header */
1407 lsa_header->age = 0;
1408 lsa_header->type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
1409 lsa_header->id = htonl(oi->interface->ifindex);
1410 lsa_header->adv_router = oi->area->ospf6->router_id;
1411 lsa_header->seqnum =
1412 ospf6_new_ls_seqnum(lsa_header->type, lsa_header->id,
1413 lsa_header->adv_router, oi->area->lsdb);
1414 lsa_header->length = htons((caddr_t)op - (caddr_t)lsa_header);
1415
1416 /* LSA checksum */
1417 ospf6_lsa_checksum(lsa_header);
1418
1419 /* create LSA */
1420 lsa = ospf6_lsa_create(lsa_header);
1421
1422 /* Originate */
1423 ospf6_lsa_originate_area(lsa, oi->area);
1424
1425 return 0;
508e53e2 1426}
1427
beadc736 1428static void ospf6_intra_prefix_update_route_origin(struct ospf6_route *oa_route,
1429 struct ospf6 *ospf6)
6942698d
CS
1430{
1431 struct ospf6_path *h_path;
1432 struct ospf6_route *g_route, *nroute;
1433
1434 /* Update Global ospf6 route path */
beadc736 1435 g_route = ospf6_route_lookup(&oa_route->prefix, ospf6->route_table);
6942698d 1436
bacd0940 1437 assert(g_route);
1438
6942698d
CS
1439 for (ospf6_route_lock(g_route); g_route &&
1440 ospf6_route_is_prefix(&oa_route->prefix, g_route);
1441 g_route = nroute) {
1442 nroute = ospf6_route_next(g_route);
1443 if (g_route->type != oa_route->type)
1444 continue;
1445 if (g_route->path.area_id != oa_route->path.area_id)
1446 continue;
1447 if (g_route->path.type != OSPF6_PATH_TYPE_INTRA)
1448 continue;
1449 if (g_route->path.cost != oa_route->path.cost)
1450 continue;
1451
1452 if (ospf6_route_is_same_origin(g_route, oa_route)) {
1453 h_path = (struct ospf6_path *)listgetdata(
1454 listhead(g_route->paths));
1455 g_route->path.origin.type = h_path->origin.type;
1456 g_route->path.origin.id = h_path->origin.id;
1457 g_route->path.origin.adv_router =
1458 h_path->origin.adv_router;
b9b87bfc
S
1459 if (nroute)
1460 ospf6_route_unlock(nroute);
6942698d
CS
1461 break;
1462 }
1463 }
1464
1465 h_path = (struct ospf6_path *)listgetdata(
1466 listhead(oa_route->paths));
1467 oa_route->path.origin.type = h_path->origin.type;
1468 oa_route->path.origin.id = h_path->origin.id;
1469 oa_route->path.origin.adv_router = h_path->origin.adv_router;
1470}
1471
03f3c1c1
CS
1472void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area *oa,
1473 struct ospf6_route *old,
1474 struct ospf6_route *route)
1475{
6942698d 1476 struct ospf6_route *old_route, *ls_entry;
03f3c1c1
CS
1477 struct ospf6_path *ecmp_path, *o_path = NULL;
1478 struct listnode *anode, *anext;
1479 struct listnode *nnode, *rnode, *rnext;
1480 struct ospf6_nexthop *nh, *rnh;
1481 char buf[PREFIX2STR_BUFFER];
1482 bool route_found = false;
cad3ca4c 1483 struct interface *ifp = NULL;
6942698d
CS
1484 struct ospf6_lsa *lsa;
1485 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
03f3c1c1
CS
1486
1487 /* check for old entry match with new route origin,
1488 * delete old entry.
1489 */
1490 for (old_route = old; old_route; old_route = old_route->next) {
1491 bool route_updated = false;
1492
1493 if (!ospf6_route_is_same(old_route, route) ||
1494 (old_route->path.type != route->path.type))
1495 continue;
1496
1497 /* Current and New route has same origin,
1498 * delete old entry.
1499 */
1500 for (ALL_LIST_ELEMENTS(old_route->paths, anode, anext,
1501 o_path)) {
1502 /* Check old route path and route has same
1503 * origin.
1504 */
1505 if (o_path->area_id != route->path.area_id ||
1506 (memcmp(&(o_path)->origin, &(route)->path.origin,
1507 sizeof(struct ospf6_ls_origin)) != 0))
1508 continue;
1509
1510 /* Cost is not same then delete current path */
1511 if (o_path->cost == route->path.cost)
1512 continue;
1513
1514 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
5e81f5dd 1515 zlog_debug(
dc138868
DL
1516 "%s: route %pFX cost old %u new %u is not same, replace route",
1517 __func__, &old_route->prefix, o_path->cost,
5e81f5dd 1518 route->path.cost);
03f3c1c1
CS
1519 }
1520
6942698d 1521 /* Remove selected current path's nh from
03f3c1c1
CS
1522 * effective nh list.
1523 */
1524 for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
1525 for (ALL_LIST_ELEMENTS(old_route->nh_list,
1526 rnode, rnext, rnh)) {
1527 if (!ospf6_nexthop_is_same(rnh, nh))
1528 continue;
1529 listnode_delete(old_route->nh_list,
1530 rnh);
1531 ospf6_nexthop_delete(rnh);
1532 route_updated = true;
1533 }
1534 }
1535
1536 listnode_delete(old_route->paths, o_path);
1537 ospf6_path_free(o_path);
1538
1539 /* Current route's path (adv_router info) is similar
1540 * to route being added.
1541 * Replace current route's path with paths list head.
1542 * Update FIB with effective NHs.
1543 */
1544 if (listcount(old_route->paths)) {
03f3c1c1
CS
1545 if (route_updated) {
1546 for (ALL_LIST_ELEMENTS(old_route->paths,
1547 anode, anext, o_path)) {
1548 ospf6_merge_nexthops(
1549 old_route->nh_list,
1550 o_path->nh_list);
1551 }
1552 /* Update ospf6 route table and
1553 * RIB/FIB with effective
1554 * nh_list
1555 */
1556 if (oa->route_table->hook_add)
beadc736 1557 (*oa->route_table->hook_add)(
e285b70d 1558 old_route);
6942698d
CS
1559
1560 if (old_route->path.origin.id ==
1561 route->path.origin.id &&
1562 old_route->path.origin.adv_router ==
1563 route->path.origin.adv_router) {
1564 ospf6_intra_prefix_update_route_origin(
beadc736 1565 old_route, oa->ospf6);
6942698d 1566 }
03f3c1c1
CS
1567 break;
1568 }
1569 } else {
1570 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
5e81f5dd 1571 zlog_debug(
dc138868
DL
1572 "%s: route %pFX old cost %u new cost %u, delete old entry.",
1573 __func__, &old_route->prefix,
5e81f5dd
DS
1574 old_route->path.cost,
1575 route->path.cost);
03f3c1c1 1576 }
6942698d
CS
1577 if (oa->route_table->hook_remove)
1578 ospf6_route_remove(old_route,
e285b70d 1579 oa->route_table);
6942698d
CS
1580 else
1581 SET_FLAG(old_route->flag,
1582 OSPF6_ROUTE_REMOVE);
03f3c1c1
CS
1583 break;
1584 }
1585 }
1586 if (route_updated)
1587 break;
1588 }
1589
1590 for (old_route = old; old_route; old_route = old_route->next) {
1591
1592 if (!ospf6_route_is_same(old_route, route) ||
1593 (old_route->path.type != route->path.type))
1594 continue;
1595
1596 /* Old Route and New Route have Equal Cost, Merge NHs */
1597 if (old_route->path.cost == route->path.cost) {
1598 route_found = true;
1599
1600 /* check if this path exists already in
1601 * route->paths list, if so, replace nh_list.
1602 */
1603 for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
1604 o_path)) {
1605 if (o_path->area_id == route->path.area_id &&
1606 (memcmp(&(o_path)->origin,
1607 &(route)->path.origin,
1608 sizeof(struct ospf6_ls_origin)) == 0))
1609 break;
1610 }
1611 /* If path is not found in old_route paths's list,
1612 * add a new path to route paths list and merge
1613 * nexthops in route->path->nh_list.
1614 * Otherwise replace existing path's nh_list.
1615 */
1616 if (o_path == NULL) {
1617 ecmp_path = ospf6_path_dup(&route->path);
1618
1619 /* Add a nh_list to new ecmp path */
1620 ospf6_copy_nexthops(ecmp_path->nh_list,
1621 route->nh_list);
03f3c1c1
CS
1622 /* Add the new path to route's path list */
1623 listnode_add_sort(old_route->paths, ecmp_path);
1624
03f3c1c1 1625 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
6942698d 1626 zlog_debug(
dc138868
DL
1627 "%s: route %pFX %p another path added with nh %u, effective paths %u nh %u",
1628 __func__, &route->prefix,
03f3c1c1
CS
1629 (void *)old_route,
1630 listcount(ecmp_path->nh_list),
5e81f5dd
DS
1631 old_route->paths ? listcount(
1632 old_route->paths)
1633 : 0,
03f3c1c1 1634 listcount(old_route->nh_list));
03f3c1c1 1635 }
6942698d 1636 } else {
03f3c1c1
CS
1637 list_delete_all_node(o_path->nh_list);
1638 ospf6_copy_nexthops(o_path->nh_list,
1639 route->nh_list);
1640
6942698d 1641 }
03f3c1c1 1642
6942698d
CS
1643 list_delete_all_node(old_route->nh_list);
1644
1645 for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
1646 o_path)) {
1647 ls_entry = ospf6_route_lookup(
1648 &o_path->ls_prefix,
1649 oa->spf_table);
1650 if (ls_entry == NULL) {
1651 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
5e81f5dd
DS
1652 zlog_debug(
1653 "%s: ls_prfix %s ls_entry not found.",
1654 __func__, buf);
6942698d 1655 continue;
03f3c1c1 1656 }
6942698d
CS
1657 lsa = ospf6_lsdb_lookup(o_path->origin.type,
1658 o_path->origin.id,
1659 o_path->origin.adv_router,
1660 oa->lsdb);
1661 if (lsa == NULL) {
1662 if (IS_OSPF6_DEBUG_EXAMIN(
1663 INTRA_PREFIX)) {
1664 struct prefix adv_prefix;
03f3c1c1 1665
6942698d
CS
1666 ospf6_linkstate_prefix(
1667 o_path->origin.adv_router,
1668 o_path->origin.id, &adv_prefix);
5e81f5dd 1669 zlog_debug(
2dbe669b
DA
1670 "%s: adv_router %pFX lsa not found",
1671 __func__, &adv_prefix);
6942698d
CS
1672 }
1673 continue;
1674 }
1675 intra_prefix_lsa =
1676 (struct ospf6_intra_prefix_lsa *)
1677 OSPF6_LSA_HEADER_END(lsa->header);
1678
1679 if (intra_prefix_lsa->ref_adv_router
1680 == oa->ospf6->router_id) {
1681 ifp = if_lookup_prefix(
c5d28568
K
1682 &old_route->prefix,
1683 oa->ospf6->vrf_id);
cad3ca4c
S
1684 }
1685
1686 if (ifp) {
1687 /* Nexthop interface found */
1688 ospf6_route_add_nexthop(old_route,
6942698d
CS
1689 ifp->ifindex,
1690 NULL);
1691 } else {
cad3ca4c
S
1692 /* The connected interfaces between
1693 * routers can be in different networks.
1694 * In this case the matching interface
1695 * is not found. Copy nexthops from the
1696 * link state entry
1697 */
6942698d
CS
1698 ospf6_route_merge_nexthops(old_route,
1699 ls_entry);
1700 }
03f3c1c1 1701 }
6942698d 1702
2dbe669b 1703 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
5e81f5dd 1704 zlog_debug(
f6c5f2e0 1705 "%s: route %pFX %p with final effective paths %u nh %u",
2dbe669b
DA
1706 __func__, &route->prefix,
1707 (void *)old_route,
5e81f5dd
DS
1708 old_route->paths
1709 ? listcount(old_route->paths)
1710 : 0,
1711 listcount(old_route->nh_list));
6942698d
CS
1712
1713 /* used in intra_route_calculation() to add to
1714 * global ospf6 route table.
1715 */
1716 UNSET_FLAG(old_route->flag, OSPF6_ROUTE_REMOVE);
1717 SET_FLAG(old_route->flag, OSPF6_ROUTE_ADD);
1718 /* Update ospf6 route table and RIB/FIB */
1719 if (oa->route_table->hook_add)
e285b70d 1720 (*oa->route_table->hook_add)(old_route);
03f3c1c1
CS
1721 /* Delete the new route its info added to existing
1722 * route.
1723 */
1724 ospf6_route_delete(route);
1725
1726 break;
1727 }
1728 }
1729
1730 if (!route_found) {
1731 /* Add new route to existing node in ospf6 route table. */
e285b70d 1732 ospf6_route_add(route, oa->route_table);
03f3c1c1
CS
1733 }
1734}
1735
d62a17ae 1736void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa)
508e53e2 1737{
d62a17ae 1738 struct ospf6_area *oa;
1739 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1740 struct prefix ls_prefix;
03f3c1c1 1741 struct ospf6_route *route, *ls_entry, *old;
d62a17ae 1742 int prefix_num;
1743 struct ospf6_prefix *op;
1744 char *start, *current, *end;
1745 char buf[PREFIX2STR_BUFFER];
cad3ca4c 1746 struct interface *ifp = NULL;
d62a17ae 1747 int direct_connect = 0;
10efbdc2 1748 struct ospf6_path *path;
d62a17ae 1749
1750 if (OSPF6_LSA_IS_MAXAGE(lsa))
1751 return;
1752
1753 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
15569c58 1754 zlog_debug("%s: LSA %s found", __func__, lsa->name);
d62a17ae 1755
1756 oa = OSPF6_AREA(lsa->lsdb->data);
1757
1758 intra_prefix_lsa =
1759 (struct ospf6_intra_prefix_lsa *)OSPF6_LSA_HEADER_END(
1760 lsa->header);
1761 if (intra_prefix_lsa->ref_type == htons(OSPF6_LSTYPE_ROUTER))
1762 ospf6_linkstate_prefix(intra_prefix_lsa->ref_adv_router,
26e14616 1763 intra_prefix_lsa->ref_id, &ls_prefix);
d62a17ae 1764 else if (intra_prefix_lsa->ref_type == htons(OSPF6_LSTYPE_NETWORK))
1765 ospf6_linkstate_prefix(intra_prefix_lsa->ref_adv_router,
1766 intra_prefix_lsa->ref_id, &ls_prefix);
1767 else {
1768 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
1769 zlog_debug("Unknown reference LS-type: %#hx",
1770 ntohs(intra_prefix_lsa->ref_type));
1771 return;
1772 }
1773
1774 ls_entry = ospf6_route_lookup(&ls_prefix, oa->spf_table);
1775 if (ls_entry == NULL) {
1776 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
1777 ospf6_linkstate_prefix2str(&ls_prefix, buf,
1778 sizeof(buf));
1779 zlog_debug("LS entry does not exist: %s", buf);
1780 }
1781 return;
1782 }
1783
1784 if (intra_prefix_lsa->ref_adv_router == oa->ospf6->router_id) {
1785 /* the intra-prefix are directly connected */
1786 direct_connect = 1;
1787 }
1788
1789 prefix_num = ntohs(intra_prefix_lsa->prefix_num);
1790 start = (caddr_t)intra_prefix_lsa
1791 + sizeof(struct ospf6_intra_prefix_lsa);
1792 end = OSPF6_LSA_END(lsa->header);
1793 for (current = start; current < end; current += OSPF6_PREFIX_SIZE(op)) {
1794 op = (struct ospf6_prefix *)current;
1795 if (prefix_num == 0)
1796 break;
1797 if (end < current + OSPF6_PREFIX_SIZE(op))
1798 break;
1799
1800 /* Appendix A.4.1.1 */
1801 if (CHECK_FLAG(op->prefix_options, OSPF6_PREFIX_OPTION_NU)) {
1802 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
1803 ospf6_linkstate_prefix2str(
1804 (struct prefix *)OSPF6_PREFIX_BODY(op),
1805 buf, sizeof(buf));
1806 zlog_debug(
1807 "%s: Skipping Prefix %s has NU option set",
1808 __func__, buf);
1809 }
1810 continue;
1811 }
1812
1813 route = ospf6_route_create();
1814
1815 memset(&route->prefix, 0, sizeof(struct prefix));
1816 route->prefix.family = AF_INET6;
1817 route->prefix.prefixlen = op->prefix_length;
b8ce0c36 1818 ospf6_prefix_in6_addr(&route->prefix.u.prefix6,
1819 intra_prefix_lsa, op);
d62a17ae 1820
1821 route->type = OSPF6_DEST_TYPE_NETWORK;
1822 route->path.origin.type = lsa->header->type;
1823 route->path.origin.id = lsa->header->id;
1824 route->path.origin.adv_router = lsa->header->adv_router;
1825 route->path.prefix_options = op->prefix_options;
1826 route->path.area_id = oa->area_id;
1827 route->path.type = OSPF6_PATH_TYPE_INTRA;
1828 route->path.metric_type = 1;
1829 route->path.cost =
1830 ls_entry->path.cost + ntohs(op->prefix_metric);
6942698d
CS
1831 memcpy(&route->path.ls_prefix, &ls_prefix,
1832 sizeof(struct prefix));
d62a17ae 1833 if (direct_connect) {
c5d28568
K
1834 ifp = if_lookup_prefix(&route->prefix,
1835 oa->ospf6->vrf_id);
cad3ca4c
S
1836 }
1837
1838 if (ifp) {
1839 /* Nexthop interface found */
1840 ospf6_route_add_nexthop(route, ifp->ifindex, NULL);
d62a17ae 1841 } else {
cad3ca4c
S
1842 /* The connected interfaces between routers can be in
1843 * different networks. In this case the matching
1844 * interface is not found. Copy nexthops from the
1845 * link state entry
1846 */
d62a17ae 1847 ospf6_route_copy_nexthops(route, ls_entry);
1848 }
1849
10efbdc2
CS
1850 path = ospf6_path_dup(&route->path);
1851 ospf6_copy_nexthops(path->nh_list, route->path.nh_list);
1852 listnode_add_sort(route->paths, path);
1853
03f3c1c1 1854 old = ospf6_route_lookup(&route->prefix, oa->route_table);
beabf870 1855 if (old) {
03f3c1c1
CS
1856 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
1857 prefix2str(&route->prefix, buf, sizeof(buf));
15569c58
DA
1858 zlog_debug(
1859 "%s Update route: %s old cost %u new cost %u paths %u nh %u",
1860 __func__, buf, old->path.cost,
1861 route->path.cost,
1862 listcount(route->paths),
1863 listcount(route->nh_list));
03f3c1c1
CS
1864 }
1865 ospf6_intra_prefix_route_ecmp_path(oa, old, route);
1866 } else {
1867 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
1868 prefix2str(&route->prefix, buf, sizeof(buf));
15569c58
DA
1869 zlog_debug(
1870 "%s route %s add with cost %u paths %u nh %u",
1871 __func__, buf, route->path.cost,
1872 listcount(route->paths),
1873 listcount(route->nh_list));
03f3c1c1 1874 }
e285b70d 1875 ospf6_route_add(route, oa->route_table);
d62a17ae 1876 }
d62a17ae 1877 prefix_num--;
e68a6767
DD
1878 }
1879
d62a17ae 1880 if (current != end && IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
1881 zlog_debug("Trailing garbage ignored");
718e3744 1882}
1883
6942698d
CS
1884static void ospf6_intra_prefix_lsa_remove_update_route(struct ospf6_lsa *lsa,
1885 struct ospf6_area *oa,
1886 struct ospf6_route *route)
1887{
1888 struct listnode *anode, *anext;
1889 struct listnode *nnode, *rnode, *rnext;
1890 struct ospf6_nexthop *nh, *rnh;
1891 struct ospf6_path *o_path;
1892 bool nh_updated = false;
1893 char buf[PREFIX2STR_BUFFER];
1894
1895 /* Iterate all paths of route to find maching
1896 * with LSA remove info.
1897 * If route->path is same, replace
1898 * from paths list.
1899 */
1900 for (ALL_LIST_ELEMENTS(route->paths, anode, anext, o_path)) {
1901 if ((o_path->origin.type != lsa->header->type) ||
1902 (o_path->origin.adv_router != lsa->header->adv_router) ||
1903 (o_path->origin.id != lsa->header->id))
1904 continue;
1905
1906 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
1907 prefix2str(&route->prefix, buf, sizeof(buf));
1908 zlog_debug(
1909 "%s: route %s path found with cost %u nh %u to remove.",
5e81f5dd 1910 __func__, buf, o_path->cost,
6942698d
CS
1911 listcount(o_path->nh_list));
1912 }
1913
1914 /* Remove found path's nh_list from
1915 * the route's nh_list.
1916 */
1917 for (ALL_LIST_ELEMENTS_RO(o_path->nh_list, nnode, nh)) {
1918 for (ALL_LIST_ELEMENTS(route->nh_list, rnode,
1919 rnext, rnh)) {
1920 if (!ospf6_nexthop_is_same(rnh, nh))
1921 continue;
1922 listnode_delete(route->nh_list, rnh);
1923 ospf6_nexthop_delete(rnh);
1924 }
1925 }
1926 /* Delete the path from route's
1927 * path list
1928 */
1929 listnode_delete(route->paths, o_path);
1930 ospf6_path_free(o_path);
1931 nh_updated = true;
1932 break;
1933 }
1934
1935 if (nh_updated) {
1936 /* Iterate all paths and merge nexthop,
1937 * unlesss any of the nexthop similar to
1938 * ones deleted as part of path deletion.
1939 */
1940 for (ALL_LIST_ELEMENTS(route->paths, anode, anext, o_path))
1941 ospf6_merge_nexthops(route->nh_list, o_path->nh_list);
1942
1943
1944 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
1945 prefix2str(&route->prefix, buf, sizeof(buf));
5e81f5dd
DS
1946 zlog_debug(
1947 "%s: route %s update paths %u nh %u", __func__,
1948 buf, route->paths ? listcount(route->paths) : 0,
1949 route->nh_list ? listcount(route->nh_list) : 0);
6942698d
CS
1950 }
1951
1952 /* Update Global Route table and
1953 * RIB/FIB with effective
1954 * nh_list
1955 */
1956 if (oa->route_table->hook_add)
e285b70d 1957 (*oa->route_table->hook_add)(route);
6942698d
CS
1958
1959 /* route's primary path is similar
1960 * to LSA, replace route's primary
1961 * path with route's paths list
1962 * head.
1963 */
1964 if ((route->path.origin.id == lsa->header->id) &&
1965 (route->path.origin.adv_router ==
1966 lsa->header->adv_router)) {
beadc736 1967 ospf6_intra_prefix_update_route_origin(route,
1968 oa->ospf6);
6942698d
CS
1969 }
1970 }
1971
1972}
1973
d62a17ae 1974void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa *lsa)
718e3744 1975{
d62a17ae 1976 struct ospf6_area *oa;
1977 struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
1978 struct prefix prefix;
6942698d 1979 struct ospf6_route *route, *nroute;
d62a17ae 1980 int prefix_num;
1981 struct ospf6_prefix *op;
1982 char *start, *current, *end;
1983 char buf[PREFIX2STR_BUFFER];
1984
1985 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
15569c58 1986 zlog_debug("%s: %s disappearing", __func__, lsa->name);
d62a17ae 1987
1988 oa = OSPF6_AREA(lsa->lsdb->data);
1989
1990 intra_prefix_lsa =
1991 (struct ospf6_intra_prefix_lsa *)OSPF6_LSA_HEADER_END(
1992 lsa->header);
1993
1994 prefix_num = ntohs(intra_prefix_lsa->prefix_num);
1995 start = (caddr_t)intra_prefix_lsa
1996 + sizeof(struct ospf6_intra_prefix_lsa);
1997 end = OSPF6_LSA_END(lsa->header);
1998 for (current = start; current < end; current += OSPF6_PREFIX_SIZE(op)) {
1999 op = (struct ospf6_prefix *)current;
2000 if (prefix_num == 0)
2001 break;
2002 if (end < current + OSPF6_PREFIX_SIZE(op))
2003 break;
2004 prefix_num--;
2005
2006 memset(&prefix, 0, sizeof(struct prefix));
2007 prefix.family = AF_INET6;
2008 prefix.prefixlen = op->prefix_length;
b8ce0c36 2009 ospf6_prefix_in6_addr(&prefix.u.prefix6, intra_prefix_lsa, op);
d62a17ae 2010
2011 route = ospf6_route_lookup(&prefix, oa->route_table);
2012 if (route == NULL)
2013 continue;
2014
2015 for (ospf6_route_lock(route);
2016 route && ospf6_route_is_prefix(&prefix, route);
2017 route = nroute) {
2018 nroute = ospf6_route_next(route);
2019 if (route->type != OSPF6_DEST_TYPE_NETWORK)
2020 continue;
2021 if (route->path.area_id != oa->area_id)
2022 continue;
2023 if (route->path.type != OSPF6_PATH_TYPE_INTRA)
2024 continue;
03f3c1c1
CS
2025 /* Route has multiple ECMP paths, remove matching
2026 * path. Update current route's effective nh list
2027 * after removal of one of the path.
2028 */
2029 if (listcount(route->paths) > 1) {
6942698d
CS
2030 ospf6_intra_prefix_lsa_remove_update_route(
2031 lsa, oa, route);
03f3c1c1
CS
2032 } else {
2033
2034 if (route->path.origin.type != lsa->header->type
2035 || route->path.origin.id != lsa->header->id
2036 || route->path.origin.adv_router
2037 != lsa->header->adv_router)
2038 continue;
2039
2040 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
2041 prefix2str(&route->prefix, buf,
2042 sizeof(buf));
15569c58
DA
2043 zlog_debug(
2044 "%s: route remove %s with path type %u cost %u paths %u nh %u",
2045 __func__, buf, route->path.type,
2046 route->path.cost,
2047 listcount(route->paths),
2048 listcount(route->nh_list));
03f3c1c1 2049 }
e285b70d 2050 ospf6_route_remove(route, oa->route_table);
d62a17ae 2051 }
d62a17ae 2052 }
2053 if (route)
2054 ospf6_route_unlock(route);
2055 }
2056
2057 if (current != end && IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
2058 zlog_debug("Trailing garbage ignored");
718e3744 2059}
2060
d62a17ae 2061void ospf6_intra_route_calculation(struct ospf6_area *oa)
718e3744 2062{
d62a17ae 2063 struct ospf6_route *route, *nroute;
d7c0a89a 2064 uint16_t type;
d62a17ae 2065 struct ospf6_lsa *lsa;
e285b70d
IR
2066 void (*hook_add)(struct ospf6_route *) = NULL;
2067 void (*hook_remove)(struct ospf6_route *) = NULL;
35769de4 2068 char buf[PREFIX2STR_BUFFER];
d62a17ae 2069
2070 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
2071 zlog_debug("Re-examin intra-routes for area %s", oa->name);
2072
2073 hook_add = oa->route_table->hook_add;
2074 hook_remove = oa->route_table->hook_remove;
2075 oa->route_table->hook_add = NULL;
2076 oa->route_table->hook_remove = NULL;
2077
2078 for (route = ospf6_route_head(oa->route_table); route;
2079 route = ospf6_route_next(route))
2080 route->flag = OSPF6_ROUTE_REMOVE;
2081
2082 type = htons(OSPF6_LSTYPE_INTRA_PREFIX);
2083 for (ALL_LSDB_TYPED(oa->lsdb, type, lsa))
2084 ospf6_intra_prefix_lsa_add(lsa);
2085
2086 oa->route_table->hook_add = hook_add;
2087 oa->route_table->hook_remove = hook_remove;
2088
2089 for (route = ospf6_route_head(oa->route_table); route; route = nroute) {
35769de4
K
2090 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) {
2091 prefix2str(&route->prefix, buf, sizeof(buf));
2092 zlog_debug("%s: route %s, flag 0x%x", __func__, buf,
2093 route->flag);
2094 }
2095
d62a17ae 2096 nroute = ospf6_route_next(route);
2097 if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE)
2098 && CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD)) {
2099 UNSET_FLAG(route->flag, OSPF6_ROUTE_REMOVE);
2100 UNSET_FLAG(route->flag, OSPF6_ROUTE_ADD);
2101 }
2102
2103 if (CHECK_FLAG(route->flag, OSPF6_ROUTE_REMOVE))
e285b70d 2104 ospf6_route_remove(route, oa->route_table);
d62a17ae 2105 else if (CHECK_FLAG(route->flag, OSPF6_ROUTE_ADD)
2106 || CHECK_FLAG(route->flag, OSPF6_ROUTE_CHANGE)) {
2107 if (hook_add)
e285b70d 2108 (*hook_add)(route);
d62a17ae 2109 route->flag = 0;
2110 } else {
2111 /* Redo the summaries as things might have changed */
35769de4
K
2112 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
2113 zlog_debug("%s: Originate summary for route %s",
2114 __func__, buf);
beadc736 2115 ospf6_abr_originate_summary(route, oa->ospf6);
d62a17ae 2116 route->flag = 0;
2117 }
ca1f4309 2118 }
508e53e2 2119
d62a17ae 2120 if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
2121 zlog_debug("Re-examin intra-routes for area %s: Done",
2122 oa->name);
718e3744 2123}
2124
d62a17ae 2125static void ospf6_brouter_debug_print(struct ospf6_route *brouter)
cf1ce250 2126{
d7c0a89a 2127 uint32_t brouter_id;
d62a17ae 2128 char brouter_name[16];
2129 char area_name[16];
2130 char destination[64];
68bfcc05 2131 char installed[64], changed[64];
d62a17ae 2132 struct timeval now, res;
2133 char id[16], adv_router[16];
2134 char capa[16], options[16];
2135
2136 brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
2137 inet_ntop(AF_INET, &brouter_id, brouter_name, sizeof(brouter_name));
2138 inet_ntop(AF_INET, &brouter->path.area_id, area_name,
2139 sizeof(area_name));
2140 ospf6_linkstate_prefix2str(&brouter->prefix, destination,
2141 sizeof(destination));
2142
2143 monotime(&now);
2144 timersub(&now, &brouter->installed, &res);
2145 timerstring(&res, installed, sizeof(installed));
2146
2147 monotime(&now);
2148 timersub(&now, &brouter->changed, &res);
2149 timerstring(&res, changed, sizeof(changed));
2150
2151 inet_ntop(AF_INET, &brouter->path.origin.id, id, sizeof(id));
2152 inet_ntop(AF_INET, &brouter->path.origin.adv_router, adv_router,
2153 sizeof(adv_router));
2154
2155 ospf6_options_printbuf(brouter->path.options, options, sizeof(options));
2156 ospf6_capability_printbuf(brouter->path.router_bits, capa,
2157 sizeof(capa));
2158
2159 zlog_info("Brouter: %s via area %s", brouter_name, area_name);
2160 zlog_info(" memory: prev: %p this: %p next: %p parent rnode: %p",
2161 (void *)brouter->prev, (void *)brouter, (void *)brouter->next,
2162 (void *)brouter->rnode);
2163 zlog_info(" type: %d prefix: %s installed: %s changed: %s",
2164 brouter->type, destination, installed, changed);
2165 zlog_info(" lock: %d flags: %s%s%s%s", brouter->lock,
2166 (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_BEST) ? "B" : "-"),
2167 (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_ADD) ? "A" : "-"),
2168 (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE) ? "R" : "-"),
2169 (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_CHANGE) ? "C" : "-"));
2170 zlog_info(" path type: %s ls-origin %s id: %s adv-router %s",
2171 OSPF6_PATH_TYPE_NAME(brouter->path.type),
2172 ospf6_lstype_name(brouter->path.origin.type), id, adv_router);
2173 zlog_info(" options: %s router-bits: %s metric-type: %d metric: %d/%d",
2174 options, capa, brouter->path.metric_type, brouter->path.cost,
2175 brouter->path.u.cost_e2);
804a3294
CS
2176 zlog_info(" paths %u nh %u", listcount(brouter->paths),
2177 listcount(brouter->nh_list));
cf1ce250
PJ
2178}
2179
d62a17ae 2180void ospf6_intra_brouter_calculation(struct ospf6_area *oa)
718e3744 2181{
d62a17ae 2182 struct ospf6_route *brouter, *nbrouter, *copy;
e285b70d
IR
2183 void (*hook_add)(struct ospf6_route *) = NULL;
2184 void (*hook_remove)(struct ospf6_route *) = NULL;
d7c0a89a 2185 uint32_t brouter_id;
d62a17ae 2186 char brouter_name[16];
2187
a2d0055a
CS
2188 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id) ||
2189 IS_OSPF6_DEBUG_ROUTE(MEMORY))
ad500b22
K
2190 zlog_debug("%s: border-router calculation for area %s",
2191 __func__, oa->name);
d62a17ae 2192
2193 hook_add = oa->ospf6->brouter_table->hook_add;
2194 hook_remove = oa->ospf6->brouter_table->hook_remove;
2195 oa->ospf6->brouter_table->hook_add = NULL;
2196 oa->ospf6->brouter_table->hook_remove = NULL;
2197
2198 /* withdraw the previous router entries for the area */
2199 for (brouter = ospf6_route_head(oa->ospf6->brouter_table); brouter;
2200 brouter = ospf6_route_next(brouter)) {
2201 brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
2202 inet_ntop(AF_INET, &brouter_id, brouter_name,
2203 sizeof(brouter_name));
c601fa3f 2204
d62a17ae 2205 if (brouter->path.area_id != oa->area_id)
2206 continue;
c601fa3f 2207
d62a17ae 2208 SET_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE);
2209
2210 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id)
2211 || IS_OSPF6_DEBUG_ROUTE(MEMORY)) {
ad500b22
K
2212 zlog_debug("%p: mark as removing: area %s brouter %s",
2213 (void *)brouter, oa->name, brouter_name);
d62a17ae 2214 ospf6_brouter_debug_print(brouter);
2215 }
2216 }
2217
2218 for (brouter = ospf6_route_head(oa->spf_table); brouter;
2219 brouter = ospf6_route_next(brouter)) {
2220 brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
2221 inet_ntop(AF_INET, &brouter_id, brouter_name,
2222 sizeof(brouter_name));
2223
2224 if (brouter->type != OSPF6_DEST_TYPE_LINKSTATE)
2225 continue;
c601fa3f 2226
d62a17ae 2227 if (ospf6_linkstate_prefix_id(&brouter->prefix) != htonl(0))
2228 continue;
c601fa3f 2229
d62a17ae 2230 if (!CHECK_FLAG(brouter->path.router_bits, OSPF6_ROUTER_BIT_E)
2231 && !CHECK_FLAG(brouter->path.router_bits,
2232 OSPF6_ROUTER_BIT_B))
2233 continue;
2234
2235 if (!OSPF6_OPT_ISSET(brouter->path.options, OSPF6_OPT_V6)
2236 || !OSPF6_OPT_ISSET(brouter->path.options, OSPF6_OPT_R))
2237 continue;
2238
2239 copy = ospf6_route_copy(brouter);
2240 copy->type = OSPF6_DEST_TYPE_ROUTER;
2241 copy->path.area_id = oa->area_id;
e285b70d 2242 ospf6_route_add(copy, oa->ospf6->brouter_table);
d62a17ae 2243
2244 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(brouter_id)
2245 || IS_OSPF6_DEBUG_ROUTE(MEMORY)) {
ad500b22
K
2246 zlog_debug("%p: transfer: area %s brouter %s",
2247 (void *)brouter, oa->name, brouter_name);
d62a17ae 2248 ospf6_brouter_debug_print(brouter);
2249 }
2250 }
2251
2252 oa->ospf6->brouter_table->hook_add = hook_add;
2253 oa->ospf6->brouter_table->hook_remove = hook_remove;
2254
2255 for (brouter = ospf6_route_head(oa->ospf6->brouter_table); brouter;
2256 brouter = nbrouter) {
a2d0055a 2257
33fb59c3
QY
2258 /*
2259 * brouter may have been "deleted" in the last loop iteration.
2260 * If this is the case there is still 1 final refcount lock
2261 * taken by ospf6_route_next, that will be released by the same
2262 * call and result in deletion. To avoid heap UAF we must then
2263 * skip processing the deleted route.
2264 */
2265 if (brouter->lock == 1) {
a2d0055a
CS
2266 if (IS_OSPF6_DEBUG_ROUTE(MEMORY))
2267 ospf6_brouter_debug_print(brouter);
33fb59c3
QY
2268 nbrouter = ospf6_route_next(brouter);
2269 continue;
2270 } else {
2271 nbrouter = ospf6_route_next(brouter);
2272 }
2273
d62a17ae 2274 brouter_id = ADV_ROUTER_IN_PREFIX(&brouter->prefix);
2275 inet_ntop(AF_INET, &brouter_id, brouter_name,
2276 sizeof(brouter_name));
2277
2278 if (brouter->path.area_id != oa->area_id)
2279 continue;
2280
2281 if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_WAS_REMOVED))
2282 continue;
2283
c601fa3f
CS
2284 /* After iterating spf_table for all routers including
2285 * intra brouter, clear mark for remove flag for
2286 * inter border router if its adv router present in
2287 * SPF table.
2288 */
2289 if (brouter->path.type == OSPF6_PATH_TYPE_INTER) {
2290 struct prefix adv_prefix;
2291
2292 ospf6_linkstate_prefix(brouter->path.origin.adv_router,
2293 htonl(0), &adv_prefix);
2294
2295 if (ospf6_route_lookup(&adv_prefix, oa->spf_table)) {
2296 if (IS_OSPF6_DEBUG_BROUTER) {
15569c58
DA
2297 zlog_debug(
2298 "%s: keep inter brouter %s as adv router 0x%x found in spf",
2299 __func__, brouter_name,
2300 brouter->path.origin
2301 .adv_router);
c601fa3f
CS
2302 ospf6_brouter_debug_print(brouter);
2303 }
2304 UNSET_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE);
2305 }
2306 }
2307
d62a17ae 2308 if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE)
2309 && CHECK_FLAG(brouter->flag, OSPF6_ROUTE_ADD)) {
2310 UNSET_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE);
2311 UNSET_FLAG(brouter->flag, OSPF6_ROUTE_ADD);
2312 }
2313
2314 if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_REMOVE)) {
2315 if (IS_OSPF6_DEBUG_BROUTER
2316 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2317 brouter_id)
2318 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2319 oa->area_id))
ad500b22 2320 zlog_debug(
15569c58
DA
2321 "%s: brouter %s disappears via area %s",
2322 __func__, brouter_name, oa->name);
a2d0055a
CS
2323 /* This is used to protect nbrouter from removed from
2324 * the table. For an example, ospf6_abr_examin_summary,
2325 * removes brouters which are marked for remove.
2326 */
2327 oa->intra_brouter_calc = 1;
e285b70d 2328 ospf6_route_remove(brouter, oa->ospf6->brouter_table);
d62a17ae 2329 brouter = NULL;
2330 } else if (CHECK_FLAG(brouter->flag, OSPF6_ROUTE_ADD)
2331 || CHECK_FLAG(brouter->flag, OSPF6_ROUTE_CHANGE)) {
2332 if (IS_OSPF6_DEBUG_BROUTER
2333 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2334 brouter_id)
2335 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2336 oa->area_id))
a2d0055a 2337 zlog_info("%s: brouter %s appears via area %s",
15569c58 2338 __func__, brouter_name, oa->name);
d62a17ae 2339
2340 /* newly added */
2341 if (hook_add)
e285b70d 2342 (*hook_add)(brouter);
d62a17ae 2343 } else {
2344 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ID(
2345 brouter_id)
2346 || IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(
2347 oa->area_id))
ad500b22
K
2348 zlog_debug(
2349 "brouter %s still exists via area %s",
2350 brouter_name, oa->name);
d62a17ae 2351 /* But re-originate summaries */
beadc736 2352 ospf6_abr_originate_summary(brouter, oa->ospf6);
d62a17ae 2353 }
2354
2355 if (brouter) {
2356 UNSET_FLAG(brouter->flag, OSPF6_ROUTE_ADD);
2357 UNSET_FLAG(brouter->flag, OSPF6_ROUTE_CHANGE);
2358 }
a2d0055a
CS
2359 /* Reset for nbrouter */
2360 oa->intra_brouter_calc = 0;
d62a17ae 2361 }
2362
a2d0055a
CS
2363 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ID(oa->area_id) ||
2364 IS_OSPF6_DEBUG_ROUTE(MEMORY))
ad500b22
K
2365 zlog_debug("%s: border-router calculation for area %s: done",
2366 __func__, oa->name);
718e3744 2367}
2368
4062abfa 2369static struct ospf6_lsa_handler router_handler = {
2b64873d
DL
2370 .lh_type = OSPF6_LSTYPE_ROUTER,
2371 .lh_name = "Router",
2372 .lh_short_name = "Rtr",
2373 .lh_show = ospf6_router_lsa_show,
2374 .lh_get_prefix_str = ospf6_router_lsa_get_nbr_id,
2375 .lh_debug = 0};
2376
4062abfa 2377static struct ospf6_lsa_handler network_handler = {
2b64873d
DL
2378 .lh_type = OSPF6_LSTYPE_NETWORK,
2379 .lh_name = "Network",
2380 .lh_short_name = "Net",
2381 .lh_show = ospf6_network_lsa_show,
2382 .lh_get_prefix_str = ospf6_network_lsa_get_ar_id,
2383 .lh_debug = 0};
2384
4062abfa 2385static struct ospf6_lsa_handler link_handler = {
2b64873d
DL
2386 .lh_type = OSPF6_LSTYPE_LINK,
2387 .lh_name = "Link",
2388 .lh_short_name = "Lnk",
2389 .lh_show = ospf6_link_lsa_show,
2390 .lh_get_prefix_str = ospf6_link_lsa_get_prefix_str,
2391 .lh_debug = 0};
2392
4062abfa 2393static struct ospf6_lsa_handler intra_prefix_handler = {
3981b5c7
VJ
2394 .lh_type = OSPF6_LSTYPE_INTRA_PREFIX,
2395 .lh_name = "Intra-Prefix",
2396 .lh_short_name = "INP",
2397 .lh_show = ospf6_intra_prefix_lsa_show,
2398 .lh_get_prefix_str = ospf6_intra_prefix_lsa_get_prefix_str,
996c9314 2399 .lh_debug = 0};
d62a17ae 2400
2401void ospf6_intra_init(void)
718e3744 2402{
d62a17ae 2403 ospf6_install_lsa_handler(&router_handler);
2404 ospf6_install_lsa_handler(&network_handler);
2405 ospf6_install_lsa_handler(&link_handler);
2406 ospf6_install_lsa_handler(&intra_prefix_handler);
718e3744 2407}
2408
cb4b8845
PJ
2409DEFUN (debug_ospf6_brouter,
2410 debug_ospf6_brouter_cmd,
2411 "debug ospf6 border-routers",
2412 DEBUG_STR
2413 OSPF6_STR
2414 "Debug border router\n"
2415 )
2416{
d62a17ae 2417 OSPF6_DEBUG_BROUTER_ON();
2418 return CMD_SUCCESS;
cb4b8845
PJ
2419}
2420
2421DEFUN (no_debug_ospf6_brouter,
2422 no_debug_ospf6_brouter_cmd,
2423 "no debug ospf6 border-routers",
2424 NO_STR
2425 DEBUG_STR
2426 OSPF6_STR
2427 "Debug border router\n"
2428 )
2429{
d62a17ae 2430 OSPF6_DEBUG_BROUTER_OFF();
2431 return CMD_SUCCESS;
cb4b8845
PJ
2432}
2433
2434DEFUN (debug_ospf6_brouter_router,
2435 debug_ospf6_brouter_router_cmd,
2436 "debug ospf6 border-routers router-id A.B.C.D",
2437 DEBUG_STR
2438 OSPF6_STR
2439 "Debug border router\n"
2440 "Debug specific border router\n"
2441 "Specify border-router's router-id\n"
2442 )
2443{
d62a17ae 2444 int idx_ipv4 = 4;
d7c0a89a 2445 uint32_t router_id;
d62a17ae 2446 inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
2447 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_ON(router_id);
2448 return CMD_SUCCESS;
cb4b8845
PJ
2449}
2450
2451DEFUN (no_debug_ospf6_brouter_router,
2452 no_debug_ospf6_brouter_router_cmd,
2453 "no debug ospf6 border-routers router-id",
2454 NO_STR
2455 DEBUG_STR
2456 OSPF6_STR
2457 "Debug border router\n"
2458 "Debug specific border router\n"
2459 )
2460{
d62a17ae 2461 OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER_OFF();
2462 return CMD_SUCCESS;
cb4b8845
PJ
2463}
2464
2465DEFUN (debug_ospf6_brouter_area,
2466 debug_ospf6_brouter_area_cmd,
2467 "debug ospf6 border-routers area-id A.B.C.D",
2468 DEBUG_STR
2469 OSPF6_STR
2470 "Debug border router\n"
2471 "Debug border routers in specific Area\n"
2472 "Specify Area-ID\n"
2473 )
2474{
d62a17ae 2475 int idx_ipv4 = 4;
d7c0a89a 2476 uint32_t area_id;
d62a17ae 2477 inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id);
2478 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_ON(area_id);
2479 return CMD_SUCCESS;
cb4b8845
PJ
2480}
2481
2482DEFUN (no_debug_ospf6_brouter_area,
2483 no_debug_ospf6_brouter_area_cmd,
2484 "no debug ospf6 border-routers area-id",
2485 NO_STR
2486 DEBUG_STR
2487 OSPF6_STR
2488 "Debug border router\n"
2489 "Debug border routers in specific Area\n"
2490 )
2491{
d62a17ae 2492 OSPF6_DEBUG_BROUTER_SPECIFIC_AREA_OFF();
2493 return CMD_SUCCESS;
cb4b8845
PJ
2494}
2495
d62a17ae 2496int config_write_ospf6_debug_brouter(struct vty *vty)
cb4b8845 2497{
d62a17ae 2498 char buf[16];
2499 if (IS_OSPF6_DEBUG_BROUTER)
2500 vty_out(vty, "debug ospf6 border-routers\n");
2501 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_ROUTER) {
2502 inet_ntop(AF_INET, &conf_debug_ospf6_brouter_specific_router_id,
2503 buf, sizeof(buf));
2504 vty_out(vty, "debug ospf6 border-routers router-id %s\n", buf);
2505 }
2506 if (IS_OSPF6_DEBUG_BROUTER_SPECIFIC_AREA) {
2507 inet_ntop(AF_INET, &conf_debug_ospf6_brouter_specific_area_id,
2508 buf, sizeof(buf));
2509 vty_out(vty, "debug ospf6 border-routers area-id %s\n", buf);
2510 }
2511 return 0;
cb4b8845
PJ
2512}
2513
d62a17ae 2514void install_element_ospf6_debug_brouter(void)
cb4b8845 2515{
d62a17ae 2516 install_element(ENABLE_NODE, &debug_ospf6_brouter_cmd);
2517 install_element(ENABLE_NODE, &debug_ospf6_brouter_router_cmd);
2518 install_element(ENABLE_NODE, &debug_ospf6_brouter_area_cmd);
2519 install_element(ENABLE_NODE, &no_debug_ospf6_brouter_cmd);
2520 install_element(ENABLE_NODE, &no_debug_ospf6_brouter_router_cmd);
2521 install_element(ENABLE_NODE, &no_debug_ospf6_brouter_area_cmd);
2522 install_element(CONFIG_NODE, &debug_ospf6_brouter_cmd);
2523 install_element(CONFIG_NODE, &debug_ospf6_brouter_router_cmd);
2524 install_element(CONFIG_NODE, &debug_ospf6_brouter_area_cmd);
2525 install_element(CONFIG_NODE, &no_debug_ospf6_brouter_cmd);
2526 install_element(CONFIG_NODE, &no_debug_ospf6_brouter_router_cmd);
2527 install_element(CONFIG_NODE, &no_debug_ospf6_brouter_area_cmd);
cb4b8845 2528}