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