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