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