]> git.proxmox.com Git - mirror_frr.git/blame - isisd/isis_circuit.c
frr: Remove HAVE_IPV6 from code base
[mirror_frr.git] / isisd / isis_circuit.c
CommitLineData
eb5d44eb 1/*
2 * IS-IS Rout(e)ing protocol - isis_circuit.h
3 *
4 * Copyright (C) 2001,2002 Sampo Saaristo
5 * Tampere University of Technology
6 * Institute of Communications Engineering
7 *
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)
11 * any later version.
12 *
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
16 * more details.
17
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.
21 */
eb5d44eb 22#include <zebra.h>
37da8c01 23#ifdef GNU_LINUX
eb5d44eb 24#include <net/ethernet.h>
37da8c01 25#else
26#include <netinet/if_ether.h>
27#endif
eb5d44eb 28
238497fc
PJ
29#ifndef ETHER_ADDR_LEN
30#define ETHER_ADDR_LEN ETHERADDRL
31#endif
32
eb5d44eb 33#include "log.h"
34#include "memory.h"
b2d7c082 35#include "vrf.h"
eb5d44eb 36#include "if.h"
37#include "linklist.h"
38#include "command.h"
39#include "thread.h"
f8c06e2c 40#include "vty.h"
eb5d44eb 41#include "hash.h"
42#include "prefix.h"
43#include "stream.h"
676a4ea3 44#include "qobj.h"
eb5d44eb 45
46#include "isisd/dict.h"
eb5d44eb 47#include "isisd/isis_constants.h"
48#include "isisd/isis_common.h"
3f045a08 49#include "isisd/isis_flags.h"
eb5d44eb 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"
eb5d44eb 59#include "isisd/isisd.h"
60#include "isisd/isis_csm.h"
61#include "isisd/isis_events.h"
f8c06e2c 62#include "isisd/isis_te.h"
eb5d44eb 63
676a4ea3
DL
64DEFINE_QOBJ_TYPE(isis_circuit)
65
41b36e90
PJ
66/*
67 * Prototypes.
68 */
41b36e90
PJ
69int isis_interface_config_write(struct vty *);
70int isis_if_new_hook(struct interface *);
71int isis_if_delete_hook(struct interface *);
72
eb5d44eb 73struct isis_circuit *
74isis_circuit_new ()
75{
76 struct isis_circuit *circuit;
77 int i;
78
3fdb2dd9 79 circuit = XCALLOC (MTYPE_ISIS_CIRCUIT, sizeof (struct isis_circuit));
3f045a08 80 if (circuit == NULL)
f390d2c7 81 {
82 zlog_err ("Can't malloc isis circuit");
83 return NULL;
84 }
85
3f045a08
JB
86 /*
87 * Default values
88 */
89 circuit->is_type = IS_LEVEL_1_AND_2;
90 circuit->flags = 0;
91 circuit->pad_hellos = 1;
92 for (i = 0; i < 2; i++)
93 {
94 circuit->hello_interval[i] = DEFAULT_HELLO_INTERVAL;
95 circuit->hello_multiplier[i] = DEFAULT_HELLO_MULTIPLIER;
96 circuit->csnp_interval[i] = DEFAULT_CSNP_INTERVAL;
97 circuit->psnp_interval[i] = DEFAULT_PSNP_INTERVAL;
98 circuit->priority[i] = DEFAULT_PRIORITY;
47a928fb 99 circuit->metric[i] = DEFAULT_CIRCUIT_METRIC;
3f045a08
JB
100 circuit->te_metric[i] = DEFAULT_CIRCUIT_METRIC;
101 }
102
f8c06e2c
OD
103 circuit->mtc = mpls_te_circuit_new();
104
676a4ea3
DL
105 QOBJ_REG (circuit, isis_circuit);
106
eb5d44eb 107 return circuit;
108}
109
3f045a08
JB
110void
111isis_circuit_del (struct isis_circuit *circuit)
112{
113 if (!circuit)
114 return;
115
676a4ea3
DL
116 QOBJ_UNREG (circuit);
117
3f045a08
JB
118 isis_circuit_if_unbind (circuit, circuit->interface);
119
120 /* and lastly the circuit itself */
121 XFREE (MTYPE_ISIS_CIRCUIT, circuit);
122
123 return;
124}
125
eb5d44eb 126void
127isis_circuit_configure (struct isis_circuit *circuit, struct isis_area *area)
128{
3f045a08 129 assert (area);
eb5d44eb 130 circuit->area = area;
3f045a08 131
eb5d44eb 132 /*
ddfdbd32
CF
133 * Whenever the is-type of an area is changed, the is-type of each circuit
134 * in that area is updated to a non-empty subset of the area is-type.
135 * Inversely, when configuring a new circuit, this property should be
136 * ensured as well.
eb5d44eb 137 */
ddfdbd32
CF
138 if (area->is_type != IS_LEVEL_1_AND_2)
139 circuit->is_type = area->is_type;
eb5d44eb 140
141 /*
142 * Add the circuit into area
143 */
144 listnode_add (area->circuit_list, circuit);
145
146 circuit->idx = flags_get_index (&area->flags);
eb5d44eb 147
148 return;
149}
150
f390d2c7 151void
3f045a08 152isis_circuit_deconfigure (struct isis_circuit *circuit, struct isis_area *area)
eb5d44eb 153{
eb5d44eb 154 /* Free the index of SRM and SSN flags */
155 flags_free_index (&area->flags, circuit->idx);
3f045a08
JB
156 circuit->idx = 0;
157 /* Remove circuit from area */
158 assert (circuit->area == area);
159 listnode_delete (area->circuit_list, circuit);
160 circuit->area = NULL;
eb5d44eb 161
162 return;
163}
164
165struct isis_circuit *
166circuit_lookup_by_ifp (struct interface *ifp, struct list *list)
167{
168 struct isis_circuit *circuit = NULL;
169 struct listnode *node;
f390d2c7 170
eb5d44eb 171 if (!list)
172 return NULL;
f390d2c7 173
1eb8ef25 174 for (ALL_LIST_ELEMENTS_RO (list, node, circuit))
175 if (circuit->interface == ifp)
3f045a08
JB
176 {
177 assert (ifp->info == circuit);
178 return circuit;
179 }
180
eb5d44eb 181 return NULL;
182}
183
184struct isis_circuit *
185circuit_scan_by_ifp (struct interface *ifp)
186{
187 struct isis_area *area;
188 struct listnode *node;
189 struct isis_circuit *circuit;
190
3f045a08
JB
191 if (ifp->info)
192 return (struct isis_circuit *)ifp->info;
eb5d44eb 193
3f045a08 194 if (isis->area_list)
f390d2c7 195 {
3f045a08
JB
196 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
197 {
198 circuit = circuit_lookup_by_ifp (ifp, area->circuit_list);
199 if (circuit)
200 return circuit;
201 }
f390d2c7 202 }
eb5d44eb 203 return circuit_lookup_by_ifp (ifp, isis->init_circ_list);
204}
205
eb5d44eb 206void
f891f443 207isis_circuit_add_addr (struct isis_circuit *circuit,
208 struct connected *connected)
eb5d44eb 209{
3f045a08 210 struct listnode *node;
eb5d44eb 211 struct prefix_ipv4 *ipv4;
4690c7d7
DS
212#if defined(EXTREME_DEBUG)
213 char buf[PREFIX2STR_BUFFER];
214#endif
eb5d44eb 215 struct prefix_ipv6 *ipv6;
f891f443 216
f891f443 217 if (connected->address->family == AF_INET)
f390d2c7 218 {
3f045a08
JB
219 u_int32_t addr = connected->address->u.prefix4.s_addr;
220 addr = ntohl (addr);
221 if (IPV4_NET0(addr) ||
222 IPV4_NET127(addr) ||
223 IN_CLASSD(addr) ||
224 IPV4_LINKLOCAL(addr))
225 return;
226
227 for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, node, ipv4))
228 if (prefix_same ((struct prefix *) ipv4, connected->address))
229 return;
230
f390d2c7 231 ipv4 = prefix_ipv4_new ();
f891f443 232 ipv4->prefixlen = connected->address->prefixlen;
233 ipv4->prefix = connected->address->u.prefix4;
f390d2c7 234 listnode_add (circuit->ip_addrs, ipv4);
f8c06e2c
OD
235
236 /* Update MPLS TE Local IP address parameter */
237 set_circuitparams_local_ipaddr (circuit->mtc, ipv4->prefix);
238
0dae85e6 239 if (circuit->area)
3f045a08 240 lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
f891f443 241
eb5d44eb 242#ifdef EXTREME_DEBUG
4690c7d7 243 prefix2str (connected->address, buf, sizeof (buf));
529d65b3 244 zlog_debug ("Added IP address %s to circuit %d", buf,
f390d2c7 245 circuit->circuit_id);
246#endif /* EXTREME_DEBUG */
247 }
f891f443 248 if (connected->address->family == AF_INET6)
f390d2c7 249 {
3f045a08
JB
250 if (IN6_IS_ADDR_LOOPBACK(&connected->address->u.prefix6))
251 return;
252
253 for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_link, node, ipv6))
254 if (prefix_same ((struct prefix *) ipv6, connected->address))
255 return;
256 for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, node, ipv6))
257 if (prefix_same ((struct prefix *) ipv6, connected->address))
258 return;
259
f390d2c7 260 ipv6 = prefix_ipv6_new ();
f891f443 261 ipv6->prefixlen = connected->address->prefixlen;
262 ipv6->prefix = connected->address->u.prefix6;
263
f390d2c7 264 if (IN6_IS_ADDR_LINKLOCAL (&ipv6->prefix))
f891f443 265 listnode_add (circuit->ipv6_link, ipv6);
f390d2c7 266 else
f891f443 267 listnode_add (circuit->ipv6_non_link, ipv6);
0dae85e6 268 if (circuit->area)
3f045a08 269 lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
f891f443 270
eb5d44eb 271#ifdef EXTREME_DEBUG
4690c7d7 272 prefix2str (connected->address, buf, sizeof (buf));
529d65b3 273 zlog_debug ("Added IPv6 address %s to circuit %d", buf,
f390d2c7 274 circuit->circuit_id);
275#endif /* EXTREME_DEBUG */
276 }
eb5d44eb 277 return;
278}
279
280void
281isis_circuit_del_addr (struct isis_circuit *circuit,
f390d2c7 282 struct connected *connected)
eb5d44eb 283{
f891f443 284 struct prefix_ipv4 *ipv4, *ip = NULL;
285 struct listnode *node;
4690c7d7 286 char buf[PREFIX2STR_BUFFER];
f891f443 287 struct prefix_ipv6 *ipv6, *ip6 = NULL;
41b36e90 288 int found = 0;
f891f443 289
f891f443 290 if (connected->address->family == AF_INET)
291 {
292 ipv4 = prefix_ipv4_new ();
293 ipv4->prefixlen = connected->address->prefixlen;
294 ipv4->prefix = connected->address->u.prefix4;
eb5d44eb 295
1eb8ef25 296 for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, node, ip))
3f045a08 297 if (prefix_same ((struct prefix *) ip, (struct prefix *) ipv4))
1eb8ef25 298 break;
f891f443 299
300 if (ip)
301 {
302 listnode_delete (circuit->ip_addrs, ip);
3f045a08
JB
303 if (circuit->area)
304 lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
f891f443 305 }
306 else
307 {
4690c7d7 308 prefix2str (connected->address, buf, sizeof (buf));
3f045a08
JB
309 zlog_warn ("Nonexitant ip address %s removal attempt from \
310 circuit %d", buf, circuit->circuit_id);
16c7aedc
CF
311 zlog_warn ("Current ip addresses on %s:", circuit->interface->name);
312 for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, node, ip))
313 {
314 prefix2str((struct prefix*)ip, (char *)buf, BUFSIZ);
315 zlog_warn(" %s", buf);
316 }
317 zlog_warn("End of addresses");
f891f443 318 }
e8aca32f
DL
319
320 prefix_ipv4_free (ipv4);
f891f443 321 }
f891f443 322 if (connected->address->family == AF_INET6)
323 {
324 ipv6 = prefix_ipv6_new ();
325 ipv6->prefixlen = connected->address->prefixlen;
326 ipv6->prefix = connected->address->u.prefix6;
327
328 if (IN6_IS_ADDR_LINKLOCAL (&ipv6->prefix))
329 {
1eb8ef25 330 for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_link, node, ip6))
f891f443 331 {
f891f443 332 if (prefix_same ((struct prefix *) ip6, (struct prefix *) ipv6))
333 break;
334 }
335 if (ip6)
336 {
337 listnode_delete (circuit->ipv6_link, ip6);
338 found = 1;
339 }
340 }
341 else
342 {
1eb8ef25 343 for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, node, ip6))
f891f443 344 {
f891f443 345 if (prefix_same ((struct prefix *) ip6, (struct prefix *) ipv6))
346 break;
347 }
348 if (ip6)
349 {
350 listnode_delete (circuit->ipv6_non_link, ip6);
351 found = 1;
352 }
353 }
354
355 if (!found)
356 {
4690c7d7 357 prefix2str (connected->address, buf, sizeof (buf));
3f045a08
JB
358 zlog_warn ("Nonexitant ip address %s removal attempt from \
359 circuit %d", buf, circuit->circuit_id);
16c7aedc
CF
360 zlog_warn ("Current ip addresses on %s:", circuit->interface->name);
361 for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_link, node, ip6))
362 {
363 prefix2str((struct prefix*)ip6, (char *)buf, BUFSIZ);
364 zlog_warn(" %s", buf);
365 }
366 zlog_warn(" -----");
367 for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, node, ip6))
368 {
369 prefix2str((struct prefix*)ip6, (char *)buf, BUFSIZ);
370 zlog_warn(" %s", buf);
371 }
372 zlog_warn("End of addresses");
f891f443 373 }
3f045a08
JB
374 else if (circuit->area)
375 lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
e8aca32f
DL
376
377 prefix_ipv6_free (ipv6);
f891f443 378 }
f891f443 379 return;
eb5d44eb 380}
381
3f045a08
JB
382static u_char
383isis_circuit_id_gen (struct interface *ifp)
384{
385 u_char id = 0;
386 char ifname[16];
387 unsigned int i;
388 int start = -1, end = -1;
389
390 /*
391 * Get a stable circuit id from ifname. This makes
392 * the ifindex from flapping when netdevs are created
393 * and deleted on the fly. Note that this circuit id
394 * is used in pseudo lsps so it is better to be stable.
395 * The following code works on any reasonanle ifname
396 * like: eth1 or trk-1.1 etc.
397 */
398 for (i = 0; i < strlen (ifp->name); i++)
399 {
27b87393 400 if (isdigit((unsigned char)ifp->name[i]))
3f045a08
JB
401 {
402 if (start < 0)
403 {
404 start = i;
405 end = i + 1;
406 }
407 else
408 {
409 end = i + 1;
410 }
411 }
412 else if (start >= 0)
413 break;
414 }
415
416 if ((start >= 0) && (end >= start) && (end - start) < 16)
417 {
418 memset (ifname, 0, 16);
419 strncpy (ifname, &ifp->name[start], end - start);
420 id = (u_char)atoi(ifname);
421 }
422
423 /* Try to be unique. */
424 if (!id)
425 id = (u_char)((ifp->ifindex & 0xff) | 0x80);
426
427 return id;
428}
429
eb5d44eb 430void
431isis_circuit_if_add (struct isis_circuit *circuit, struct interface *ifp)
432{
1eb8ef25 433 struct listnode *node, *nnode;
eb5d44eb 434 struct connected *conn;
435
3f045a08 436 circuit->circuit_id = isis_circuit_id_gen (ifp);
eb5d44eb 437
3f045a08 438 isis_circuit_if_bind (circuit, ifp);
eb5d44eb 439 /* isis_circuit_update_addrs (circuit, ifp); */
440
f390d2c7 441 if (if_is_broadcast (ifp))
442 {
3f045a08
JB
443 if (circuit->circ_type_config == CIRCUIT_T_P2P)
444 circuit->circ_type = CIRCUIT_T_P2P;
f390d2c7 445 else
3f045a08 446 circuit->circ_type = CIRCUIT_T_BROADCAST;
f390d2c7 447 }
448 else if (if_is_pointopoint (ifp))
449 {
450 circuit->circ_type = CIRCUIT_T_P2P;
451 }
3f045a08
JB
452 else if (if_is_loopback (ifp))
453 {
454 circuit->circ_type = CIRCUIT_T_LOOPBACK;
455 circuit->is_passive = 1;
456 }
f390d2c7 457 else
458 {
c89c05dd 459 /* It's normal in case of loopback etc. */
460 if (isis->debugs & DEBUG_EVENTS)
3f045a08
JB
461 zlog_debug ("isis_circuit_if_add: unsupported media");
462 circuit->circ_type = CIRCUIT_T_UNKNOWN;
f390d2c7 463 }
464
3f045a08 465 circuit->ip_addrs = list_new ();
3f045a08
JB
466 circuit->ipv6_link = list_new ();
467 circuit->ipv6_non_link = list_new ();
3f045a08 468
1eb8ef25 469 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, conn))
470 isis_circuit_add_addr (circuit, conn);
eb5d44eb 471
472 return;
473}
474
475void
3f045a08 476isis_circuit_if_del (struct isis_circuit *circuit, struct interface *ifp)
eb5d44eb 477{
3f045a08
JB
478 struct listnode *node, *nnode;
479 struct connected *conn;
f390d2c7 480
3f045a08 481 assert (circuit->interface == ifp);
eb5d44eb 482
3f045a08
JB
483 /* destroy addresses */
484 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, conn))
485 isis_circuit_del_addr (circuit, conn);
eb5d44eb 486
3f045a08 487 if (circuit->ip_addrs)
f390d2c7 488 {
3f045a08
JB
489 assert (listcount(circuit->ip_addrs) == 0);
490 list_delete (circuit->ip_addrs);
491 circuit->ip_addrs = NULL;
f390d2c7 492 }
3f045a08 493
3f045a08 494 if (circuit->ipv6_link)
f390d2c7 495 {
3f045a08
JB
496 assert (listcount(circuit->ipv6_link) == 0);
497 list_delete (circuit->ipv6_link);
498 circuit->ipv6_link = NULL;
f390d2c7 499 }
3f045a08
JB
500
501 if (circuit->ipv6_non_link)
f390d2c7 502 {
3f045a08
JB
503 assert (listcount(circuit->ipv6_non_link) == 0);
504 list_delete (circuit->ipv6_non_link);
505 circuit->ipv6_non_link = NULL;
f390d2c7 506 }
3f045a08
JB
507
508 circuit->circ_type = CIRCUIT_T_UNKNOWN;
509 circuit->circuit_id = 0;
eb5d44eb 510
eb5d44eb 511 return;
512}
513
514void
3f045a08
JB
515isis_circuit_if_bind (struct isis_circuit *circuit, struct interface *ifp)
516{
517 assert (circuit != NULL);
518 assert (ifp != NULL);
519 if (circuit->interface)
520 assert (circuit->interface == ifp);
521 else
522 circuit->interface = ifp;
523 if (ifp->info)
524 assert (ifp->info == circuit);
525 else
526 ifp->info = circuit;
f8c06e2c 527 isis_link_params_update (circuit, ifp);
3f045a08
JB
528}
529
530void
531isis_circuit_if_unbind (struct isis_circuit *circuit, struct interface *ifp)
eb5d44eb 532{
3f045a08
JB
533 assert (circuit != NULL);
534 assert (ifp != NULL);
535 assert (circuit->interface == ifp);
536 assert (ifp->info == circuit);
eb5d44eb 537 circuit->interface = NULL;
3f045a08
JB
538 ifp->info = NULL;
539}
f390d2c7 540
3f045a08
JB
541static void
542isis_circuit_update_all_srmflags (struct isis_circuit *circuit, int is_set)
543{
544 struct isis_area *area;
545 struct isis_lsp *lsp;
546 dnode_t *dnode, *dnode_next;
547 int level;
548
549 assert (circuit);
550 area = circuit->area;
551 assert (area);
552 for (level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++)
553 {
554 if (level & circuit->is_type)
555 {
556 if (area->lspdb[level - 1] &&
557 dict_count (area->lspdb[level - 1]) > 0)
558 {
559 for (dnode = dict_first (area->lspdb[level - 1]);
560 dnode != NULL; dnode = dnode_next)
561 {
562 dnode_next = dict_next (area->lspdb[level - 1], dnode);
563 lsp = dnode_get (dnode);
564 if (is_set)
565 {
566 ISIS_SET_FLAG (lsp->SRMflags, circuit);
567 }
568 else
569 {
570 ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
571 }
572 }
573 }
574 }
575 }
eb5d44eb 576}
577
b20ccb3a
CF
578size_t
579isis_circuit_pdu_size(struct isis_circuit *circuit)
580{
581 return ISO_MTU(circuit);
582}
583
584void
585isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream)
586{
587 size_t stream_size = isis_circuit_pdu_size(circuit);
588
589 if (!*stream)
590 {
591 *stream = stream_new(stream_size);
592 }
593 else
594 {
595 if (STREAM_SIZE(*stream) != stream_size)
596 stream_resize(*stream, stream_size);
597 stream_reset(*stream);
598 }
599}
600
5904f19f
RW
601void
602isis_circuit_prepare (struct isis_circuit *circuit)
603{
604#ifdef GNU_LINUX
605 THREAD_READ_ON (master, circuit->t_read, isis_receive, circuit,
606 circuit->fd);
607#else
608 THREAD_TIMER_MSEC_ON (master, circuit->t_read, isis_receive, circuit,
609 listcount (circuit->area->circuit_list) * 100);
610#endif
611}
612
3f045a08 613int
eb5d44eb 614isis_circuit_up (struct isis_circuit *circuit)
615{
3f045a08
JB
616 int retv;
617
618 /* Set the flags for all the lsps of the circuit. */
619 isis_circuit_update_all_srmflags (circuit, 1);
620
621 if (circuit->state == C_STATE_UP)
622 return ISIS_OK;
623
624 if (circuit->is_passive)
625 return ISIS_OK;
eb5d44eb 626
b20ccb3a
CF
627 if (circuit->area->lsp_mtu > isis_circuit_pdu_size(circuit))
628 {
629 zlog_err("Interface MTU %zu on %s is too low to support area lsp mtu %u!",
630 isis_circuit_pdu_size(circuit), circuit->interface->name,
631 circuit->area->lsp_mtu);
ba75ed2c 632 isis_circuit_update_all_srmflags(circuit, 0);
b20ccb3a
CF
633 return ISIS_ERROR;
634 }
635
f390d2c7 636 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
637 {
3f045a08
JB
638 /*
639 * Get the Hardware Address
640 */
3f045a08
JB
641 if (circuit->interface->hw_addr_len != ETH_ALEN)
642 {
643 zlog_warn ("unsupported link layer");
644 }
645 else
646 {
647 memcpy (circuit->u.bc.snpa, circuit->interface->hw_addr, ETH_ALEN);
648 }
649#ifdef EXTREME_DEGUG
650 zlog_debug ("isis_circuit_if_add: if_id %d, isomtu %d snpa %s",
651 circuit->interface->ifindex, ISO_MTU (circuit),
652 snpa_print (circuit->u.bc.snpa));
653#endif /* EXTREME_DEBUG */
3f045a08
JB
654
655 circuit->u.bc.adjdb[0] = list_new ();
656 circuit->u.bc.adjdb[1] = list_new ();
657
f390d2c7 658 /*
659 * ISO 10589 - 8.4.1 Enabling of broadcast circuits
660 */
661
662 /* initilizing the hello sending threads
663 * for a broadcast IF
664 */
665
666 /* 8.4.1 a) commence sending of IIH PDUs */
667
3f045a08
JB
668 if (circuit->is_type & IS_LEVEL_1)
669 {
670 thread_add_event (master, send_lan_l1_hello, circuit, 0);
671 circuit->u.bc.lan_neighs[0] = list_new ();
672 }
f390d2c7 673
3f045a08
JB
674 if (circuit->is_type & IS_LEVEL_2)
675 {
676 thread_add_event (master, send_lan_l2_hello, circuit, 0);
677 circuit->u.bc.lan_neighs[1] = list_new ();
678 }
f390d2c7 679
680 /* 8.4.1 b) FIXME: solicit ES - 8.4.6 */
681 /* 8.4.1 c) FIXME: listen for ESH PDUs */
682
683 /* 8.4.1 d) */
684 /* dr election will commence in... */
3f045a08
JB
685 if (circuit->is_type & IS_LEVEL_1)
686 THREAD_TIMER_ON (master, circuit->u.bc.t_run_dr[0], isis_run_dr_l1,
687 circuit, 2 * circuit->hello_interval[0]);
688 if (circuit->is_type & IS_LEVEL_2)
689 THREAD_TIMER_ON (master, circuit->u.bc.t_run_dr[1], isis_run_dr_l2,
690 circuit, 2 * circuit->hello_interval[1]);
f390d2c7 691 }
692 else
693 {
694 /* initializing the hello send threads
695 * for a ptp IF
696 */
3f045a08 697 circuit->u.p2p.neighbor = NULL;
f390d2c7 698 thread_add_event (master, send_p2p_hello, circuit, 0);
f390d2c7 699 }
eb5d44eb 700
701 /* initializing PSNP timers */
3f045a08
JB
702 if (circuit->is_type & IS_LEVEL_1)
703 THREAD_TIMER_ON (master, circuit->t_send_psnp[0], send_l1_psnp, circuit,
704 isis_jitter (circuit->psnp_interval[0], PSNP_JITTER));
705
706 if (circuit->is_type & IS_LEVEL_2)
707 THREAD_TIMER_ON (master, circuit->t_send_psnp[1], send_l2_psnp, circuit,
708 isis_jitter (circuit->psnp_interval[1], PSNP_JITTER));
f390d2c7 709
3f045a08
JB
710 /* unified init for circuits; ignore warnings below this level */
711 retv = isis_sock_init (circuit);
712 if (retv != ISIS_OK)
f390d2c7 713 {
3f045a08
JB
714 isis_circuit_down (circuit);
715 return retv;
f390d2c7 716 }
717
3f045a08 718 /* initialize the circuit streams after opening connection */
b20ccb3a
CF
719 isis_circuit_stream(circuit, &circuit->rcv_stream);
720 isis_circuit_stream(circuit, &circuit->snd_stream);
eb5d44eb 721
5904f19f 722 isis_circuit_prepare (circuit);
3f045a08
JB
723
724 circuit->lsp_queue = list_new ();
725 circuit->lsp_queue_last_cleared = time (NULL);
726
727 return ISIS_OK;
eb5d44eb 728}
729
730void
731isis_circuit_down (struct isis_circuit *circuit)
732{
3f045a08
JB
733 if (circuit->state != C_STATE_UP)
734 return;
735
736 /* Clear the flags for all the lsps of the circuit. */
737 isis_circuit_update_all_srmflags (circuit, 0);
738
f390d2c7 739 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
740 {
3f045a08
JB
741 /* destroy neighbour lists */
742 if (circuit->u.bc.lan_neighs[0])
743 {
744 list_delete (circuit->u.bc.lan_neighs[0]);
745 circuit->u.bc.lan_neighs[0] = NULL;
746 }
747 if (circuit->u.bc.lan_neighs[1])
748 {
749 list_delete (circuit->u.bc.lan_neighs[1]);
750 circuit->u.bc.lan_neighs[1] = NULL;
751 }
752 /* destroy adjacency databases */
753 if (circuit->u.bc.adjdb[0])
754 {
755 circuit->u.bc.adjdb[0]->del = isis_delete_adj;
756 list_delete (circuit->u.bc.adjdb[0]);
757 circuit->u.bc.adjdb[0] = NULL;
758 }
759 if (circuit->u.bc.adjdb[1])
760 {
761 circuit->u.bc.adjdb[1]->del = isis_delete_adj;
762 list_delete (circuit->u.bc.adjdb[1]);
763 circuit->u.bc.adjdb[1] = NULL;
764 }
765 if (circuit->u.bc.is_dr[0])
766 {
767 isis_dr_resign (circuit, 1);
768 circuit->u.bc.is_dr[0] = 0;
769 }
770 memset (circuit->u.bc.l1_desig_is, 0, ISIS_SYS_ID_LEN + 1);
771 if (circuit->u.bc.is_dr[1])
772 {
773 isis_dr_resign (circuit, 2);
774 circuit->u.bc.is_dr[1] = 0;
775 }
776 memset (circuit->u.bc.l2_desig_is, 0, ISIS_SYS_ID_LEN + 1);
777 memset (circuit->u.bc.snpa, 0, ETH_ALEN);
778
f390d2c7 779 THREAD_TIMER_OFF (circuit->u.bc.t_send_lan_hello[0]);
780 THREAD_TIMER_OFF (circuit->u.bc.t_send_lan_hello[1]);
f891f443 781 THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[0]);
782 THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[1]);
3f045a08
JB
783 THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[0]);
784 THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[1]);
414766a1
CF
785 circuit->lsp_regenerate_pending[0] = 0;
786 circuit->lsp_regenerate_pending[1] = 0;
f390d2c7 787 }
788 else if (circuit->circ_type == CIRCUIT_T_P2P)
789 {
3f045a08
JB
790 isis_delete_adj (circuit->u.p2p.neighbor);
791 circuit->u.p2p.neighbor = NULL;
f390d2c7 792 THREAD_TIMER_OFF (circuit->u.p2p.t_send_p2p_hello);
793 }
3f045a08
JB
794
795 /* Cancel all active threads */
796 THREAD_TIMER_OFF (circuit->t_send_csnp[0]);
797 THREAD_TIMER_OFF (circuit->t_send_csnp[1]);
798 THREAD_TIMER_OFF (circuit->t_send_psnp[0]);
799 THREAD_TIMER_OFF (circuit->t_send_psnp[1]);
800 THREAD_OFF (circuit->t_read);
801
802 if (circuit->lsp_queue)
803 {
804 circuit->lsp_queue->del = NULL;
805 list_delete (circuit->lsp_queue);
806 circuit->lsp_queue = NULL;
807 }
808
809 /* send one gratuitous hello to spead up convergence */
810 if (circuit->is_type & IS_LEVEL_1)
811 send_hello (circuit, IS_LEVEL_1);
812 if (circuit->is_type & IS_LEVEL_2)
813 send_hello (circuit, IS_LEVEL_2);
814
815 circuit->upadjcount[0] = 0;
816 circuit->upadjcount[1] = 0;
817
eb5d44eb 818 /* close the socket */
3f045a08
JB
819 if (circuit->fd)
820 {
821 close (circuit->fd);
822 circuit->fd = 0;
823 }
824
825 if (circuit->rcv_stream != NULL)
826 {
827 stream_free (circuit->rcv_stream);
828 circuit->rcv_stream = NULL;
829 }
830
831 if (circuit->snd_stream != NULL)
832 {
833 stream_free (circuit->snd_stream);
834 circuit->snd_stream = NULL;
835 }
836
837 thread_cancel_event (master, circuit);
eb5d44eb 838
839 return;
840}
841
842void
843circuit_update_nlpids (struct isis_circuit *circuit)
844{
845 circuit->nlpids.count = 0;
f390d2c7 846
847 if (circuit->ip_router)
848 {
849 circuit->nlpids.nlpids[0] = NLPID_IP;
850 circuit->nlpids.count++;
851 }
f390d2c7 852 if (circuit->ipv6_router)
853 {
854 circuit->nlpids.nlpids[circuit->nlpids.count] = NLPID_IPV6;
855 circuit->nlpids.count++;
856 }
eb5d44eb 857 return;
858}
859
3f045a08
JB
860void
861isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty,
862 char detail)
863{
864 if (detail == ISIS_UI_LEVEL_BRIEF)
865 {
866 vty_out (vty, " %-12s", circuit->interface->name);
867 vty_out (vty, "0x%-7x", circuit->circuit_id);
868 vty_out (vty, "%-9s", circuit_state2string (circuit->state));
869 vty_out (vty, "%-9s", circuit_type2string (circuit->circ_type));
870 vty_out (vty, "%-9s", circuit_t2string (circuit->is_type));
871 vty_out (vty, "%s", VTY_NEWLINE);
872 }
873
874 if (detail == ISIS_UI_LEVEL_DETAIL)
875 {
b00d7939
CF
876 struct listnode *node;
877 struct prefix *ip_addr;
c761364c 878 char buf[BUFSIZ];
b00d7939 879
3f045a08
JB
880 vty_out (vty, " Interface: %s", circuit->interface->name);
881 vty_out (vty, ", State: %s", circuit_state2string (circuit->state));
882 if (circuit->is_passive)
883 vty_out (vty, ", Passive");
884 else
885 vty_out (vty, ", Active");
886 vty_out (vty, ", Circuit Id: 0x%x", circuit->circuit_id);
887 vty_out (vty, "%s", VTY_NEWLINE);
888 vty_out (vty, " Type: %s", circuit_type2string (circuit->circ_type));
889 vty_out (vty, ", Level: %s", circuit_t2string (circuit->is_type));
890 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
891 vty_out (vty, ", SNPA: %-10s", snpa_print (circuit->u.bc.snpa));
892 vty_out (vty, "%s", VTY_NEWLINE);
893 if (circuit->is_type & IS_LEVEL_1)
894 {
895 vty_out (vty, " Level-1 Information:%s", VTY_NEWLINE);
896 if (circuit->area->newmetric)
897 vty_out (vty, " Metric: %d", circuit->te_metric[0]);
898 else
899 vty_out (vty, " Metric: %d",
47a928fb 900 circuit->metric[0]);
3f045a08
JB
901 if (!circuit->is_passive)
902 {
903 vty_out (vty, ", Active neighbors: %u%s",
904 circuit->upadjcount[0], VTY_NEWLINE);
905 vty_out (vty, " Hello interval: %u, "
906 "Holddown count: %u %s%s",
907 circuit->hello_interval[0],
908 circuit->hello_multiplier[0],
909 (circuit->pad_hellos ? "(pad)" : "(no-pad)"),
910 VTY_NEWLINE);
911 vty_out (vty, " CNSP interval: %u, "
912 "PSNP interval: %u%s",
913 circuit->csnp_interval[0],
914 circuit->psnp_interval[0], VTY_NEWLINE);
915 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
916 vty_out (vty, " LAN Priority: %u, %s%s",
917 circuit->priority[0],
918 (circuit->u.bc.is_dr[0] ? \
919 "is DIS" : "is not DIS"), VTY_NEWLINE);
920 }
921 else
922 {
923 vty_out (vty, "%s", VTY_NEWLINE);
924 }
925 }
926 if (circuit->is_type & IS_LEVEL_2)
927 {
928 vty_out (vty, " Level-2 Information:%s", VTY_NEWLINE);
929 if (circuit->area->newmetric)
930 vty_out (vty, " Metric: %d", circuit->te_metric[1]);
931 else
932 vty_out (vty, " Metric: %d",
47a928fb 933 circuit->metric[1]);
3f045a08
JB
934 if (!circuit->is_passive)
935 {
936 vty_out (vty, ", Active neighbors: %u%s",
937 circuit->upadjcount[1], VTY_NEWLINE);
938 vty_out (vty, " Hello interval: %u, "
939 "Holddown count: %u %s%s",
940 circuit->hello_interval[1],
941 circuit->hello_multiplier[1],
942 (circuit->pad_hellos ? "(pad)" : "(no-pad)"),
943 VTY_NEWLINE);
944 vty_out (vty, " CNSP interval: %u, "
945 "PSNP interval: %u%s",
946 circuit->csnp_interval[1],
947 circuit->psnp_interval[1], VTY_NEWLINE);
948 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
949 vty_out (vty, " LAN Priority: %u, %s%s",
950 circuit->priority[1],
951 (circuit->u.bc.is_dr[1] ? \
952 "is DIS" : "is not DIS"), VTY_NEWLINE);
953 }
954 else
955 {
956 vty_out (vty, "%s", VTY_NEWLINE);
957 }
958 }
959 if (circuit->ip_addrs && listcount (circuit->ip_addrs) > 0)
960 {
3f045a08
JB
961 vty_out (vty, " IP Prefix(es):%s", VTY_NEWLINE);
962 for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, node, ip_addr))
963 {
4690c7d7 964 prefix2str (ip_addr, buf, sizeof (buf)),
3f045a08
JB
965 vty_out (vty, " %s%s", buf, VTY_NEWLINE);
966 }
967 }
b00d7939
CF
968 if (circuit->ipv6_link && listcount(circuit->ipv6_link) > 0)
969 {
970 vty_out(vty, " IPv6 Link-Locals:%s", VTY_NEWLINE);
971 for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_link, node, ip_addr))
972 {
973 prefix2str(ip_addr, (char*)buf, BUFSIZ),
974 vty_out(vty, " %s%s", buf, VTY_NEWLINE);
975 }
976 }
881d5b3b 977 if (circuit->ipv6_non_link && listcount(circuit->ipv6_non_link) > 0)
b00d7939
CF
978 {
979 vty_out(vty, " IPv6 Prefixes:%s", VTY_NEWLINE);
980 for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, node, ip_addr))
981 {
982 prefix2str(ip_addr, (char*)buf, BUFSIZ),
983 vty_out(vty, " %s%s", buf, VTY_NEWLINE);
984 }
985 }
986
3f045a08
JB
987 vty_out (vty, "%s", VTY_NEWLINE);
988 }
989 return;
990}
991
eb5d44eb 992int
f390d2c7 993isis_interface_config_write (struct vty *vty)
eb5d44eb 994{
eb5d44eb 995 int write = 0;
3fdb2dd9 996 struct listnode *node, *node2;
eb5d44eb 997 struct interface *ifp;
998 struct isis_area *area;
3f045a08 999 struct isis_circuit *circuit;
eb5d44eb 1000 int i;
eb5d44eb 1001
b2d7c082 1002 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
eb5d44eb 1003 {
84361d61
DS
1004 if (ifp->ifindex == IFINDEX_DELETED)
1005 continue;
1006
3f045a08
JB
1007 /* IF name */
1008 vty_out (vty, "interface %s%s", ifp->name, VTY_NEWLINE);
1009 write++;
1010 /* IF desc */
1011 if (ifp->desc)
1012 {
1013 vty_out (vty, " description %s%s", ifp->desc, VTY_NEWLINE);
1014 write++;
1015 }
1016 /* ISIS Circuit */
1017 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node2, area))
1018 {
1019 circuit = circuit_lookup_by_ifp (ifp, area->circuit_list);
1020 if (circuit == NULL)
1021 continue;
1022 if (circuit->ip_router)
1023 {
1024 vty_out (vty, " ip router isis %s%s", area->area_tag,
1025 VTY_NEWLINE);
1026 write++;
1027 }
1028 if (circuit->is_passive)
1029 {
1030 vty_out (vty, " isis passive%s", VTY_NEWLINE);
1031 write++;
1032 }
1033 if (circuit->circ_type_config == CIRCUIT_T_P2P)
1034 {
1035 vty_out (vty, " isis network point-to-point%s", VTY_NEWLINE);
1036 write++;
1037 }
3f045a08
JB
1038 if (circuit->ipv6_router)
1039 {
1040 vty_out (vty, " ipv6 router isis %s%s", area->area_tag,
1041 VTY_NEWLINE);
1042 write++;
1043 }
eb5d44eb 1044
3f045a08
JB
1045 /* ISIS - circuit type */
1046 if (circuit->is_type == IS_LEVEL_1)
1047 {
1048 vty_out (vty, " isis circuit-type level-1%s", VTY_NEWLINE);
1049 write++;
1050 }
1051 else
1052 {
1053 if (circuit->is_type == IS_LEVEL_2)
1054 {
1055 vty_out (vty, " isis circuit-type level-2-only%s",
1056 VTY_NEWLINE);
1057 write++;
1058 }
1059 }
1060
1061 /* ISIS - CSNP interval */
1062 if (circuit->csnp_interval[0] == circuit->csnp_interval[1])
1063 {
1064 if (circuit->csnp_interval[0] != DEFAULT_CSNP_INTERVAL)
1065 {
1066 vty_out (vty, " isis csnp-interval %d%s",
1067 circuit->csnp_interval[0], VTY_NEWLINE);
1068 write++;
1069 }
1070 }
1071 else
1072 {
1073 for (i = 0; i < 2; i++)
1074 {
1075 if (circuit->csnp_interval[i] != DEFAULT_CSNP_INTERVAL)
1076 {
1077 vty_out (vty, " isis csnp-interval %d level-%d%s",
1078 circuit->csnp_interval[i], i + 1, VTY_NEWLINE);
1079 write++;
1080 }
1081 }
1082 }
1083
1084 /* ISIS - PSNP interval */
1085 if (circuit->psnp_interval[0] == circuit->psnp_interval[1])
1086 {
1087 if (circuit->psnp_interval[0] != DEFAULT_PSNP_INTERVAL)
1088 {
1089 vty_out (vty, " isis psnp-interval %d%s",
1090 circuit->psnp_interval[0], VTY_NEWLINE);
1091 write++;
1092 }
1093 }
1094 else
1095 {
1096 for (i = 0; i < 2; i++)
1097 {
1098 if (circuit->psnp_interval[i] != DEFAULT_PSNP_INTERVAL)
1099 {
1100 vty_out (vty, " isis psnp-interval %d level-%d%s",
1101 circuit->psnp_interval[i], i + 1, VTY_NEWLINE);
1102 write++;
1103 }
1104 }
1105 }
1106
1107 /* ISIS - Hello padding - Defaults to true so only display if false */
1108 if (circuit->pad_hellos == 0)
1109 {
1110 vty_out (vty, " no isis hello padding%s", VTY_NEWLINE);
1111 write++;
1112 }
1113
1114 /* ISIS - Hello interval */
1115 if (circuit->hello_interval[0] == circuit->hello_interval[1])
1116 {
1117 if (circuit->hello_interval[0] != DEFAULT_HELLO_INTERVAL)
1118 {
1119 vty_out (vty, " isis hello-interval %d%s",
1120 circuit->hello_interval[0], VTY_NEWLINE);
1121 write++;
1122 }
1123 }
1124 else
1125 {
1126 for (i = 0; i < 2; i++)
1127 {
1128 if (circuit->hello_interval[i] != DEFAULT_HELLO_INTERVAL)
1129 {
1130 vty_out (vty, " isis hello-interval %d level-%d%s",
1131 circuit->hello_interval[i], i + 1, VTY_NEWLINE);
1132 write++;
1133 }
1134 }
1135 }
1136
1137 /* ISIS - Hello Multiplier */
1138 if (circuit->hello_multiplier[0] == circuit->hello_multiplier[1])
1139 {
1140 if (circuit->hello_multiplier[0] != DEFAULT_HELLO_MULTIPLIER)
1141 {
1142 vty_out (vty, " isis hello-multiplier %d%s",
1143 circuit->hello_multiplier[0], VTY_NEWLINE);
1144 write++;
1145 }
1146 }
1147 else
1148 {
1149 for (i = 0; i < 2; i++)
1150 {
1151 if (circuit->hello_multiplier[i] != DEFAULT_HELLO_MULTIPLIER)
1152 {
1153 vty_out (vty, " isis hello-multiplier %d level-%d%s",
1154 circuit->hello_multiplier[i], i + 1,
1155 VTY_NEWLINE);
1156 write++;
1157 }
1158 }
1159 }
1160
1161 /* ISIS - Priority */
1162 if (circuit->priority[0] == circuit->priority[1])
1163 {
1164 if (circuit->priority[0] != DEFAULT_PRIORITY)
1165 {
1166 vty_out (vty, " isis priority %d%s",
1167 circuit->priority[0], VTY_NEWLINE);
1168 write++;
1169 }
1170 }
1171 else
1172 {
1173 for (i = 0; i < 2; i++)
1174 {
1175 if (circuit->priority[i] != DEFAULT_PRIORITY)
1176 {
1177 vty_out (vty, " isis priority %d level-%d%s",
1178 circuit->priority[i], i + 1, VTY_NEWLINE);
1179 write++;
1180 }
1181 }
1182 }
1183
1184 /* ISIS - Metric */
1185 if (circuit->te_metric[0] == circuit->te_metric[1])
1186 {
1187 if (circuit->te_metric[0] != DEFAULT_CIRCUIT_METRIC)
1188 {
1189 vty_out (vty, " isis metric %d%s", circuit->te_metric[0],
1190 VTY_NEWLINE);
1191 write++;
1192 }
1193 }
1194 else
1195 {
1196 for (i = 0; i < 2; i++)
1197 {
1198 if (circuit->te_metric[i] != DEFAULT_CIRCUIT_METRIC)
1199 {
1200 vty_out (vty, " isis metric %d level-%d%s",
1201 circuit->te_metric[i], i + 1, VTY_NEWLINE);
1202 write++;
1203 }
1204 }
1205 }
1206 if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5)
1207 {
1208 vty_out (vty, " isis password md5 %s%s", circuit->passwd.passwd,
1209 VTY_NEWLINE);
1210 write++;
1211 }
1212 else if (circuit->passwd.type == ISIS_PASSWD_TYPE_CLEARTXT)
1213 {
1214 vty_out (vty, " isis password clear %s%s", circuit->passwd.passwd,
1215 VTY_NEWLINE);
1216 write++;
1217 }
1218 }
1219 vty_out (vty, "!%s", VTY_NEWLINE);
eb5d44eb 1220 }
f390d2c7 1221
eb5d44eb 1222 return write;
1223}
eb5d44eb 1224
65f9a9a8
DL
1225struct isis_circuit *
1226isis_circuit_create (struct isis_area *area, struct interface *ifp)
eb5d44eb 1227{
9af60119
DL
1228 struct isis_circuit *circuit = circuit_scan_by_ifp (ifp);
1229 if (circuit && circuit->area)
1230 return NULL;
1231 circuit = isis_csm_state_change (ISIS_ENABLE, circuit, area);
eb735f67
CF
1232 if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP)
1233 return circuit;
65f9a9a8
DL
1234 isis_circuit_if_bind (circuit, ifp);
1235 return circuit;
eb5d44eb 1236}
1237
65f9a9a8
DL
1238void
1239isis_circuit_af_set (struct isis_circuit *circuit, bool ip_router, bool ipv6_router)
eb5d44eb 1240{
65f9a9a8
DL
1241 struct isis_area *area = circuit->area;
1242 bool change = circuit->ip_router != ip_router || circuit->ipv6_router != ipv6_router;
19dd696b 1243 bool was_enabled = !!circuit->area;
eb5d44eb 1244
65f9a9a8
DL
1245 area->ip_circuits += ip_router - circuit->ip_router;
1246 area->ipv6_circuits += ipv6_router - circuit->ipv6_router;
1247 circuit->ip_router = ip_router;
1248 circuit->ipv6_router = ipv6_router;
f390d2c7 1249
65f9a9a8
DL
1250 if (!change)
1251 return;
3f045a08 1252
65f9a9a8 1253 circuit_update_nlpids (circuit);
3f045a08 1254
65f9a9a8 1255 if (!ip_router && !ipv6_router)
eb5d44eb 1256 isis_csm_state_change (ISIS_DISABLE, circuit, area);
65f9a9a8
DL
1257 else if (!was_enabled)
1258 isis_csm_state_change (ISIS_ENABLE, circuit, area);
233d97e9 1259 else
233d97e9 1260 lsp_regenerate_schedule(circuit->area, circuit->is_type, 0);
3f045a08 1261}
eb5d44eb 1262
65f9a9a8
DL
1263int
1264isis_circuit_passive_set (struct isis_circuit *circuit, bool passive)
3f045a08 1265{
65f9a9a8
DL
1266 if (circuit->is_passive == passive)
1267 return 0;
3f045a08 1268
65f9a9a8
DL
1269 if (if_is_loopback (circuit->interface) && !passive)
1270 return -1;
3f045a08
JB
1271
1272 if (circuit->state != C_STATE_UP)
1273 {
65f9a9a8 1274 circuit->is_passive = passive;
3f045a08 1275 }
f390d2c7 1276 else
1277 {
3f045a08
JB
1278 struct isis_area *area = circuit->area;
1279 isis_csm_state_change (ISIS_DISABLE, circuit, area);
65f9a9a8 1280 circuit->is_passive = passive;
3f045a08 1281 isis_csm_state_change (ISIS_ENABLE, circuit, area);
f390d2c7 1282 }
1283
65f9a9a8 1284 return 0;
eb5d44eb 1285}
1286
65f9a9a8
DL
1287int
1288isis_circuit_metric_set (struct isis_circuit *circuit, int level, int metric)
3f045a08 1289{
65f9a9a8
DL
1290 assert (level == IS_LEVEL_1 || level == IS_LEVEL_2);
1291 if (metric > MAX_WIDE_LINK_METRIC)
1292 return -1;
1293 if (circuit->area && circuit->area->oldmetric
1294 && metric > MAX_NARROW_LINK_METRIC)
1295 return -1;
eb5d44eb 1296
65f9a9a8 1297 circuit->te_metric[level - 1] = metric;
47a928fb 1298 circuit->metric[level - 1] = metric;
f390d2c7 1299
65f9a9a8
DL
1300 if (circuit->area)
1301 lsp_regenerate_schedule (circuit->area, level, 0);
1302 return 0;
eb5d44eb 1303}
1304
50c7d14a
CF
1305int
1306isis_circuit_passwd_unset (struct isis_circuit *circuit)
eb5d44eb 1307{
50c7d14a
CF
1308 memset(&circuit->passwd, 0, sizeof(circuit->passwd));
1309 return 0;
3f045a08
JB
1310}
1311
50c7d14a
CF
1312static int
1313isis_circuit_passwd_set (struct isis_circuit *circuit, u_char passwd_type, const char *passwd)
3f045a08
JB
1314{
1315 int len;
f390d2c7 1316
50c7d14a
CF
1317 if (!passwd)
1318 return -1;
1319
1320 len = strlen(passwd);
f390d2c7 1321 if (len > 254)
50c7d14a 1322 return -1;
f390d2c7 1323
50c7d14a
CF
1324 circuit->passwd.len = len;
1325 strncpy((char *)circuit->passwd.passwd, passwd, 255);
1326 circuit->passwd.type = passwd_type;
1327 return 0;
eb5d44eb 1328}
1329
50c7d14a
CF
1330int
1331isis_circuit_passwd_cleartext_set (struct isis_circuit *circuit, const char *passwd)
eb5d44eb 1332{
50c7d14a
CF
1333 return isis_circuit_passwd_set (circuit, ISIS_PASSWD_TYPE_CLEARTXT, passwd);
1334}
f390d2c7 1335
50c7d14a
CF
1336int
1337isis_circuit_passwd_hmac_md5_set (struct isis_circuit *circuit, const char *passwd)
1338{
1339 return isis_circuit_passwd_set (circuit, ISIS_PASSWD_TYPE_HMAC_MD5, passwd);
eb5d44eb 1340}
3f045a08 1341struct cmd_node interface_node = {
eb5d44eb 1342 INTERFACE_NODE,
1343 "%s(config-if)# ",
1344 1,
1345};
1346
65f9a9a8
DL
1347int
1348isis_circuit_circ_type_set(struct isis_circuit *circuit, int circ_type)
3f045a08 1349{
65f9a9a8
DL
1350 /* Changing the network type to/of loopback or unknown interfaces
1351 * is not supported. */
1352 if (circ_type == CIRCUIT_T_UNKNOWN
1353 || circ_type == CIRCUIT_T_LOOPBACK
65f9a9a8 1354 || circuit->circ_type == CIRCUIT_T_LOOPBACK)
3f045a08 1355 {
65f9a9a8
DL
1356 if (circuit->circ_type != circ_type)
1357 return -1;
1358 else
1359 return 0;
3f045a08
JB
1360 }
1361
65f9a9a8
DL
1362 if (circuit->circ_type == circ_type)
1363 return 0;
3f045a08
JB
1364
1365 if (circuit->state != C_STATE_UP)
1366 {
65f9a9a8
DL
1367 circuit->circ_type = circ_type;
1368 circuit->circ_type_config = circ_type;
3f045a08
JB
1369 }
1370 else
1371 {
1372 struct isis_area *area = circuit->area;
65f9a9a8
DL
1373 if (circ_type == CIRCUIT_T_BROADCAST
1374 && !if_is_broadcast(circuit->interface))
1375 return -1;
3f045a08 1376
65f9a9a8
DL
1377 isis_csm_state_change(ISIS_DISABLE, circuit, area);
1378 circuit->circ_type = circ_type;
1379 circuit->circ_type_config = circ_type;
1380 isis_csm_state_change(ISIS_ENABLE, circuit, area);
3f045a08 1381 }
65f9a9a8 1382 return 0;
3f045a08
JB
1383}
1384
eb5d44eb 1385int
1386isis_if_new_hook (struct interface *ifp)
1387{
eb5d44eb 1388 return 0;
1389}
1390
1391int
1392isis_if_delete_hook (struct interface *ifp)
1393{
e38e0df0
SV
1394 struct isis_circuit *circuit;
1395 /* Clean up the circuit data */
1396 if (ifp && ifp->info)
1397 {
1398 circuit = ifp->info;
1399 isis_csm_state_change (IF_DOWN_FROM_Z, circuit, circuit->area);
1400 isis_csm_state_change (ISIS_DISABLE, circuit, circuit->area);
1401 }
1402
eb5d44eb 1403 return 0;
1404}
1405
eb5d44eb 1406void
1407isis_circuit_init ()
1408{
eb5d44eb 1409 /* Initialize Zebra interface data structure */
eb5d44eb 1410 if_add_hook (IF_NEW_HOOK, isis_if_new_hook);
1411 if_add_hook (IF_DELETE_HOOK, isis_if_delete_hook);
1412
1413 /* Install interface node */
1414 install_node (&interface_node, isis_interface_config_write);
0b84f294 1415 if_cmd_init ();
eb5d44eb 1416
65f9a9a8 1417 isis_vty_init ();
eb5d44eb 1418}