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