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