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