blob: 1d1a59ef8be6de33ef9b6ba7497211846769af16 [file] [log] [blame]
jardineb5d44e2003-12-23 08:09:43 +00001/*
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 */
jardineb5d44e2003-12-23 08:09:43 +000022#include <zebra.h>
hasso37da8c02004-05-19 11:38:40 +000023#ifdef GNU_LINUX
jardineb5d44e2003-12-23 08:09:43 +000024#include <net/ethernet.h>
hasso37da8c02004-05-19 11:38:40 +000025#else
26#include <netinet/if_ether.h>
27#endif
jardineb5d44e2003-12-23 08:09:43 +000028
Paul Jakma238497f2007-08-07 18:49:18 +000029#ifndef ETHER_ADDR_LEN
30#define ETHER_ADDR_LEN ETHERADDRL
31#endif
32
jardineb5d44e2003-12-23 08:09:43 +000033#include "log.h"
34#include "memory.h"
35#include "if.h"
36#include "linklist.h"
37#include "command.h"
38#include "thread.h"
Olivier Dugeon4f593572016-04-19 19:03:05 +020039#include "vty.h"
jardineb5d44e2003-12-23 08:09:43 +000040#include "hash.h"
41#include "prefix.h"
42#include "stream.h"
43
44#include "isisd/dict.h"
45#include "isisd/include-netbsd/iso.h"
46#include "isisd/isis_constants.h"
47#include "isisd/isis_common.h"
Josh Bailey3f045a02012-03-24 08:35:20 -070048#include "isisd/isis_flags.h"
jardineb5d44e2003-12-23 08:09:43 +000049#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"
jardineb5d44e2003-12-23 08:09:43 +000058#include "isisd/isisd.h"
59#include "isisd/isis_csm.h"
60#include "isisd/isis_events.h"
Olivier Dugeon4f593572016-04-19 19:03:05 +020061#include "isisd/isis_te.h"
jardineb5d44e2003-12-23 08:09:43 +000062
Paul Jakma41b36e92006-12-08 01:09:50 +000063/*
64 * Prototypes.
65 */
Paul Jakma41b36e92006-12-08 01:09:50 +000066int isis_interface_config_write(struct vty *);
67int isis_if_new_hook(struct interface *);
68int isis_if_delete_hook(struct interface *);
69
jardineb5d44e2003-12-23 08:09:43 +000070struct isis_circuit *
71isis_circuit_new ()
72{
73 struct isis_circuit *circuit;
74 int i;
75
hasso3fdb2dd2005-09-28 18:45:54 +000076 circuit = XCALLOC (MTYPE_ISIS_CIRCUIT, sizeof (struct isis_circuit));
Josh Bailey3f045a02012-03-24 08:35:20 -070077 if (circuit == NULL)
hassof390d2c2004-09-10 20:48:21 +000078 {
79 zlog_err ("Can't malloc isis circuit");
80 return NULL;
81 }
82
Josh Bailey3f045a02012-03-24 08:35:20 -070083 /*
84 * Default values
85 */
86 circuit->is_type = IS_LEVEL_1_AND_2;
87 circuit->flags = 0;
88 circuit->pad_hellos = 1;
89 for (i = 0; i < 2; i++)
90 {
91 circuit->hello_interval[i] = DEFAULT_HELLO_INTERVAL;
92 circuit->hello_multiplier[i] = DEFAULT_HELLO_MULTIPLIER;
93 circuit->csnp_interval[i] = DEFAULT_CSNP_INTERVAL;
94 circuit->psnp_interval[i] = DEFAULT_PSNP_INTERVAL;
95 circuit->priority[i] = DEFAULT_PRIORITY;
David Lamparterf2634132016-07-28 17:23:32 +020096 circuit->metric[i] = DEFAULT_CIRCUIT_METRIC;
Josh Bailey3f045a02012-03-24 08:35:20 -070097 circuit->te_metric[i] = DEFAULT_CIRCUIT_METRIC;
98 }
99
Olivier Dugeon4f593572016-04-19 19:03:05 +0200100 circuit->mtc = mpls_te_circuit_new();
101
jardineb5d44e2003-12-23 08:09:43 +0000102 return circuit;
103}
104
jardineb5d44e2003-12-23 08:09:43 +0000105void
Josh Bailey3f045a02012-03-24 08:35:20 -0700106isis_circuit_del (struct isis_circuit *circuit)
107{
108 if (!circuit)
109 return;
110
111 isis_circuit_if_unbind (circuit, circuit->interface);
112
113 /* and lastly the circuit itself */
114 XFREE (MTYPE_ISIS_CIRCUIT, circuit);
115
116 return;
117}
118
119void
jardineb5d44e2003-12-23 08:09:43 +0000120isis_circuit_configure (struct isis_circuit *circuit, struct isis_area *area)
121{
Josh Bailey3f045a02012-03-24 08:35:20 -0700122 assert (area);
jardineb5d44e2003-12-23 08:09:43 +0000123 circuit->area = area;
Josh Bailey3f045a02012-03-24 08:35:20 -0700124
jardineb5d44e2003-12-23 08:09:43 +0000125 /*
Christian Franke7324ae12015-11-10 18:04:48 +0100126 * Whenever the is-type of an area is changed, the is-type of each circuit
127 * in that area is updated to a non-empty subset of the area is-type.
128 * Inversely, when configuring a new circuit, this property should be
129 * ensured as well.
jardineb5d44e2003-12-23 08:09:43 +0000130 */
Christian Franke7324ae12015-11-10 18:04:48 +0100131 if (area->is_type != IS_LEVEL_1_AND_2)
132 circuit->is_type = area->is_type;
jardineb5d44e2003-12-23 08:09:43 +0000133
134 /*
135 * Add the circuit into area
136 */
137 listnode_add (area->circuit_list, circuit);
138
139 circuit->idx = flags_get_index (&area->flags);
jardineb5d44e2003-12-23 08:09:43 +0000140
141 return;
142}
143
hassof390d2c2004-09-10 20:48:21 +0000144void
Josh Bailey3f045a02012-03-24 08:35:20 -0700145isis_circuit_deconfigure (struct isis_circuit *circuit, struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +0000146{
jardineb5d44e2003-12-23 08:09:43 +0000147 /* Free the index of SRM and SSN flags */
148 flags_free_index (&area->flags, circuit->idx);
Josh Bailey3f045a02012-03-24 08:35:20 -0700149 circuit->idx = 0;
150 /* Remove circuit from area */
151 assert (circuit->area == area);
152 listnode_delete (area->circuit_list, circuit);
153 circuit->area = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000154
155 return;
156}
157
158struct isis_circuit *
159circuit_lookup_by_ifp (struct interface *ifp, struct list *list)
160{
161 struct isis_circuit *circuit = NULL;
162 struct listnode *node;
hassof390d2c2004-09-10 20:48:21 +0000163
jardineb5d44e2003-12-23 08:09:43 +0000164 if (!list)
165 return NULL;
hassof390d2c2004-09-10 20:48:21 +0000166
paul1eb8ef22005-04-07 07:30:20 +0000167 for (ALL_LIST_ELEMENTS_RO (list, node, circuit))
168 if (circuit->interface == ifp)
Josh Bailey3f045a02012-03-24 08:35:20 -0700169 {
170 assert (ifp->info == circuit);
171 return circuit;
172 }
173
jardineb5d44e2003-12-23 08:09:43 +0000174 return NULL;
175}
176
177struct isis_circuit *
178circuit_scan_by_ifp (struct interface *ifp)
179{
180 struct isis_area *area;
181 struct listnode *node;
182 struct isis_circuit *circuit;
183
Josh Bailey3f045a02012-03-24 08:35:20 -0700184 if (ifp->info)
185 return (struct isis_circuit *)ifp->info;
jardineb5d44e2003-12-23 08:09:43 +0000186
Josh Bailey3f045a02012-03-24 08:35:20 -0700187 if (isis->area_list)
hassof390d2c2004-09-10 20:48:21 +0000188 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700189 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
190 {
191 circuit = circuit_lookup_by_ifp (ifp, area->circuit_list);
192 if (circuit)
193 return circuit;
194 }
hassof390d2c2004-09-10 20:48:21 +0000195 }
jardineb5d44e2003-12-23 08:09:43 +0000196 return circuit_lookup_by_ifp (ifp, isis->init_circ_list);
197}
198
jardineb5d44e2003-12-23 08:09:43 +0000199void
hassof891f442004-09-14 13:54:30 +0000200isis_circuit_add_addr (struct isis_circuit *circuit,
201 struct connected *connected)
jardineb5d44e2003-12-23 08:09:43 +0000202{
Josh Bailey3f045a02012-03-24 08:35:20 -0700203 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +0000204 struct prefix_ipv4 *ipv4;
hassof390d2c2004-09-10 20:48:21 +0000205 u_char buf[BUFSIZ];
jardineb5d44e2003-12-23 08:09:43 +0000206#ifdef HAVE_IPV6
207 struct prefix_ipv6 *ipv6;
208#endif /* HAVE_IPV6 */
hassof891f442004-09-14 13:54:30 +0000209
jardineb5d44e2003-12-23 08:09:43 +0000210 memset (&buf, 0, BUFSIZ);
hassof891f442004-09-14 13:54:30 +0000211 if (connected->address->family == AF_INET)
hassof390d2c2004-09-10 20:48:21 +0000212 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700213 u_int32_t addr = connected->address->u.prefix4.s_addr;
214 addr = ntohl (addr);
215 if (IPV4_NET0(addr) ||
216 IPV4_NET127(addr) ||
217 IN_CLASSD(addr) ||
218 IPV4_LINKLOCAL(addr))
219 return;
220
221 for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, node, ipv4))
222 if (prefix_same ((struct prefix *) ipv4, connected->address))
223 return;
224
hassof390d2c2004-09-10 20:48:21 +0000225 ipv4 = prefix_ipv4_new ();
hassof891f442004-09-14 13:54:30 +0000226 ipv4->prefixlen = connected->address->prefixlen;
227 ipv4->prefix = connected->address->u.prefix4;
hassof390d2c2004-09-10 20:48:21 +0000228 listnode_add (circuit->ip_addrs, ipv4);
Olivier Dugeon4f593572016-04-19 19:03:05 +0200229
230 /* Update MPLS TE Local IP address parameter */
231 set_circuitparams_local_ipaddr (circuit->mtc, ipv4->prefix);
232
hasso0dae85e2004-09-26 19:53:47 +0000233 if (circuit->area)
Josh Bailey3f045a02012-03-24 08:35:20 -0700234 lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
hassof891f442004-09-14 13:54:30 +0000235
jardineb5d44e2003-12-23 08:09:43 +0000236#ifdef EXTREME_DEBUG
hassof891f442004-09-14 13:54:30 +0000237 prefix2str (connected->address, buf, BUFSIZ);
hasso529d65b2004-12-24 00:14:50 +0000238 zlog_debug ("Added IP address %s to circuit %d", buf,
hassof390d2c2004-09-10 20:48:21 +0000239 circuit->circuit_id);
240#endif /* EXTREME_DEBUG */
jardineb5d44e2003-12-23 08:09:43 +0000241 }
hassof390d2c2004-09-10 20:48:21 +0000242#ifdef HAVE_IPV6
hassof891f442004-09-14 13:54:30 +0000243 if (connected->address->family == AF_INET6)
hassof390d2c2004-09-10 20:48:21 +0000244 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700245 if (IN6_IS_ADDR_LOOPBACK(&connected->address->u.prefix6))
246 return;
247
248 for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_link, node, ipv6))
249 if (prefix_same ((struct prefix *) ipv6, connected->address))
250 return;
251 for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, node, ipv6))
252 if (prefix_same ((struct prefix *) ipv6, connected->address))
253 return;
254
hassof390d2c2004-09-10 20:48:21 +0000255 ipv6 = prefix_ipv6_new ();
hassof891f442004-09-14 13:54:30 +0000256 ipv6->prefixlen = connected->address->prefixlen;
257 ipv6->prefix = connected->address->u.prefix6;
258
hassof390d2c2004-09-10 20:48:21 +0000259 if (IN6_IS_ADDR_LINKLOCAL (&ipv6->prefix))
hassof891f442004-09-14 13:54:30 +0000260 listnode_add (circuit->ipv6_link, ipv6);
hassof390d2c2004-09-10 20:48:21 +0000261 else
hassof891f442004-09-14 13:54:30 +0000262 listnode_add (circuit->ipv6_non_link, ipv6);
hasso0dae85e2004-09-26 19:53:47 +0000263 if (circuit->area)
Josh Bailey3f045a02012-03-24 08:35:20 -0700264 lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
hassof891f442004-09-14 13:54:30 +0000265
jardineb5d44e2003-12-23 08:09:43 +0000266#ifdef EXTREME_DEBUG
hassof891f442004-09-14 13:54:30 +0000267 prefix2str (connected->address, buf, BUFSIZ);
hasso529d65b2004-12-24 00:14:50 +0000268 zlog_debug ("Added IPv6 address %s to circuit %d", buf,
hassof390d2c2004-09-10 20:48:21 +0000269 circuit->circuit_id);
270#endif /* EXTREME_DEBUG */
271 }
jardineb5d44e2003-12-23 08:09:43 +0000272#endif /* HAVE_IPV6 */
jardineb5d44e2003-12-23 08:09:43 +0000273 return;
274}
275
276void
277isis_circuit_del_addr (struct isis_circuit *circuit,
hassof390d2c2004-09-10 20:48:21 +0000278 struct connected *connected)
jardineb5d44e2003-12-23 08:09:43 +0000279{
hassof891f442004-09-14 13:54:30 +0000280 struct prefix_ipv4 *ipv4, *ip = NULL;
281 struct listnode *node;
hassof891f442004-09-14 13:54:30 +0000282 u_char buf[BUFSIZ];
283#ifdef HAVE_IPV6
284 struct prefix_ipv6 *ipv6, *ip6 = NULL;
Paul Jakma41b36e92006-12-08 01:09:50 +0000285 int found = 0;
hassof891f442004-09-14 13:54:30 +0000286#endif /* HAVE_IPV6 */
jardineb5d44e2003-12-23 08:09:43 +0000287
hassof891f442004-09-14 13:54:30 +0000288 memset (&buf, 0, BUFSIZ);
289 if (connected->address->family == AF_INET)
290 {
291 ipv4 = prefix_ipv4_new ();
292 ipv4->prefixlen = connected->address->prefixlen;
293 ipv4->prefix = connected->address->u.prefix4;
294
paul1eb8ef22005-04-07 07:30:20 +0000295 for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, node, ip))
Josh Bailey3f045a02012-03-24 08:35:20 -0700296 if (prefix_same ((struct prefix *) ip, (struct prefix *) ipv4))
paul1eb8ef22005-04-07 07:30:20 +0000297 break;
hassof891f442004-09-14 13:54:30 +0000298
299 if (ip)
300 {
301 listnode_delete (circuit->ip_addrs, ip);
Josh Bailey3f045a02012-03-24 08:35:20 -0700302 if (circuit->area)
303 lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
hassof891f442004-09-14 13:54:30 +0000304 }
305 else
306 {
hassof7c43dc2004-09-26 16:24:14 +0000307 prefix2str (connected->address, (char *)buf, BUFSIZ);
Josh Bailey3f045a02012-03-24 08:35:20 -0700308 zlog_warn ("Nonexitant ip address %s removal attempt from \
309 circuit %d", buf, circuit->circuit_id);
Christian Frankeec874162015-11-10 18:33:12 +0100310 zlog_warn ("Current ip addresses on %s:", circuit->interface->name);
311 for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, node, ip))
312 {
313 prefix2str((struct prefix*)ip, (char *)buf, BUFSIZ);
314 zlog_warn(" %s", buf);
315 }
316 zlog_warn("End of addresses");
hassof891f442004-09-14 13:54:30 +0000317 }
David Lampartere8aca322012-11-27 01:10:30 +0000318
319 prefix_ipv4_free (ipv4);
hassof891f442004-09-14 13:54:30 +0000320 }
321#ifdef HAVE_IPV6
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 {
paul1eb8ef22005-04-07 07:30:20 +0000330 for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_link, node, ip6))
hassof891f442004-09-14 13:54:30 +0000331 {
hassof891f442004-09-14 13:54:30 +0000332 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 {
paul1eb8ef22005-04-07 07:30:20 +0000343 for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, node, ip6))
hassof891f442004-09-14 13:54:30 +0000344 {
hassof891f442004-09-14 13:54:30 +0000345 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 {
hassof7c43dc2004-09-26 16:24:14 +0000357 prefix2str (connected->address, (char *)buf, BUFSIZ);
Josh Bailey3f045a02012-03-24 08:35:20 -0700358 zlog_warn ("Nonexitant ip address %s removal attempt from \
359 circuit %d", buf, circuit->circuit_id);
Christian Frankeec874162015-11-10 18:33:12 +0100360 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");
hassof891f442004-09-14 13:54:30 +0000373 }
Josh Bailey3f045a02012-03-24 08:35:20 -0700374 else if (circuit->area)
375 lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
David Lampartere8aca322012-11-27 01:10:30 +0000376
377 prefix_ipv6_free (ipv6);
hassof891f442004-09-14 13:54:30 +0000378 }
379#endif /* HAVE_IPV6 */
380 return;
jardineb5d44e2003-12-23 08:09:43 +0000381}
382
Josh Bailey3f045a02012-03-24 08:35:20 -0700383static u_char
384isis_circuit_id_gen (struct interface *ifp)
385{
386 u_char id = 0;
387 char ifname[16];
388 unsigned int i;
389 int start = -1, end = -1;
390
391 /*
392 * Get a stable circuit id from ifname. This makes
393 * the ifindex from flapping when netdevs are created
394 * and deleted on the fly. Note that this circuit id
395 * is used in pseudo lsps so it is better to be stable.
396 * The following code works on any reasonanle ifname
397 * like: eth1 or trk-1.1 etc.
398 */
399 for (i = 0; i < strlen (ifp->name); i++)
400 {
David Lamparter52f02b42015-04-10 09:14:30 +0200401 if (isdigit((unsigned char)ifp->name[i]))
Josh Bailey3f045a02012-03-24 08:35:20 -0700402 {
403 if (start < 0)
404 {
405 start = i;
406 end = i + 1;
407 }
408 else
409 {
410 end = i + 1;
411 }
412 }
413 else if (start >= 0)
414 break;
415 }
416
417 if ((start >= 0) && (end >= start) && (end - start) < 16)
418 {
419 memset (ifname, 0, 16);
420 strncpy (ifname, &ifp->name[start], end - start);
421 id = (u_char)atoi(ifname);
422 }
423
424 /* Try to be unique. */
425 if (!id)
426 id = (u_char)((ifp->ifindex & 0xff) | 0x80);
427
428 return id;
429}
430
jardineb5d44e2003-12-23 08:09:43 +0000431void
432isis_circuit_if_add (struct isis_circuit *circuit, struct interface *ifp)
433{
paul1eb8ef22005-04-07 07:30:20 +0000434 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +0000435 struct connected *conn;
436
Josh Bailey3f045a02012-03-24 08:35:20 -0700437 circuit->circuit_id = isis_circuit_id_gen (ifp);
hassof390d2c2004-09-10 20:48:21 +0000438
Josh Bailey3f045a02012-03-24 08:35:20 -0700439 isis_circuit_if_bind (circuit, ifp);
jardineb5d44e2003-12-23 08:09:43 +0000440 /* isis_circuit_update_addrs (circuit, ifp); */
441
hassof390d2c2004-09-10 20:48:21 +0000442 if (if_is_broadcast (ifp))
443 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700444 if (circuit->circ_type_config == CIRCUIT_T_P2P)
445 circuit->circ_type = CIRCUIT_T_P2P;
hassof390d2c2004-09-10 20:48:21 +0000446 else
Josh Bailey3f045a02012-03-24 08:35:20 -0700447 circuit->circ_type = CIRCUIT_T_BROADCAST;
hassof390d2c2004-09-10 20:48:21 +0000448 }
449 else if (if_is_pointopoint (ifp))
450 {
451 circuit->circ_type = CIRCUIT_T_P2P;
452 }
Josh Bailey3f045a02012-03-24 08:35:20 -0700453 else if (if_is_loopback (ifp))
454 {
455 circuit->circ_type = CIRCUIT_T_LOOPBACK;
456 circuit->is_passive = 1;
457 }
hassof390d2c2004-09-10 20:48:21 +0000458 else
459 {
hassoc89c05d2005-09-04 21:36:36 +0000460 /* It's normal in case of loopback etc. */
461 if (isis->debugs & DEBUG_EVENTS)
Josh Bailey3f045a02012-03-24 08:35:20 -0700462 zlog_debug ("isis_circuit_if_add: unsupported media");
463 circuit->circ_type = CIRCUIT_T_UNKNOWN;
hassof390d2c2004-09-10 20:48:21 +0000464 }
465
Josh Bailey3f045a02012-03-24 08:35:20 -0700466 circuit->ip_addrs = list_new ();
467#ifdef HAVE_IPV6
468 circuit->ipv6_link = list_new ();
469 circuit->ipv6_non_link = list_new ();
470#endif /* HAVE_IPV6 */
471
paul1eb8ef22005-04-07 07:30:20 +0000472 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, conn))
473 isis_circuit_add_addr (circuit, conn);
jardineb5d44e2003-12-23 08:09:43 +0000474
475 return;
476}
477
478void
Josh Bailey3f045a02012-03-24 08:35:20 -0700479isis_circuit_if_del (struct isis_circuit *circuit, struct interface *ifp)
jardineb5d44e2003-12-23 08:09:43 +0000480{
Josh Bailey3f045a02012-03-24 08:35:20 -0700481 struct listnode *node, *nnode;
482 struct connected *conn;
hassof390d2c2004-09-10 20:48:21 +0000483
Josh Bailey3f045a02012-03-24 08:35:20 -0700484 assert (circuit->interface == ifp);
485
486 /* destroy addresses */
487 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, conn))
488 isis_circuit_del_addr (circuit, conn);
489
490 if (circuit->ip_addrs)
hassof390d2c2004-09-10 20:48:21 +0000491 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700492 assert (listcount(circuit->ip_addrs) == 0);
493 list_delete (circuit->ip_addrs);
494 circuit->ip_addrs = NULL;
hassof390d2c2004-09-10 20:48:21 +0000495 }
jardineb5d44e2003-12-23 08:09:43 +0000496
Josh Bailey3f045a02012-03-24 08:35:20 -0700497#ifdef HAVE_IPV6
498 if (circuit->ipv6_link)
hassof390d2c2004-09-10 20:48:21 +0000499 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700500 assert (listcount(circuit->ipv6_link) == 0);
501 list_delete (circuit->ipv6_link);
502 circuit->ipv6_link = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000503 }
jardineb5d44e2003-12-23 08:09:43 +0000504
Josh Bailey3f045a02012-03-24 08:35:20 -0700505 if (circuit->ipv6_non_link)
hassof390d2c2004-09-10 20:48:21 +0000506 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700507 assert (listcount(circuit->ipv6_non_link) == 0);
508 list_delete (circuit->ipv6_non_link);
509 circuit->ipv6_non_link = NULL;
hassof390d2c2004-09-10 20:48:21 +0000510 }
Josh Bailey3f045a02012-03-24 08:35:20 -0700511#endif /* HAVE_IPV6 */
512
513 circuit->circ_type = CIRCUIT_T_UNKNOWN;
514 circuit->circuit_id = 0;
jardineb5d44e2003-12-23 08:09:43 +0000515
jardineb5d44e2003-12-23 08:09:43 +0000516 return;
517}
518
519void
Josh Bailey3f045a02012-03-24 08:35:20 -0700520isis_circuit_if_bind (struct isis_circuit *circuit, struct interface *ifp)
jardineb5d44e2003-12-23 08:09:43 +0000521{
Josh Bailey3f045a02012-03-24 08:35:20 -0700522 assert (circuit != NULL);
523 assert (ifp != NULL);
524 if (circuit->interface)
525 assert (circuit->interface == ifp);
526 else
527 circuit->interface = ifp;
528 if (ifp->info)
529 assert (ifp->info == circuit);
530 else
531 ifp->info = circuit;
Olivier Dugeon4f593572016-04-19 19:03:05 +0200532 isis_link_params_update (circuit, ifp);
Josh Bailey3f045a02012-03-24 08:35:20 -0700533}
534
535void
536isis_circuit_if_unbind (struct isis_circuit *circuit, struct interface *ifp)
537{
538 assert (circuit != NULL);
539 assert (ifp != NULL);
540 assert (circuit->interface == ifp);
541 assert (ifp->info == circuit);
jardineb5d44e2003-12-23 08:09:43 +0000542 circuit->interface = NULL;
Josh Bailey3f045a02012-03-24 08:35:20 -0700543 ifp->info = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000544}
545
Josh Bailey3f045a02012-03-24 08:35:20 -0700546static void
547isis_circuit_update_all_srmflags (struct isis_circuit *circuit, int is_set)
548{
549 struct isis_area *area;
550 struct isis_lsp *lsp;
551 dnode_t *dnode, *dnode_next;
552 int level;
553
554 assert (circuit);
555 area = circuit->area;
556 assert (area);
557 for (level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++)
558 {
559 if (level & circuit->is_type)
560 {
561 if (area->lspdb[level - 1] &&
562 dict_count (area->lspdb[level - 1]) > 0)
563 {
564 for (dnode = dict_first (area->lspdb[level - 1]);
565 dnode != NULL; dnode = dnode_next)
566 {
567 dnode_next = dict_next (area->lspdb[level - 1], dnode);
568 lsp = dnode_get (dnode);
569 if (is_set)
570 {
571 ISIS_SET_FLAG (lsp->SRMflags, circuit);
572 }
573 else
574 {
575 ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
576 }
577 }
578 }
579 }
580 }
581}
582
Christian Frankef1fc1db2015-11-10 18:43:31 +0100583size_t
584isis_circuit_pdu_size(struct isis_circuit *circuit)
585{
586 return ISO_MTU(circuit);
587}
588
589void
590isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream)
591{
592 size_t stream_size = isis_circuit_pdu_size(circuit);
593
594 if (!*stream)
595 {
596 *stream = stream_new(stream_size);
597 }
598 else
599 {
600 if (STREAM_SIZE(*stream) != stream_size)
601 stream_resize(*stream, stream_size);
602 stream_reset(*stream);
603 }
604}
605
Josh Bailey3f045a02012-03-24 08:35:20 -0700606int
jardineb5d44e2003-12-23 08:09:43 +0000607isis_circuit_up (struct isis_circuit *circuit)
608{
Josh Bailey3f045a02012-03-24 08:35:20 -0700609 int retv;
610
611 /* Set the flags for all the lsps of the circuit. */
612 isis_circuit_update_all_srmflags (circuit, 1);
613
614 if (circuit->state == C_STATE_UP)
615 return ISIS_OK;
616
617 if (circuit->is_passive)
618 return ISIS_OK;
jardineb5d44e2003-12-23 08:09:43 +0000619
Christian Frankef1fc1db2015-11-10 18:43:31 +0100620 if (circuit->area->lsp_mtu > isis_circuit_pdu_size(circuit))
621 {
622 zlog_err("Interface MTU %zu on %s is too low to support area lsp mtu %u!",
623 isis_circuit_pdu_size(circuit), circuit->interface->name,
624 circuit->area->lsp_mtu);
Christian Franke8ed8d0b2016-04-03 12:46:26 -0300625 isis_circuit_update_all_srmflags(circuit, 0);
Christian Frankef1fc1db2015-11-10 18:43:31 +0100626 return ISIS_ERROR;
627 }
628
hassof390d2c2004-09-10 20:48:21 +0000629 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
630 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700631 /*
632 * Get the Hardware Address
633 */
Josh Bailey3f045a02012-03-24 08:35:20 -0700634 if (circuit->interface->hw_addr_len != ETH_ALEN)
635 {
636 zlog_warn ("unsupported link layer");
637 }
638 else
639 {
640 memcpy (circuit->u.bc.snpa, circuit->interface->hw_addr, ETH_ALEN);
641 }
642#ifdef EXTREME_DEGUG
643 zlog_debug ("isis_circuit_if_add: if_id %d, isomtu %d snpa %s",
644 circuit->interface->ifindex, ISO_MTU (circuit),
645 snpa_print (circuit->u.bc.snpa));
646#endif /* EXTREME_DEBUG */
Josh Bailey3f045a02012-03-24 08:35:20 -0700647
648 circuit->u.bc.adjdb[0] = list_new ();
649 circuit->u.bc.adjdb[1] = list_new ();
650
hassof390d2c2004-09-10 20:48:21 +0000651 /*
652 * ISO 10589 - 8.4.1 Enabling of broadcast circuits
653 */
jardineb5d44e2003-12-23 08:09:43 +0000654
hassof390d2c2004-09-10 20:48:21 +0000655 /* initilizing the hello sending threads
656 * for a broadcast IF
657 */
jardineb5d44e2003-12-23 08:09:43 +0000658
hassof390d2c2004-09-10 20:48:21 +0000659 /* 8.4.1 a) commence sending of IIH PDUs */
660
Josh Bailey3f045a02012-03-24 08:35:20 -0700661 if (circuit->is_type & IS_LEVEL_1)
662 {
663 thread_add_event (master, send_lan_l1_hello, circuit, 0);
664 circuit->u.bc.lan_neighs[0] = list_new ();
665 }
hassof390d2c2004-09-10 20:48:21 +0000666
Josh Bailey3f045a02012-03-24 08:35:20 -0700667 if (circuit->is_type & IS_LEVEL_2)
668 {
669 thread_add_event (master, send_lan_l2_hello, circuit, 0);
670 circuit->u.bc.lan_neighs[1] = list_new ();
671 }
hassof390d2c2004-09-10 20:48:21 +0000672
673 /* 8.4.1 b) FIXME: solicit ES - 8.4.6 */
674 /* 8.4.1 c) FIXME: listen for ESH PDUs */
675
676 /* 8.4.1 d) */
677 /* dr election will commence in... */
Josh Bailey3f045a02012-03-24 08:35:20 -0700678 if (circuit->is_type & IS_LEVEL_1)
679 THREAD_TIMER_ON (master, circuit->u.bc.t_run_dr[0], isis_run_dr_l1,
680 circuit, 2 * circuit->hello_interval[0]);
681 if (circuit->is_type & IS_LEVEL_2)
682 THREAD_TIMER_ON (master, circuit->u.bc.t_run_dr[1], isis_run_dr_l2,
683 circuit, 2 * circuit->hello_interval[1]);
jardineb5d44e2003-12-23 08:09:43 +0000684 }
hassof390d2c2004-09-10 20:48:21 +0000685 else
686 {
687 /* initializing the hello send threads
688 * for a ptp IF
689 */
Josh Bailey3f045a02012-03-24 08:35:20 -0700690 circuit->u.p2p.neighbor = NULL;
hassof390d2c2004-09-10 20:48:21 +0000691 thread_add_event (master, send_p2p_hello, circuit, 0);
jardineb5d44e2003-12-23 08:09:43 +0000692 }
693
jardineb5d44e2003-12-23 08:09:43 +0000694 /* initializing PSNP timers */
Josh Bailey3f045a02012-03-24 08:35:20 -0700695 if (circuit->is_type & IS_LEVEL_1)
696 THREAD_TIMER_ON (master, circuit->t_send_psnp[0], send_l1_psnp, circuit,
697 isis_jitter (circuit->psnp_interval[0], PSNP_JITTER));
698
699 if (circuit->is_type & IS_LEVEL_2)
700 THREAD_TIMER_ON (master, circuit->t_send_psnp[1], send_l2_psnp, circuit,
701 isis_jitter (circuit->psnp_interval[1], PSNP_JITTER));
702
703 /* unified init for circuits; ignore warnings below this level */
704 retv = isis_sock_init (circuit);
705 if (retv != ISIS_OK)
hassof390d2c2004-09-10 20:48:21 +0000706 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700707 isis_circuit_down (circuit);
708 return retv;
hassof390d2c2004-09-10 20:48:21 +0000709 }
710
Josh Bailey3f045a02012-03-24 08:35:20 -0700711 /* initialize the circuit streams after opening connection */
Christian Frankef1fc1db2015-11-10 18:43:31 +0100712 isis_circuit_stream(circuit, &circuit->rcv_stream);
713 isis_circuit_stream(circuit, &circuit->snd_stream);
jardineb5d44e2003-12-23 08:09:43 +0000714
jardineb5d44e2003-12-23 08:09:43 +0000715#ifdef GNU_LINUX
hassof390d2c2004-09-10 20:48:21 +0000716 THREAD_READ_ON (master, circuit->t_read, isis_receive, circuit,
Josh Bailey3f045a02012-03-24 08:35:20 -0700717 circuit->fd);
jardineb5d44e2003-12-23 08:09:43 +0000718#else
hassof390d2c2004-09-10 20:48:21 +0000719 THREAD_TIMER_ON (master, circuit->t_read, isis_receive, circuit,
Josh Bailey3f045a02012-03-24 08:35:20 -0700720 circuit->fd);
jardineb5d44e2003-12-23 08:09:43 +0000721#endif
Josh Bailey3f045a02012-03-24 08:35:20 -0700722
723 circuit->lsp_queue = list_new ();
724 circuit->lsp_queue_last_cleared = time (NULL);
725
726 return ISIS_OK;
jardineb5d44e2003-12-23 08:09:43 +0000727}
728
729void
730isis_circuit_down (struct isis_circuit *circuit)
731{
Josh Bailey3f045a02012-03-24 08:35:20 -0700732 if (circuit->state != C_STATE_UP)
733 return;
734
735 /* Clear the flags for all the lsps of the circuit. */
736 isis_circuit_update_all_srmflags (circuit, 0);
737
hassof390d2c2004-09-10 20:48:21 +0000738 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
739 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700740 /* destroy neighbour lists */
741 if (circuit->u.bc.lan_neighs[0])
742 {
743 list_delete (circuit->u.bc.lan_neighs[0]);
744 circuit->u.bc.lan_neighs[0] = NULL;
745 }
746 if (circuit->u.bc.lan_neighs[1])
747 {
748 list_delete (circuit->u.bc.lan_neighs[1]);
749 circuit->u.bc.lan_neighs[1] = NULL;
750 }
751 /* destroy adjacency databases */
752 if (circuit->u.bc.adjdb[0])
753 {
754 circuit->u.bc.adjdb[0]->del = isis_delete_adj;
755 list_delete (circuit->u.bc.adjdb[0]);
756 circuit->u.bc.adjdb[0] = NULL;
757 }
758 if (circuit->u.bc.adjdb[1])
759 {
760 circuit->u.bc.adjdb[1]->del = isis_delete_adj;
761 list_delete (circuit->u.bc.adjdb[1]);
762 circuit->u.bc.adjdb[1] = NULL;
763 }
764 if (circuit->u.bc.is_dr[0])
765 {
766 isis_dr_resign (circuit, 1);
767 circuit->u.bc.is_dr[0] = 0;
768 }
769 memset (circuit->u.bc.l1_desig_is, 0, ISIS_SYS_ID_LEN + 1);
770 if (circuit->u.bc.is_dr[1])
771 {
772 isis_dr_resign (circuit, 2);
773 circuit->u.bc.is_dr[1] = 0;
774 }
775 memset (circuit->u.bc.l2_desig_is, 0, ISIS_SYS_ID_LEN + 1);
776 memset (circuit->u.bc.snpa, 0, ETH_ALEN);
777
hassof390d2c2004-09-10 20:48:21 +0000778 THREAD_TIMER_OFF (circuit->u.bc.t_send_lan_hello[0]);
779 THREAD_TIMER_OFF (circuit->u.bc.t_send_lan_hello[1]);
hassof891f442004-09-14 13:54:30 +0000780 THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[0]);
781 THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[1]);
Josh Bailey3f045a02012-03-24 08:35:20 -0700782 THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[0]);
783 THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[1]);
Christian Franke61010c32015-11-10 18:43:34 +0100784 circuit->lsp_regenerate_pending[0] = 0;
785 circuit->lsp_regenerate_pending[1] = 0;
hassof390d2c2004-09-10 20:48:21 +0000786 }
787 else if (circuit->circ_type == CIRCUIT_T_P2P)
788 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700789 isis_delete_adj (circuit->u.p2p.neighbor);
790 circuit->u.p2p.neighbor = NULL;
hassof390d2c2004-09-10 20:48:21 +0000791 THREAD_TIMER_OFF (circuit->u.p2p.t_send_p2p_hello);
792 }
Josh Bailey3f045a02012-03-24 08:35:20 -0700793
794 /* Cancel all active threads */
795 THREAD_TIMER_OFF (circuit->t_send_csnp[0]);
796 THREAD_TIMER_OFF (circuit->t_send_csnp[1]);
797 THREAD_TIMER_OFF (circuit->t_send_psnp[0]);
798 THREAD_TIMER_OFF (circuit->t_send_psnp[1]);
799 THREAD_OFF (circuit->t_read);
800
801 if (circuit->lsp_queue)
802 {
803 circuit->lsp_queue->del = NULL;
804 list_delete (circuit->lsp_queue);
805 circuit->lsp_queue = NULL;
806 }
807
808 /* send one gratuitous hello to spead up convergence */
809 if (circuit->is_type & IS_LEVEL_1)
810 send_hello (circuit, IS_LEVEL_1);
811 if (circuit->is_type & IS_LEVEL_2)
812 send_hello (circuit, IS_LEVEL_2);
813
814 circuit->upadjcount[0] = 0;
815 circuit->upadjcount[1] = 0;
816
jardineb5d44e2003-12-23 08:09:43 +0000817 /* close the socket */
Josh Bailey3f045a02012-03-24 08:35:20 -0700818 if (circuit->fd)
819 {
820 close (circuit->fd);
821 circuit->fd = 0;
822 }
823
824 if (circuit->rcv_stream != NULL)
825 {
826 stream_free (circuit->rcv_stream);
827 circuit->rcv_stream = NULL;
828 }
829
830 if (circuit->snd_stream != NULL)
831 {
832 stream_free (circuit->snd_stream);
833 circuit->snd_stream = NULL;
834 }
835
836 thread_cancel_event (master, circuit);
jardineb5d44e2003-12-23 08:09:43 +0000837
838 return;
839}
840
841void
842circuit_update_nlpids (struct isis_circuit *circuit)
843{
844 circuit->nlpids.count = 0;
hassof390d2c2004-09-10 20:48:21 +0000845
846 if (circuit->ip_router)
847 {
848 circuit->nlpids.nlpids[0] = NLPID_IP;
849 circuit->nlpids.count++;
850 }
jardineb5d44e2003-12-23 08:09:43 +0000851#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000852 if (circuit->ipv6_router)
853 {
854 circuit->nlpids.nlpids[circuit->nlpids.count] = NLPID_IPV6;
855 circuit->nlpids.count++;
856 }
jardineb5d44e2003-12-23 08:09:43 +0000857#endif /* HAVE_IPV6 */
858 return;
859}
860
Josh Bailey3f045a02012-03-24 08:35:20 -0700861void
862isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty,
863 char detail)
864{
865 if (detail == ISIS_UI_LEVEL_BRIEF)
866 {
867 vty_out (vty, " %-12s", circuit->interface->name);
868 vty_out (vty, "0x%-7x", circuit->circuit_id);
869 vty_out (vty, "%-9s", circuit_state2string (circuit->state));
870 vty_out (vty, "%-9s", circuit_type2string (circuit->circ_type));
871 vty_out (vty, "%-9s", circuit_t2string (circuit->is_type));
872 vty_out (vty, "%s", VTY_NEWLINE);
873 }
874
875 if (detail == ISIS_UI_LEVEL_DETAIL)
876 {
Christian Frankecb32a192015-11-10 18:33:13 +0100877 struct listnode *node;
878 struct prefix *ip_addr;
879 u_char buf[BUFSIZ];
880
Josh Bailey3f045a02012-03-24 08:35:20 -0700881 vty_out (vty, " Interface: %s", circuit->interface->name);
882 vty_out (vty, ", State: %s", circuit_state2string (circuit->state));
883 if (circuit->is_passive)
884 vty_out (vty, ", Passive");
885 else
886 vty_out (vty, ", Active");
887 vty_out (vty, ", Circuit Id: 0x%x", circuit->circuit_id);
888 vty_out (vty, "%s", VTY_NEWLINE);
889 vty_out (vty, " Type: %s", circuit_type2string (circuit->circ_type));
890 vty_out (vty, ", Level: %s", circuit_t2string (circuit->is_type));
891 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
892 vty_out (vty, ", SNPA: %-10s", snpa_print (circuit->u.bc.snpa));
893 vty_out (vty, "%s", VTY_NEWLINE);
894 if (circuit->is_type & IS_LEVEL_1)
895 {
896 vty_out (vty, " Level-1 Information:%s", VTY_NEWLINE);
897 if (circuit->area->newmetric)
898 vty_out (vty, " Metric: %d", circuit->te_metric[0]);
899 else
900 vty_out (vty, " Metric: %d",
David Lamparterf2634132016-07-28 17:23:32 +0200901 circuit->metric[0]);
Josh Bailey3f045a02012-03-24 08:35:20 -0700902 if (!circuit->is_passive)
903 {
904 vty_out (vty, ", Active neighbors: %u%s",
905 circuit->upadjcount[0], VTY_NEWLINE);
906 vty_out (vty, " Hello interval: %u, "
907 "Holddown count: %u %s%s",
908 circuit->hello_interval[0],
909 circuit->hello_multiplier[0],
910 (circuit->pad_hellos ? "(pad)" : "(no-pad)"),
911 VTY_NEWLINE);
912 vty_out (vty, " CNSP interval: %u, "
913 "PSNP interval: %u%s",
914 circuit->csnp_interval[0],
915 circuit->psnp_interval[0], VTY_NEWLINE);
916 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
917 vty_out (vty, " LAN Priority: %u, %s%s",
918 circuit->priority[0],
919 (circuit->u.bc.is_dr[0] ? \
920 "is DIS" : "is not DIS"), VTY_NEWLINE);
921 }
922 else
923 {
924 vty_out (vty, "%s", VTY_NEWLINE);
925 }
926 }
927 if (circuit->is_type & IS_LEVEL_2)
928 {
929 vty_out (vty, " Level-2 Information:%s", VTY_NEWLINE);
930 if (circuit->area->newmetric)
931 vty_out (vty, " Metric: %d", circuit->te_metric[1]);
932 else
933 vty_out (vty, " Metric: %d",
David Lamparterf2634132016-07-28 17:23:32 +0200934 circuit->metric[1]);
Josh Bailey3f045a02012-03-24 08:35:20 -0700935 if (!circuit->is_passive)
936 {
937 vty_out (vty, ", Active neighbors: %u%s",
938 circuit->upadjcount[1], VTY_NEWLINE);
939 vty_out (vty, " Hello interval: %u, "
940 "Holddown count: %u %s%s",
941 circuit->hello_interval[1],
942 circuit->hello_multiplier[1],
943 (circuit->pad_hellos ? "(pad)" : "(no-pad)"),
944 VTY_NEWLINE);
945 vty_out (vty, " CNSP interval: %u, "
946 "PSNP interval: %u%s",
947 circuit->csnp_interval[1],
948 circuit->psnp_interval[1], VTY_NEWLINE);
949 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
950 vty_out (vty, " LAN Priority: %u, %s%s",
951 circuit->priority[1],
952 (circuit->u.bc.is_dr[1] ? \
953 "is DIS" : "is not DIS"), VTY_NEWLINE);
954 }
955 else
956 {
957 vty_out (vty, "%s", VTY_NEWLINE);
958 }
959 }
960 if (circuit->ip_addrs && listcount (circuit->ip_addrs) > 0)
961 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700962 vty_out (vty, " IP Prefix(es):%s", VTY_NEWLINE);
963 for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, node, ip_addr))
964 {
965 prefix2str (ip_addr, (char*)buf, BUFSIZ),
966 vty_out (vty, " %s%s", buf, VTY_NEWLINE);
967 }
968 }
Christian Frankecb32a192015-11-10 18:33:13 +0100969 if (circuit->ipv6_link && listcount(circuit->ipv6_link) > 0)
970 {
971 vty_out(vty, " IPv6 Link-Locals:%s", VTY_NEWLINE);
972 for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_link, node, ip_addr))
973 {
974 prefix2str(ip_addr, (char*)buf, BUFSIZ),
975 vty_out(vty, " %s%s", buf, VTY_NEWLINE);
976 }
977 }
Christian Franke985823f2016-06-14 20:07:05 +0200978 if (circuit->ipv6_non_link && listcount(circuit->ipv6_non_link) > 0)
Christian Frankecb32a192015-11-10 18:33:13 +0100979 {
980 vty_out(vty, " IPv6 Prefixes:%s", VTY_NEWLINE);
981 for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, node, ip_addr))
982 {
983 prefix2str(ip_addr, (char*)buf, BUFSIZ),
984 vty_out(vty, " %s%s", buf, VTY_NEWLINE);
985 }
986 }
987
Josh Bailey3f045a02012-03-24 08:35:20 -0700988 vty_out (vty, "%s", VTY_NEWLINE);
989 }
990 return;
991}
992
jardineb5d44e2003-12-23 08:09:43 +0000993int
hassof390d2c2004-09-10 20:48:21 +0000994isis_interface_config_write (struct vty *vty)
jardineb5d44e2003-12-23 08:09:43 +0000995{
jardineb5d44e2003-12-23 08:09:43 +0000996 int write = 0;
hasso3fdb2dd2005-09-28 18:45:54 +0000997 struct listnode *node, *node2;
jardineb5d44e2003-12-23 08:09:43 +0000998 struct interface *ifp;
999 struct isis_area *area;
Josh Bailey3f045a02012-03-24 08:35:20 -07001000 struct isis_circuit *circuit;
jardineb5d44e2003-12-23 08:09:43 +00001001 int i;
jardineb5d44e2003-12-23 08:09:43 +00001002
hasso3fdb2dd2005-09-28 18:45:54 +00001003 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
jardineb5d44e2003-12-23 08:09:43 +00001004 {
Josh Bailey3f045a02012-03-24 08:35:20 -07001005 /* IF name */
1006 vty_out (vty, "interface %s%s", ifp->name, VTY_NEWLINE);
1007 write++;
1008 /* IF desc */
1009 if (ifp->desc)
1010 {
1011 vty_out (vty, " description %s%s", ifp->desc, VTY_NEWLINE);
1012 write++;
1013 }
1014 /* ISIS Circuit */
1015 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node2, area))
1016 {
1017 circuit = circuit_lookup_by_ifp (ifp, area->circuit_list);
1018 if (circuit == NULL)
1019 continue;
1020 if (circuit->ip_router)
1021 {
1022 vty_out (vty, " ip router isis %s%s", area->area_tag,
1023 VTY_NEWLINE);
1024 write++;
1025 }
1026 if (circuit->is_passive)
1027 {
1028 vty_out (vty, " isis passive%s", VTY_NEWLINE);
1029 write++;
1030 }
1031 if (circuit->circ_type_config == CIRCUIT_T_P2P)
1032 {
1033 vty_out (vty, " isis network point-to-point%s", VTY_NEWLINE);
1034 write++;
1035 }
jardineb5d44e2003-12-23 08:09:43 +00001036#ifdef HAVE_IPV6
Josh Bailey3f045a02012-03-24 08:35:20 -07001037 if (circuit->ipv6_router)
1038 {
1039 vty_out (vty, " ipv6 router isis %s%s", area->area_tag,
1040 VTY_NEWLINE);
1041 write++;
1042 }
jardineb5d44e2003-12-23 08:09:43 +00001043#endif /* HAVE_IPV6 */
jardineb5d44e2003-12-23 08:09:43 +00001044
Josh Bailey3f045a02012-03-24 08:35:20 -07001045 /* 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 }
jardineb5d44e2003-12-23 08:09:43 +00001060
Josh Bailey3f045a02012-03-24 08:35:20 -07001061 /* 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 }
jardineb5d44e2003-12-23 08:09:43 +00001083
Josh Bailey3f045a02012-03-24 08:35:20 -07001084 /* 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 }
jardineb5d44e2003-12-23 08:09:43 +00001106
Josh Bailey3f045a02012-03-24 08:35:20 -07001107 /* 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 }
jardineb5d44e2003-12-23 08:09:43 +00001113
Josh Bailey3f045a02012-03-24 08:35:20 -07001114 /* 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 }
jardineb5d44e2003-12-23 08:09:43 +00001136
Josh Bailey3f045a02012-03-24 08:35:20 -07001137 /* 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);
jardineb5d44e2003-12-23 08:09:43 +00001220 }
hassof390d2c2004-09-10 20:48:21 +00001221
jardineb5d44e2003-12-23 08:09:43 +00001222 return write;
1223}
jardineb5d44e2003-12-23 08:09:43 +00001224
David Lamparter3732cba2016-07-29 16:19:40 +02001225struct isis_circuit *
1226isis_circuit_create (struct isis_area *area, struct interface *ifp)
jardineb5d44e2003-12-23 08:09:43 +00001227{
David Lamparter515812d2016-08-11 16:59:08 +02001228 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);
Christian Frankeaf177b22016-08-15 13:36:59 +02001232 if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP)
1233 return circuit;
David Lamparter3732cba2016-07-29 16:19:40 +02001234 isis_circuit_if_bind (circuit, ifp);
1235 return circuit;
jardineb5d44e2003-12-23 08:09:43 +00001236}
1237
David Lamparter3732cba2016-07-29 16:19:40 +02001238void
1239isis_circuit_af_set (struct isis_circuit *circuit, bool ip_router, bool ipv6_router)
jardineb5d44e2003-12-23 08:09:43 +00001240{
David Lamparter3732cba2016-07-29 16:19:40 +02001241 struct isis_area *area = circuit->area;
1242 bool change = circuit->ip_router != ip_router || circuit->ipv6_router != ipv6_router;
David Lamparter5a1a0872016-08-11 17:02:50 +02001243 bool was_enabled = !!circuit->area;
jardineb5d44e2003-12-23 08:09:43 +00001244
David Lamparter3732cba2016-07-29 16:19:40 +02001245 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;
hassof390d2c2004-09-10 20:48:21 +00001249
David Lamparter3732cba2016-07-29 16:19:40 +02001250 if (!change)
1251 return;
Josh Bailey3f045a02012-03-24 08:35:20 -07001252
David Lamparter3732cba2016-07-29 16:19:40 +02001253 circuit_update_nlpids (circuit);
Josh Bailey3f045a02012-03-24 08:35:20 -07001254
David Lamparter3732cba2016-07-29 16:19:40 +02001255 if (!ip_router && !ipv6_router)
jardineb5d44e2003-12-23 08:09:43 +00001256 isis_csm_state_change (ISIS_DISABLE, circuit, area);
David Lamparter3732cba2016-07-29 16:19:40 +02001257 else if (!was_enabled)
1258 isis_csm_state_change (ISIS_ENABLE, circuit, area);
Christian Franke84a4da02016-04-03 12:46:27 -03001259 else
Christian Franke84a4da02016-04-03 12:46:27 -03001260 lsp_regenerate_schedule(circuit->area, circuit->is_type, 0);
Josh Bailey3f045a02012-03-24 08:35:20 -07001261}
1262
David Lamparter3732cba2016-07-29 16:19:40 +02001263int
1264isis_circuit_passive_set (struct isis_circuit *circuit, bool passive)
Josh Bailey3f045a02012-03-24 08:35:20 -07001265{
David Lamparter3732cba2016-07-29 16:19:40 +02001266 if (circuit->is_passive == passive)
1267 return 0;
Josh Bailey3f045a02012-03-24 08:35:20 -07001268
David Lamparter3732cba2016-07-29 16:19:40 +02001269 if (if_is_loopback (circuit->interface) && !passive)
1270 return -1;
Josh Bailey3f045a02012-03-24 08:35:20 -07001271
1272 if (circuit->state != C_STATE_UP)
1273 {
David Lamparter3732cba2016-07-29 16:19:40 +02001274 circuit->is_passive = passive;
Josh Bailey3f045a02012-03-24 08:35:20 -07001275 }
1276 else
1277 {
1278 struct isis_area *area = circuit->area;
1279 isis_csm_state_change (ISIS_DISABLE, circuit, area);
David Lamparter3732cba2016-07-29 16:19:40 +02001280 circuit->is_passive = passive;
Josh Bailey3f045a02012-03-24 08:35:20 -07001281 isis_csm_state_change (ISIS_ENABLE, circuit, area);
1282 }
1283
David Lamparter3732cba2016-07-29 16:19:40 +02001284 return 0;
Josh Bailey3f045a02012-03-24 08:35:20 -07001285}
1286
David Lamparter3732cba2016-07-29 16:19:40 +02001287int
1288isis_circuit_metric_set (struct isis_circuit *circuit, int level, int metric)
jardineb5d44e2003-12-23 08:09:43 +00001289{
David Lamparter3732cba2016-07-29 16:19:40 +02001290 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;
hassof390d2c2004-09-10 20:48:21 +00001296
David Lamparter3732cba2016-07-29 16:19:40 +02001297 circuit->te_metric[level - 1] = metric;
David Lamparterf2634132016-07-28 17:23:32 +02001298 circuit->metric[level - 1] = metric;
hassof390d2c2004-09-10 20:48:21 +00001299
David Lamparter3732cba2016-07-29 16:19:40 +02001300 if (circuit->area)
1301 lsp_regenerate_schedule (circuit->area, level, 0);
1302 return 0;
jardineb5d44e2003-12-23 08:09:43 +00001303}
1304
Christian Frankef5fbfb22016-07-28 17:23:27 +02001305int
1306isis_circuit_passwd_unset (struct isis_circuit *circuit)
jardineb5d44e2003-12-23 08:09:43 +00001307{
Christian Frankef5fbfb22016-07-28 17:23:27 +02001308 memset(&circuit->passwd, 0, sizeof(circuit->passwd));
1309 return 0;
Josh Bailey3f045a02012-03-24 08:35:20 -07001310}
1311
Christian Frankef5fbfb22016-07-28 17:23:27 +02001312static int
1313isis_circuit_passwd_set (struct isis_circuit *circuit, u_char passwd_type, const char *passwd)
Josh Bailey3f045a02012-03-24 08:35:20 -07001314{
1315 int len;
Josh Bailey3f045a02012-03-24 08:35:20 -07001316
Christian Frankef5fbfb22016-07-28 17:23:27 +02001317 if (!passwd)
1318 return -1;
1319
1320 len = strlen(passwd);
Josh Bailey3f045a02012-03-24 08:35:20 -07001321 if (len > 254)
Christian Frankef5fbfb22016-07-28 17:23:27 +02001322 return -1;
hassof390d2c2004-09-10 20:48:21 +00001323
Christian Frankef5fbfb22016-07-28 17:23:27 +02001324 circuit->passwd.len = len;
1325 strncpy((char *)circuit->passwd.passwd, passwd, 255);
1326 circuit->passwd.type = passwd_type;
1327 return 0;
jardineb5d44e2003-12-23 08:09:43 +00001328}
1329
Christian Frankef5fbfb22016-07-28 17:23:27 +02001330int
1331isis_circuit_passwd_cleartext_set (struct isis_circuit *circuit, const char *passwd)
jardineb5d44e2003-12-23 08:09:43 +00001332{
Christian Frankef5fbfb22016-07-28 17:23:27 +02001333 return isis_circuit_passwd_set (circuit, ISIS_PASSWD_TYPE_CLEARTXT, passwd);
1334}
hassof390d2c2004-09-10 20:48:21 +00001335
Christian Frankef5fbfb22016-07-28 17:23:27 +02001336int
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);
jardineb5d44e2003-12-23 08:09:43 +00001340}
Josh Bailey3f045a02012-03-24 08:35:20 -07001341struct cmd_node interface_node = {
jardineb5d44e2003-12-23 08:09:43 +00001342 INTERFACE_NODE,
1343 "%s(config-if)# ",
1344 1,
1345};
1346
David Lamparter3732cba2016-07-29 16:19:40 +02001347int
1348isis_circuit_circ_type_set(struct isis_circuit *circuit, int circ_type)
Josh Bailey3f045a02012-03-24 08:35:20 -07001349{
David Lamparter3732cba2016-07-29 16:19:40 +02001350 /* 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
David Lamparter3732cba2016-07-29 16:19:40 +02001354 || circuit->circ_type == CIRCUIT_T_LOOPBACK)
1355 {
1356 if (circuit->circ_type != circ_type)
1357 return -1;
1358 else
1359 return 0;
1360 }
Josh Bailey3f045a02012-03-24 08:35:20 -07001361
David Lamparter3732cba2016-07-29 16:19:40 +02001362 if (circuit->circ_type == circ_type)
1363 return 0;
Josh Bailey3f045a02012-03-24 08:35:20 -07001364
1365 if (circuit->state != C_STATE_UP)
1366 {
David Lamparter3732cba2016-07-29 16:19:40 +02001367 circuit->circ_type = circ_type;
1368 circuit->circ_type_config = circ_type;
Josh Bailey3f045a02012-03-24 08:35:20 -07001369 }
1370 else
1371 {
1372 struct isis_area *area = circuit->area;
David Lamparter3732cba2016-07-29 16:19:40 +02001373 if (circ_type == CIRCUIT_T_BROADCAST
1374 && !if_is_broadcast(circuit->interface))
1375 return -1;
Josh Bailey3f045a02012-03-24 08:35:20 -07001376
David Lamparter3732cba2016-07-29 16:19:40 +02001377 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);
Josh Bailey3f045a02012-03-24 08:35:20 -07001381 }
David Lamparter3732cba2016-07-29 16:19:40 +02001382 return 0;
Josh Bailey3f045a02012-03-24 08:35:20 -07001383}
1384
jardineb5d44e2003-12-23 08:09:43 +00001385int
1386isis_if_new_hook (struct interface *ifp)
1387{
jardineb5d44e2003-12-23 08:09:43 +00001388 return 0;
1389}
1390
1391int
1392isis_if_delete_hook (struct interface *ifp)
1393{
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001394 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
jardineb5d44e2003-12-23 08:09:43 +00001403 return 0;
1404}
1405
jardineb5d44e2003-12-23 08:09:43 +00001406void
1407isis_circuit_init ()
1408{
jardineb5d44e2003-12-23 08:09:43 +00001409 /* Initialize Zebra interface data structure */
jardineb5d44e2003-12-23 08:09:43 +00001410 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);
1415 install_element (CONFIG_NODE, &interface_cmd);
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001416 install_element (CONFIG_NODE, &no_interface_cmd);
jardineb5d44e2003-12-23 08:09:43 +00001417
1418 install_default (INTERFACE_NODE);
1419 install_element (INTERFACE_NODE, &interface_desc_cmd);
1420 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
1421
David Lamparter3732cba2016-07-29 16:19:40 +02001422 isis_vty_init ();
jardineb5d44e2003-12-23 08:09:43 +00001423}