2 * IS-IS Rout(e)ing protocol - isis_circuit.h
4 * Copyright (C) 2001,2002 Sampo Saaristo
5 * Tampere University of Technology
6 * Institute of Communications Engineering
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public Licenseas published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
13 * This program is distributed in the hope that it will be useful,but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include <net/ethernet.h>
26 #include <netinet/if_ether.h>
29 #ifndef ETHER_ADDR_LEN
30 #define ETHER_ADDR_LEN ETHERADDRL
44 #include "isisd/dict.h"
45 #include "isisd/include-netbsd/iso.h"
46 #include "isisd/isis_constants.h"
47 #include "isisd/isis_common.h"
48 #include "isisd/isis_flags.h"
49 #include "isisd/isis_circuit.h"
50 #include "isisd/isis_tlv.h"
51 #include "isisd/isis_lsp.h"
52 #include "isisd/isis_pdu.h"
53 #include "isisd/isis_network.h"
54 #include "isisd/isis_misc.h"
55 #include "isisd/isis_constants.h"
56 #include "isisd/isis_adjacency.h"
57 #include "isisd/isis_dr.h"
58 #include "isisd/isisd.h"
59 #include "isisd/isis_csm.h"
60 #include "isisd/isis_events.h"
65 int isis_interface_config_write(struct vty
*);
66 int isis_if_new_hook(struct interface
*);
67 int isis_if_delete_hook(struct interface
*);
72 struct isis_circuit
*circuit
;
75 circuit
= XCALLOC (MTYPE_ISIS_CIRCUIT
, sizeof (struct isis_circuit
));
78 zlog_err ("Can't malloc isis circuit");
85 circuit
->is_type
= IS_LEVEL_1_AND_2
;
87 circuit
->pad_hellos
= 1;
88 for (i
= 0; i
< 2; i
++)
90 circuit
->hello_interval
[i
] = DEFAULT_HELLO_INTERVAL
;
91 circuit
->hello_multiplier
[i
] = DEFAULT_HELLO_MULTIPLIER
;
92 circuit
->csnp_interval
[i
] = DEFAULT_CSNP_INTERVAL
;
93 circuit
->psnp_interval
[i
] = DEFAULT_PSNP_INTERVAL
;
94 circuit
->priority
[i
] = DEFAULT_PRIORITY
;
95 circuit
->metric
[i
] = DEFAULT_CIRCUIT_METRIC
;
96 circuit
->te_metric
[i
] = DEFAULT_CIRCUIT_METRIC
;
103 isis_circuit_del (struct isis_circuit
*circuit
)
108 isis_circuit_if_unbind (circuit
, circuit
->interface
);
110 /* and lastly the circuit itself */
111 XFREE (MTYPE_ISIS_CIRCUIT
, circuit
);
117 isis_circuit_configure (struct isis_circuit
*circuit
, struct isis_area
*area
)
120 circuit
->area
= area
;
123 * Whenever the is-type of an area is changed, the is-type of each circuit
124 * in that area is updated to a non-empty subset of the area is-type.
125 * Inversely, when configuring a new circuit, this property should be
128 if (area
->is_type
!= IS_LEVEL_1_AND_2
)
129 circuit
->is_type
= area
->is_type
;
132 * Add the circuit into area
134 listnode_add (area
->circuit_list
, circuit
);
136 circuit
->idx
= flags_get_index (&area
->flags
);
142 isis_circuit_deconfigure (struct isis_circuit
*circuit
, struct isis_area
*area
)
144 /* Free the index of SRM and SSN flags */
145 flags_free_index (&area
->flags
, circuit
->idx
);
147 /* Remove circuit from area */
148 assert (circuit
->area
== area
);
149 listnode_delete (area
->circuit_list
, circuit
);
150 circuit
->area
= NULL
;
155 struct isis_circuit
*
156 circuit_lookup_by_ifp (struct interface
*ifp
, struct list
*list
)
158 struct isis_circuit
*circuit
= NULL
;
159 struct listnode
*node
;
164 for (ALL_LIST_ELEMENTS_RO (list
, node
, circuit
))
165 if (circuit
->interface
== ifp
)
167 assert (ifp
->info
== circuit
);
174 struct isis_circuit
*
175 circuit_scan_by_ifp (struct interface
*ifp
)
177 struct isis_area
*area
;
178 struct listnode
*node
;
179 struct isis_circuit
*circuit
;
182 return (struct isis_circuit
*)ifp
->info
;
186 for (ALL_LIST_ELEMENTS_RO (isis
->area_list
, node
, area
))
188 circuit
= circuit_lookup_by_ifp (ifp
, area
->circuit_list
);
193 return circuit_lookup_by_ifp (ifp
, isis
->init_circ_list
);
197 isis_circuit_add_addr (struct isis_circuit
*circuit
,
198 struct connected
*connected
)
200 struct listnode
*node
;
201 struct prefix_ipv4
*ipv4
;
202 #if defined(EXTREME_DEBUG)
203 char buf
[PREFIX2STR_BUFFER
];
205 struct prefix_ipv6
*ipv6
;
207 if (connected
->address
->family
== AF_INET
)
209 u_int32_t addr
= connected
->address
->u
.prefix4
.s_addr
;
211 if (IPV4_NET0(addr
) ||
214 IPV4_LINKLOCAL(addr
))
217 for (ALL_LIST_ELEMENTS_RO (circuit
->ip_addrs
, node
, ipv4
))
218 if (prefix_same ((struct prefix
*) ipv4
, connected
->address
))
221 ipv4
= prefix_ipv4_new ();
222 ipv4
->prefixlen
= connected
->address
->prefixlen
;
223 ipv4
->prefix
= connected
->address
->u
.prefix4
;
224 listnode_add (circuit
->ip_addrs
, ipv4
);
226 lsp_regenerate_schedule (circuit
->area
, circuit
->is_type
, 0);
229 prefix2str (connected
->address
, buf
, sizeof (buf
));
230 zlog_debug ("Added IP address %s to circuit %d", buf
,
231 circuit
->circuit_id
);
232 #endif /* EXTREME_DEBUG */
234 if (connected
->address
->family
== AF_INET6
)
236 if (IN6_IS_ADDR_LOOPBACK(&connected
->address
->u
.prefix6
))
239 for (ALL_LIST_ELEMENTS_RO (circuit
->ipv6_link
, node
, ipv6
))
240 if (prefix_same ((struct prefix
*) ipv6
, connected
->address
))
242 for (ALL_LIST_ELEMENTS_RO (circuit
->ipv6_non_link
, node
, ipv6
))
243 if (prefix_same ((struct prefix
*) ipv6
, connected
->address
))
246 ipv6
= prefix_ipv6_new ();
247 ipv6
->prefixlen
= connected
->address
->prefixlen
;
248 ipv6
->prefix
= connected
->address
->u
.prefix6
;
250 if (IN6_IS_ADDR_LINKLOCAL (&ipv6
->prefix
))
251 listnode_add (circuit
->ipv6_link
, ipv6
);
253 listnode_add (circuit
->ipv6_non_link
, ipv6
);
255 lsp_regenerate_schedule (circuit
->area
, circuit
->is_type
, 0);
258 prefix2str (connected
->address
, buf
, sizeof (buf
));
259 zlog_debug ("Added IPv6 address %s to circuit %d", buf
,
260 circuit
->circuit_id
);
261 #endif /* EXTREME_DEBUG */
267 isis_circuit_del_addr (struct isis_circuit
*circuit
,
268 struct connected
*connected
)
270 struct prefix_ipv4
*ipv4
, *ip
= NULL
;
271 struct listnode
*node
;
272 char buf
[PREFIX2STR_BUFFER
];
274 struct prefix_ipv6
*ipv6
, *ip6
= NULL
;
276 #endif /* HAVE_IPV6 */
278 if (connected
->address
->family
== AF_INET
)
280 ipv4
= prefix_ipv4_new ();
281 ipv4
->prefixlen
= connected
->address
->prefixlen
;
282 ipv4
->prefix
= connected
->address
->u
.prefix4
;
284 for (ALL_LIST_ELEMENTS_RO (circuit
->ip_addrs
, node
, ip
))
285 if (prefix_same ((struct prefix
*) ip
, (struct prefix
*) ipv4
))
290 listnode_delete (circuit
->ip_addrs
, ip
);
292 lsp_regenerate_schedule (circuit
->area
, circuit
->is_type
, 0);
296 prefix2str (connected
->address
, buf
, sizeof (buf
));
297 zlog_warn ("Nonexitant ip address %s removal attempt from \
298 circuit %d", buf
, circuit
->circuit_id
);
299 zlog_warn ("Current ip addresses on %s:", circuit
->interface
->name
);
300 for (ALL_LIST_ELEMENTS_RO(circuit
->ip_addrs
, node
, ip
))
302 prefix2str((struct prefix
*)ip
, (char *)buf
, BUFSIZ
);
303 zlog_warn(" %s", buf
);
305 zlog_warn("End of addresses");
308 prefix_ipv4_free (ipv4
);
311 if (connected
->address
->family
== AF_INET6
)
313 ipv6
= prefix_ipv6_new ();
314 ipv6
->prefixlen
= connected
->address
->prefixlen
;
315 ipv6
->prefix
= connected
->address
->u
.prefix6
;
317 if (IN6_IS_ADDR_LINKLOCAL (&ipv6
->prefix
))
319 for (ALL_LIST_ELEMENTS_RO (circuit
->ipv6_link
, node
, ip6
))
321 if (prefix_same ((struct prefix
*) ip6
, (struct prefix
*) ipv6
))
326 listnode_delete (circuit
->ipv6_link
, ip6
);
332 for (ALL_LIST_ELEMENTS_RO (circuit
->ipv6_non_link
, node
, ip6
))
334 if (prefix_same ((struct prefix
*) ip6
, (struct prefix
*) ipv6
))
339 listnode_delete (circuit
->ipv6_non_link
, ip6
);
346 prefix2str (connected
->address
, buf
, sizeof (buf
));
347 zlog_warn ("Nonexitant ip address %s removal attempt from \
348 circuit %d", buf
, circuit
->circuit_id
);
349 zlog_warn ("Current ip addresses on %s:", circuit
->interface
->name
);
350 for (ALL_LIST_ELEMENTS_RO(circuit
->ipv6_link
, node
, ip6
))
352 prefix2str((struct prefix
*)ip6
, (char *)buf
, BUFSIZ
);
353 zlog_warn(" %s", buf
);
356 for (ALL_LIST_ELEMENTS_RO(circuit
->ipv6_non_link
, node
, ip6
))
358 prefix2str((struct prefix
*)ip6
, (char *)buf
, BUFSIZ
);
359 zlog_warn(" %s", buf
);
361 zlog_warn("End of addresses");
363 else if (circuit
->area
)
364 lsp_regenerate_schedule (circuit
->area
, circuit
->is_type
, 0);
366 prefix_ipv6_free (ipv6
);
368 #endif /* HAVE_IPV6 */
373 isis_circuit_id_gen (struct interface
*ifp
)
378 int start
= -1, end
= -1;
381 * Get a stable circuit id from ifname. This makes
382 * the ifindex from flapping when netdevs are created
383 * and deleted on the fly. Note that this circuit id
384 * is used in pseudo lsps so it is better to be stable.
385 * The following code works on any reasonanle ifname
386 * like: eth1 or trk-1.1 etc.
388 for (i
= 0; i
< strlen (ifp
->name
); i
++)
390 if (isdigit((unsigned char)ifp
->name
[i
]))
406 if ((start
>= 0) && (end
>= start
) && (end
- start
) < 16)
408 memset (ifname
, 0, 16);
409 strncpy (ifname
, &ifp
->name
[start
], end
- start
);
410 id
= (u_char
)atoi(ifname
);
413 /* Try to be unique. */
415 id
= (u_char
)((ifp
->ifindex
& 0xff) | 0x80);
421 isis_circuit_if_add (struct isis_circuit
*circuit
, struct interface
*ifp
)
423 struct listnode
*node
, *nnode
;
424 struct connected
*conn
;
426 circuit
->circuit_id
= isis_circuit_id_gen (ifp
);
428 isis_circuit_if_bind (circuit
, ifp
);
429 /* isis_circuit_update_addrs (circuit, ifp); */
431 if (if_is_broadcast (ifp
))
433 if (circuit
->circ_type_config
== CIRCUIT_T_P2P
)
434 circuit
->circ_type
= CIRCUIT_T_P2P
;
436 circuit
->circ_type
= CIRCUIT_T_BROADCAST
;
438 else if (if_is_pointopoint (ifp
))
440 circuit
->circ_type
= CIRCUIT_T_P2P
;
442 else if (if_is_loopback (ifp
))
444 circuit
->circ_type
= CIRCUIT_T_LOOPBACK
;
445 circuit
->is_passive
= 1;
449 /* It's normal in case of loopback etc. */
450 if (isis
->debugs
& DEBUG_EVENTS
)
451 zlog_debug ("isis_circuit_if_add: unsupported media");
452 circuit
->circ_type
= CIRCUIT_T_UNKNOWN
;
455 circuit
->ip_addrs
= list_new ();
457 circuit
->ipv6_link
= list_new ();
458 circuit
->ipv6_non_link
= list_new ();
459 #endif /* HAVE_IPV6 */
461 for (ALL_LIST_ELEMENTS (ifp
->connected
, node
, nnode
, conn
))
462 isis_circuit_add_addr (circuit
, conn
);
468 isis_circuit_if_del (struct isis_circuit
*circuit
, struct interface
*ifp
)
470 struct listnode
*node
, *nnode
;
471 struct connected
*conn
;
473 assert (circuit
->interface
== ifp
);
475 /* destroy addresses */
476 for (ALL_LIST_ELEMENTS (ifp
->connected
, node
, nnode
, conn
))
477 isis_circuit_del_addr (circuit
, conn
);
479 if (circuit
->ip_addrs
)
481 assert (listcount(circuit
->ip_addrs
) == 0);
482 list_delete (circuit
->ip_addrs
);
483 circuit
->ip_addrs
= NULL
;
487 if (circuit
->ipv6_link
)
489 assert (listcount(circuit
->ipv6_link
) == 0);
490 list_delete (circuit
->ipv6_link
);
491 circuit
->ipv6_link
= NULL
;
494 if (circuit
->ipv6_non_link
)
496 assert (listcount(circuit
->ipv6_non_link
) == 0);
497 list_delete (circuit
->ipv6_non_link
);
498 circuit
->ipv6_non_link
= NULL
;
500 #endif /* HAVE_IPV6 */
502 circuit
->circ_type
= CIRCUIT_T_UNKNOWN
;
503 circuit
->circuit_id
= 0;
509 isis_circuit_if_bind (struct isis_circuit
*circuit
, struct interface
*ifp
)
511 assert (circuit
!= NULL
);
512 assert (ifp
!= NULL
);
513 if (circuit
->interface
)
514 assert (circuit
->interface
== ifp
);
516 circuit
->interface
= ifp
;
518 assert (ifp
->info
== circuit
);
524 isis_circuit_if_unbind (struct isis_circuit
*circuit
, struct interface
*ifp
)
526 assert (circuit
!= NULL
);
527 assert (ifp
!= NULL
);
528 assert (circuit
->interface
== ifp
);
529 assert (ifp
->info
== circuit
);
530 circuit
->interface
= NULL
;
535 isis_circuit_update_all_srmflags (struct isis_circuit
*circuit
, int is_set
)
537 struct isis_area
*area
;
538 struct isis_lsp
*lsp
;
539 dnode_t
*dnode
, *dnode_next
;
543 area
= circuit
->area
;
545 for (level
= ISIS_LEVEL1
; level
<= ISIS_LEVEL2
; level
++)
547 if (level
& circuit
->is_type
)
549 if (area
->lspdb
[level
- 1] &&
550 dict_count (area
->lspdb
[level
- 1]) > 0)
552 for (dnode
= dict_first (area
->lspdb
[level
- 1]);
553 dnode
!= NULL
; dnode
= dnode_next
)
555 dnode_next
= dict_next (area
->lspdb
[level
- 1], dnode
);
556 lsp
= dnode_get (dnode
);
559 ISIS_SET_FLAG (lsp
->SRMflags
, circuit
);
563 ISIS_CLEAR_FLAG (lsp
->SRMflags
, circuit
);
572 isis_circuit_pdu_size(struct isis_circuit
*circuit
)
574 return ISO_MTU(circuit
);
578 isis_circuit_stream(struct isis_circuit
*circuit
, struct stream
**stream
)
580 size_t stream_size
= isis_circuit_pdu_size(circuit
);
584 *stream
= stream_new(stream_size
);
588 if (STREAM_SIZE(*stream
) != stream_size
)
589 stream_resize(*stream
, stream_size
);
590 stream_reset(*stream
);
595 isis_circuit_up (struct isis_circuit
*circuit
)
599 /* Set the flags for all the lsps of the circuit. */
600 isis_circuit_update_all_srmflags (circuit
, 1);
602 if (circuit
->state
== C_STATE_UP
)
605 if (circuit
->is_passive
)
608 if (circuit
->area
->lsp_mtu
> isis_circuit_pdu_size(circuit
))
610 zlog_err("Interface MTU %zu on %s is too low to support area lsp mtu %u!",
611 isis_circuit_pdu_size(circuit
), circuit
->interface
->name
,
612 circuit
->area
->lsp_mtu
);
613 isis_circuit_update_all_srmflags(circuit
, 0);
617 if (circuit
->circ_type
== CIRCUIT_T_BROADCAST
)
620 * Get the Hardware Address
622 if (circuit
->interface
->hw_addr_len
!= ETH_ALEN
)
624 zlog_warn ("unsupported link layer");
628 memcpy (circuit
->u
.bc
.snpa
, circuit
->interface
->hw_addr
, ETH_ALEN
);
631 zlog_debug ("isis_circuit_if_add: if_id %d, isomtu %d snpa %s",
632 circuit
->interface
->ifindex
, ISO_MTU (circuit
),
633 snpa_print (circuit
->u
.bc
.snpa
));
634 #endif /* EXTREME_DEBUG */
636 circuit
->u
.bc
.adjdb
[0] = list_new ();
637 circuit
->u
.bc
.adjdb
[1] = list_new ();
640 * ISO 10589 - 8.4.1 Enabling of broadcast circuits
643 /* initilizing the hello sending threads
647 /* 8.4.1 a) commence sending of IIH PDUs */
649 if (circuit
->is_type
& IS_LEVEL_1
)
651 thread_add_event (master
, send_lan_l1_hello
, circuit
, 0);
652 circuit
->u
.bc
.lan_neighs
[0] = list_new ();
655 if (circuit
->is_type
& IS_LEVEL_2
)
657 thread_add_event (master
, send_lan_l2_hello
, circuit
, 0);
658 circuit
->u
.bc
.lan_neighs
[1] = list_new ();
661 /* 8.4.1 b) FIXME: solicit ES - 8.4.6 */
662 /* 8.4.1 c) FIXME: listen for ESH PDUs */
665 /* dr election will commence in... */
666 if (circuit
->is_type
& IS_LEVEL_1
)
667 THREAD_TIMER_ON (master
, circuit
->u
.bc
.t_run_dr
[0], isis_run_dr_l1
,
668 circuit
, 2 * circuit
->hello_interval
[0]);
669 if (circuit
->is_type
& IS_LEVEL_2
)
670 THREAD_TIMER_ON (master
, circuit
->u
.bc
.t_run_dr
[1], isis_run_dr_l2
,
671 circuit
, 2 * circuit
->hello_interval
[1]);
675 /* initializing the hello send threads
678 circuit
->u
.p2p
.neighbor
= NULL
;
679 thread_add_event (master
, send_p2p_hello
, circuit
, 0);
682 /* initializing PSNP timers */
683 if (circuit
->is_type
& IS_LEVEL_1
)
684 THREAD_TIMER_ON (master
, circuit
->t_send_psnp
[0], send_l1_psnp
, circuit
,
685 isis_jitter (circuit
->psnp_interval
[0], PSNP_JITTER
));
687 if (circuit
->is_type
& IS_LEVEL_2
)
688 THREAD_TIMER_ON (master
, circuit
->t_send_psnp
[1], send_l2_psnp
, circuit
,
689 isis_jitter (circuit
->psnp_interval
[1], PSNP_JITTER
));
691 /* unified init for circuits; ignore warnings below this level */
692 retv
= isis_sock_init (circuit
);
695 isis_circuit_down (circuit
);
699 /* initialize the circuit streams after opening connection */
700 isis_circuit_stream(circuit
, &circuit
->rcv_stream
);
701 isis_circuit_stream(circuit
, &circuit
->snd_stream
);
704 THREAD_READ_ON (master
, circuit
->t_read
, isis_receive
, circuit
,
707 THREAD_TIMER_ON (master
, circuit
->t_read
, isis_receive
, circuit
,
711 circuit
->lsp_queue
= list_new ();
712 circuit
->lsp_queue_last_cleared
= time (NULL
);
718 isis_circuit_down (struct isis_circuit
*circuit
)
720 if (circuit
->state
!= C_STATE_UP
)
723 /* Clear the flags for all the lsps of the circuit. */
724 isis_circuit_update_all_srmflags (circuit
, 0);
726 if (circuit
->circ_type
== CIRCUIT_T_BROADCAST
)
728 /* destroy neighbour lists */
729 if (circuit
->u
.bc
.lan_neighs
[0])
731 list_delete (circuit
->u
.bc
.lan_neighs
[0]);
732 circuit
->u
.bc
.lan_neighs
[0] = NULL
;
734 if (circuit
->u
.bc
.lan_neighs
[1])
736 list_delete (circuit
->u
.bc
.lan_neighs
[1]);
737 circuit
->u
.bc
.lan_neighs
[1] = NULL
;
739 /* destroy adjacency databases */
740 if (circuit
->u
.bc
.adjdb
[0])
742 circuit
->u
.bc
.adjdb
[0]->del
= isis_delete_adj
;
743 list_delete (circuit
->u
.bc
.adjdb
[0]);
744 circuit
->u
.bc
.adjdb
[0] = NULL
;
746 if (circuit
->u
.bc
.adjdb
[1])
748 circuit
->u
.bc
.adjdb
[1]->del
= isis_delete_adj
;
749 list_delete (circuit
->u
.bc
.adjdb
[1]);
750 circuit
->u
.bc
.adjdb
[1] = NULL
;
752 if (circuit
->u
.bc
.is_dr
[0])
754 isis_dr_resign (circuit
, 1);
755 circuit
->u
.bc
.is_dr
[0] = 0;
757 memset (circuit
->u
.bc
.l1_desig_is
, 0, ISIS_SYS_ID_LEN
+ 1);
758 if (circuit
->u
.bc
.is_dr
[1])
760 isis_dr_resign (circuit
, 2);
761 circuit
->u
.bc
.is_dr
[1] = 0;
763 memset (circuit
->u
.bc
.l2_desig_is
, 0, ISIS_SYS_ID_LEN
+ 1);
764 memset (circuit
->u
.bc
.snpa
, 0, ETH_ALEN
);
766 THREAD_TIMER_OFF (circuit
->u
.bc
.t_send_lan_hello
[0]);
767 THREAD_TIMER_OFF (circuit
->u
.bc
.t_send_lan_hello
[1]);
768 THREAD_TIMER_OFF (circuit
->u
.bc
.t_run_dr
[0]);
769 THREAD_TIMER_OFF (circuit
->u
.bc
.t_run_dr
[1]);
770 THREAD_TIMER_OFF (circuit
->u
.bc
.t_refresh_pseudo_lsp
[0]);
771 THREAD_TIMER_OFF (circuit
->u
.bc
.t_refresh_pseudo_lsp
[1]);
772 circuit
->lsp_regenerate_pending
[0] = 0;
773 circuit
->lsp_regenerate_pending
[1] = 0;
775 else if (circuit
->circ_type
== CIRCUIT_T_P2P
)
777 isis_delete_adj (circuit
->u
.p2p
.neighbor
);
778 circuit
->u
.p2p
.neighbor
= NULL
;
779 THREAD_TIMER_OFF (circuit
->u
.p2p
.t_send_p2p_hello
);
782 /* Cancel all active threads */
783 THREAD_TIMER_OFF (circuit
->t_send_csnp
[0]);
784 THREAD_TIMER_OFF (circuit
->t_send_csnp
[1]);
785 THREAD_TIMER_OFF (circuit
->t_send_psnp
[0]);
786 THREAD_TIMER_OFF (circuit
->t_send_psnp
[1]);
787 THREAD_OFF (circuit
->t_read
);
789 if (circuit
->lsp_queue
)
791 circuit
->lsp_queue
->del
= NULL
;
792 list_delete (circuit
->lsp_queue
);
793 circuit
->lsp_queue
= NULL
;
796 /* send one gratuitous hello to spead up convergence */
797 if (circuit
->is_type
& IS_LEVEL_1
)
798 send_hello (circuit
, IS_LEVEL_1
);
799 if (circuit
->is_type
& IS_LEVEL_2
)
800 send_hello (circuit
, IS_LEVEL_2
);
802 circuit
->upadjcount
[0] = 0;
803 circuit
->upadjcount
[1] = 0;
805 /* close the socket */
812 if (circuit
->rcv_stream
!= NULL
)
814 stream_free (circuit
->rcv_stream
);
815 circuit
->rcv_stream
= NULL
;
818 if (circuit
->snd_stream
!= NULL
)
820 stream_free (circuit
->snd_stream
);
821 circuit
->snd_stream
= NULL
;
824 thread_cancel_event (master
, circuit
);
830 circuit_update_nlpids (struct isis_circuit
*circuit
)
832 circuit
->nlpids
.count
= 0;
834 if (circuit
->ip_router
)
836 circuit
->nlpids
.nlpids
[0] = NLPID_IP
;
837 circuit
->nlpids
.count
++;
840 if (circuit
->ipv6_router
)
842 circuit
->nlpids
.nlpids
[circuit
->nlpids
.count
] = NLPID_IPV6
;
843 circuit
->nlpids
.count
++;
845 #endif /* HAVE_IPV6 */
850 isis_circuit_print_vty (struct isis_circuit
*circuit
, struct vty
*vty
,
853 if (detail
== ISIS_UI_LEVEL_BRIEF
)
855 vty_out (vty
, " %-12s", circuit
->interface
->name
);
856 vty_out (vty
, "0x%-7x", circuit
->circuit_id
);
857 vty_out (vty
, "%-9s", circuit_state2string (circuit
->state
));
858 vty_out (vty
, "%-9s", circuit_type2string (circuit
->circ_type
));
859 vty_out (vty
, "%-9s", circuit_t2string (circuit
->is_type
));
860 vty_out (vty
, "%s", VTY_NEWLINE
);
863 if (detail
== ISIS_UI_LEVEL_DETAIL
)
865 struct listnode
*node
;
866 struct prefix
*ip_addr
;
869 vty_out (vty
, " Interface: %s", circuit
->interface
->name
);
870 vty_out (vty
, ", State: %s", circuit_state2string (circuit
->state
));
871 if (circuit
->is_passive
)
872 vty_out (vty
, ", Passive");
874 vty_out (vty
, ", Active");
875 vty_out (vty
, ", Circuit Id: 0x%x", circuit
->circuit_id
);
876 vty_out (vty
, "%s", VTY_NEWLINE
);
877 vty_out (vty
, " Type: %s", circuit_type2string (circuit
->circ_type
));
878 vty_out (vty
, ", Level: %s", circuit_t2string (circuit
->is_type
));
879 if (circuit
->circ_type
== CIRCUIT_T_BROADCAST
)
880 vty_out (vty
, ", SNPA: %-10s", snpa_print (circuit
->u
.bc
.snpa
));
881 vty_out (vty
, "%s", VTY_NEWLINE
);
882 if (circuit
->is_type
& IS_LEVEL_1
)
884 vty_out (vty
, " Level-1 Information:%s", VTY_NEWLINE
);
885 if (circuit
->area
->newmetric
)
886 vty_out (vty
, " Metric: %d", circuit
->te_metric
[0]);
888 vty_out (vty
, " Metric: %d",
890 if (!circuit
->is_passive
)
892 vty_out (vty
, ", Active neighbors: %u%s",
893 circuit
->upadjcount
[0], VTY_NEWLINE
);
894 vty_out (vty
, " Hello interval: %u, "
895 "Holddown count: %u %s%s",
896 circuit
->hello_interval
[0],
897 circuit
->hello_multiplier
[0],
898 (circuit
->pad_hellos
? "(pad)" : "(no-pad)"),
900 vty_out (vty
, " CNSP interval: %u, "
901 "PSNP interval: %u%s",
902 circuit
->csnp_interval
[0],
903 circuit
->psnp_interval
[0], VTY_NEWLINE
);
904 if (circuit
->circ_type
== CIRCUIT_T_BROADCAST
)
905 vty_out (vty
, " LAN Priority: %u, %s%s",
906 circuit
->priority
[0],
907 (circuit
->u
.bc
.is_dr
[0] ? \
908 "is DIS" : "is not DIS"), VTY_NEWLINE
);
912 vty_out (vty
, "%s", VTY_NEWLINE
);
915 if (circuit
->is_type
& IS_LEVEL_2
)
917 vty_out (vty
, " Level-2 Information:%s", VTY_NEWLINE
);
918 if (circuit
->area
->newmetric
)
919 vty_out (vty
, " Metric: %d", circuit
->te_metric
[1]);
921 vty_out (vty
, " Metric: %d",
923 if (!circuit
->is_passive
)
925 vty_out (vty
, ", Active neighbors: %u%s",
926 circuit
->upadjcount
[1], VTY_NEWLINE
);
927 vty_out (vty
, " Hello interval: %u, "
928 "Holddown count: %u %s%s",
929 circuit
->hello_interval
[1],
930 circuit
->hello_multiplier
[1],
931 (circuit
->pad_hellos
? "(pad)" : "(no-pad)"),
933 vty_out (vty
, " CNSP interval: %u, "
934 "PSNP interval: %u%s",
935 circuit
->csnp_interval
[1],
936 circuit
->psnp_interval
[1], VTY_NEWLINE
);
937 if (circuit
->circ_type
== CIRCUIT_T_BROADCAST
)
938 vty_out (vty
, " LAN Priority: %u, %s%s",
939 circuit
->priority
[1],
940 (circuit
->u
.bc
.is_dr
[1] ? \
941 "is DIS" : "is not DIS"), VTY_NEWLINE
);
945 vty_out (vty
, "%s", VTY_NEWLINE
);
948 if (circuit
->ip_addrs
&& listcount (circuit
->ip_addrs
) > 0)
950 vty_out (vty
, " IP Prefix(es):%s", VTY_NEWLINE
);
951 for (ALL_LIST_ELEMENTS_RO (circuit
->ip_addrs
, node
, ip_addr
))
953 prefix2str (ip_addr
, buf
, sizeof (buf
)),
954 vty_out (vty
, " %s%s", buf
, VTY_NEWLINE
);
957 if (circuit
->ipv6_link
&& listcount(circuit
->ipv6_link
) > 0)
959 vty_out(vty
, " IPv6 Link-Locals:%s", VTY_NEWLINE
);
960 for (ALL_LIST_ELEMENTS_RO(circuit
->ipv6_link
, node
, ip_addr
))
962 prefix2str(ip_addr
, (char*)buf
, BUFSIZ
),
963 vty_out(vty
, " %s%s", buf
, VTY_NEWLINE
);
966 if (circuit
->ipv6_link
&& listcount(circuit
->ipv6_non_link
) > 0)
968 vty_out(vty
, " IPv6 Prefixes:%s", VTY_NEWLINE
);
969 for (ALL_LIST_ELEMENTS_RO(circuit
->ipv6_non_link
, node
, ip_addr
))
971 prefix2str(ip_addr
, (char*)buf
, BUFSIZ
),
972 vty_out(vty
, " %s%s", buf
, VTY_NEWLINE
);
976 vty_out (vty
, "%s", VTY_NEWLINE
);
982 isis_interface_config_write (struct vty
*vty
)
985 struct listnode
*node
, *node2
;
986 struct interface
*ifp
;
987 struct isis_area
*area
;
988 struct isis_circuit
*circuit
;
991 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), node
, ifp
))
993 if (ifp
->ifindex
== IFINDEX_DELETED
)
997 vty_out (vty
, "interface %s%s", ifp
->name
, VTY_NEWLINE
);
1002 vty_out (vty
, " description %s%s", ifp
->desc
, VTY_NEWLINE
);
1006 for (ALL_LIST_ELEMENTS_RO (isis
->area_list
, node2
, area
))
1008 circuit
= circuit_lookup_by_ifp (ifp
, area
->circuit_list
);
1009 if (circuit
== NULL
)
1011 if (circuit
->ip_router
)
1013 vty_out (vty
, " ip router isis %s%s", area
->area_tag
,
1017 if (circuit
->is_passive
)
1019 vty_out (vty
, " isis passive%s", VTY_NEWLINE
);
1022 if (circuit
->circ_type_config
== CIRCUIT_T_P2P
)
1024 vty_out (vty
, " isis network point-to-point%s", VTY_NEWLINE
);
1028 if (circuit
->ipv6_router
)
1030 vty_out (vty
, " ipv6 router isis %s%s", area
->area_tag
,
1034 #endif /* HAVE_IPV6 */
1036 /* ISIS - circuit type */
1037 if (circuit
->is_type
== IS_LEVEL_1
)
1039 vty_out (vty
, " isis circuit-type level-1%s", VTY_NEWLINE
);
1044 if (circuit
->is_type
== IS_LEVEL_2
)
1046 vty_out (vty
, " isis circuit-type level-2-only%s",
1052 /* ISIS - CSNP interval */
1053 if (circuit
->csnp_interval
[0] == circuit
->csnp_interval
[1])
1055 if (circuit
->csnp_interval
[0] != DEFAULT_CSNP_INTERVAL
)
1057 vty_out (vty
, " isis csnp-interval %d%s",
1058 circuit
->csnp_interval
[0], VTY_NEWLINE
);
1064 for (i
= 0; i
< 2; i
++)
1066 if (circuit
->csnp_interval
[i
] != DEFAULT_CSNP_INTERVAL
)
1068 vty_out (vty
, " isis csnp-interval %d level-%d%s",
1069 circuit
->csnp_interval
[i
], i
+ 1, VTY_NEWLINE
);
1075 /* ISIS - PSNP interval */
1076 if (circuit
->psnp_interval
[0] == circuit
->psnp_interval
[1])
1078 if (circuit
->psnp_interval
[0] != DEFAULT_PSNP_INTERVAL
)
1080 vty_out (vty
, " isis psnp-interval %d%s",
1081 circuit
->psnp_interval
[0], VTY_NEWLINE
);
1087 for (i
= 0; i
< 2; i
++)
1089 if (circuit
->psnp_interval
[i
] != DEFAULT_PSNP_INTERVAL
)
1091 vty_out (vty
, " isis psnp-interval %d level-%d%s",
1092 circuit
->psnp_interval
[i
], i
+ 1, VTY_NEWLINE
);
1098 /* ISIS - Hello padding - Defaults to true so only display if false */
1099 if (circuit
->pad_hellos
== 0)
1101 vty_out (vty
, " no isis hello padding%s", VTY_NEWLINE
);
1105 /* ISIS - Hello interval */
1106 if (circuit
->hello_interval
[0] == circuit
->hello_interval
[1])
1108 if (circuit
->hello_interval
[0] != DEFAULT_HELLO_INTERVAL
)
1110 vty_out (vty
, " isis hello-interval %d%s",
1111 circuit
->hello_interval
[0], VTY_NEWLINE
);
1117 for (i
= 0; i
< 2; i
++)
1119 if (circuit
->hello_interval
[i
] != DEFAULT_HELLO_INTERVAL
)
1121 vty_out (vty
, " isis hello-interval %d level-%d%s",
1122 circuit
->hello_interval
[i
], i
+ 1, VTY_NEWLINE
);
1128 /* ISIS - Hello Multiplier */
1129 if (circuit
->hello_multiplier
[0] == circuit
->hello_multiplier
[1])
1131 if (circuit
->hello_multiplier
[0] != DEFAULT_HELLO_MULTIPLIER
)
1133 vty_out (vty
, " isis hello-multiplier %d%s",
1134 circuit
->hello_multiplier
[0], VTY_NEWLINE
);
1140 for (i
= 0; i
< 2; i
++)
1142 if (circuit
->hello_multiplier
[i
] != DEFAULT_HELLO_MULTIPLIER
)
1144 vty_out (vty
, " isis hello-multiplier %d level-%d%s",
1145 circuit
->hello_multiplier
[i
], i
+ 1,
1152 /* ISIS - Priority */
1153 if (circuit
->priority
[0] == circuit
->priority
[1])
1155 if (circuit
->priority
[0] != DEFAULT_PRIORITY
)
1157 vty_out (vty
, " isis priority %d%s",
1158 circuit
->priority
[0], VTY_NEWLINE
);
1164 for (i
= 0; i
< 2; i
++)
1166 if (circuit
->priority
[i
] != DEFAULT_PRIORITY
)
1168 vty_out (vty
, " isis priority %d level-%d%s",
1169 circuit
->priority
[i
], i
+ 1, VTY_NEWLINE
);
1176 if (circuit
->te_metric
[0] == circuit
->te_metric
[1])
1178 if (circuit
->te_metric
[0] != DEFAULT_CIRCUIT_METRIC
)
1180 vty_out (vty
, " isis metric %d%s", circuit
->te_metric
[0],
1187 for (i
= 0; i
< 2; i
++)
1189 if (circuit
->te_metric
[i
] != DEFAULT_CIRCUIT_METRIC
)
1191 vty_out (vty
, " isis metric %d level-%d%s",
1192 circuit
->te_metric
[i
], i
+ 1, VTY_NEWLINE
);
1197 if (circuit
->passwd
.type
== ISIS_PASSWD_TYPE_HMAC_MD5
)
1199 vty_out (vty
, " isis password md5 %s%s", circuit
->passwd
.passwd
,
1203 else if (circuit
->passwd
.type
== ISIS_PASSWD_TYPE_CLEARTXT
)
1205 vty_out (vty
, " isis password clear %s%s", circuit
->passwd
.passwd
,
1210 vty_out (vty
, "!%s", VTY_NEWLINE
);
1216 struct isis_circuit
*
1217 isis_circuit_create (struct isis_area
*area
, struct interface
*ifp
)
1219 struct isis_circuit
*circuit
= circuit_scan_by_ifp (ifp
);
1220 if (circuit
&& circuit
->area
)
1222 circuit
= isis_csm_state_change (ISIS_ENABLE
, circuit
, area
);
1223 if (circuit
->state
!= C_STATE_CONF
&& circuit
->state
!= C_STATE_UP
)
1225 isis_circuit_if_bind (circuit
, ifp
);
1230 isis_circuit_af_set (struct isis_circuit
*circuit
, bool ip_router
, bool ipv6_router
)
1232 struct isis_area
*area
= circuit
->area
;
1233 bool change
= circuit
->ip_router
!= ip_router
|| circuit
->ipv6_router
!= ipv6_router
;
1234 bool was_enabled
= !!circuit
->area
;
1236 area
->ip_circuits
+= ip_router
- circuit
->ip_router
;
1237 area
->ipv6_circuits
+= ipv6_router
- circuit
->ipv6_router
;
1238 circuit
->ip_router
= ip_router
;
1239 circuit
->ipv6_router
= ipv6_router
;
1244 circuit_update_nlpids (circuit
);
1246 if (!ip_router
&& !ipv6_router
)
1247 isis_csm_state_change (ISIS_DISABLE
, circuit
, area
);
1248 else if (!was_enabled
)
1249 isis_csm_state_change (ISIS_ENABLE
, circuit
, area
);
1251 lsp_regenerate_schedule(circuit
->area
, circuit
->is_type
, 0);
1255 isis_circuit_passive_set (struct isis_circuit
*circuit
, bool passive
)
1257 if (circuit
->is_passive
== passive
)
1260 if (if_is_loopback (circuit
->interface
) && !passive
)
1263 if (circuit
->state
!= C_STATE_UP
)
1265 circuit
->is_passive
= passive
;
1269 struct isis_area
*area
= circuit
->area
;
1270 isis_csm_state_change (ISIS_DISABLE
, circuit
, area
);
1271 circuit
->is_passive
= passive
;
1272 isis_csm_state_change (ISIS_ENABLE
, circuit
, area
);
1279 isis_circuit_metric_set (struct isis_circuit
*circuit
, int level
, int metric
)
1281 assert (level
== IS_LEVEL_1
|| level
== IS_LEVEL_2
);
1282 if (metric
> MAX_WIDE_LINK_METRIC
)
1284 if (circuit
->area
&& circuit
->area
->oldmetric
1285 && metric
> MAX_NARROW_LINK_METRIC
)
1288 circuit
->te_metric
[level
- 1] = metric
;
1289 circuit
->metric
[level
- 1] = metric
;
1292 lsp_regenerate_schedule (circuit
->area
, level
, 0);
1297 isis_circuit_passwd_unset (struct isis_circuit
*circuit
)
1299 memset(&circuit
->passwd
, 0, sizeof(circuit
->passwd
));
1304 isis_circuit_passwd_set (struct isis_circuit
*circuit
, u_char passwd_type
, const char *passwd
)
1311 len
= strlen(passwd
);
1315 circuit
->passwd
.len
= len
;
1316 strncpy((char *)circuit
->passwd
.passwd
, passwd
, 255);
1317 circuit
->passwd
.type
= passwd_type
;
1322 isis_circuit_passwd_cleartext_set (struct isis_circuit
*circuit
, const char *passwd
)
1324 return isis_circuit_passwd_set (circuit
, ISIS_PASSWD_TYPE_CLEARTXT
, passwd
);
1328 isis_circuit_passwd_hmac_md5_set (struct isis_circuit
*circuit
, const char *passwd
)
1330 return isis_circuit_passwd_set (circuit
, ISIS_PASSWD_TYPE_HMAC_MD5
, passwd
);
1332 struct cmd_node interface_node
= {
1339 isis_circuit_circ_type_set(struct isis_circuit
*circuit
, int circ_type
)
1341 /* Changing the network type to/of loopback or unknown interfaces
1342 * is not supported. */
1343 if (circ_type
== CIRCUIT_T_UNKNOWN
1344 || circ_type
== CIRCUIT_T_LOOPBACK
1345 || circuit
->circ_type
== CIRCUIT_T_LOOPBACK
)
1347 if (circuit
->circ_type
!= circ_type
)
1353 if (circuit
->circ_type
== circ_type
)
1356 if (circuit
->state
!= C_STATE_UP
)
1358 circuit
->circ_type
= circ_type
;
1359 circuit
->circ_type_config
= circ_type
;
1363 struct isis_area
*area
= circuit
->area
;
1364 if (circ_type
== CIRCUIT_T_BROADCAST
1365 && !if_is_broadcast(circuit
->interface
))
1368 isis_csm_state_change(ISIS_DISABLE
, circuit
, area
);
1369 circuit
->circ_type
= circ_type
;
1370 circuit
->circ_type_config
= circ_type
;
1371 isis_csm_state_change(ISIS_ENABLE
, circuit
, area
);
1377 isis_if_new_hook (struct interface
*ifp
)
1383 isis_if_delete_hook (struct interface
*ifp
)
1385 struct isis_circuit
*circuit
;
1386 /* Clean up the circuit data */
1387 if (ifp
&& ifp
->info
)
1389 circuit
= ifp
->info
;
1390 isis_csm_state_change (IF_DOWN_FROM_Z
, circuit
, circuit
->area
);
1391 isis_csm_state_change (ISIS_DISABLE
, circuit
, circuit
->area
);
1398 isis_circuit_init ()
1400 /* Initialize Zebra interface data structure */
1401 if_add_hook (IF_NEW_HOOK
, isis_if_new_hook
);
1402 if_add_hook (IF_DELETE_HOOK
, isis_if_delete_hook
);
1404 /* Install interface node */
1405 install_node (&interface_node
, isis_interface_config_write
);
1406 install_element (CONFIG_NODE
, &interface_cmd
);
1407 install_element (CONFIG_NODE
, &no_interface_cmd
);
1409 install_default (INTERFACE_NODE
);
1410 install_element (INTERFACE_NODE
, &interface_desc_cmd
);
1411 install_element (INTERFACE_NODE
, &no_interface_desc_cmd
);