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