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