]> git.proxmox.com Git - mirror_frr.git/blob - ospf6d/ospf6_interface.c
*: Add camelCase JSON keys in addition to PascalCase
[mirror_frr.git] / ospf6d / ospf6_interface.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 "memory.h"
24 #include "if.h"
25 #include "log.h"
26 #include "command.h"
27 #include "thread.h"
28 #include "prefix.h"
29 #include "plist.h"
30 #include "zclient.h"
31
32 #include "ospf6_lsa.h"
33 #include "ospf6_lsdb.h"
34 #include "ospf6_top.h"
35 #include "ospf6_network.h"
36 #include "ospf6_message.h"
37 #include "ospf6_route.h"
38 #include "ospf6_area.h"
39 #include "ospf6_abr.h"
40 #include "ospf6_interface.h"
41 #include "ospf6_neighbor.h"
42 #include "ospf6_intra.h"
43 #include "ospf6_spf.h"
44 #include "ospf6d.h"
45 #include "ospf6_bfd.h"
46 #include "ospf6_zebra.h"
47 #include "ospf6_gr.h"
48 #include "lib/json.h"
49
50 DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_IF, "OSPF6 interface");
51 DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names");
52 DEFINE_QOBJ_TYPE(ospf6_interface);
53 DEFINE_HOOK(ospf6_interface_change,
54 (struct ospf6_interface * oi, int state, int old_state),
55 (oi, state, old_state));
56
57 unsigned char conf_debug_ospf6_interface = 0;
58
59 const char *const ospf6_interface_state_str[] = {
60 "None", "Down", "Loopback", "Waiting", "PointToPoint",
61 "DROther", "BDR", "DR", NULL};
62
63 int ospf6_interface_neighbor_count(struct ospf6_interface *oi)
64 {
65 int count = 0;
66 struct ospf6_neighbor *nbr = NULL;
67 struct listnode *node;
68
69 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, nbr)) {
70 /* Down state is not shown. */
71 if (nbr->state == OSPF6_NEIGHBOR_DOWN)
72 continue;
73 count++;
74 }
75
76 return count;
77 }
78
79 struct ospf6_interface *ospf6_interface_lookup_by_ifindex(ifindex_t ifindex,
80 vrf_id_t vrf_id)
81 {
82 struct ospf6_interface *oi;
83 struct interface *ifp;
84
85 ifp = if_lookup_by_index(ifindex, vrf_id);
86 if (ifp == NULL)
87 return (struct ospf6_interface *)NULL;
88
89 oi = (struct ospf6_interface *)ifp->info;
90 return oi;
91 }
92
93 /* schedule routing table recalculation */
94 static void ospf6_interface_lsdb_hook(struct ospf6_lsa *lsa,
95 unsigned int reason)
96 {
97 struct ospf6_interface *oi;
98
99 if (lsa == NULL)
100 return;
101
102 oi = lsa->lsdb->data;
103 switch (ntohs(lsa->header->type)) {
104 case OSPF6_LSTYPE_LINK:
105 if (oi->state == OSPF6_INTERFACE_DR)
106 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
107 if (oi->area)
108 ospf6_spf_schedule(oi->area->ospf6, reason);
109 break;
110
111 default:
112 break;
113 }
114 }
115
116 static void ospf6_interface_lsdb_hook_add(struct ospf6_lsa *lsa)
117 {
118 ospf6_interface_lsdb_hook(lsa, ospf6_lsadd_to_spf_reason(lsa));
119 }
120
121 static void ospf6_interface_lsdb_hook_remove(struct ospf6_lsa *lsa)
122 {
123 ospf6_interface_lsdb_hook(lsa, ospf6_lsremove_to_spf_reason(lsa));
124 }
125
126 static uint8_t ospf6_default_iftype(struct interface *ifp)
127 {
128 if (if_is_pointopoint(ifp))
129 return OSPF_IFTYPE_POINTOPOINT;
130 else if (if_is_loopback(ifp))
131 return OSPF_IFTYPE_LOOPBACK;
132 else
133 return OSPF_IFTYPE_BROADCAST;
134 }
135
136 static uint32_t ospf6_interface_get_cost(struct ospf6_interface *oi)
137 {
138 /* If all else fails, use default OSPF cost */
139 uint32_t cost;
140 uint32_t bw, refbw;
141 struct ospf6 *ospf6;
142 /* interface speed and bw can be 0 in some platforms,
143 * use ospf default bw. If bw is configured then it would
144 * be used.
145 */
146 if (!oi->interface->bandwidth && oi->interface->speed) {
147 bw = oi->interface->speed;
148 } else {
149 bw = oi->interface->bandwidth ? oi->interface->bandwidth
150 : OSPF6_INTERFACE_BANDWIDTH;
151 }
152
153 ospf6 = oi->interface->vrf->info;
154 refbw = ospf6 ? ospf6->ref_bandwidth : OSPF6_REFERENCE_BANDWIDTH;
155
156 /* A specifed ip ospf cost overrides a calculated one. */
157 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST))
158 cost = oi->cost;
159 else {
160 cost = (uint32_t)((double)refbw / (double)bw + (double)0.5);
161 if (cost < 1)
162 cost = 1;
163 else if (cost > UINT32_MAX)
164 cost = UINT32_MAX;
165 }
166
167 return cost;
168 }
169
170 static void ospf6_interface_force_recalculate_cost(struct ospf6_interface *oi)
171 {
172 /* update cost held in route_connected list in ospf6_interface */
173 ospf6_interface_connected_route_update(oi->interface);
174
175 /* execute LSA hooks */
176 if (oi->area) {
177 OSPF6_LINK_LSA_SCHEDULE(oi);
178 OSPF6_ROUTER_LSA_SCHEDULE(oi->area);
179 OSPF6_NETWORK_LSA_SCHEDULE(oi);
180 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
181 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
182 }
183 }
184
185 static void ospf6_interface_recalculate_cost(struct ospf6_interface *oi)
186 {
187 uint32_t newcost;
188
189 newcost = ospf6_interface_get_cost(oi);
190 if (newcost == oi->cost)
191 return;
192 oi->cost = newcost;
193
194 ospf6_interface_force_recalculate_cost(oi);
195 }
196
197 /* Create new ospf6 interface structure */
198 struct ospf6_interface *ospf6_interface_create(struct interface *ifp)
199 {
200 struct ospf6_interface *oi;
201 unsigned int iobuflen;
202
203 oi = XCALLOC(MTYPE_OSPF6_IF, sizeof(struct ospf6_interface));
204
205 oi->obuf = ospf6_fifo_new();
206
207 oi->area = (struct ospf6_area *)NULL;
208 oi->neighbor_list = list_new();
209 oi->neighbor_list->cmp = ospf6_neighbor_cmp;
210 oi->linklocal_addr = (struct in6_addr *)NULL;
211 oi->instance_id = OSPF6_INTERFACE_INSTANCE_ID;
212 oi->transdelay = OSPF6_INTERFACE_TRANSDELAY;
213 oi->priority = OSPF6_INTERFACE_PRIORITY;
214
215 oi->hello_interval = OSPF_HELLO_INTERVAL_DEFAULT;
216 oi->dead_interval = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT;
217 oi->rxmt_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT;
218 oi->type = ospf6_default_iftype(ifp);
219 oi->state = OSPF6_INTERFACE_DOWN;
220 oi->flag = 0;
221 oi->mtu_ignore = 0;
222 oi->c_ifmtu = 0;
223
224 /* Try to adjust I/O buffer size with IfMtu */
225 oi->ifmtu = ifp->mtu6;
226 iobuflen = ospf6_iobuf_size(ifp->mtu6);
227 if (oi->ifmtu > iobuflen) {
228 if (IS_OSPF6_DEBUG_INTERFACE)
229 zlog_debug(
230 "Interface %s: IfMtu is adjusted to I/O buffer size: %d.",
231 ifp->name, iobuflen);
232 oi->ifmtu = iobuflen;
233 }
234
235 QOBJ_REG(oi, ospf6_interface);
236
237 oi->lsupdate_list = ospf6_lsdb_create(oi);
238 oi->lsack_list = ospf6_lsdb_create(oi);
239 oi->lsdb = ospf6_lsdb_create(oi);
240 oi->lsdb->hook_add = ospf6_interface_lsdb_hook_add;
241 oi->lsdb->hook_remove = ospf6_interface_lsdb_hook_remove;
242 oi->lsdb_self = ospf6_lsdb_create(oi);
243
244 oi->route_connected =
245 OSPF6_ROUTE_TABLE_CREATE(INTERFACE, CONNECTED_ROUTES);
246 oi->route_connected->scope = oi;
247
248 /* link both */
249 oi->interface = ifp;
250 ifp->info = oi;
251
252 /* Compute cost. */
253 oi->cost = ospf6_interface_get_cost(oi);
254
255 return oi;
256 }
257
258 void ospf6_interface_delete(struct ospf6_interface *oi)
259 {
260 struct listnode *node, *nnode;
261 struct ospf6_neighbor *on;
262
263 QOBJ_UNREG(oi);
264
265 ospf6_fifo_free(oi->obuf);
266
267 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
268 ospf6_neighbor_delete(on);
269
270 list_delete(&oi->neighbor_list);
271
272 THREAD_OFF(oi->thread_send_hello);
273 THREAD_OFF(oi->thread_send_lsupdate);
274 THREAD_OFF(oi->thread_send_lsack);
275 THREAD_OFF(oi->thread_sso);
276 THREAD_OFF(oi->thread_wait_timer);
277
278 ospf6_lsdb_remove_all(oi->lsdb);
279 ospf6_lsdb_remove_all(oi->lsupdate_list);
280 ospf6_lsdb_remove_all(oi->lsack_list);
281
282 ospf6_lsdb_delete(oi->lsdb);
283 ospf6_lsdb_delete(oi->lsdb_self);
284
285 ospf6_lsdb_delete(oi->lsupdate_list);
286 ospf6_lsdb_delete(oi->lsack_list);
287
288 ospf6_route_table_delete(oi->route_connected);
289
290 /* cut link */
291 oi->interface->info = NULL;
292
293 /* plist_name */
294 if (oi->plist_name)
295 XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name);
296
297 /* disable from area list if possible */
298 ospf6_area_interface_delete(oi);
299
300 /* Free BFD allocated data. */
301 XFREE(MTYPE_TMP, oi->bfd_config.profile);
302
303 XFREE(MTYPE_OSPF6_IF, oi);
304 }
305
306 void ospf6_interface_enable(struct ospf6_interface *oi)
307 {
308 UNSET_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE);
309 ospf6_interface_state_update(oi->interface);
310 }
311
312 void ospf6_interface_disable(struct ospf6_interface *oi)
313 {
314 SET_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE);
315
316 thread_execute(master, interface_down, oi, 0);
317
318 ospf6_lsdb_remove_all(oi->lsdb);
319 ospf6_lsdb_remove_all(oi->lsdb_self);
320 ospf6_lsdb_remove_all(oi->lsupdate_list);
321 ospf6_lsdb_remove_all(oi->lsack_list);
322
323 THREAD_OFF(oi->thread_send_hello);
324 THREAD_OFF(oi->thread_send_lsupdate);
325 THREAD_OFF(oi->thread_send_lsack);
326 THREAD_OFF(oi->thread_sso);
327
328 THREAD_OFF(oi->thread_network_lsa);
329 THREAD_OFF(oi->thread_link_lsa);
330 THREAD_OFF(oi->thread_intra_prefix_lsa);
331 THREAD_OFF(oi->thread_as_extern_lsa);
332 THREAD_OFF(oi->thread_wait_timer);
333 }
334
335 static struct in6_addr *
336 ospf6_interface_get_linklocal_address(struct interface *ifp)
337 {
338 struct listnode *n;
339 struct connected *c;
340 struct in6_addr *l = (struct in6_addr *)NULL;
341
342 /* for each connected address */
343 for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) {
344 /* if family not AF_INET6, ignore */
345 if (c->address->family != AF_INET6)
346 continue;
347
348 /* linklocal scope check */
349 if (IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6))
350 l = &c->address->u.prefix6;
351 }
352 return l;
353 }
354
355 void ospf6_interface_state_update(struct interface *ifp)
356 {
357 struct ospf6_interface *oi;
358 unsigned int iobuflen;
359
360 oi = (struct ospf6_interface *)ifp->info;
361 if (oi == NULL)
362 return;
363 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
364 return;
365
366 /* Adjust the mtu values if the kernel told us something new */
367 if (ifp->mtu6 != oi->ifmtu) {
368 /* If nothing configured, accept it and check for buffer size */
369 if (!oi->c_ifmtu) {
370 oi->ifmtu = ifp->mtu6;
371 iobuflen = ospf6_iobuf_size(ifp->mtu6);
372 if (oi->ifmtu > iobuflen) {
373 if (IS_OSPF6_DEBUG_INTERFACE)
374 zlog_debug(
375 "Interface %s: IfMtu is adjusted to I/O buffer size: %d.",
376 ifp->name, iobuflen);
377 oi->ifmtu = iobuflen;
378 }
379 } else if (oi->c_ifmtu > ifp->mtu6) {
380 oi->ifmtu = ifp->mtu6;
381 zlog_warn(
382 "Configured mtu %u on %s overridden by kernel %u",
383 oi->c_ifmtu, ifp->name, ifp->mtu6);
384 } else
385 oi->ifmtu = oi->c_ifmtu;
386 }
387
388 if (if_is_operative(ifp)
389 && (ospf6_interface_get_linklocal_address(oi->interface)
390 || if_is_loopback(oi->interface)))
391 thread_execute(master, interface_up, oi, 0);
392 else
393 thread_execute(master, interface_down, oi, 0);
394
395 return;
396 }
397
398 void ospf6_interface_connected_route_update(struct interface *ifp)
399 {
400 struct ospf6_interface *oi;
401 struct ospf6_route *route;
402 struct connected *c;
403 struct listnode *node, *nnode;
404 struct in6_addr nh_addr;
405
406 oi = (struct ospf6_interface *)ifp->info;
407 if (oi == NULL)
408 return;
409
410 /* reset linklocal pointer */
411 oi->linklocal_addr = ospf6_interface_get_linklocal_address(ifp);
412
413 /* if area is null, do not make connected-route list */
414 if (oi->area == NULL)
415 return;
416
417 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
418 return;
419
420 /* update "route to advertise" interface route table */
421 ospf6_route_remove_all(oi->route_connected);
422
423 for (ALL_LIST_ELEMENTS(oi->interface->connected, node, nnode, c)) {
424 if (c->address->family != AF_INET6)
425 continue;
426
427 CONTINUE_IF_ADDRESS_LINKLOCAL(IS_OSPF6_DEBUG_INTERFACE,
428 c->address);
429 CONTINUE_IF_ADDRESS_UNSPECIFIED(IS_OSPF6_DEBUG_INTERFACE,
430 c->address);
431 CONTINUE_IF_ADDRESS_LOOPBACK(IS_OSPF6_DEBUG_INTERFACE,
432 c->address);
433 CONTINUE_IF_ADDRESS_V4COMPAT(IS_OSPF6_DEBUG_INTERFACE,
434 c->address);
435 CONTINUE_IF_ADDRESS_V4MAPPED(IS_OSPF6_DEBUG_INTERFACE,
436 c->address);
437
438 /* apply filter */
439 if (oi->plist_name) {
440 struct prefix_list *plist;
441 enum prefix_list_type ret;
442
443 plist = prefix_list_lookup(AFI_IP6, oi->plist_name);
444 ret = prefix_list_apply(plist, (void *)c->address);
445 if (ret == PREFIX_DENY) {
446 if (IS_OSPF6_DEBUG_INTERFACE)
447 zlog_debug(
448 "%pFX on %s filtered by prefix-list %s ",
449 c->address, oi->interface->name,
450 oi->plist_name);
451 continue;
452 }
453 }
454
455 route = ospf6_route_create(oi->area->ospf6);
456 memcpy(&route->prefix, c->address, sizeof(struct prefix));
457 apply_mask(&route->prefix);
458 route->type = OSPF6_DEST_TYPE_NETWORK;
459 route->path.area_id = oi->area->area_id;
460 route->path.type = OSPF6_PATH_TYPE_INTRA;
461 route->path.cost = oi->cost;
462 inet_pton(AF_INET6, "::1", &nh_addr);
463 ospf6_route_add_nexthop(route, oi->interface->ifindex,
464 &nh_addr);
465 ospf6_route_add(route, oi->route_connected);
466 }
467
468 /* create new Link-LSA */
469 OSPF6_LINK_LSA_SCHEDULE(oi);
470 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
471 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
472 }
473
474 static int ospf6_interface_state_change(uint8_t next_state,
475 struct ospf6_interface *oi)
476 {
477 uint8_t prev_state;
478 struct ospf6 *ospf6;
479
480 prev_state = oi->state;
481 oi->state = next_state;
482
483 if (prev_state == next_state)
484 return -1;
485
486 if (!oi->area)
487 return -1;
488
489 /* log */
490 if (IS_OSPF6_DEBUG_INTERFACE) {
491 zlog_debug("Interface state change %s: %s -> %s",
492 oi->interface->name,
493 ospf6_interface_state_str[prev_state],
494 ospf6_interface_state_str[next_state]);
495 }
496 oi->state_change++;
497
498 ospf6 = oi->area->ospf6;
499
500 if ((prev_state == OSPF6_INTERFACE_DR
501 || prev_state == OSPF6_INTERFACE_BDR)
502 && (next_state != OSPF6_INTERFACE_DR
503 && next_state != OSPF6_INTERFACE_BDR))
504 ospf6_sso(oi->interface->ifindex, &alldrouters6,
505 IPV6_LEAVE_GROUP, ospf6->fd);
506
507 if ((prev_state != OSPF6_INTERFACE_DR
508 && prev_state != OSPF6_INTERFACE_BDR)
509 && (next_state == OSPF6_INTERFACE_DR
510 || next_state == OSPF6_INTERFACE_BDR))
511 ospf6_sso(oi->interface->ifindex, &alldrouters6,
512 IPV6_JOIN_GROUP, ospf6->fd);
513
514 OSPF6_ROUTER_LSA_SCHEDULE(oi->area);
515 OSPF6_LINK_LSA_SCHEDULE(oi);
516 if (next_state == OSPF6_INTERFACE_DOWN) {
517 OSPF6_NETWORK_LSA_EXECUTE(oi);
518 OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi);
519 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
520 OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi);
521 } else if (prev_state == OSPF6_INTERFACE_DR
522 || next_state == OSPF6_INTERFACE_DR) {
523 OSPF6_NETWORK_LSA_SCHEDULE(oi);
524 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
525 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
526 }
527
528 hook_call(ospf6_interface_change, oi, next_state, prev_state);
529
530 return 0;
531 }
532
533
534 /* DR Election, RFC2328 section 9.4 */
535
536 #define IS_ELIGIBLE(n) \
537 ((n)->state >= OSPF6_NEIGHBOR_TWOWAY && (n)->priority != 0)
538
539 static struct ospf6_neighbor *better_bdrouter(struct ospf6_neighbor *a,
540 struct ospf6_neighbor *b)
541 {
542 if ((a == NULL || !IS_ELIGIBLE(a) || a->drouter == a->router_id)
543 && (b == NULL || !IS_ELIGIBLE(b) || b->drouter == b->router_id))
544 return NULL;
545 else if (a == NULL || !IS_ELIGIBLE(a) || a->drouter == a->router_id)
546 return b;
547 else if (b == NULL || !IS_ELIGIBLE(b) || b->drouter == b->router_id)
548 return a;
549
550 if (a->bdrouter == a->router_id && b->bdrouter != b->router_id)
551 return a;
552 if (a->bdrouter != a->router_id && b->bdrouter == b->router_id)
553 return b;
554
555 if (a->priority > b->priority)
556 return a;
557 if (a->priority < b->priority)
558 return b;
559
560 if (ntohl(a->router_id) > ntohl(b->router_id))
561 return a;
562 if (ntohl(a->router_id) < ntohl(b->router_id))
563 return b;
564
565 zlog_warn("Router-ID duplicate ?");
566 return a;
567 }
568
569 static struct ospf6_neighbor *better_drouter(struct ospf6_neighbor *a,
570 struct ospf6_neighbor *b)
571 {
572 if ((a == NULL || !IS_ELIGIBLE(a) || a->drouter != a->router_id)
573 && (b == NULL || !IS_ELIGIBLE(b) || b->drouter != b->router_id))
574 return NULL;
575 else if (a == NULL || !IS_ELIGIBLE(a) || a->drouter != a->router_id)
576 return b;
577 else if (b == NULL || !IS_ELIGIBLE(b) || b->drouter != b->router_id)
578 return a;
579
580 if (a->drouter == a->router_id && b->drouter != b->router_id)
581 return a;
582 if (a->drouter != a->router_id && b->drouter == b->router_id)
583 return b;
584
585 if (a->priority > b->priority)
586 return a;
587 if (a->priority < b->priority)
588 return b;
589
590 if (ntohl(a->router_id) > ntohl(b->router_id))
591 return a;
592 if (ntohl(a->router_id) < ntohl(b->router_id))
593 return b;
594
595 zlog_warn("Router-ID duplicate ?");
596 return a;
597 }
598
599 uint8_t dr_election(struct ospf6_interface *oi)
600 {
601 struct listnode *node, *nnode;
602 struct ospf6_neighbor *on, *drouter, *bdrouter, myself;
603 struct ospf6_neighbor *best_drouter, *best_bdrouter;
604 uint8_t next_state = 0;
605
606 drouter = bdrouter = NULL;
607 best_drouter = best_bdrouter = NULL;
608
609 /* pseudo neighbor myself, including noting current DR/BDR (1) */
610 memset(&myself, 0, sizeof(myself));
611 inet_ntop(AF_INET, &oi->area->ospf6->router_id, myself.name,
612 sizeof(myself.name));
613 myself.state = OSPF6_NEIGHBOR_TWOWAY;
614 myself.drouter = oi->drouter;
615 myself.bdrouter = oi->bdrouter;
616 myself.priority = oi->priority;
617 myself.router_id = oi->area->ospf6->router_id;
618
619 /* Electing BDR (2) */
620 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
621 bdrouter = better_bdrouter(bdrouter, on);
622
623 best_bdrouter = bdrouter;
624 bdrouter = better_bdrouter(best_bdrouter, &myself);
625
626 /* Electing DR (3) */
627 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
628 drouter = better_drouter(drouter, on);
629
630 best_drouter = drouter;
631 drouter = better_drouter(best_drouter, &myself);
632 if (drouter == NULL)
633 drouter = bdrouter;
634
635 /* the router itself is newly/no longer DR/BDR (4) */
636 if ((drouter == &myself && myself.drouter != myself.router_id)
637 || (drouter != &myself && myself.drouter == myself.router_id)
638 || (bdrouter == &myself && myself.bdrouter != myself.router_id)
639 || (bdrouter != &myself && myself.bdrouter == myself.router_id)) {
640 myself.drouter = (drouter ? drouter->router_id : htonl(0));
641 myself.bdrouter = (bdrouter ? bdrouter->router_id : htonl(0));
642
643 /* compatible to Electing BDR (2) */
644 bdrouter = better_bdrouter(best_bdrouter, &myself);
645
646 /* compatible to Electing DR (3) */
647 drouter = better_drouter(best_drouter, &myself);
648 if (drouter == NULL)
649 drouter = bdrouter;
650 }
651
652 /* Set interface state accordingly (5) */
653 if (drouter && drouter == &myself)
654 next_state = OSPF6_INTERFACE_DR;
655 else if (bdrouter && bdrouter == &myself)
656 next_state = OSPF6_INTERFACE_BDR;
657 else
658 next_state = OSPF6_INTERFACE_DROTHER;
659
660 /* If NBMA, schedule Start for each neighbor having priority of 0 (6) */
661 /* XXX */
662
663 /* If DR or BDR change, invoke AdjOK? for each neighbor (7) */
664 /* RFC 2328 section 12.4. Originating LSAs (3) will be handled
665 accordingly after AdjOK */
666 if (oi->drouter != (drouter ? drouter->router_id : htonl(0))
667 || oi->bdrouter != (bdrouter ? bdrouter->router_id : htonl(0))) {
668 if (IS_OSPF6_DEBUG_INTERFACE)
669 zlog_debug("DR Election on %s: DR: %s BDR: %s",
670 oi->interface->name,
671 (drouter ? drouter->name : "0.0.0.0"),
672 (bdrouter ? bdrouter->name : "0.0.0.0"));
673
674 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, on)) {
675 if (on->state < OSPF6_NEIGHBOR_TWOWAY)
676 continue;
677 /* Schedule AdjOK. */
678 thread_add_event(master, adj_ok, on, 0,
679 &on->thread_adj_ok);
680 }
681 }
682
683 oi->drouter = (drouter ? drouter->router_id : htonl(0));
684 oi->bdrouter = (bdrouter ? bdrouter->router_id : htonl(0));
685 return next_state;
686 }
687
688 #ifdef __FreeBSD__
689
690 #include <ifaddrs.h>
691
692 static bool ifmaddr_check(ifindex_t ifindex, struct in6_addr *addr)
693 {
694 struct ifmaddrs *ifmap, *ifma;
695 struct sockaddr_dl *sdl;
696 struct sockaddr_in6 *sin6;
697 bool found = false;
698
699 if (getifmaddrs(&ifmap) != 0)
700 return false;
701
702 for (ifma = ifmap; ifma; ifma = ifma->ifma_next) {
703 if (ifma->ifma_name == NULL || ifma->ifma_addr == NULL)
704 continue;
705 if (ifma->ifma_name->sa_family != AF_LINK)
706 continue;
707 if (ifma->ifma_addr->sa_family != AF_INET6)
708 continue;
709 sdl = (struct sockaddr_dl *)ifma->ifma_name;
710 sin6 = (struct sockaddr_in6 *)ifma->ifma_addr;
711 if (sdl->sdl_index == ifindex
712 && memcmp(&sin6->sin6_addr, addr, IPV6_MAX_BYTELEN) == 0) {
713 found = true;
714 break;
715 }
716 }
717
718 if (ifmap)
719 freeifmaddrs(ifmap);
720
721 return found;
722 }
723
724 #endif /* __FreeBSD__ */
725
726 /* Interface State Machine */
727 int interface_up(struct thread *thread)
728 {
729 struct ospf6_interface *oi;
730 struct ospf6 *ospf6;
731
732 oi = (struct ospf6_interface *)THREAD_ARG(thread);
733 assert(oi && oi->interface);
734
735 if (!oi->type_cfg)
736 oi->type = ospf6_default_iftype(oi->interface);
737
738 thread_cancel(&oi->thread_sso);
739
740 if (IS_OSPF6_DEBUG_INTERFACE)
741 zlog_debug("Interface Event %s: [InterfaceUp]",
742 oi->interface->name);
743
744 /* check physical interface is up */
745 if (!if_is_operative(oi->interface)) {
746 zlog_warn("Interface %s is down, can't execute [InterfaceUp]",
747 oi->interface->name);
748 return 0;
749 }
750
751 /* check interface has a link-local address */
752 if (!(ospf6_interface_get_linklocal_address(oi->interface)
753 || if_is_loopback(oi->interface))) {
754 zlog_warn(
755 "Interface %s has no link local address, can't execute [InterfaceUp]",
756 oi->interface->name);
757 return 0;
758 }
759
760 /* Recompute cost */
761 ospf6_interface_recalculate_cost(oi);
762
763 /* if already enabled, do nothing */
764 if (oi->state > OSPF6_INTERFACE_DOWN) {
765 if (IS_OSPF6_DEBUG_INTERFACE)
766 zlog_debug("Interface %s already enabled",
767 oi->interface->name);
768 return 0;
769 }
770
771 /* If no area assigned, return */
772 if (oi->area == NULL) {
773 zlog_warn(
774 "%s: Not scheduling Hello for %s as there is no area assigned yet",
775 __func__, oi->interface->name);
776 return 0;
777 }
778
779 #ifdef __FreeBSD__
780 /*
781 * There's a delay in FreeBSD between issuing a command to leave a
782 * multicast group and an actual leave. If we execute "no router ospf6"
783 * and "router ospf6" fast enough, we can end up in a situation when OS
784 * performs the leave later than it performs the join and the interface
785 * remains without a multicast group. We have to do the join only after
786 * the interface actually left the group.
787 */
788 if (ifmaddr_check(oi->interface->ifindex, &allspfrouters6)) {
789 zlog_info(
790 "Interface %s is still in all routers group, rescheduling for SSO",
791 oi->interface->name);
792 thread_add_timer(master, interface_up, oi,
793 OSPF6_INTERFACE_SSO_RETRY_INT,
794 &oi->thread_sso);
795 return 0;
796 }
797 #endif /* __FreeBSD__ */
798
799 ospf6 = oi->area->ospf6;
800
801 /* Join AllSPFRouters */
802 if (ospf6_sso(oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP,
803 ospf6->fd)
804 < 0) {
805 if (oi->sso_try_cnt++ < OSPF6_INTERFACE_SSO_RETRY_MAX) {
806 zlog_info(
807 "Scheduling %s for sso retry, trial count: %d",
808 oi->interface->name, oi->sso_try_cnt);
809 thread_add_timer(master, interface_up, oi,
810 OSPF6_INTERFACE_SSO_RETRY_INT,
811 &oi->thread_sso);
812 }
813 return 0;
814 }
815 oi->sso_try_cnt = 0; /* Reset on success */
816
817 /* Update interface route */
818 ospf6_interface_connected_route_update(oi->interface);
819
820 /* Schedule Hello */
821 if (!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE)
822 && !if_is_loopback(oi->interface)) {
823 thread_add_event(master, ospf6_hello_send, oi, 0,
824 &oi->thread_send_hello);
825 }
826
827 /* decide next interface state */
828 if (oi->type == OSPF_IFTYPE_LOOPBACK) {
829 ospf6_interface_state_change(OSPF6_INTERFACE_LOOPBACK, oi);
830 } else if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
831 ospf6_interface_state_change(OSPF6_INTERFACE_POINTTOPOINT, oi);
832 } else if (oi->priority == 0)
833 ospf6_interface_state_change(OSPF6_INTERFACE_DROTHER, oi);
834 else {
835 ospf6_interface_state_change(OSPF6_INTERFACE_WAITING, oi);
836 thread_add_timer(master, wait_timer, oi, oi->dead_interval,
837 &oi->thread_wait_timer);
838 }
839
840 return 0;
841 }
842
843 int wait_timer(struct thread *thread)
844 {
845 struct ospf6_interface *oi;
846
847 oi = (struct ospf6_interface *)THREAD_ARG(thread);
848 assert(oi && oi->interface);
849
850 if (IS_OSPF6_DEBUG_INTERFACE)
851 zlog_debug("Interface Event %s: [WaitTimer]",
852 oi->interface->name);
853
854 if (oi->state == OSPF6_INTERFACE_WAITING)
855 ospf6_interface_state_change(dr_election(oi), oi);
856
857 return 0;
858 }
859
860 int backup_seen(struct thread *thread)
861 {
862 struct ospf6_interface *oi;
863
864 oi = (struct ospf6_interface *)THREAD_ARG(thread);
865 assert(oi && oi->interface);
866
867 if (IS_OSPF6_DEBUG_INTERFACE)
868 zlog_debug("Interface Event %s: [BackupSeen]",
869 oi->interface->name);
870
871 if (oi->state == OSPF6_INTERFACE_WAITING)
872 ospf6_interface_state_change(dr_election(oi), oi);
873
874 return 0;
875 }
876
877 int neighbor_change(struct thread *thread)
878 {
879 struct ospf6_interface *oi;
880
881 oi = (struct ospf6_interface *)THREAD_ARG(thread);
882 assert(oi && oi->interface);
883
884 if (IS_OSPF6_DEBUG_INTERFACE)
885 zlog_debug("Interface Event %s: [NeighborChange]",
886 oi->interface->name);
887
888 if (oi->state == OSPF6_INTERFACE_DROTHER
889 || oi->state == OSPF6_INTERFACE_BDR
890 || oi->state == OSPF6_INTERFACE_DR)
891 ospf6_interface_state_change(dr_election(oi), oi);
892
893 return 0;
894 }
895
896 int interface_down(struct thread *thread)
897 {
898 struct ospf6_interface *oi;
899 struct listnode *node, *nnode;
900 struct ospf6_neighbor *on;
901 struct ospf6 *ospf6;
902
903 oi = (struct ospf6_interface *)THREAD_ARG(thread);
904 assert(oi && oi->interface);
905
906 if (IS_OSPF6_DEBUG_INTERFACE)
907 zlog_debug("Interface Event %s: [InterfaceDown]",
908 oi->interface->name);
909
910 /* Stop Hellos */
911 THREAD_OFF(oi->thread_send_hello);
912
913 /* Stop trying to set socket options. */
914 THREAD_OFF(oi->thread_sso);
915
916 /* Cease the HELPER role for all the neighbours
917 * of this interface.
918 */
919 if (ospf6_interface_neighbor_count(oi)) {
920 struct listnode *ln;
921 struct ospf6_neighbor *nbr = NULL;
922
923 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, ln, nbr))
924 ospf6_gr_helper_exit(nbr, OSPF6_GR_HELPER_TOPO_CHG);
925 }
926
927 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
928 ospf6_neighbor_delete(on);
929
930 list_delete_all_node(oi->neighbor_list);
931
932 /* When interface state is reset, also reset information about
933 * DR election, as it is no longer valid. */
934 oi->drouter = oi->prev_drouter = htonl(0);
935 oi->bdrouter = oi->prev_bdrouter = htonl(0);
936
937 if (oi->area == NULL)
938 return 0;
939
940 ospf6 = oi->area->ospf6;
941 /* Leave AllSPFRouters */
942 if (oi->state > OSPF6_INTERFACE_DOWN)
943 ospf6_sso(oi->interface->ifindex, &allspfrouters6,
944 IPV6_LEAVE_GROUP, ospf6->fd);
945
946 /* deal with write fifo */
947 ospf6_fifo_flush(oi->obuf);
948 if (oi->on_write_q) {
949 listnode_delete(ospf6->oi_write_q, oi);
950 if (list_isempty(ospf6->oi_write_q))
951 thread_cancel(&ospf6->t_write);
952 oi->on_write_q = 0;
953 }
954
955 ospf6_interface_state_change(OSPF6_INTERFACE_DOWN, oi);
956
957 return 0;
958 }
959
960
961 static const char *ospf6_iftype_str(uint8_t iftype)
962 {
963 switch (iftype) {
964 case OSPF_IFTYPE_LOOPBACK:
965 return "LOOPBACK";
966 case OSPF_IFTYPE_BROADCAST:
967 return "BROADCAST";
968 case OSPF_IFTYPE_POINTOPOINT:
969 return "POINTOPOINT";
970 }
971 return "UNKNOWN";
972 }
973
974 #if CONFDATE > 20220709
975 CPP_NOTICE("Time to remove ospf6Enabled from JSON output")
976 #endif
977
978 /* show specified interface structure */
979 static int ospf6_interface_show(struct vty *vty, struct interface *ifp,
980 json_object *json_obj, bool use_json)
981 {
982 struct ospf6_interface *oi;
983 struct connected *c;
984 struct prefix *p;
985 struct listnode *i;
986 char strbuf[PREFIX2STR_BUFFER], drouter[32], bdrouter[32];
987 uint8_t default_iftype;
988 struct timeval res, now;
989 char duration[32];
990 struct ospf6_lsa *lsa, *lsanext;
991 json_object *json_arr;
992 json_object *json_addr;
993
994 default_iftype = ospf6_default_iftype(ifp);
995
996 if (use_json) {
997 json_object_string_add(json_obj, "status",
998 (if_is_operative(ifp) ? "up" : "down"));
999 json_object_string_add(json_obj, "type",
1000 ospf6_iftype_str(default_iftype));
1001 json_object_int_add(json_obj, "interfaceId", ifp->ifindex);
1002
1003 if (ifp->info == NULL) {
1004 json_object_boolean_false_add(json_obj, "ospf6Enabled");
1005 return 0;
1006 }
1007 json_object_boolean_true_add(json_obj, "ospf6Enabled");
1008
1009 oi = (struct ospf6_interface *)ifp->info;
1010
1011 if (if_is_operative(ifp) && oi->type != default_iftype)
1012 json_object_string_add(json_obj, "operatingAsType",
1013 ospf6_iftype_str(oi->type));
1014
1015 } else {
1016 vty_out(vty, "%s is %s, type %s\n", ifp->name,
1017 (if_is_operative(ifp) ? "up" : "down"),
1018 ospf6_iftype_str(default_iftype));
1019 vty_out(vty, " Interface ID: %d\n", ifp->ifindex);
1020
1021 if (ifp->info == NULL) {
1022 vty_out(vty, " OSPF not enabled on this interface\n");
1023 return 0;
1024 }
1025 oi = (struct ospf6_interface *)ifp->info;
1026
1027 if (if_is_operative(ifp) && oi->type != default_iftype)
1028 vty_out(vty, " Operating as type %s\n",
1029 ospf6_iftype_str(oi->type));
1030 }
1031
1032 if (use_json) {
1033 json_arr = json_object_new_array();
1034 for (ALL_LIST_ELEMENTS_RO(ifp->connected, i, c)) {
1035 json_addr = json_object_new_object();
1036 p = c->address;
1037 prefix2str(p, strbuf, sizeof(strbuf));
1038 switch (p->family) {
1039 case AF_INET:
1040 json_object_string_add(json_addr, "type",
1041 "inet");
1042 json_object_string_add(json_addr, "address",
1043 strbuf);
1044 json_object_array_add(json_arr, json_addr);
1045 break;
1046 case AF_INET6:
1047 json_object_string_add(json_addr, "type",
1048 "inet6");
1049 json_object_string_add(json_addr, "address",
1050 strbuf);
1051 json_object_array_add(json_arr, json_addr);
1052 break;
1053 default:
1054 json_object_string_add(json_addr, "type",
1055 "unknown");
1056 json_object_string_add(json_addr, "address",
1057 strbuf);
1058 json_object_array_add(json_arr, json_addr);
1059 break;
1060 }
1061 }
1062 json_object_object_add(json_obj, "internetAddress", json_arr);
1063 } else {
1064 vty_out(vty, " Internet Address:\n");
1065
1066 for (ALL_LIST_ELEMENTS_RO(ifp->connected, i, c)) {
1067 p = c->address;
1068 prefix2str(p, strbuf, sizeof(strbuf));
1069 switch (p->family) {
1070 case AF_INET:
1071 vty_out(vty, " inet : %pFX\n", p);
1072 break;
1073 case AF_INET6:
1074 vty_out(vty, " inet6: %pFX\n", p);
1075 break;
1076 default:
1077 vty_out(vty, " ??? : %pFX\n", p);
1078 break;
1079 }
1080 }
1081 }
1082
1083 if (use_json) {
1084 if (oi->area) {
1085 json_object_boolean_true_add(json_obj,
1086 "attachedToArea");
1087 json_object_int_add(json_obj, "instanceId",
1088 oi->instance_id);
1089 json_object_int_add(json_obj, "interfaceMtu",
1090 oi->ifmtu);
1091 json_object_int_add(json_obj, "autoDetect", ifp->mtu6);
1092 json_object_string_add(json_obj, "mtuMismatchDetection",
1093 oi->mtu_ignore ? "disabled"
1094 : "enabled");
1095 inet_ntop(AF_INET, &oi->area->area_id, strbuf,
1096 sizeof(strbuf));
1097 json_object_string_add(json_obj, "areaId", strbuf);
1098 json_object_int_add(json_obj, "cost", oi->cost);
1099 } else
1100 json_object_boolean_false_add(json_obj,
1101 "attachedToArea");
1102
1103 } else {
1104 if (oi->area) {
1105 vty_out(vty,
1106 " Instance ID %d, Interface MTU %d (autodetect: %d)\n",
1107 oi->instance_id, oi->ifmtu, ifp->mtu6);
1108 vty_out(vty, " MTU mismatch detection: %s\n",
1109 oi->mtu_ignore ? "disabled" : "enabled");
1110 inet_ntop(AF_INET, &oi->area->area_id, strbuf,
1111 sizeof(strbuf));
1112 vty_out(vty, " Area ID %s, Cost %u\n", strbuf,
1113 oi->cost);
1114 } else
1115 vty_out(vty, " Not Attached to Area\n");
1116 }
1117
1118 if (use_json) {
1119 json_object_string_add(json_obj, "ospf6InterfaceState",
1120 ospf6_interface_state_str[oi->state]);
1121 json_object_int_add(json_obj, "transmitDelaySec",
1122 oi->transdelay);
1123 json_object_int_add(json_obj, "priority", oi->priority);
1124 json_object_int_add(json_obj, "timerIntervalsConfigHello",
1125 oi->hello_interval);
1126 json_object_int_add(json_obj, "timerIntervalsConfigDead",
1127 oi->dead_interval);
1128 json_object_int_add(json_obj, "timerIntervalsConfigRetransmit",
1129 oi->rxmt_interval);
1130 } else {
1131 vty_out(vty, " State %s, Transmit Delay %d sec, Priority %d\n",
1132 ospf6_interface_state_str[oi->state], oi->transdelay,
1133 oi->priority);
1134 vty_out(vty, " Timer intervals configured:\n");
1135 vty_out(vty, " Hello %d, Dead %d, Retransmit %d\n",
1136 oi->hello_interval, oi->dead_interval,
1137 oi->rxmt_interval);
1138 }
1139
1140 inet_ntop(AF_INET, &oi->drouter, drouter, sizeof(drouter));
1141 inet_ntop(AF_INET, &oi->bdrouter, bdrouter, sizeof(bdrouter));
1142 if (use_json) {
1143 json_object_string_add(json_obj, "dr", drouter);
1144 json_object_string_add(json_obj, "bdr", bdrouter);
1145 json_object_int_add(json_obj, "numberOfInterfaceScopedLsa",
1146 oi->lsdb->count);
1147 } else {
1148 vty_out(vty, " DR: %s BDR: %s\n", drouter, bdrouter);
1149 vty_out(vty, " Number of I/F scoped LSAs is %u\n",
1150 oi->lsdb->count);
1151 }
1152
1153 monotime(&now);
1154
1155 if (use_json) {
1156 timerclear(&res);
1157 if (oi->thread_send_lsupdate)
1158 timersub(&oi->thread_send_lsupdate->u.sands, &now,
1159 &res);
1160 timerstring(&res, duration, sizeof(duration));
1161 json_object_int_add(json_obj, "pendingLsaLsUpdateCount",
1162 oi->lsupdate_list->count);
1163 json_object_string_add(json_obj, "pendingLsaLsUpdateTime",
1164 duration);
1165 json_object_string_add(
1166 json_obj, "lsUpdateSendThread",
1167 (oi->thread_send_lsupdate ? "on" : "off"));
1168
1169 json_arr = json_object_new_array();
1170 for (ALL_LSDB(oi->lsupdate_list, lsa, lsanext))
1171 json_object_array_add(
1172 json_arr, json_object_new_string(lsa->name));
1173 json_object_object_add(json_obj, "pendingLsaLsUpdate",
1174 json_arr);
1175
1176 timerclear(&res);
1177 if (oi->thread_send_lsack)
1178 timersub(&oi->thread_send_lsack->u.sands, &now, &res);
1179 timerstring(&res, duration, sizeof(duration));
1180
1181 json_object_int_add(json_obj, "pendingLsaLsAckCount",
1182 oi->lsack_list->count);
1183 json_object_string_add(json_obj, "pendingLsaLsAckTime",
1184 duration);
1185 json_object_string_add(json_obj, "lsAckSendThread",
1186 (oi->thread_send_lsack ? "on" : "off"));
1187
1188 json_arr = json_object_new_array();
1189 for (ALL_LSDB(oi->lsack_list, lsa, lsanext))
1190 json_object_array_add(
1191 json_arr, json_object_new_string(lsa->name));
1192 json_object_object_add(json_obj, "pendingLsaLsAck", json_arr);
1193
1194 } else {
1195 timerclear(&res);
1196 if (oi->thread_send_lsupdate)
1197 timersub(&oi->thread_send_lsupdate->u.sands, &now,
1198 &res);
1199 timerstring(&res, duration, sizeof(duration));
1200 vty_out(vty,
1201 " %d Pending LSAs for LSUpdate in Time %s [thread %s]\n",
1202 oi->lsupdate_list->count, duration,
1203 (oi->thread_send_lsupdate ? "on" : "off"));
1204 for (ALL_LSDB(oi->lsupdate_list, lsa, lsanext))
1205 vty_out(vty, " %s\n", lsa->name);
1206
1207 timerclear(&res);
1208 if (oi->thread_send_lsack)
1209 timersub(&oi->thread_send_lsack->u.sands, &now, &res);
1210 timerstring(&res, duration, sizeof(duration));
1211 vty_out(vty,
1212 " %d Pending LSAs for LSAck in Time %s [thread %s]\n",
1213 oi->lsack_list->count, duration,
1214 (oi->thread_send_lsack ? "on" : "off"));
1215 for (ALL_LSDB(oi->lsack_list, lsa, lsanext))
1216 vty_out(vty, " %s\n", lsa->name);
1217 }
1218
1219 /* BFD specific. */
1220 if (oi->bfd_config.enabled) {
1221 if (use_json) {
1222 struct json_object *json_bfd = json_object_new_object();
1223
1224 json_object_int_add(
1225 json_bfd, "detectMultiplier",
1226 oi->bfd_config.detection_multiplier);
1227 json_object_int_add(json_bfd, "rxMinInterval",
1228 oi->bfd_config.min_rx);
1229 json_object_int_add(json_bfd, "txMinInterval",
1230 oi->bfd_config.min_tx);
1231 json_object_object_add(json_obj, "peerBfdInfo",
1232 json_bfd);
1233 } else {
1234 vty_out(vty,
1235 " BFD: Detect Multiplier: %d, Min Rx interval: %d, Min Tx interval: %d\n",
1236 oi->bfd_config.detection_multiplier,
1237 oi->bfd_config.min_rx, oi->bfd_config.min_tx);
1238 }
1239 }
1240
1241 return 0;
1242 }
1243
1244 /* Find the global address to be used as a forwarding address in NSSA LSA.*/
1245 struct in6_addr *ospf6_interface_get_global_address(struct interface *ifp)
1246 {
1247 struct listnode *n;
1248 struct connected *c;
1249
1250 /* for each connected address */
1251 for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) {
1252 /* if family not AF_INET6, ignore */
1253 if (c->address->family != AF_INET6)
1254 continue;
1255
1256 if (!IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6))
1257 return &c->address->u.prefix6;
1258 }
1259
1260 return NULL;
1261 }
1262
1263
1264 static int show_ospf6_interface_common(struct vty *vty, vrf_id_t vrf_id,
1265 int argc, struct cmd_token **argv,
1266 int idx_ifname, int intf_idx,
1267 int json_idx, bool uj)
1268 {
1269
1270 struct vrf *vrf = vrf_lookup_by_id(vrf_id);
1271 struct interface *ifp;
1272 json_object *json;
1273 json_object *json_int;
1274
1275 if (uj) {
1276 json = json_object_new_object();
1277 if (argc == json_idx) {
1278 ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id);
1279 json_int = json_object_new_object();
1280 if (ifp == NULL) {
1281 json_object_string_add(json, "noSuchInterface",
1282 argv[idx_ifname]->arg);
1283 vty_json(vty, json);
1284 json_object_free(json_int);
1285 return CMD_WARNING;
1286 }
1287 ospf6_interface_show(vty, ifp, json_int, uj);
1288 json_object_object_add(json, ifp->name, json_int);
1289 } else {
1290 FOR_ALL_INTERFACES (vrf, ifp) {
1291 json_int = json_object_new_object();
1292 ospf6_interface_show(vty, ifp, json_int, uj);
1293 json_object_object_add(json, ifp->name,
1294 json_int);
1295 }
1296 }
1297 vty_json(vty, json);
1298 } else {
1299 if (argc == intf_idx) {
1300 ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id);
1301 if (ifp == NULL) {
1302 vty_out(vty, "No such Interface: %s\n",
1303 argv[idx_ifname]->arg);
1304 return CMD_WARNING;
1305 }
1306 ospf6_interface_show(vty, ifp, NULL, uj);
1307 } else {
1308 FOR_ALL_INTERFACES (vrf, ifp)
1309 ospf6_interface_show(vty, ifp, NULL, uj);
1310 }
1311 }
1312 return CMD_SUCCESS;
1313 }
1314
1315 /* show interface */
1316 DEFUN(show_ipv6_ospf6_interface, show_ipv6_ospf6_interface_ifname_cmd,
1317 "show ipv6 ospf6 [vrf <NAME|all>] interface [IFNAME] [json]",
1318 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1319 "All VRFs\n" INTERFACE_STR IFNAME_STR JSON_STR)
1320 {
1321 int idx_ifname = 4;
1322 int intf_idx = 5;
1323 int json_idx = 6;
1324 struct listnode *node;
1325 struct ospf6 *ospf6;
1326 const char *vrf_name = NULL;
1327 bool all_vrf = false;
1328 int idx_vrf = 0;
1329 bool uj = use_json(argc, argv);
1330
1331 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1332 if (idx_vrf > 0) {
1333 idx_ifname += 2;
1334 intf_idx += 2;
1335 json_idx += 2;
1336 }
1337
1338 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1339 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1340 show_ospf6_interface_common(vty, ospf6->vrf_id, argc,
1341 argv, idx_ifname, intf_idx,
1342 json_idx, uj);
1343
1344 if (!all_vrf)
1345 break;
1346 }
1347 }
1348
1349 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1350
1351 return CMD_SUCCESS;
1352 }
1353
1354 static int ospf6_interface_show_traffic(struct vty *vty,
1355 struct interface *intf_ifp,
1356 int display_once, json_object *json,
1357 bool use_json, vrf_id_t vrf_id)
1358 {
1359 struct interface *ifp;
1360 struct vrf *vrf = NULL;
1361 struct ospf6_interface *oi = NULL;
1362 json_object *json_interface;
1363
1364 if (!display_once && !use_json) {
1365 vty_out(vty, "\n");
1366 vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s\n", "Interface",
1367 " HELLO", " DB-Desc", " LS-Req", " LS-Update",
1368 " LS-Ack");
1369 vty_out(vty, "%-10s%-18s%-18s%-17s%-17s%-17s\n", "",
1370 " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx",
1371 " Rx/Tx");
1372 vty_out(vty,
1373 "--------------------------------------------------------------------------------------------\n");
1374 }
1375
1376 if (intf_ifp == NULL) {
1377 vrf = vrf_lookup_by_id(vrf_id);
1378 FOR_ALL_INTERFACES (vrf, ifp) {
1379 if (ifp->info)
1380 oi = (struct ospf6_interface *)ifp->info;
1381 else
1382 continue;
1383
1384 if (use_json) {
1385 json_interface = json_object_new_object();
1386 json_object_int_add(json_interface, "helloRx",
1387 oi->hello_in);
1388 json_object_int_add(json_interface, "helloTx",
1389 oi->hello_out);
1390 json_object_int_add(json_interface, "dbDescRx",
1391 oi->db_desc_in);
1392 json_object_int_add(json_interface, "dbDescTx",
1393 oi->db_desc_out);
1394 json_object_int_add(json_interface, "lsReqRx",
1395 oi->ls_req_in);
1396 json_object_int_add(json_interface, "lsReqTx",
1397 oi->ls_req_out);
1398 json_object_int_add(json_interface,
1399 "lsUpdateRx",
1400 oi->ls_upd_in);
1401 json_object_int_add(json_interface,
1402 "lsUpdateTx",
1403 oi->ls_upd_out);
1404 json_object_int_add(json_interface, "lsAckRx",
1405 oi->ls_ack_in);
1406 json_object_int_add(json_interface, "lsAckTx",
1407 oi->ls_ack_out);
1408
1409 json_object_object_add(json,
1410 oi->interface->name,
1411 json_interface);
1412 } else
1413 vty_out(vty,
1414 "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n",
1415 oi->interface->name, oi->hello_in,
1416 oi->hello_out, oi->db_desc_in,
1417 oi->db_desc_out, oi->ls_req_in,
1418 oi->ls_req_out, oi->ls_upd_in,
1419 oi->ls_upd_out, oi->ls_ack_in,
1420 oi->ls_ack_out);
1421 }
1422 } else {
1423 oi = intf_ifp->info;
1424 if (oi == NULL)
1425 return CMD_WARNING;
1426
1427 if (use_json) {
1428 json_interface = json_object_new_object();
1429 json_object_int_add(json_interface, "helloRx",
1430 oi->hello_in);
1431 json_object_int_add(json_interface, "helloTx",
1432 oi->hello_out);
1433 json_object_int_add(json_interface, "dbDescRx",
1434 oi->db_desc_in);
1435 json_object_int_add(json_interface, "dbDescTx",
1436 oi->db_desc_out);
1437 json_object_int_add(json_interface, "lsReqRx",
1438 oi->ls_req_in);
1439 json_object_int_add(json_interface, "lsReqTx",
1440 oi->ls_req_out);
1441 json_object_int_add(json_interface, "lsUpdateRx",
1442 oi->ls_upd_in);
1443 json_object_int_add(json_interface, "lsUpdateTx",
1444 oi->ls_upd_out);
1445 json_object_int_add(json_interface, "lsAckRx",
1446 oi->ls_ack_in);
1447 json_object_int_add(json_interface, "lsAckTx",
1448 oi->ls_ack_out);
1449
1450 json_object_object_add(json, oi->interface->name,
1451 json_interface);
1452 } else
1453 vty_out(vty,
1454 "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n",
1455 oi->interface->name, oi->hello_in,
1456 oi->hello_out, oi->db_desc_in, oi->db_desc_out,
1457 oi->ls_req_in, oi->ls_req_out, oi->ls_upd_in,
1458 oi->ls_upd_out, oi->ls_ack_in, oi->ls_ack_out);
1459 }
1460
1461 return CMD_SUCCESS;
1462 }
1463
1464 static int ospf6_interface_show_traffic_common(struct vty *vty, int argc,
1465 struct cmd_token **argv,
1466 vrf_id_t vrf_id, bool uj)
1467 {
1468 int idx_ifname = 0;
1469 int display_once = 0;
1470 char *intf_name = NULL;
1471 struct interface *ifp = NULL;
1472 json_object *json = NULL;
1473
1474 if (uj)
1475 json = json_object_new_object();
1476
1477 if (argv_find(argv, argc, "IFNAME", &idx_ifname)) {
1478 intf_name = argv[idx_ifname]->arg;
1479 ifp = if_lookup_by_name(intf_name, vrf_id);
1480 if (uj) {
1481 if (ifp == NULL) {
1482 json_object_string_add(json, "status",
1483 "No Such Interface");
1484 json_object_string_add(json, "interface",
1485 intf_name);
1486 vty_json(vty, json);
1487 return CMD_WARNING;
1488 }
1489 if (ifp->info == NULL) {
1490 json_object_string_add(
1491 json, "status",
1492 "OSPF not enabled on this interface");
1493 json_object_string_add(json, "interface",
1494 intf_name);
1495 vty_json(vty, json);
1496 return 0;
1497 }
1498 } else {
1499 if (ifp == NULL) {
1500 vty_out(vty, "No such Interface: %s\n",
1501 intf_name);
1502 return CMD_WARNING;
1503 }
1504 if (ifp->info == NULL) {
1505 vty_out(vty,
1506 " OSPF not enabled on this interface %s\n",
1507 intf_name);
1508 return 0;
1509 }
1510 }
1511 }
1512
1513 ospf6_interface_show_traffic(vty, ifp, display_once, json, uj, vrf_id);
1514
1515 if (uj)
1516 vty_json(vty, json);
1517
1518 return CMD_SUCCESS;
1519 }
1520
1521 /* show interface */
1522 DEFUN(show_ipv6_ospf6_interface_traffic, show_ipv6_ospf6_interface_traffic_cmd,
1523 "show ipv6 ospf6 [vrf <NAME|all>] interface traffic [IFNAME] [json]",
1524 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1525 "All VRFs\n" INTERFACE_STR
1526 "Protocol Packet counters\n" IFNAME_STR JSON_STR)
1527 {
1528 struct ospf6 *ospf6;
1529 struct listnode *node;
1530 const char *vrf_name = NULL;
1531 bool all_vrf = false;
1532 int idx_vrf = 0;
1533 bool uj = use_json(argc, argv);
1534
1535 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1536
1537 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1538 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1539 ospf6_interface_show_traffic_common(vty, argc, argv,
1540 ospf6->vrf_id, uj);
1541
1542 if (!all_vrf)
1543 break;
1544 }
1545 }
1546
1547 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1548
1549 return CMD_SUCCESS;
1550 }
1551
1552
1553 DEFUN(show_ipv6_ospf6_interface_ifname_prefix,
1554 show_ipv6_ospf6_interface_ifname_prefix_cmd,
1555 "show ipv6 ospf6 [vrf <NAME|all>] interface IFNAME prefix\
1556 [<\
1557 detail\
1558 |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
1559 >] [json]",
1560 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1561 "All VRFs\n" INTERFACE_STR IFNAME_STR
1562 "Display connected prefixes to advertise\n"
1563 "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR
1564 OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR
1565 "Display details of the prefixes\n" JSON_STR)
1566 {
1567 int idx_ifname = 4;
1568 int idx_prefix = 6;
1569 struct ospf6_interface *oi;
1570 bool uj = use_json(argc, argv);
1571
1572 struct ospf6 *ospf6;
1573 struct listnode *node;
1574 struct interface *ifp;
1575 const char *vrf_name = NULL;
1576 bool all_vrf = false;
1577 int idx_vrf = 0;
1578
1579 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1580 if (idx_vrf > 0) {
1581 idx_ifname += 2;
1582 idx_prefix += 2;
1583 }
1584
1585 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1586 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1587 ifp = if_lookup_by_name(argv[idx_ifname]->arg,
1588 ospf6->vrf_id);
1589 if (ifp == NULL) {
1590 vty_out(vty, "No such Interface: %s\n",
1591 argv[idx_ifname]->arg);
1592 return CMD_WARNING;
1593 }
1594
1595 oi = ifp->info;
1596 if (oi == NULL
1597 || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
1598 vty_out(vty,
1599 "Interface %s not attached to area\n",
1600 argv[idx_ifname]->arg);
1601 return CMD_WARNING;
1602 }
1603
1604 ospf6_route_table_show(vty, idx_prefix, argc, argv,
1605 oi->route_connected, uj);
1606
1607 if (!all_vrf)
1608 break;
1609 }
1610 }
1611
1612 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1613
1614 return CMD_SUCCESS;
1615 }
1616
1617 DEFUN(show_ipv6_ospf6_interface_prefix, show_ipv6_ospf6_interface_prefix_cmd,
1618 "show ipv6 ospf6 [vrf <NAME|all>] interface prefix\
1619 [<\
1620 detail\
1621 |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
1622 >] [json]",
1623 SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
1624 "All VRFs\n" INTERFACE_STR
1625 "Display connected prefixes to advertise\n"
1626 "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR
1627 OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR
1628 "Display details of the prefixes\n" JSON_STR)
1629 {
1630 struct vrf *vrf = NULL;
1631 int idx_prefix = 5;
1632 struct ospf6_interface *oi;
1633 struct interface *ifp;
1634 bool uj = use_json(argc, argv);
1635 struct listnode *node;
1636 struct ospf6 *ospf6;
1637 const char *vrf_name = NULL;
1638 bool all_vrf = false;
1639 int idx_vrf = 0;
1640
1641 OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
1642 if (idx_vrf > 0)
1643 idx_prefix += 2;
1644
1645 for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
1646 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
1647 vrf = vrf_lookup_by_id(ospf6->vrf_id);
1648 FOR_ALL_INTERFACES (vrf, ifp) {
1649 oi = (struct ospf6_interface *)ifp->info;
1650 if (oi == NULL
1651 || CHECK_FLAG(oi->flag,
1652 OSPF6_INTERFACE_DISABLE))
1653 continue;
1654
1655 ospf6_route_table_show(vty, idx_prefix, argc,
1656 argv,
1657 oi->route_connected, uj);
1658 }
1659 if (!all_vrf)
1660 break;
1661 }
1662 }
1663
1664 OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
1665
1666 return CMD_SUCCESS;
1667 }
1668
1669 void ospf6_interface_start(struct ospf6_interface *oi)
1670 {
1671 struct ospf6 *ospf6;
1672 struct ospf6_area *oa;
1673
1674 if (oi->area_id_format == OSPF6_AREA_FMT_UNSET)
1675 return;
1676
1677 if (oi->area)
1678 return;
1679
1680 ospf6 = oi->interface->vrf->info;
1681 if (!ospf6)
1682 return;
1683
1684 oa = ospf6_area_lookup(oi->area_id, ospf6);
1685 if (oa == NULL)
1686 oa = ospf6_area_create(oi->area_id, ospf6, oi->area_id_format);
1687
1688 /* attach interface to area */
1689 listnode_add(oa->if_list, oi);
1690 oi->area = oa;
1691
1692 SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
1693
1694 /* start up */
1695 ospf6_interface_enable(oi);
1696
1697 /* If the router is ABR, originate summary routes */
1698 if (ospf6_check_and_set_router_abr(ospf6))
1699 ospf6_abr_enable_area(oa);
1700 }
1701
1702 void ospf6_interface_stop(struct ospf6_interface *oi)
1703 {
1704 struct ospf6_area *oa;
1705
1706 oa = oi->area;
1707 if (!oa)
1708 return;
1709
1710 ospf6_interface_disable(oi);
1711
1712 listnode_delete(oa->if_list, oi);
1713 oi->area = NULL;
1714
1715 if (oa->if_list->count == 0) {
1716 UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
1717 ospf6_abr_disable_area(oa);
1718 }
1719 }
1720
1721 /* interface variable set command */
1722 DEFUN (ipv6_ospf6_area,
1723 ipv6_ospf6_area_cmd,
1724 "ipv6 ospf6 area <A.B.C.D|(0-4294967295)>",
1725 IP6_STR
1726 OSPF6_STR
1727 "Specify the OSPF6 area ID\n"
1728 "OSPF6 area ID in IPv4 address notation\n"
1729 "OSPF6 area ID in decimal notation\n")
1730 {
1731 VTY_DECLVAR_CONTEXT(interface, ifp);
1732 struct ospf6_interface *oi;
1733 int idx_ipv4 = 3;
1734 uint32_t area_id;
1735 int format;
1736
1737 assert(ifp);
1738
1739 oi = (struct ospf6_interface *)ifp->info;
1740 if (oi == NULL)
1741 oi = ospf6_interface_create(ifp);
1742 assert(oi);
1743
1744 if (oi->area) {
1745 vty_out(vty, "%s already attached to Area %s\n",
1746 oi->interface->name, oi->area->name);
1747 return CMD_SUCCESS;
1748 }
1749
1750 if (str2area_id(argv[idx_ipv4]->arg, &area_id, &format)) {
1751 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
1752 return CMD_WARNING_CONFIG_FAILED;
1753 }
1754
1755 oi->area_id = area_id;
1756 oi->area_id_format = format;
1757
1758 ospf6_interface_start(oi);
1759
1760 return CMD_SUCCESS;
1761 }
1762
1763 DEFUN (no_ipv6_ospf6_area,
1764 no_ipv6_ospf6_area_cmd,
1765 "no ipv6 ospf6 area [<A.B.C.D|(0-4294967295)>]",
1766 NO_STR
1767 IP6_STR
1768 OSPF6_STR
1769 "Specify the OSPF6 area ID\n"
1770 "OSPF6 area ID in IPv4 address notation\n"
1771 "OSPF6 area ID in decimal notation\n")
1772 {
1773 VTY_DECLVAR_CONTEXT(interface, ifp);
1774 struct ospf6_interface *oi;
1775
1776 assert(ifp);
1777
1778 oi = (struct ospf6_interface *)ifp->info;
1779 if (oi == NULL)
1780 oi = ospf6_interface_create(ifp);
1781 assert(oi);
1782
1783 ospf6_interface_stop(oi);
1784
1785 oi->area_id = 0;
1786 oi->area_id_format = OSPF6_AREA_FMT_UNSET;
1787
1788 return CMD_SUCCESS;
1789 }
1790
1791 DEFUN (ipv6_ospf6_ifmtu,
1792 ipv6_ospf6_ifmtu_cmd,
1793 "ipv6 ospf6 ifmtu (1-65535)",
1794 IP6_STR
1795 OSPF6_STR
1796 "Interface MTU\n"
1797 "OSPFv3 Interface MTU\n"
1798 )
1799 {
1800 VTY_DECLVAR_CONTEXT(interface, ifp);
1801 int idx_number = 3;
1802 struct ospf6_interface *oi;
1803 unsigned int ifmtu, iobuflen;
1804 struct listnode *node, *nnode;
1805 struct ospf6_neighbor *on;
1806
1807 assert(ifp);
1808
1809 oi = (struct ospf6_interface *)ifp->info;
1810 if (oi == NULL)
1811 oi = ospf6_interface_create(ifp);
1812 assert(oi);
1813
1814 ifmtu = strtol(argv[idx_number]->arg, NULL, 10);
1815
1816 if (oi->c_ifmtu == ifmtu)
1817 return CMD_SUCCESS;
1818
1819 if (ifp->mtu6 != 0 && ifp->mtu6 < ifmtu) {
1820 vty_out(vty,
1821 "%s's ospf6 ifmtu cannot go beyond physical mtu (%d)\n",
1822 ifp->name, ifp->mtu6);
1823 return CMD_WARNING_CONFIG_FAILED;
1824 }
1825
1826 if (oi->ifmtu < ifmtu) {
1827 iobuflen = ospf6_iobuf_size(ifmtu);
1828 if (iobuflen < ifmtu) {
1829 vty_out(vty,
1830 "%s's ifmtu is adjusted to I/O buffer size (%d).\n",
1831 ifp->name, iobuflen);
1832 oi->ifmtu = oi->c_ifmtu = iobuflen;
1833 } else
1834 oi->ifmtu = oi->c_ifmtu = ifmtu;
1835 } else
1836 oi->ifmtu = oi->c_ifmtu = ifmtu;
1837
1838 /* re-establish adjacencies */
1839 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
1840 THREAD_OFF(on->inactivity_timer);
1841 thread_add_event(master, inactivity_timer, on, 0, NULL);
1842 }
1843
1844 return CMD_SUCCESS;
1845 }
1846
1847 DEFUN (no_ipv6_ospf6_ifmtu,
1848 no_ipv6_ospf6_ifmtu_cmd,
1849 "no ipv6 ospf6 ifmtu [(1-65535)]",
1850 NO_STR
1851 IP6_STR
1852 OSPF6_STR
1853 "Interface MTU\n"
1854 "OSPFv3 Interface MTU\n"
1855 )
1856 {
1857 VTY_DECLVAR_CONTEXT(interface, ifp);
1858 struct ospf6_interface *oi;
1859 unsigned int iobuflen;
1860 struct listnode *node, *nnode;
1861 struct ospf6_neighbor *on;
1862
1863 assert(ifp);
1864
1865 oi = (struct ospf6_interface *)ifp->info;
1866 if (oi == NULL)
1867 oi = ospf6_interface_create(ifp);
1868 assert(oi);
1869
1870 if (oi->ifmtu < ifp->mtu) {
1871 iobuflen = ospf6_iobuf_size(ifp->mtu);
1872 if (iobuflen < ifp->mtu) {
1873 vty_out(vty,
1874 "%s's ifmtu is adjusted to I/O buffer size (%d).\n",
1875 ifp->name, iobuflen);
1876 oi->ifmtu = iobuflen;
1877 } else
1878 oi->ifmtu = ifp->mtu;
1879 } else
1880 oi->ifmtu = ifp->mtu;
1881
1882 oi->c_ifmtu = 0;
1883
1884 /* re-establish adjacencies */
1885 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
1886 THREAD_OFF(on->inactivity_timer);
1887 thread_add_event(master, inactivity_timer, on, 0, NULL);
1888 }
1889
1890 return CMD_SUCCESS;
1891 }
1892
1893 DEFUN (ipv6_ospf6_cost,
1894 ipv6_ospf6_cost_cmd,
1895 "ipv6 ospf6 cost (1-65535)",
1896 IP6_STR
1897 OSPF6_STR
1898 "Interface cost\n"
1899 "Outgoing metric of this interface\n")
1900 {
1901 VTY_DECLVAR_CONTEXT(interface, ifp);
1902 int idx_number = 3;
1903 struct ospf6_interface *oi;
1904 unsigned long int lcost;
1905
1906 assert(ifp);
1907
1908 oi = (struct ospf6_interface *)ifp->info;
1909 if (oi == NULL)
1910 oi = ospf6_interface_create(ifp);
1911 assert(oi);
1912
1913 lcost = strtol(argv[idx_number]->arg, NULL, 10);
1914
1915 if (lcost > UINT32_MAX) {
1916 vty_out(vty, "Cost %ld is out of range\n", lcost);
1917 return CMD_WARNING_CONFIG_FAILED;
1918 }
1919
1920 SET_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST);
1921 if (oi->cost == lcost)
1922 return CMD_SUCCESS;
1923
1924 oi->cost = lcost;
1925 ospf6_interface_force_recalculate_cost(oi);
1926
1927 return CMD_SUCCESS;
1928 }
1929
1930 DEFUN (no_ipv6_ospf6_cost,
1931 no_ipv6_ospf6_cost_cmd,
1932 "no ipv6 ospf6 cost [(1-65535)]",
1933 NO_STR
1934 IP6_STR
1935 OSPF6_STR
1936 "Calculate interface cost from bandwidth\n"
1937 "Outgoing metric of this interface\n")
1938 {
1939 VTY_DECLVAR_CONTEXT(interface, ifp);
1940 struct ospf6_interface *oi;
1941 assert(ifp);
1942
1943 oi = (struct ospf6_interface *)ifp->info;
1944 if (oi == NULL)
1945 oi = ospf6_interface_create(ifp);
1946 assert(oi);
1947
1948 UNSET_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST);
1949
1950 ospf6_interface_recalculate_cost(oi);
1951
1952 return CMD_SUCCESS;
1953 }
1954
1955 DEFUN (auto_cost_reference_bandwidth,
1956 auto_cost_reference_bandwidth_cmd,
1957 "auto-cost reference-bandwidth (1-4294967)",
1958 "Calculate OSPF interface cost according to bandwidth\n"
1959 "Use reference bandwidth method to assign OSPF cost\n"
1960 "The reference bandwidth in terms of Mbits per second\n")
1961 {
1962 VTY_DECLVAR_CONTEXT(ospf6, o);
1963 int idx_number = 2;
1964 struct ospf6_area *oa;
1965 struct ospf6_interface *oi;
1966 struct listnode *i, *j;
1967 uint32_t refbw;
1968
1969 refbw = strtol(argv[idx_number]->arg, NULL, 10);
1970 if (refbw < 1 || refbw > 4294967) {
1971 vty_out(vty, "reference-bandwidth value is invalid\n");
1972 return CMD_WARNING_CONFIG_FAILED;
1973 }
1974
1975 /* If reference bandwidth is changed. */
1976 if ((refbw) == o->ref_bandwidth)
1977 return CMD_SUCCESS;
1978
1979 o->ref_bandwidth = refbw;
1980 for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa))
1981 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi))
1982 ospf6_interface_recalculate_cost(oi);
1983
1984 return CMD_SUCCESS;
1985 }
1986
1987 DEFUN (no_auto_cost_reference_bandwidth,
1988 no_auto_cost_reference_bandwidth_cmd,
1989 "no auto-cost reference-bandwidth [(1-4294967)]",
1990 NO_STR
1991 "Calculate OSPF interface cost according to bandwidth\n"
1992 "Use reference bandwidth method to assign OSPF cost\n"
1993 "The reference bandwidth in terms of Mbits per second\n")
1994 {
1995 VTY_DECLVAR_CONTEXT(ospf6, o);
1996 struct ospf6_area *oa;
1997 struct ospf6_interface *oi;
1998 struct listnode *i, *j;
1999
2000 if (o->ref_bandwidth == OSPF6_REFERENCE_BANDWIDTH)
2001 return CMD_SUCCESS;
2002
2003 o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH;
2004 for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa))
2005 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi))
2006 ospf6_interface_recalculate_cost(oi);
2007
2008 return CMD_SUCCESS;
2009 }
2010
2011
2012 DEFUN (ospf6_write_multiplier,
2013 ospf6_write_multiplier_cmd,
2014 "write-multiplier (1-100)",
2015 "Write multiplier\n"
2016 "Maximum number of interface serviced per write\n")
2017 {
2018 VTY_DECLVAR_CONTEXT(ospf6, o);
2019 uint32_t write_oi_count;
2020
2021 write_oi_count = strtol(argv[1]->arg, NULL, 10);
2022 if (write_oi_count < 1 || write_oi_count > 100) {
2023 vty_out(vty, "write-multiplier value is invalid\n");
2024 return CMD_WARNING_CONFIG_FAILED;
2025 }
2026
2027 o->write_oi_count = write_oi_count;
2028 return CMD_SUCCESS;
2029 }
2030
2031 DEFUN (no_ospf6_write_multiplier,
2032 no_ospf6_write_multiplier_cmd,
2033 "no write-multiplier (1-100)",
2034 NO_STR
2035 "Write multiplier\n"
2036 "Maximum number of interface serviced per write\n")
2037 {
2038 VTY_DECLVAR_CONTEXT(ospf6, o);
2039
2040 o->write_oi_count = OSPF6_WRITE_INTERFACE_COUNT_DEFAULT;
2041 return CMD_SUCCESS;
2042 }
2043
2044 DEFUN (ipv6_ospf6_hellointerval,
2045 ipv6_ospf6_hellointerval_cmd,
2046 "ipv6 ospf6 hello-interval (1-65535)",
2047 IP6_STR
2048 OSPF6_STR
2049 "Time between HELLO packets\n"
2050 SECONDS_STR)
2051 {
2052 VTY_DECLVAR_CONTEXT(interface, ifp);
2053 int idx_number = 3;
2054 struct ospf6_interface *oi;
2055 assert(ifp);
2056
2057 oi = (struct ospf6_interface *)ifp->info;
2058 if (oi == NULL)
2059 oi = ospf6_interface_create(ifp);
2060 assert(oi);
2061
2062 oi->hello_interval = strmatch(argv[0]->text, "no")
2063 ? OSPF_HELLO_INTERVAL_DEFAULT
2064 : strtoul(argv[idx_number]->arg, NULL, 10);
2065 return CMD_SUCCESS;
2066 }
2067
2068 ALIAS (ipv6_ospf6_hellointerval,
2069 no_ipv6_ospf6_hellointerval_cmd,
2070 "no ipv6 ospf6 hello-interval [(1-65535)]",
2071 NO_STR
2072 IP6_STR
2073 OSPF6_STR
2074 "Time between HELLO packets\n"
2075 SECONDS_STR)
2076
2077 /* interface variable set command */
2078 DEFUN (ipv6_ospf6_deadinterval,
2079 ipv6_ospf6_deadinterval_cmd,
2080 "ipv6 ospf6 dead-interval (1-65535)",
2081 IP6_STR
2082 OSPF6_STR
2083 "Interval time after which a neighbor is declared down\n"
2084 SECONDS_STR)
2085 {
2086 VTY_DECLVAR_CONTEXT(interface, ifp);
2087 int idx_number = 3;
2088 struct ospf6_interface *oi;
2089 assert(ifp);
2090
2091 oi = (struct ospf6_interface *)ifp->info;
2092 if (oi == NULL)
2093 oi = ospf6_interface_create(ifp);
2094 assert(oi);
2095
2096 oi->dead_interval = strmatch(argv[0]->arg, "no")
2097 ? OSPF_ROUTER_DEAD_INTERVAL_DEFAULT
2098 : strtoul(argv[idx_number]->arg, NULL, 10);
2099 return CMD_SUCCESS;
2100 }
2101
2102 ALIAS (ipv6_ospf6_deadinterval,
2103 no_ipv6_ospf6_deadinterval_cmd,
2104 "no ipv6 ospf6 dead-interval [(1-65535)]",
2105 NO_STR
2106 IP6_STR
2107 OSPF6_STR
2108 "Interval time after which a neighbor is declared down\n"
2109 SECONDS_STR)
2110
2111 /* interface variable set command */
2112 DEFUN (ipv6_ospf6_transmitdelay,
2113 ipv6_ospf6_transmitdelay_cmd,
2114 "ipv6 ospf6 transmit-delay (1-3600)",
2115 IP6_STR
2116 OSPF6_STR
2117 "Link state transmit delay\n"
2118 SECONDS_STR)
2119 {
2120 VTY_DECLVAR_CONTEXT(interface, ifp);
2121 int idx_number = 3;
2122 struct ospf6_interface *oi;
2123 assert(ifp);
2124
2125 oi = (struct ospf6_interface *)ifp->info;
2126 if (oi == NULL)
2127 oi = ospf6_interface_create(ifp);
2128 assert(oi);
2129
2130 oi->transdelay = strmatch(argv[0]->text, "no")
2131 ? OSPF6_INTERFACE_TRANSDELAY
2132 : strtoul(argv[idx_number]->arg, NULL, 10);
2133 return CMD_SUCCESS;
2134 }
2135
2136 ALIAS (ipv6_ospf6_transmitdelay,
2137 no_ipv6_ospf6_transmitdelay_cmd,
2138 "no ipv6 ospf6 transmit-delay [(1-3600)]",
2139 NO_STR
2140 IP6_STR
2141 OSPF6_STR
2142 "Link state transmit delay\n"
2143 SECONDS_STR)
2144
2145 /* interface variable set command */
2146 DEFUN (ipv6_ospf6_retransmitinterval,
2147 ipv6_ospf6_retransmitinterval_cmd,
2148 "ipv6 ospf6 retransmit-interval (1-65535)",
2149 IP6_STR
2150 OSPF6_STR
2151 "Time between retransmitting lost link state advertisements\n"
2152 SECONDS_STR)
2153 {
2154 VTY_DECLVAR_CONTEXT(interface, ifp);
2155 int idx_number = 3;
2156 struct ospf6_interface *oi;
2157 assert(ifp);
2158
2159 oi = (struct ospf6_interface *)ifp->info;
2160 if (oi == NULL)
2161 oi = ospf6_interface_create(ifp);
2162 assert(oi);
2163
2164 oi->rxmt_interval = strmatch(argv[0]->text, "no")
2165 ? OSPF_RETRANSMIT_INTERVAL_DEFAULT
2166 : strtoul(argv[idx_number]->arg, NULL, 10);
2167 return CMD_SUCCESS;
2168 }
2169
2170 ALIAS (ipv6_ospf6_retransmitinterval,
2171 no_ipv6_ospf6_retransmitinterval_cmd,
2172 "no ipv6 ospf6 retransmit-interval [(1-65535)]",
2173 NO_STR
2174 IP6_STR
2175 OSPF6_STR
2176 "Time between retransmitting lost link state advertisements\n"
2177 SECONDS_STR)
2178
2179 /* interface variable set command */
2180 DEFUN (ipv6_ospf6_priority,
2181 ipv6_ospf6_priority_cmd,
2182 "ipv6 ospf6 priority (0-255)",
2183 IP6_STR
2184 OSPF6_STR
2185 "Router priority\n"
2186 "Priority value\n")
2187 {
2188 VTY_DECLVAR_CONTEXT(interface, ifp);
2189 int idx_number = 3;
2190 struct ospf6_interface *oi;
2191 assert(ifp);
2192
2193 oi = (struct ospf6_interface *)ifp->info;
2194 if (oi == NULL)
2195 oi = ospf6_interface_create(ifp);
2196 assert(oi);
2197
2198 oi->priority = strmatch(argv[0]->text, "no")
2199 ? OSPF6_INTERFACE_PRIORITY
2200 : strtoul(argv[idx_number]->arg, NULL, 10);
2201
2202 if (oi->area
2203 && (oi->state == OSPF6_INTERFACE_DROTHER
2204 || oi->state == OSPF6_INTERFACE_BDR
2205 || oi->state == OSPF6_INTERFACE_DR)) {
2206 if (ospf6_interface_state_change(dr_election(oi), oi) == -1)
2207 OSPF6_LINK_LSA_SCHEDULE(oi);
2208 }
2209
2210 return CMD_SUCCESS;
2211 }
2212
2213 ALIAS (ipv6_ospf6_priority,
2214 no_ipv6_ospf6_priority_cmd,
2215 "no ipv6 ospf6 priority [(0-255)]",
2216 NO_STR
2217 IP6_STR
2218 OSPF6_STR
2219 "Router priority\n"
2220 "Priority value\n")
2221
2222 DEFUN (ipv6_ospf6_instance,
2223 ipv6_ospf6_instance_cmd,
2224 "ipv6 ospf6 instance-id (0-255)",
2225 IP6_STR
2226 OSPF6_STR
2227 "Instance ID for this interface\n"
2228 "Instance ID value\n")
2229 {
2230 VTY_DECLVAR_CONTEXT(interface, ifp);
2231 int idx_number = 3;
2232 struct ospf6_interface *oi;
2233 assert(ifp);
2234
2235 oi = (struct ospf6_interface *)ifp->info;
2236 if (oi == NULL)
2237 oi = ospf6_interface_create(ifp);
2238 assert(oi);
2239
2240 oi->instance_id = strmatch(argv[0]->text, "no")
2241 ? OSPF6_INTERFACE_INSTANCE_ID
2242 : strtoul(argv[idx_number]->arg, NULL, 10);
2243 return CMD_SUCCESS;
2244 }
2245
2246 ALIAS (ipv6_ospf6_instance,
2247 no_ipv6_ospf6_instance_cmd,
2248 "no ipv6 ospf6 instance-id [(0-255)]",
2249 NO_STR
2250 IP6_STR
2251 OSPF6_STR
2252 "Instance ID for this interface\n"
2253 "Instance ID value\n")
2254
2255 DEFUN (ipv6_ospf6_passive,
2256 ipv6_ospf6_passive_cmd,
2257 "ipv6 ospf6 passive",
2258 IP6_STR
2259 OSPF6_STR
2260 "Passive interface; no adjacency will be formed on this interface\n"
2261 )
2262 {
2263 VTY_DECLVAR_CONTEXT(interface, ifp);
2264 struct ospf6_interface *oi;
2265 struct listnode *node, *nnode;
2266 struct ospf6_neighbor *on;
2267
2268 assert(ifp);
2269
2270 oi = (struct ospf6_interface *)ifp->info;
2271 if (oi == NULL)
2272 oi = ospf6_interface_create(ifp);
2273 assert(oi);
2274
2275 SET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE);
2276 THREAD_OFF(oi->thread_send_hello);
2277 THREAD_OFF(oi->thread_sso);
2278
2279 for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
2280 THREAD_OFF(on->inactivity_timer);
2281 thread_add_event(master, inactivity_timer, on, 0, NULL);
2282 }
2283
2284 return CMD_SUCCESS;
2285 }
2286
2287 DEFUN (no_ipv6_ospf6_passive,
2288 no_ipv6_ospf6_passive_cmd,
2289 "no ipv6 ospf6 passive",
2290 NO_STR
2291 IP6_STR
2292 OSPF6_STR
2293 "passive interface: No Adjacency will be formed on this I/F\n"
2294 )
2295 {
2296 VTY_DECLVAR_CONTEXT(interface, ifp);
2297 struct ospf6_interface *oi;
2298 assert(ifp);
2299
2300 oi = (struct ospf6_interface *)ifp->info;
2301 if (oi == NULL)
2302 oi = ospf6_interface_create(ifp);
2303 assert(oi);
2304
2305 UNSET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE);
2306 THREAD_OFF(oi->thread_send_hello);
2307 THREAD_OFF(oi->thread_sso);
2308
2309 /* don't send hellos over loopback interface */
2310 if (!if_is_loopback(oi->interface))
2311 thread_add_event(master, ospf6_hello_send, oi, 0,
2312 &oi->thread_send_hello);
2313
2314 return CMD_SUCCESS;
2315 }
2316
2317 DEFUN (ipv6_ospf6_mtu_ignore,
2318 ipv6_ospf6_mtu_ignore_cmd,
2319 "ipv6 ospf6 mtu-ignore",
2320 IP6_STR
2321 OSPF6_STR
2322 "Disable MTU mismatch detection on this interface\n"
2323 )
2324 {
2325 VTY_DECLVAR_CONTEXT(interface, ifp);
2326 struct ospf6_interface *oi;
2327 assert(ifp);
2328
2329 oi = (struct ospf6_interface *)ifp->info;
2330 if (oi == NULL)
2331 oi = ospf6_interface_create(ifp);
2332 assert(oi);
2333
2334 oi->mtu_ignore = 1;
2335
2336 return CMD_SUCCESS;
2337 }
2338
2339 DEFUN (no_ipv6_ospf6_mtu_ignore,
2340 no_ipv6_ospf6_mtu_ignore_cmd,
2341 "no ipv6 ospf6 mtu-ignore",
2342 NO_STR
2343 IP6_STR
2344 OSPF6_STR
2345 "Disable MTU mismatch detection on this interface\n"
2346 )
2347 {
2348 VTY_DECLVAR_CONTEXT(interface, ifp);
2349 struct ospf6_interface *oi;
2350 assert(ifp);
2351
2352 oi = (struct ospf6_interface *)ifp->info;
2353 if (oi == NULL)
2354 oi = ospf6_interface_create(ifp);
2355 assert(oi);
2356
2357 oi->mtu_ignore = 0;
2358
2359 return CMD_SUCCESS;
2360 }
2361
2362 DEFUN (ipv6_ospf6_advertise_prefix_list,
2363 ipv6_ospf6_advertise_prefix_list_cmd,
2364 "ipv6 ospf6 advertise prefix-list WORD",
2365 IP6_STR
2366 OSPF6_STR
2367 "Advertising options\n"
2368 "Filter prefix using prefix-list\n"
2369 "Prefix list name\n"
2370 )
2371 {
2372 VTY_DECLVAR_CONTEXT(interface, ifp);
2373 int idx_word = 4;
2374 struct ospf6_interface *oi;
2375 assert(ifp);
2376
2377 oi = (struct ospf6_interface *)ifp->info;
2378 if (oi == NULL)
2379 oi = ospf6_interface_create(ifp);
2380 assert(oi);
2381
2382 if (oi->plist_name)
2383 XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name);
2384 oi->plist_name = XSTRDUP(MTYPE_CFG_PLIST_NAME, argv[idx_word]->arg);
2385
2386 ospf6_interface_connected_route_update(oi->interface);
2387
2388 if (oi->area) {
2389 OSPF6_LINK_LSA_SCHEDULE(oi);
2390 if (oi->state == OSPF6_INTERFACE_DR) {
2391 OSPF6_NETWORK_LSA_SCHEDULE(oi);
2392 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
2393 }
2394 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
2395 }
2396
2397 return CMD_SUCCESS;
2398 }
2399
2400 DEFUN (no_ipv6_ospf6_advertise_prefix_list,
2401 no_ipv6_ospf6_advertise_prefix_list_cmd,
2402 "no ipv6 ospf6 advertise prefix-list [WORD]",
2403 NO_STR
2404 IP6_STR
2405 OSPF6_STR
2406 "Advertising options\n"
2407 "Filter prefix using prefix-list\n"
2408 "Prefix list name\n")
2409 {
2410 VTY_DECLVAR_CONTEXT(interface, ifp);
2411 struct ospf6_interface *oi;
2412 assert(ifp);
2413
2414 oi = (struct ospf6_interface *)ifp->info;
2415 if (oi == NULL)
2416 oi = ospf6_interface_create(ifp);
2417 assert(oi);
2418
2419 if (oi->plist_name)
2420 XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name);
2421
2422 ospf6_interface_connected_route_update(oi->interface);
2423
2424 if (oi->area) {
2425 OSPF6_LINK_LSA_SCHEDULE(oi);
2426 if (oi->state == OSPF6_INTERFACE_DR) {
2427 OSPF6_NETWORK_LSA_SCHEDULE(oi);
2428 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
2429 }
2430 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
2431 }
2432
2433 return CMD_SUCCESS;
2434 }
2435
2436 DEFUN (ipv6_ospf6_network,
2437 ipv6_ospf6_network_cmd,
2438 "ipv6 ospf6 network <broadcast|point-to-point>",
2439 IP6_STR
2440 OSPF6_STR
2441 "Network type\n"
2442 "Specify OSPF6 broadcast network\n"
2443 "Specify OSPF6 point-to-point network\n"
2444 )
2445 {
2446 VTY_DECLVAR_CONTEXT(interface, ifp);
2447 int idx_network = 3;
2448 struct ospf6_interface *oi;
2449 assert(ifp);
2450
2451 oi = (struct ospf6_interface *)ifp->info;
2452 if (oi == NULL) {
2453 oi = ospf6_interface_create(ifp);
2454 }
2455 assert(oi);
2456
2457 oi->type_cfg = true;
2458
2459 if (strncmp(argv[idx_network]->arg, "b", 1) == 0) {
2460 if (oi->type == OSPF_IFTYPE_BROADCAST)
2461 return CMD_SUCCESS;
2462
2463 oi->type = OSPF_IFTYPE_BROADCAST;
2464 } else if (strncmp(argv[idx_network]->arg, "point-to-p", 10) == 0) {
2465 if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
2466 return CMD_SUCCESS;
2467 }
2468 oi->type = OSPF_IFTYPE_POINTOPOINT;
2469 }
2470
2471 /* Reset the interface */
2472 thread_execute(master, interface_down, oi, 0);
2473 thread_execute(master, interface_up, oi, 0);
2474
2475 return CMD_SUCCESS;
2476 }
2477
2478 DEFUN (no_ipv6_ospf6_network,
2479 no_ipv6_ospf6_network_cmd,
2480 "no ipv6 ospf6 network [<broadcast|point-to-point>]",
2481 NO_STR
2482 IP6_STR
2483 OSPF6_STR
2484 "Set default network type\n"
2485 "Specify OSPF6 broadcast network\n"
2486 "Specify OSPF6 point-to-point network\n")
2487 {
2488 VTY_DECLVAR_CONTEXT(interface, ifp);
2489 struct ospf6_interface *oi;
2490 int type;
2491
2492 assert(ifp);
2493
2494 oi = (struct ospf6_interface *)ifp->info;
2495 if (oi == NULL) {
2496 return CMD_SUCCESS;
2497 }
2498
2499 oi->type_cfg = false;
2500
2501 type = ospf6_default_iftype(ifp);
2502 if (oi->type == type) {
2503 return CMD_SUCCESS;
2504 }
2505 oi->type = type;
2506
2507 /* Reset the interface */
2508 thread_execute(master, interface_down, oi, 0);
2509 thread_execute(master, interface_up, oi, 0);
2510
2511 return CMD_SUCCESS;
2512 }
2513
2514 static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf)
2515 {
2516 struct ospf6_interface *oi;
2517 struct interface *ifp;
2518 char buf[INET_ADDRSTRLEN];
2519
2520 FOR_ALL_INTERFACES (vrf, ifp) {
2521 oi = (struct ospf6_interface *)ifp->info;
2522 if (oi == NULL)
2523 continue;
2524
2525 if_vty_config_start(vty, ifp);
2526
2527 if (ifp->desc)
2528 vty_out(vty, " description %s\n", ifp->desc);
2529 if (oi->area_id_format != OSPF6_AREA_FMT_UNSET) {
2530 area_id2str(buf, sizeof(buf), oi->area_id,
2531 oi->area_id_format);
2532 vty_out(vty, " ipv6 ospf6 area %s\n", buf);
2533 }
2534 if (oi->c_ifmtu)
2535 vty_out(vty, " ipv6 ospf6 ifmtu %d\n", oi->c_ifmtu);
2536
2537 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST))
2538 vty_out(vty, " ipv6 ospf6 cost %d\n", oi->cost);
2539
2540 if (oi->hello_interval != OSPF6_INTERFACE_HELLO_INTERVAL)
2541 vty_out(vty, " ipv6 ospf6 hello-interval %d\n",
2542 oi->hello_interval);
2543
2544 if (oi->dead_interval != OSPF6_INTERFACE_DEAD_INTERVAL)
2545 vty_out(vty, " ipv6 ospf6 dead-interval %d\n",
2546 oi->dead_interval);
2547
2548 if (oi->rxmt_interval != OSPF6_INTERFACE_RXMT_INTERVAL)
2549 vty_out(vty, " ipv6 ospf6 retransmit-interval %d\n",
2550 oi->rxmt_interval);
2551
2552 if (oi->priority != OSPF6_INTERFACE_PRIORITY)
2553 vty_out(vty, " ipv6 ospf6 priority %d\n", oi->priority);
2554
2555 if (oi->transdelay != OSPF6_INTERFACE_TRANSDELAY)
2556 vty_out(vty, " ipv6 ospf6 transmit-delay %d\n",
2557 oi->transdelay);
2558
2559 if (oi->instance_id != OSPF6_INTERFACE_INSTANCE_ID)
2560 vty_out(vty, " ipv6 ospf6 instance-id %d\n",
2561 oi->instance_id);
2562
2563 if (oi->plist_name)
2564 vty_out(vty, " ipv6 ospf6 advertise prefix-list %s\n",
2565 oi->plist_name);
2566
2567 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE))
2568 vty_out(vty, " ipv6 ospf6 passive\n");
2569
2570 if (oi->mtu_ignore)
2571 vty_out(vty, " ipv6 ospf6 mtu-ignore\n");
2572
2573 if (oi->type_cfg && oi->type == OSPF_IFTYPE_POINTOPOINT)
2574 vty_out(vty, " ipv6 ospf6 network point-to-point\n");
2575 else if (oi->type_cfg && oi->type == OSPF_IFTYPE_BROADCAST)
2576 vty_out(vty, " ipv6 ospf6 network broadcast\n");
2577
2578 ospf6_bfd_write_config(vty, oi);
2579
2580 if_vty_config_end(vty);
2581 }
2582 return 0;
2583 }
2584
2585 /* Configuration write function for ospfd. */
2586 static int config_write_interface(struct vty *vty)
2587 {
2588 int write = 0;
2589 struct vrf *vrf = NULL;
2590
2591 /* Display all VRF aware OSPF interface configuration */
2592 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2593 write += config_write_ospf6_interface(vty, vrf);
2594 }
2595
2596 return write;
2597 }
2598
2599 static int ospf6_ifp_create(struct interface *ifp)
2600 {
2601 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
2602 zlog_debug("Zebra Interface add: %s index %d mtu %d", ifp->name,
2603 ifp->ifindex, ifp->mtu6);
2604
2605 if (ifp->info)
2606 ospf6_interface_start(ifp->info);
2607
2608 return 0;
2609 }
2610
2611 static int ospf6_ifp_up(struct interface *ifp)
2612 {
2613 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
2614 zlog_debug(
2615 "Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d",
2616 ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
2617 ifp->metric, ifp->mtu6, ifp->bandwidth);
2618
2619 ospf6_interface_state_update(ifp);
2620
2621 return 0;
2622 }
2623
2624 static int ospf6_ifp_down(struct interface *ifp)
2625 {
2626 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
2627 zlog_debug(
2628 "Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d",
2629 ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
2630 ifp->metric, ifp->mtu6, ifp->bandwidth);
2631
2632 ospf6_interface_state_update(ifp);
2633
2634 return 0;
2635 }
2636
2637 static int ospf6_ifp_destroy(struct interface *ifp)
2638 {
2639 if (if_is_up(ifp))
2640 zlog_warn("Zebra: got delete of %s, but interface is still up",
2641 ifp->name);
2642
2643 if (IS_OSPF6_DEBUG_ZEBRA(RECV))
2644 zlog_debug("Zebra Interface delete: %s index %d mtu %d",
2645 ifp->name, ifp->ifindex, ifp->mtu6);
2646
2647 if (ifp->info)
2648 ospf6_interface_stop(ifp->info);
2649
2650 return 0;
2651 }
2652
2653 void ospf6_interface_init(void)
2654 {
2655 /* Install interface node. */
2656 if_cmd_init(config_write_interface);
2657 if_zapi_callbacks(ospf6_ifp_create, ospf6_ifp_up,
2658 ospf6_ifp_down, ospf6_ifp_destroy);
2659
2660 install_element(VIEW_NODE, &show_ipv6_ospf6_interface_prefix_cmd);
2661 install_element(VIEW_NODE, &show_ipv6_ospf6_interface_ifname_cmd);
2662 install_element(VIEW_NODE,
2663 &show_ipv6_ospf6_interface_ifname_prefix_cmd);
2664 install_element(VIEW_NODE, &show_ipv6_ospf6_interface_traffic_cmd);
2665
2666 install_element(INTERFACE_NODE, &ipv6_ospf6_area_cmd);
2667 install_element(INTERFACE_NODE, &no_ipv6_ospf6_area_cmd);
2668 install_element(INTERFACE_NODE, &ipv6_ospf6_cost_cmd);
2669 install_element(INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd);
2670 install_element(INTERFACE_NODE, &ipv6_ospf6_ifmtu_cmd);
2671 install_element(INTERFACE_NODE, &no_ipv6_ospf6_ifmtu_cmd);
2672
2673 install_element(INTERFACE_NODE, &ipv6_ospf6_deadinterval_cmd);
2674 install_element(INTERFACE_NODE, &ipv6_ospf6_hellointerval_cmd);
2675 install_element(INTERFACE_NODE, &ipv6_ospf6_priority_cmd);
2676 install_element(INTERFACE_NODE, &ipv6_ospf6_retransmitinterval_cmd);
2677 install_element(INTERFACE_NODE, &ipv6_ospf6_transmitdelay_cmd);
2678 install_element(INTERFACE_NODE, &ipv6_ospf6_instance_cmd);
2679 install_element(INTERFACE_NODE, &no_ipv6_ospf6_deadinterval_cmd);
2680 install_element(INTERFACE_NODE, &no_ipv6_ospf6_hellointerval_cmd);
2681 install_element(INTERFACE_NODE, &no_ipv6_ospf6_priority_cmd);
2682 install_element(INTERFACE_NODE, &no_ipv6_ospf6_retransmitinterval_cmd);
2683 install_element(INTERFACE_NODE, &no_ipv6_ospf6_transmitdelay_cmd);
2684 install_element(INTERFACE_NODE, &no_ipv6_ospf6_instance_cmd);
2685
2686 install_element(INTERFACE_NODE, &ipv6_ospf6_passive_cmd);
2687 install_element(INTERFACE_NODE, &no_ipv6_ospf6_passive_cmd);
2688
2689 install_element(INTERFACE_NODE, &ipv6_ospf6_mtu_ignore_cmd);
2690 install_element(INTERFACE_NODE, &no_ipv6_ospf6_mtu_ignore_cmd);
2691
2692 install_element(INTERFACE_NODE, &ipv6_ospf6_advertise_prefix_list_cmd);
2693 install_element(INTERFACE_NODE,
2694 &no_ipv6_ospf6_advertise_prefix_list_cmd);
2695
2696 install_element(INTERFACE_NODE, &ipv6_ospf6_network_cmd);
2697 install_element(INTERFACE_NODE, &no_ipv6_ospf6_network_cmd);
2698
2699 /* reference bandwidth commands */
2700 install_element(OSPF6_NODE, &auto_cost_reference_bandwidth_cmd);
2701 install_element(OSPF6_NODE, &no_auto_cost_reference_bandwidth_cmd);
2702 /* write-multiplier commands */
2703 install_element(OSPF6_NODE, &ospf6_write_multiplier_cmd);
2704 install_element(OSPF6_NODE, &no_ospf6_write_multiplier_cmd);
2705 }
2706
2707 /* Clear the specified interface structure */
2708 void ospf6_interface_clear(struct interface *ifp)
2709 {
2710 struct ospf6_interface *oi;
2711
2712 if (!if_is_operative(ifp))
2713 return;
2714
2715 if (ifp->info == NULL)
2716 return;
2717
2718 oi = (struct ospf6_interface *)ifp->info;
2719
2720 if (IS_OSPF6_DEBUG_INTERFACE)
2721 zlog_debug("Interface %s: clear by reset", ifp->name);
2722
2723 /* Reset the interface */
2724 thread_execute(master, interface_down, oi, 0);
2725 thread_execute(master, interface_up, oi, 0);
2726 }
2727
2728 /* Clear interface */
2729 DEFUN (clear_ipv6_ospf6_interface,
2730 clear_ipv6_ospf6_interface_cmd,
2731 "clear ipv6 ospf6 [vrf NAME] interface [IFNAME]",
2732 CLEAR_STR
2733 IP6_STR
2734 OSPF6_STR
2735 VRF_CMD_HELP_STR
2736 INTERFACE_STR
2737 IFNAME_STR
2738 )
2739 {
2740 struct vrf *vrf;
2741 int idx_vrf = 3;
2742 int idx_ifname = 4;
2743 struct interface *ifp;
2744 const char *vrf_name;
2745
2746 if (argv_find(argv, argc, "vrf", &idx_vrf))
2747 vrf_name = argv[idx_vrf + 1]->arg;
2748 else
2749 vrf_name = VRF_DEFAULT_NAME;
2750 vrf = vrf_lookup_by_name(vrf_name);
2751 if (!vrf) {
2752 vty_out(vty, "%% VRF %s not found\n", vrf_name);
2753 return CMD_WARNING;
2754 }
2755
2756 if (!argv_find(argv, argc, "IFNAME", &idx_ifname)) {
2757 /* Clear all the ospfv3 interfaces. */
2758 FOR_ALL_INTERFACES (vrf, ifp)
2759 ospf6_interface_clear(ifp);
2760 } else {
2761 /* Interface name is specified. */
2762 ifp = if_lookup_by_name_vrf(argv[idx_ifname]->arg, vrf);
2763 if (!ifp) {
2764 vty_out(vty, "No such Interface: %s\n",
2765 argv[idx_ifname]->arg);
2766 return CMD_WARNING;
2767 }
2768 ospf6_interface_clear(ifp);
2769 }
2770
2771 return CMD_SUCCESS;
2772 }
2773
2774 void install_element_ospf6_clear_interface(void)
2775 {
2776 install_element(ENABLE_NODE, &clear_ipv6_ospf6_interface_cmd);
2777 }
2778
2779 DEFUN (debug_ospf6_interface,
2780 debug_ospf6_interface_cmd,
2781 "debug ospf6 interface",
2782 DEBUG_STR
2783 OSPF6_STR
2784 "Debug OSPFv3 Interface\n"
2785 )
2786 {
2787 OSPF6_DEBUG_INTERFACE_ON();
2788 return CMD_SUCCESS;
2789 }
2790
2791 DEFUN (no_debug_ospf6_interface,
2792 no_debug_ospf6_interface_cmd,
2793 "no debug ospf6 interface",
2794 NO_STR
2795 DEBUG_STR
2796 OSPF6_STR
2797 "Debug OSPFv3 Interface\n"
2798 )
2799 {
2800 OSPF6_DEBUG_INTERFACE_OFF();
2801 return CMD_SUCCESS;
2802 }
2803
2804 int config_write_ospf6_debug_interface(struct vty *vty)
2805 {
2806 if (IS_OSPF6_DEBUG_INTERFACE)
2807 vty_out(vty, "debug ospf6 interface\n");
2808 return 0;
2809 }
2810
2811 void install_element_ospf6_debug_interface(void)
2812 {
2813 install_element(ENABLE_NODE, &debug_ospf6_interface_cmd);
2814 install_element(ENABLE_NODE, &no_debug_ospf6_interface_cmd);
2815 install_element(CONFIG_NODE, &debug_ospf6_interface_cmd);
2816 install_element(CONFIG_NODE, &no_debug_ospf6_interface_cmd);
2817 }