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; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 #include <net/ethernet.h>
26 #include <netinet/if_ether.h>
29 #ifndef ETHER_ADDR_LEN
30 #define ETHER_ADDR_LEN ETHERADDRL
46 #include "isisd/dict.h"
47 #include "isisd/isis_constants.h"
48 #include "isisd/isis_common.h"
49 #include "isisd/isis_flags.h"
50 #include "isisd/isis_circuit.h"
51 #include "isisd/isis_tlv.h"
52 #include "isisd/isis_lsp.h"
53 #include "isisd/isis_pdu.h"
54 #include "isisd/isis_network.h"
55 #include "isisd/isis_misc.h"
56 #include "isisd/isis_constants.h"
57 #include "isisd/isis_adjacency.h"
58 #include "isisd/isis_dr.h"
59 #include "isisd/isisd.h"
60 #include "isisd/isis_csm.h"
61 #include "isisd/isis_events.h"
62 #include "isisd/isis_te.h"
63 #include "isisd/isis_mt.h"
65 DEFINE_QOBJ_TYPE(isis_circuit
)
70 int isis_interface_config_write(struct vty
*);
71 int isis_if_new_hook(struct interface
*);
72 int isis_if_delete_hook(struct interface
*);
77 struct isis_circuit
*circuit
;
80 circuit
= XCALLOC (MTYPE_ISIS_CIRCUIT
, sizeof (struct isis_circuit
));
83 zlog_err ("Can't malloc isis circuit");
90 circuit
->is_type
= IS_LEVEL_1_AND_2
;
92 circuit
->pad_hellos
= 1;
93 for (i
= 0; i
< 2; i
++)
95 circuit
->hello_interval
[i
] = DEFAULT_HELLO_INTERVAL
;
96 circuit
->hello_multiplier
[i
] = DEFAULT_HELLO_MULTIPLIER
;
97 circuit
->csnp_interval
[i
] = DEFAULT_CSNP_INTERVAL
;
98 circuit
->psnp_interval
[i
] = DEFAULT_PSNP_INTERVAL
;
99 circuit
->priority
[i
] = DEFAULT_PRIORITY
;
100 circuit
->metric
[i
] = DEFAULT_CIRCUIT_METRIC
;
101 circuit
->te_metric
[i
] = DEFAULT_CIRCUIT_METRIC
;
104 circuit
->mtc
= mpls_te_circuit_new();
106 circuit_mt_init(circuit
);
108 QOBJ_REG (circuit
, isis_circuit
);
114 isis_circuit_del (struct isis_circuit
*circuit
)
119 QOBJ_UNREG (circuit
);
121 isis_circuit_if_unbind (circuit
, circuit
->interface
);
123 circuit_mt_finish(circuit
);
125 /* and lastly the circuit itself */
126 XFREE (MTYPE_ISIS_CIRCUIT
, circuit
);
132 isis_circuit_configure (struct isis_circuit
*circuit
, struct isis_area
*area
)
135 circuit
->area
= area
;
138 * Whenever the is-type of an area is changed, the is-type of each circuit
139 * in that area is updated to a non-empty subset of the area is-type.
140 * Inversely, when configuring a new circuit, this property should be
143 if (area
->is_type
!= IS_LEVEL_1_AND_2
)
144 circuit
->is_type
= area
->is_type
;
147 * Add the circuit into area
149 listnode_add (area
->circuit_list
, circuit
);
151 circuit
->idx
= flags_get_index (&area
->flags
);
157 isis_circuit_deconfigure (struct isis_circuit
*circuit
, struct isis_area
*area
)
159 /* Free the index of SRM and SSN flags */
160 flags_free_index (&area
->flags
, circuit
->idx
);
162 /* Remove circuit from area */
163 assert (circuit
->area
== area
);
164 listnode_delete (area
->circuit_list
, circuit
);
165 circuit
->area
= NULL
;
170 struct isis_circuit
*
171 circuit_lookup_by_ifp (struct interface
*ifp
, struct list
*list
)
173 struct isis_circuit
*circuit
= NULL
;
174 struct listnode
*node
;
179 for (ALL_LIST_ELEMENTS_RO (list
, node
, circuit
))
180 if (circuit
->interface
== ifp
)
182 assert (ifp
->info
== circuit
);
189 struct isis_circuit
*
190 circuit_scan_by_ifp (struct interface
*ifp
)
192 struct isis_area
*area
;
193 struct listnode
*node
;
194 struct isis_circuit
*circuit
;
197 return (struct isis_circuit
*)ifp
->info
;
201 for (ALL_LIST_ELEMENTS_RO (isis
->area_list
, node
, area
))
203 circuit
= circuit_lookup_by_ifp (ifp
, area
->circuit_list
);
208 return circuit_lookup_by_ifp (ifp
, isis
->init_circ_list
);
212 isis_circuit_add_addr (struct isis_circuit
*circuit
,
213 struct connected
*connected
)
215 struct listnode
*node
;
216 struct prefix_ipv4
*ipv4
;
217 #if defined(EXTREME_DEBUG)
218 char buf
[PREFIX2STR_BUFFER
];
220 struct prefix_ipv6
*ipv6
;
222 if (connected
->address
->family
== AF_INET
)
224 u_int32_t addr
= connected
->address
->u
.prefix4
.s_addr
;
226 if (IPV4_NET0(addr
) ||
229 IPV4_LINKLOCAL(addr
))
232 for (ALL_LIST_ELEMENTS_RO (circuit
->ip_addrs
, node
, ipv4
))
233 if (prefix_same ((struct prefix
*) ipv4
, connected
->address
))
236 ipv4
= prefix_ipv4_new ();
237 ipv4
->prefixlen
= connected
->address
->prefixlen
;
238 ipv4
->prefix
= connected
->address
->u
.prefix4
;
239 listnode_add (circuit
->ip_addrs
, ipv4
);
241 /* Update MPLS TE Local IP address parameter */
242 set_circuitparams_local_ipaddr (circuit
->mtc
, ipv4
->prefix
);
245 lsp_regenerate_schedule (circuit
->area
, circuit
->is_type
, 0);
248 prefix2str (connected
->address
, buf
, sizeof (buf
));
249 zlog_debug ("Added IP address %s to circuit %d", buf
,
250 circuit
->circuit_id
);
251 #endif /* EXTREME_DEBUG */
253 if (connected
->address
->family
== AF_INET6
)
255 if (IN6_IS_ADDR_LOOPBACK(&connected
->address
->u
.prefix6
))
258 for (ALL_LIST_ELEMENTS_RO (circuit
->ipv6_link
, node
, ipv6
))
259 if (prefix_same ((struct prefix
*) ipv6
, connected
->address
))
261 for (ALL_LIST_ELEMENTS_RO (circuit
->ipv6_non_link
, node
, ipv6
))
262 if (prefix_same ((struct prefix
*) ipv6
, connected
->address
))
265 ipv6
= prefix_ipv6_new ();
266 ipv6
->prefixlen
= connected
->address
->prefixlen
;
267 ipv6
->prefix
= connected
->address
->u
.prefix6
;
269 if (IN6_IS_ADDR_LINKLOCAL (&ipv6
->prefix
))
270 listnode_add (circuit
->ipv6_link
, ipv6
);
272 listnode_add (circuit
->ipv6_non_link
, ipv6
);
274 lsp_regenerate_schedule (circuit
->area
, circuit
->is_type
, 0);
277 prefix2str (connected
->address
, buf
, sizeof (buf
));
278 zlog_debug ("Added IPv6 address %s to circuit %d", buf
,
279 circuit
->circuit_id
);
280 #endif /* EXTREME_DEBUG */
286 isis_circuit_del_addr (struct isis_circuit
*circuit
,
287 struct connected
*connected
)
289 struct prefix_ipv4
*ipv4
, *ip
= NULL
;
290 struct listnode
*node
;
291 char buf
[PREFIX2STR_BUFFER
];
292 struct prefix_ipv6
*ipv6
, *ip6
= NULL
;
295 if (connected
->address
->family
== AF_INET
)
297 ipv4
= prefix_ipv4_new ();
298 ipv4
->prefixlen
= connected
->address
->prefixlen
;
299 ipv4
->prefix
= connected
->address
->u
.prefix4
;
301 for (ALL_LIST_ELEMENTS_RO (circuit
->ip_addrs
, node
, ip
))
302 if (prefix_same ((struct prefix
*) ip
, (struct prefix
*) ipv4
))
307 listnode_delete (circuit
->ip_addrs
, ip
);
309 lsp_regenerate_schedule (circuit
->area
, circuit
->is_type
, 0);
313 prefix2str (connected
->address
, buf
, sizeof (buf
));
314 zlog_warn ("Nonexistant ip address %s removal attempt from \
315 circuit %d", buf
, circuit
->circuit_id
);
316 zlog_warn ("Current ip addresses on %s:", circuit
->interface
->name
);
317 for (ALL_LIST_ELEMENTS_RO(circuit
->ip_addrs
, node
, ip
))
319 prefix2str(ip
, buf
, sizeof(buf
));
320 zlog_warn(" %s", buf
);
322 zlog_warn("End of addresses");
325 prefix_ipv4_free (ipv4
);
327 if (connected
->address
->family
== AF_INET6
)
329 ipv6
= prefix_ipv6_new ();
330 ipv6
->prefixlen
= connected
->address
->prefixlen
;
331 ipv6
->prefix
= connected
->address
->u
.prefix6
;
333 if (IN6_IS_ADDR_LINKLOCAL (&ipv6
->prefix
))
335 for (ALL_LIST_ELEMENTS_RO (circuit
->ipv6_link
, node
, ip6
))
337 if (prefix_same ((struct prefix
*) ip6
, (struct prefix
*) ipv6
))
342 listnode_delete (circuit
->ipv6_link
, ip6
);
348 for (ALL_LIST_ELEMENTS_RO (circuit
->ipv6_non_link
, node
, ip6
))
350 if (prefix_same ((struct prefix
*) ip6
, (struct prefix
*) ipv6
))
355 listnode_delete (circuit
->ipv6_non_link
, ip6
);
362 prefix2str (connected
->address
, buf
, sizeof (buf
));
363 zlog_warn ("Nonexitant ip address %s removal attempt from \
364 circuit %d", buf
, circuit
->circuit_id
);
365 zlog_warn ("Current ip addresses on %s:", circuit
->interface
->name
);
366 for (ALL_LIST_ELEMENTS_RO(circuit
->ipv6_link
, node
, ip6
))
368 prefix2str((struct prefix
*)ip6
, (char *)buf
, BUFSIZ
);
369 zlog_warn(" %s", buf
);
372 for (ALL_LIST_ELEMENTS_RO(circuit
->ipv6_non_link
, node
, ip6
))
374 prefix2str((struct prefix
*)ip6
, (char *)buf
, BUFSIZ
);
375 zlog_warn(" %s", buf
);
377 zlog_warn("End of addresses");
379 else if (circuit
->area
)
380 lsp_regenerate_schedule (circuit
->area
, circuit
->is_type
, 0);
382 prefix_ipv6_free (ipv6
);
388 isis_circuit_id_gen (struct interface
*ifp
)
393 int start
= -1, end
= -1;
396 * Get a stable circuit id from ifname. This makes
397 * the ifindex from flapping when netdevs are created
398 * and deleted on the fly. Note that this circuit id
399 * is used in pseudo lsps so it is better to be stable.
400 * The following code works on any reasonanle ifname
401 * like: eth1 or trk-1.1 etc.
403 for (i
= 0; i
< strlen (ifp
->name
); i
++)
405 if (isdigit((unsigned char)ifp
->name
[i
]))
421 if ((start
>= 0) && (end
>= start
) && (end
- start
) < 16)
423 memset (ifname
, 0, 16);
424 strncpy (ifname
, &ifp
->name
[start
], end
- start
);
425 id
= (u_char
)atoi(ifname
);
428 /* Try to be unique. */
430 id
= (u_char
)((ifp
->ifindex
& 0xff) | 0x80);
436 isis_circuit_if_add (struct isis_circuit
*circuit
, struct interface
*ifp
)
438 struct listnode
*node
, *nnode
;
439 struct connected
*conn
;
441 circuit
->circuit_id
= isis_circuit_id_gen (ifp
);
443 isis_circuit_if_bind (circuit
, ifp
);
444 /* isis_circuit_update_addrs (circuit, ifp); */
446 if (if_is_broadcast (ifp
))
448 if (circuit
->circ_type_config
== CIRCUIT_T_P2P
)
449 circuit
->circ_type
= CIRCUIT_T_P2P
;
451 circuit
->circ_type
= CIRCUIT_T_BROADCAST
;
453 else if (if_is_pointopoint (ifp
))
455 circuit
->circ_type
= CIRCUIT_T_P2P
;
457 else if (if_is_loopback (ifp
))
459 circuit
->circ_type
= CIRCUIT_T_LOOPBACK
;
460 circuit
->is_passive
= 1;
464 /* It's normal in case of loopback etc. */
465 if (isis
->debugs
& DEBUG_EVENTS
)
466 zlog_debug ("isis_circuit_if_add: unsupported media");
467 circuit
->circ_type
= CIRCUIT_T_UNKNOWN
;
470 circuit
->ip_addrs
= list_new ();
471 circuit
->ipv6_link
= list_new ();
472 circuit
->ipv6_non_link
= list_new ();
474 for (ALL_LIST_ELEMENTS (ifp
->connected
, node
, nnode
, conn
))
475 isis_circuit_add_addr (circuit
, conn
);
481 isis_circuit_if_del (struct isis_circuit
*circuit
, struct interface
*ifp
)
483 struct listnode
*node
, *nnode
;
484 struct connected
*conn
;
486 assert (circuit
->interface
== ifp
);
488 /* destroy addresses */
489 for (ALL_LIST_ELEMENTS (ifp
->connected
, node
, nnode
, conn
))
490 isis_circuit_del_addr (circuit
, conn
);
492 if (circuit
->ip_addrs
)
494 assert (listcount(circuit
->ip_addrs
) == 0);
495 list_delete (circuit
->ip_addrs
);
496 circuit
->ip_addrs
= NULL
;
499 if (circuit
->ipv6_link
)
501 assert (listcount(circuit
->ipv6_link
) == 0);
502 list_delete (circuit
->ipv6_link
);
503 circuit
->ipv6_link
= NULL
;
506 if (circuit
->ipv6_non_link
)
508 assert (listcount(circuit
->ipv6_non_link
) == 0);
509 list_delete (circuit
->ipv6_non_link
);
510 circuit
->ipv6_non_link
= NULL
;
513 circuit
->circ_type
= CIRCUIT_T_UNKNOWN
;
514 circuit
->circuit_id
= 0;
520 isis_circuit_if_bind (struct isis_circuit
*circuit
, struct interface
*ifp
)
522 assert (circuit
!= NULL
);
523 assert (ifp
!= NULL
);
524 if (circuit
->interface
)
525 assert (circuit
->interface
== ifp
);
527 circuit
->interface
= ifp
;
529 assert (ifp
->info
== circuit
);
532 isis_link_params_update (circuit
, ifp
);
536 isis_circuit_if_unbind (struct isis_circuit
*circuit
, struct interface
*ifp
)
538 assert (circuit
!= NULL
);
539 assert (ifp
!= NULL
);
540 assert (circuit
->interface
== ifp
);
541 assert (ifp
->info
== circuit
);
542 circuit
->interface
= NULL
;
547 isis_circuit_update_all_srmflags (struct isis_circuit
*circuit
, int is_set
)
549 struct isis_area
*area
;
550 struct isis_lsp
*lsp
;
551 dnode_t
*dnode
, *dnode_next
;
555 area
= circuit
->area
;
557 for (level
= ISIS_LEVEL1
; level
<= ISIS_LEVEL2
; level
++)
559 if (level
& circuit
->is_type
)
561 if (area
->lspdb
[level
- 1] &&
562 dict_count (area
->lspdb
[level
- 1]) > 0)
564 for (dnode
= dict_first (area
->lspdb
[level
- 1]);
565 dnode
!= NULL
; dnode
= dnode_next
)
567 dnode_next
= dict_next (area
->lspdb
[level
- 1], dnode
);
568 lsp
= dnode_get (dnode
);
571 ISIS_SET_FLAG (lsp
->SRMflags
, circuit
);
575 ISIS_CLEAR_FLAG (lsp
->SRMflags
, circuit
);
584 isis_circuit_pdu_size(struct isis_circuit
*circuit
)
586 return ISO_MTU(circuit
);
590 isis_circuit_stream(struct isis_circuit
*circuit
, struct stream
**stream
)
592 size_t stream_size
= isis_circuit_pdu_size(circuit
);
596 *stream
= stream_new(stream_size
);
600 if (STREAM_SIZE(*stream
) != stream_size
)
601 stream_resize(*stream
, stream_size
);
602 stream_reset(*stream
);
607 isis_circuit_prepare (struct isis_circuit
*circuit
)
610 thread_add_read(master
, isis_receive
, circuit
, circuit
->fd
,
613 thread_add_timer_msec(master
, isis_receive
, circuit
,
614 listcount(circuit
->area
->circuit_list
) * 100,
620 isis_circuit_up (struct isis_circuit
*circuit
)
624 /* Set the flags for all the lsps of the circuit. */
625 isis_circuit_update_all_srmflags (circuit
, 1);
627 if (circuit
->state
== C_STATE_UP
)
630 if (circuit
->is_passive
)
633 if (circuit
->area
->lsp_mtu
> isis_circuit_pdu_size(circuit
))
635 zlog_err("Interface MTU %zu on %s is too low to support area lsp mtu %u!",
636 isis_circuit_pdu_size(circuit
), circuit
->interface
->name
,
637 circuit
->area
->lsp_mtu
);
638 isis_circuit_update_all_srmflags(circuit
, 0);
642 if (circuit
->circ_type
== CIRCUIT_T_BROADCAST
)
645 * Get the Hardware Address
647 if (circuit
->interface
->hw_addr_len
!= ETH_ALEN
)
649 zlog_warn ("unsupported link layer");
653 memcpy (circuit
->u
.bc
.snpa
, circuit
->interface
->hw_addr
, ETH_ALEN
);
656 zlog_debug ("isis_circuit_if_add: if_id %d, isomtu %d snpa %s",
657 circuit
->interface
->ifindex
, ISO_MTU (circuit
),
658 snpa_print (circuit
->u
.bc
.snpa
));
659 #endif /* EXTREME_DEBUG */
661 circuit
->u
.bc
.adjdb
[0] = list_new ();
662 circuit
->u
.bc
.adjdb
[1] = list_new ();
665 * ISO 10589 - 8.4.1 Enabling of broadcast circuits
668 /* initilizing the hello sending threads
672 /* 8.4.1 a) commence sending of IIH PDUs */
674 if (circuit
->is_type
& IS_LEVEL_1
)
676 thread_add_event(master
, send_lan_l1_hello
, circuit
, 0, NULL
);
677 circuit
->u
.bc
.lan_neighs
[0] = list_new ();
680 if (circuit
->is_type
& IS_LEVEL_2
)
682 thread_add_event(master
, send_lan_l2_hello
, circuit
, 0, NULL
);
683 circuit
->u
.bc
.lan_neighs
[1] = list_new ();
686 /* 8.4.1 b) FIXME: solicit ES - 8.4.6 */
687 /* 8.4.1 c) FIXME: listen for ESH PDUs */
690 /* dr election will commence in... */
691 if (circuit
->is_type
& IS_LEVEL_1
)
692 thread_add_timer(master
, isis_run_dr_l1
, circuit
,
693 2 * circuit
->hello_interval
[0],
694 &circuit
->u
.bc
.t_run_dr
[0]);
695 if (circuit
->is_type
& IS_LEVEL_2
)
696 thread_add_timer(master
, isis_run_dr_l2
, circuit
,
697 2 * circuit
->hello_interval
[1],
698 &circuit
->u
.bc
.t_run_dr
[1]);
702 /* initializing the hello send threads
705 circuit
->u
.p2p
.neighbor
= NULL
;
706 thread_add_event(master
, send_p2p_hello
, circuit
, 0, NULL
);
709 /* initializing PSNP timers */
710 if (circuit
->is_type
& IS_LEVEL_1
)
711 thread_add_timer(master
, send_l1_psnp
, circuit
,
712 isis_jitter(circuit
->psnp_interval
[0], PSNP_JITTER
),
713 &circuit
->t_send_psnp
[0]);
715 if (circuit
->is_type
& IS_LEVEL_2
)
716 thread_add_timer(master
, send_l2_psnp
, circuit
,
717 isis_jitter(circuit
->psnp_interval
[1], PSNP_JITTER
),
718 &circuit
->t_send_psnp
[1]);
720 /* unified init for circuits; ignore warnings below this level */
721 retv
= isis_sock_init (circuit
);
724 isis_circuit_down (circuit
);
728 /* initialize the circuit streams after opening connection */
729 isis_circuit_stream(circuit
, &circuit
->rcv_stream
);
730 isis_circuit_stream(circuit
, &circuit
->snd_stream
);
732 isis_circuit_prepare (circuit
);
734 circuit
->lsp_queue
= list_new ();
735 circuit
->lsp_queue_last_cleared
= time (NULL
);
741 isis_circuit_down (struct isis_circuit
*circuit
)
743 if (circuit
->state
!= C_STATE_UP
)
746 /* Clear the flags for all the lsps of the circuit. */
747 isis_circuit_update_all_srmflags (circuit
, 0);
749 if (circuit
->circ_type
== CIRCUIT_T_BROADCAST
)
751 /* destroy neighbour lists */
752 if (circuit
->u
.bc
.lan_neighs
[0])
754 list_delete (circuit
->u
.bc
.lan_neighs
[0]);
755 circuit
->u
.bc
.lan_neighs
[0] = NULL
;
757 if (circuit
->u
.bc
.lan_neighs
[1])
759 list_delete (circuit
->u
.bc
.lan_neighs
[1]);
760 circuit
->u
.bc
.lan_neighs
[1] = NULL
;
762 /* destroy adjacency databases */
763 if (circuit
->u
.bc
.adjdb
[0])
765 circuit
->u
.bc
.adjdb
[0]->del
= isis_delete_adj
;
766 list_delete (circuit
->u
.bc
.adjdb
[0]);
767 circuit
->u
.bc
.adjdb
[0] = NULL
;
769 if (circuit
->u
.bc
.adjdb
[1])
771 circuit
->u
.bc
.adjdb
[1]->del
= isis_delete_adj
;
772 list_delete (circuit
->u
.bc
.adjdb
[1]);
773 circuit
->u
.bc
.adjdb
[1] = NULL
;
775 if (circuit
->u
.bc
.is_dr
[0])
777 isis_dr_resign (circuit
, 1);
778 circuit
->u
.bc
.is_dr
[0] = 0;
780 memset (circuit
->u
.bc
.l1_desig_is
, 0, ISIS_SYS_ID_LEN
+ 1);
781 if (circuit
->u
.bc
.is_dr
[1])
783 isis_dr_resign (circuit
, 2);
784 circuit
->u
.bc
.is_dr
[1] = 0;
786 memset (circuit
->u
.bc
.l2_desig_is
, 0, ISIS_SYS_ID_LEN
+ 1);
787 memset (circuit
->u
.bc
.snpa
, 0, ETH_ALEN
);
789 THREAD_TIMER_OFF (circuit
->u
.bc
.t_send_lan_hello
[0]);
790 THREAD_TIMER_OFF (circuit
->u
.bc
.t_send_lan_hello
[1]);
791 THREAD_TIMER_OFF (circuit
->u
.bc
.t_run_dr
[0]);
792 THREAD_TIMER_OFF (circuit
->u
.bc
.t_run_dr
[1]);
793 THREAD_TIMER_OFF (circuit
->u
.bc
.t_refresh_pseudo_lsp
[0]);
794 THREAD_TIMER_OFF (circuit
->u
.bc
.t_refresh_pseudo_lsp
[1]);
795 circuit
->lsp_regenerate_pending
[0] = 0;
796 circuit
->lsp_regenerate_pending
[1] = 0;
798 else if (circuit
->circ_type
== CIRCUIT_T_P2P
)
800 isis_delete_adj (circuit
->u
.p2p
.neighbor
);
801 circuit
->u
.p2p
.neighbor
= NULL
;
802 THREAD_TIMER_OFF (circuit
->u
.p2p
.t_send_p2p_hello
);
805 /* Cancel all active threads */
806 THREAD_TIMER_OFF (circuit
->t_send_csnp
[0]);
807 THREAD_TIMER_OFF (circuit
->t_send_csnp
[1]);
808 THREAD_TIMER_OFF (circuit
->t_send_psnp
[0]);
809 THREAD_TIMER_OFF (circuit
->t_send_psnp
[1]);
810 THREAD_OFF (circuit
->t_read
);
812 if (circuit
->lsp_queue
)
814 circuit
->lsp_queue
->del
= NULL
;
815 list_delete (circuit
->lsp_queue
);
816 circuit
->lsp_queue
= NULL
;
819 /* send one gratuitous hello to spead up convergence */
820 if (circuit
->is_type
& IS_LEVEL_1
)
821 send_hello (circuit
, IS_LEVEL_1
);
822 if (circuit
->is_type
& IS_LEVEL_2
)
823 send_hello (circuit
, IS_LEVEL_2
);
825 circuit
->upadjcount
[0] = 0;
826 circuit
->upadjcount
[1] = 0;
828 /* close the socket */
835 if (circuit
->rcv_stream
!= NULL
)
837 stream_free (circuit
->rcv_stream
);
838 circuit
->rcv_stream
= NULL
;
841 if (circuit
->snd_stream
!= NULL
)
843 stream_free (circuit
->snd_stream
);
844 circuit
->snd_stream
= NULL
;
847 thread_cancel_event (master
, circuit
);
853 circuit_update_nlpids (struct isis_circuit
*circuit
)
855 circuit
->nlpids
.count
= 0;
857 if (circuit
->ip_router
)
859 circuit
->nlpids
.nlpids
[0] = NLPID_IP
;
860 circuit
->nlpids
.count
++;
862 if (circuit
->ipv6_router
)
864 circuit
->nlpids
.nlpids
[circuit
->nlpids
.count
] = NLPID_IPV6
;
865 circuit
->nlpids
.count
++;
871 isis_circuit_print_vty (struct isis_circuit
*circuit
, struct vty
*vty
,
874 if (detail
== ISIS_UI_LEVEL_BRIEF
)
876 vty_out (vty
, " %-12s", circuit
->interface
->name
);
877 vty_out (vty
, "0x%-7x", circuit
->circuit_id
);
878 vty_out (vty
, "%-9s", circuit_state2string (circuit
->state
));
879 vty_out (vty
, "%-9s", circuit_type2string (circuit
->circ_type
));
880 vty_out (vty
, "%-9s", circuit_t2string (circuit
->is_type
));
881 vty_out (vty
, "%s", VTY_NEWLINE
);
884 if (detail
== ISIS_UI_LEVEL_DETAIL
)
886 struct listnode
*node
;
887 struct prefix
*ip_addr
;
890 vty_out (vty
, " Interface: %s", circuit
->interface
->name
);
891 vty_out (vty
, ", State: %s", circuit_state2string (circuit
->state
));
892 if (circuit
->is_passive
)
893 vty_out (vty
, ", Passive");
895 vty_out (vty
, ", Active");
896 vty_out (vty
, ", Circuit Id: 0x%x", circuit
->circuit_id
);
897 vty_out (vty
, "%s", VTY_NEWLINE
);
898 vty_out (vty
, " Type: %s", circuit_type2string (circuit
->circ_type
));
899 vty_out (vty
, ", Level: %s", circuit_t2string (circuit
->is_type
));
900 if (circuit
->circ_type
== CIRCUIT_T_BROADCAST
)
901 vty_out (vty
, ", SNPA: %-10s", snpa_print (circuit
->u
.bc
.snpa
));
902 vty_out (vty
, "%s", VTY_NEWLINE
);
903 if (circuit
->is_type
& IS_LEVEL_1
)
905 vty_out (vty
, " Level-1 Information:%s", VTY_NEWLINE
);
906 if (circuit
->area
->newmetric
)
907 vty_out (vty
, " Metric: %d", circuit
->te_metric
[0]);
909 vty_out (vty
, " Metric: %d",
911 if (!circuit
->is_passive
)
913 vty_out (vty
, ", Active neighbors: %u%s",
914 circuit
->upadjcount
[0], VTY_NEWLINE
);
915 vty_out (vty
, " Hello interval: %u, "
916 "Holddown count: %u %s%s",
917 circuit
->hello_interval
[0],
918 circuit
->hello_multiplier
[0],
919 (circuit
->pad_hellos
? "(pad)" : "(no-pad)"),
921 vty_out (vty
, " CNSP interval: %u, "
922 "PSNP interval: %u%s",
923 circuit
->csnp_interval
[0],
924 circuit
->psnp_interval
[0], VTY_NEWLINE
);
925 if (circuit
->circ_type
== CIRCUIT_T_BROADCAST
)
926 vty_out (vty
, " LAN Priority: %u, %s%s",
927 circuit
->priority
[0],
928 (circuit
->u
.bc
.is_dr
[0] ? \
929 "is DIS" : "is not DIS"), VTY_NEWLINE
);
933 vty_out (vty
, "%s", VTY_NEWLINE
);
936 if (circuit
->is_type
& IS_LEVEL_2
)
938 vty_out (vty
, " Level-2 Information:%s", VTY_NEWLINE
);
939 if (circuit
->area
->newmetric
)
940 vty_out (vty
, " Metric: %d", circuit
->te_metric
[1]);
942 vty_out (vty
, " Metric: %d",
944 if (!circuit
->is_passive
)
946 vty_out (vty
, ", Active neighbors: %u%s",
947 circuit
->upadjcount
[1], VTY_NEWLINE
);
948 vty_out (vty
, " Hello interval: %u, "
949 "Holddown count: %u %s%s",
950 circuit
->hello_interval
[1],
951 circuit
->hello_multiplier
[1],
952 (circuit
->pad_hellos
? "(pad)" : "(no-pad)"),
954 vty_out (vty
, " CNSP interval: %u, "
955 "PSNP interval: %u%s",
956 circuit
->csnp_interval
[1],
957 circuit
->psnp_interval
[1], VTY_NEWLINE
);
958 if (circuit
->circ_type
== CIRCUIT_T_BROADCAST
)
959 vty_out (vty
, " LAN Priority: %u, %s%s",
960 circuit
->priority
[1],
961 (circuit
->u
.bc
.is_dr
[1] ? \
962 "is DIS" : "is not DIS"), VTY_NEWLINE
);
966 vty_out (vty
, "%s", VTY_NEWLINE
);
969 if (circuit
->ip_addrs
&& listcount (circuit
->ip_addrs
) > 0)
971 vty_out (vty
, " IP Prefix(es):%s", VTY_NEWLINE
);
972 for (ALL_LIST_ELEMENTS_RO (circuit
->ip_addrs
, node
, ip_addr
))
974 prefix2str (ip_addr
, buf
, sizeof (buf
)),
975 vty_out (vty
, " %s%s", buf
, VTY_NEWLINE
);
978 if (circuit
->ipv6_link
&& listcount(circuit
->ipv6_link
) > 0)
980 vty_out(vty
, " IPv6 Link-Locals:%s", VTY_NEWLINE
);
981 for (ALL_LIST_ELEMENTS_RO(circuit
->ipv6_link
, node
, ip_addr
))
983 prefix2str(ip_addr
, (char*)buf
, BUFSIZ
),
984 vty_out(vty
, " %s%s", buf
, VTY_NEWLINE
);
987 if (circuit
->ipv6_non_link
&& listcount(circuit
->ipv6_non_link
) > 0)
989 vty_out(vty
, " IPv6 Prefixes:%s", VTY_NEWLINE
);
990 for (ALL_LIST_ELEMENTS_RO(circuit
->ipv6_non_link
, node
, ip_addr
))
992 prefix2str(ip_addr
, (char*)buf
, BUFSIZ
),
993 vty_out(vty
, " %s%s", buf
, VTY_NEWLINE
);
997 vty_out (vty
, "%s", VTY_NEWLINE
);
1003 isis_interface_config_write (struct vty
*vty
)
1006 struct listnode
*node
, *node2
;
1007 struct interface
*ifp
;
1008 struct isis_area
*area
;
1009 struct isis_circuit
*circuit
;
1012 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), node
, ifp
))
1014 if (ifp
->ifindex
== IFINDEX_DELETED
)
1018 vty_out (vty
, "interface %s%s", ifp
->name
, VTY_NEWLINE
);
1023 vty_out (vty
, " description %s%s", ifp
->desc
, VTY_NEWLINE
);
1027 for (ALL_LIST_ELEMENTS_RO (isis
->area_list
, node2
, area
))
1029 circuit
= circuit_lookup_by_ifp (ifp
, area
->circuit_list
);
1030 if (circuit
== NULL
)
1032 if (circuit
->ip_router
)
1034 vty_out (vty
, " ip router isis %s%s", area
->area_tag
,
1038 if (circuit
->is_passive
)
1040 vty_out (vty
, " isis passive%s", VTY_NEWLINE
);
1043 if (circuit
->circ_type_config
== CIRCUIT_T_P2P
)
1045 vty_out (vty
, " isis network point-to-point%s", VTY_NEWLINE
);
1048 if (circuit
->ipv6_router
)
1050 vty_out (vty
, " ipv6 router isis %s%s", area
->area_tag
,
1055 /* ISIS - circuit type */
1056 if (circuit
->is_type
== IS_LEVEL_1
)
1058 vty_out (vty
, " isis circuit-type level-1%s", VTY_NEWLINE
);
1063 if (circuit
->is_type
== IS_LEVEL_2
)
1065 vty_out (vty
, " isis circuit-type level-2-only%s",
1071 /* ISIS - CSNP interval */
1072 if (circuit
->csnp_interval
[0] == circuit
->csnp_interval
[1])
1074 if (circuit
->csnp_interval
[0] != DEFAULT_CSNP_INTERVAL
)
1076 vty_out (vty
, " isis csnp-interval %d%s",
1077 circuit
->csnp_interval
[0], VTY_NEWLINE
);
1083 for (i
= 0; i
< 2; i
++)
1085 if (circuit
->csnp_interval
[i
] != DEFAULT_CSNP_INTERVAL
)
1087 vty_out (vty
, " isis csnp-interval %d level-%d%s",
1088 circuit
->csnp_interval
[i
], i
+ 1, VTY_NEWLINE
);
1094 /* ISIS - PSNP interval */
1095 if (circuit
->psnp_interval
[0] == circuit
->psnp_interval
[1])
1097 if (circuit
->psnp_interval
[0] != DEFAULT_PSNP_INTERVAL
)
1099 vty_out (vty
, " isis psnp-interval %d%s",
1100 circuit
->psnp_interval
[0], VTY_NEWLINE
);
1106 for (i
= 0; i
< 2; i
++)
1108 if (circuit
->psnp_interval
[i
] != DEFAULT_PSNP_INTERVAL
)
1110 vty_out (vty
, " isis psnp-interval %d level-%d%s",
1111 circuit
->psnp_interval
[i
], i
+ 1, VTY_NEWLINE
);
1117 /* ISIS - Hello padding - Defaults to true so only display if false */
1118 if (circuit
->pad_hellos
== 0)
1120 vty_out (vty
, " no isis hello padding%s", VTY_NEWLINE
);
1124 /* ISIS - Hello interval */
1125 if (circuit
->hello_interval
[0] == circuit
->hello_interval
[1])
1127 if (circuit
->hello_interval
[0] != DEFAULT_HELLO_INTERVAL
)
1129 vty_out (vty
, " isis hello-interval %d%s",
1130 circuit
->hello_interval
[0], VTY_NEWLINE
);
1136 for (i
= 0; i
< 2; i
++)
1138 if (circuit
->hello_interval
[i
] != DEFAULT_HELLO_INTERVAL
)
1140 vty_out (vty
, " isis hello-interval %d level-%d%s",
1141 circuit
->hello_interval
[i
], i
+ 1, VTY_NEWLINE
);
1147 /* ISIS - Hello Multiplier */
1148 if (circuit
->hello_multiplier
[0] == circuit
->hello_multiplier
[1])
1150 if (circuit
->hello_multiplier
[0] != DEFAULT_HELLO_MULTIPLIER
)
1152 vty_out (vty
, " isis hello-multiplier %d%s",
1153 circuit
->hello_multiplier
[0], VTY_NEWLINE
);
1159 for (i
= 0; i
< 2; i
++)
1161 if (circuit
->hello_multiplier
[i
] != DEFAULT_HELLO_MULTIPLIER
)
1163 vty_out (vty
, " isis hello-multiplier %d level-%d%s",
1164 circuit
->hello_multiplier
[i
], i
+ 1,
1171 /* ISIS - Priority */
1172 if (circuit
->priority
[0] == circuit
->priority
[1])
1174 if (circuit
->priority
[0] != DEFAULT_PRIORITY
)
1176 vty_out (vty
, " isis priority %d%s",
1177 circuit
->priority
[0], VTY_NEWLINE
);
1183 for (i
= 0; i
< 2; i
++)
1185 if (circuit
->priority
[i
] != DEFAULT_PRIORITY
)
1187 vty_out (vty
, " isis priority %d level-%d%s",
1188 circuit
->priority
[i
], i
+ 1, VTY_NEWLINE
);
1195 if (circuit
->te_metric
[0] == circuit
->te_metric
[1])
1197 if (circuit
->te_metric
[0] != DEFAULT_CIRCUIT_METRIC
)
1199 vty_out (vty
, " isis metric %d%s", circuit
->te_metric
[0],
1206 for (i
= 0; i
< 2; i
++)
1208 if (circuit
->te_metric
[i
] != DEFAULT_CIRCUIT_METRIC
)
1210 vty_out (vty
, " isis metric %d level-%d%s",
1211 circuit
->te_metric
[i
], i
+ 1, VTY_NEWLINE
);
1216 if (circuit
->passwd
.type
== ISIS_PASSWD_TYPE_HMAC_MD5
)
1218 vty_out (vty
, " isis password md5 %s%s", circuit
->passwd
.passwd
,
1222 else if (circuit
->passwd
.type
== ISIS_PASSWD_TYPE_CLEARTXT
)
1224 vty_out (vty
, " isis password clear %s%s", circuit
->passwd
.passwd
,
1228 write
+= circuit_write_mt_settings(circuit
, vty
);
1230 vty_out (vty
, "!%s", VTY_NEWLINE
);
1236 struct isis_circuit
*
1237 isis_circuit_create (struct isis_area
*area
, struct interface
*ifp
)
1239 struct isis_circuit
*circuit
= circuit_scan_by_ifp (ifp
);
1240 if (circuit
&& circuit
->area
)
1242 circuit
= isis_csm_state_change (ISIS_ENABLE
, circuit
, area
);
1243 if (circuit
->state
!= C_STATE_CONF
&& circuit
->state
!= C_STATE_UP
)
1245 isis_circuit_if_bind (circuit
, ifp
);
1250 isis_circuit_af_set (struct isis_circuit
*circuit
, bool ip_router
, bool ipv6_router
)
1252 struct isis_area
*area
= circuit
->area
;
1253 bool change
= circuit
->ip_router
!= ip_router
|| circuit
->ipv6_router
!= ipv6_router
;
1254 bool was_enabled
= !!circuit
->area
;
1256 area
->ip_circuits
+= ip_router
- circuit
->ip_router
;
1257 area
->ipv6_circuits
+= ipv6_router
- circuit
->ipv6_router
;
1258 circuit
->ip_router
= ip_router
;
1259 circuit
->ipv6_router
= ipv6_router
;
1264 circuit_update_nlpids (circuit
);
1266 if (!ip_router
&& !ipv6_router
)
1267 isis_csm_state_change (ISIS_DISABLE
, circuit
, area
);
1268 else if (!was_enabled
)
1269 isis_csm_state_change (ISIS_ENABLE
, circuit
, area
);
1271 lsp_regenerate_schedule(circuit
->area
, circuit
->is_type
, 0);
1275 isis_circuit_passive_set (struct isis_circuit
*circuit
, bool passive
)
1277 if (circuit
->is_passive
== passive
)
1280 if (if_is_loopback (circuit
->interface
) && !passive
)
1283 if (circuit
->state
!= C_STATE_UP
)
1285 circuit
->is_passive
= passive
;
1289 struct isis_area
*area
= circuit
->area
;
1290 isis_csm_state_change (ISIS_DISABLE
, circuit
, area
);
1291 circuit
->is_passive
= passive
;
1292 isis_csm_state_change (ISIS_ENABLE
, circuit
, area
);
1299 isis_circuit_metric_set (struct isis_circuit
*circuit
, int level
, int metric
)
1301 assert (level
== IS_LEVEL_1
|| level
== IS_LEVEL_2
);
1302 if (metric
> MAX_WIDE_LINK_METRIC
)
1304 if (circuit
->area
&& circuit
->area
->oldmetric
1305 && metric
> MAX_NARROW_LINK_METRIC
)
1308 circuit
->te_metric
[level
- 1] = metric
;
1309 circuit
->metric
[level
- 1] = metric
;
1312 lsp_regenerate_schedule (circuit
->area
, level
, 0);
1317 isis_circuit_passwd_unset (struct isis_circuit
*circuit
)
1319 memset(&circuit
->passwd
, 0, sizeof(circuit
->passwd
));
1324 isis_circuit_passwd_set (struct isis_circuit
*circuit
, u_char passwd_type
, const char *passwd
)
1331 len
= strlen(passwd
);
1335 circuit
->passwd
.len
= len
;
1336 strncpy((char *)circuit
->passwd
.passwd
, passwd
, 255);
1337 circuit
->passwd
.type
= passwd_type
;
1342 isis_circuit_passwd_cleartext_set (struct isis_circuit
*circuit
, const char *passwd
)
1344 return isis_circuit_passwd_set (circuit
, ISIS_PASSWD_TYPE_CLEARTXT
, passwd
);
1348 isis_circuit_passwd_hmac_md5_set (struct isis_circuit
*circuit
, const char *passwd
)
1350 return isis_circuit_passwd_set (circuit
, ISIS_PASSWD_TYPE_HMAC_MD5
, passwd
);
1352 struct cmd_node interface_node
= {
1359 isis_circuit_circ_type_set(struct isis_circuit
*circuit
, int circ_type
)
1361 /* Changing the network type to/of loopback or unknown interfaces
1362 * is not supported. */
1363 if (circ_type
== CIRCUIT_T_UNKNOWN
1364 || circ_type
== CIRCUIT_T_LOOPBACK
1365 || circuit
->circ_type
== CIRCUIT_T_LOOPBACK
)
1367 if (circuit
->circ_type
!= circ_type
)
1373 if (circuit
->circ_type
== circ_type
)
1376 if (circuit
->state
!= C_STATE_UP
)
1378 circuit
->circ_type
= circ_type
;
1379 circuit
->circ_type_config
= circ_type
;
1383 struct isis_area
*area
= circuit
->area
;
1384 if (circ_type
== CIRCUIT_T_BROADCAST
1385 && !if_is_broadcast(circuit
->interface
))
1388 isis_csm_state_change(ISIS_DISABLE
, circuit
, area
);
1389 circuit
->circ_type
= circ_type
;
1390 circuit
->circ_type_config
= circ_type
;
1391 isis_csm_state_change(ISIS_ENABLE
, circuit
, area
);
1397 isis_circuit_mt_enabled_set (struct isis_circuit
*circuit
, uint16_t mtid
,
1400 struct isis_circuit_mt_setting
*setting
;
1402 setting
= circuit_get_mt_setting(circuit
, mtid
);
1403 if (setting
->enabled
!= enabled
)
1405 setting
->enabled
= enabled
;
1406 lsp_regenerate_schedule (circuit
->area
, IS_LEVEL_1
| IS_LEVEL_2
, 0);
1413 isis_if_new_hook (struct interface
*ifp
)
1419 isis_if_delete_hook (struct interface
*ifp
)
1421 struct isis_circuit
*circuit
;
1422 /* Clean up the circuit data */
1423 if (ifp
&& ifp
->info
)
1425 circuit
= ifp
->info
;
1426 isis_csm_state_change (IF_DOWN_FROM_Z
, circuit
, circuit
->area
);
1427 isis_csm_state_change (ISIS_DISABLE
, circuit
, circuit
->area
);
1434 isis_circuit_init ()
1436 /* Initialize Zebra interface data structure */
1437 if_add_hook (IF_NEW_HOOK
, isis_if_new_hook
);
1438 if_add_hook (IF_DELETE_HOOK
, isis_if_delete_hook
);
1440 /* Install interface node */
1441 install_node (&interface_node
, isis_interface_config_write
);