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