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