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