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