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