blob: 04c515506a816b522335e0f7bf0e353e32dfc23d [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;
96 circuit->metrics[i].metric_default = DEFAULT_CIRCUIT_METRIC;
97 circuit->metrics[i].metric_expense = METRICS_UNSUPPORTED;
98 circuit->metrics[i].metric_error = METRICS_UNSUPPORTED;
99 circuit->metrics[i].metric_delay = METRICS_UNSUPPORTED;
100 circuit->te_metric[i] = DEFAULT_CIRCUIT_METRIC;
101 }
102
Olivier Dugeon4f593572016-04-19 19:03:05 +0200103 circuit->mtc = mpls_te_circuit_new();
104
jardineb5d44e2003-12-23 08:09:43 +0000105 return circuit;
106}
107
jardineb5d44e2003-12-23 08:09:43 +0000108void
Josh Bailey3f045a02012-03-24 08:35:20 -0700109isis_circuit_del (struct isis_circuit *circuit)
110{
111 if (!circuit)
112 return;
113
114 isis_circuit_if_unbind (circuit, circuit->interface);
115
116 /* and lastly the circuit itself */
117 XFREE (MTYPE_ISIS_CIRCUIT, circuit);
118
119 return;
120}
121
122void
jardineb5d44e2003-12-23 08:09:43 +0000123isis_circuit_configure (struct isis_circuit *circuit, struct isis_area *area)
124{
Josh Bailey3f045a02012-03-24 08:35:20 -0700125 assert (area);
jardineb5d44e2003-12-23 08:09:43 +0000126 circuit->area = area;
Josh Bailey3f045a02012-03-24 08:35:20 -0700127
jardineb5d44e2003-12-23 08:09:43 +0000128 /*
Christian Franke7324ae12015-11-10 18:04:48 +0100129 * Whenever the is-type of an area is changed, the is-type of each circuit
130 * in that area is updated to a non-empty subset of the area is-type.
131 * Inversely, when configuring a new circuit, this property should be
132 * ensured as well.
jardineb5d44e2003-12-23 08:09:43 +0000133 */
Christian Franke7324ae12015-11-10 18:04:48 +0100134 if (area->is_type != IS_LEVEL_1_AND_2)
135 circuit->is_type = area->is_type;
jardineb5d44e2003-12-23 08:09:43 +0000136
137 /*
138 * Add the circuit into area
139 */
140 listnode_add (area->circuit_list, circuit);
141
142 circuit->idx = flags_get_index (&area->flags);
jardineb5d44e2003-12-23 08:09:43 +0000143
144 return;
145}
146
hassof390d2c2004-09-10 20:48:21 +0000147void
Josh Bailey3f045a02012-03-24 08:35:20 -0700148isis_circuit_deconfigure (struct isis_circuit *circuit, struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +0000149{
jardineb5d44e2003-12-23 08:09:43 +0000150 /* Free the index of SRM and SSN flags */
151 flags_free_index (&area->flags, circuit->idx);
Josh Bailey3f045a02012-03-24 08:35:20 -0700152 circuit->idx = 0;
153 /* Remove circuit from area */
154 assert (circuit->area == area);
155 listnode_delete (area->circuit_list, circuit);
156 circuit->area = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000157
158 return;
159}
160
161struct isis_circuit *
162circuit_lookup_by_ifp (struct interface *ifp, struct list *list)
163{
164 struct isis_circuit *circuit = NULL;
165 struct listnode *node;
hassof390d2c2004-09-10 20:48:21 +0000166
jardineb5d44e2003-12-23 08:09:43 +0000167 if (!list)
168 return NULL;
hassof390d2c2004-09-10 20:48:21 +0000169
paul1eb8ef22005-04-07 07:30:20 +0000170 for (ALL_LIST_ELEMENTS_RO (list, node, circuit))
171 if (circuit->interface == ifp)
Josh Bailey3f045a02012-03-24 08:35:20 -0700172 {
173 assert (ifp->info == circuit);
174 return circuit;
175 }
176
jardineb5d44e2003-12-23 08:09:43 +0000177 return NULL;
178}
179
180struct isis_circuit *
181circuit_scan_by_ifp (struct interface *ifp)
182{
183 struct isis_area *area;
184 struct listnode *node;
185 struct isis_circuit *circuit;
186
Josh Bailey3f045a02012-03-24 08:35:20 -0700187 if (ifp->info)
188 return (struct isis_circuit *)ifp->info;
jardineb5d44e2003-12-23 08:09:43 +0000189
Josh Bailey3f045a02012-03-24 08:35:20 -0700190 if (isis->area_list)
hassof390d2c2004-09-10 20:48:21 +0000191 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700192 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
193 {
194 circuit = circuit_lookup_by_ifp (ifp, area->circuit_list);
195 if (circuit)
196 return circuit;
197 }
hassof390d2c2004-09-10 20:48:21 +0000198 }
jardineb5d44e2003-12-23 08:09:43 +0000199 return circuit_lookup_by_ifp (ifp, isis->init_circ_list);
200}
201
jardineb5d44e2003-12-23 08:09:43 +0000202void
hassof891f442004-09-14 13:54:30 +0000203isis_circuit_add_addr (struct isis_circuit *circuit,
204 struct connected *connected)
jardineb5d44e2003-12-23 08:09:43 +0000205{
Josh Bailey3f045a02012-03-24 08:35:20 -0700206 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +0000207 struct prefix_ipv4 *ipv4;
hassof390d2c2004-09-10 20:48:21 +0000208 u_char buf[BUFSIZ];
jardineb5d44e2003-12-23 08:09:43 +0000209#ifdef HAVE_IPV6
210 struct prefix_ipv6 *ipv6;
211#endif /* HAVE_IPV6 */
hassof891f442004-09-14 13:54:30 +0000212
jardineb5d44e2003-12-23 08:09:43 +0000213 memset (&buf, 0, BUFSIZ);
hassof891f442004-09-14 13:54:30 +0000214 if (connected->address->family == AF_INET)
hassof390d2c2004-09-10 20:48:21 +0000215 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700216 u_int32_t addr = connected->address->u.prefix4.s_addr;
217 addr = ntohl (addr);
218 if (IPV4_NET0(addr) ||
219 IPV4_NET127(addr) ||
220 IN_CLASSD(addr) ||
221 IPV4_LINKLOCAL(addr))
222 return;
223
224 for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, node, ipv4))
225 if (prefix_same ((struct prefix *) ipv4, connected->address))
226 return;
227
hassof390d2c2004-09-10 20:48:21 +0000228 ipv4 = prefix_ipv4_new ();
hassof891f442004-09-14 13:54:30 +0000229 ipv4->prefixlen = connected->address->prefixlen;
230 ipv4->prefix = connected->address->u.prefix4;
hassof390d2c2004-09-10 20:48:21 +0000231 listnode_add (circuit->ip_addrs, ipv4);
Olivier Dugeon4f593572016-04-19 19:03:05 +0200232
233 /* Update MPLS TE Local IP address parameter */
234 set_circuitparams_local_ipaddr (circuit->mtc, ipv4->prefix);
235
hasso0dae85e2004-09-26 19:53:47 +0000236 if (circuit->area)
Josh Bailey3f045a02012-03-24 08:35:20 -0700237 lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
hassof891f442004-09-14 13:54:30 +0000238
jardineb5d44e2003-12-23 08:09:43 +0000239#ifdef EXTREME_DEBUG
hassof891f442004-09-14 13:54:30 +0000240 prefix2str (connected->address, buf, BUFSIZ);
hasso529d65b2004-12-24 00:14:50 +0000241 zlog_debug ("Added IP address %s to circuit %d", buf,
hassof390d2c2004-09-10 20:48:21 +0000242 circuit->circuit_id);
243#endif /* EXTREME_DEBUG */
jardineb5d44e2003-12-23 08:09:43 +0000244 }
hassof390d2c2004-09-10 20:48:21 +0000245#ifdef HAVE_IPV6
hassof891f442004-09-14 13:54:30 +0000246 if (connected->address->family == AF_INET6)
hassof390d2c2004-09-10 20:48:21 +0000247 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700248 if (IN6_IS_ADDR_LOOPBACK(&connected->address->u.prefix6))
249 return;
250
251 for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_link, node, ipv6))
252 if (prefix_same ((struct prefix *) ipv6, connected->address))
253 return;
254 for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, node, ipv6))
255 if (prefix_same ((struct prefix *) ipv6, connected->address))
256 return;
257
hassof390d2c2004-09-10 20:48:21 +0000258 ipv6 = prefix_ipv6_new ();
hassof891f442004-09-14 13:54:30 +0000259 ipv6->prefixlen = connected->address->prefixlen;
260 ipv6->prefix = connected->address->u.prefix6;
261
hassof390d2c2004-09-10 20:48:21 +0000262 if (IN6_IS_ADDR_LINKLOCAL (&ipv6->prefix))
hassof891f442004-09-14 13:54:30 +0000263 listnode_add (circuit->ipv6_link, ipv6);
hassof390d2c2004-09-10 20:48:21 +0000264 else
hassof891f442004-09-14 13:54:30 +0000265 listnode_add (circuit->ipv6_non_link, ipv6);
hasso0dae85e2004-09-26 19:53:47 +0000266 if (circuit->area)
Josh Bailey3f045a02012-03-24 08:35:20 -0700267 lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
hassof891f442004-09-14 13:54:30 +0000268
jardineb5d44e2003-12-23 08:09:43 +0000269#ifdef EXTREME_DEBUG
hassof891f442004-09-14 13:54:30 +0000270 prefix2str (connected->address, buf, BUFSIZ);
hasso529d65b2004-12-24 00:14:50 +0000271 zlog_debug ("Added IPv6 address %s to circuit %d", buf,
hassof390d2c2004-09-10 20:48:21 +0000272 circuit->circuit_id);
273#endif /* EXTREME_DEBUG */
274 }
jardineb5d44e2003-12-23 08:09:43 +0000275#endif /* HAVE_IPV6 */
jardineb5d44e2003-12-23 08:09:43 +0000276 return;
277}
278
279void
280isis_circuit_del_addr (struct isis_circuit *circuit,
hassof390d2c2004-09-10 20:48:21 +0000281 struct connected *connected)
jardineb5d44e2003-12-23 08:09:43 +0000282{
hassof891f442004-09-14 13:54:30 +0000283 struct prefix_ipv4 *ipv4, *ip = NULL;
284 struct listnode *node;
hassof891f442004-09-14 13:54:30 +0000285 u_char buf[BUFSIZ];
286#ifdef HAVE_IPV6
287 struct prefix_ipv6 *ipv6, *ip6 = NULL;
Paul Jakma41b36e92006-12-08 01:09:50 +0000288 int found = 0;
hassof891f442004-09-14 13:54:30 +0000289#endif /* HAVE_IPV6 */
jardineb5d44e2003-12-23 08:09:43 +0000290
hassof891f442004-09-14 13:54:30 +0000291 memset (&buf, 0, BUFSIZ);
292 if (connected->address->family == AF_INET)
293 {
294 ipv4 = prefix_ipv4_new ();
295 ipv4->prefixlen = connected->address->prefixlen;
296 ipv4->prefix = connected->address->u.prefix4;
297
paul1eb8ef22005-04-07 07:30:20 +0000298 for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, node, ip))
Josh Bailey3f045a02012-03-24 08:35:20 -0700299 if (prefix_same ((struct prefix *) ip, (struct prefix *) ipv4))
paul1eb8ef22005-04-07 07:30:20 +0000300 break;
hassof891f442004-09-14 13:54:30 +0000301
302 if (ip)
303 {
304 listnode_delete (circuit->ip_addrs, ip);
Josh Bailey3f045a02012-03-24 08:35:20 -0700305 if (circuit->area)
306 lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
hassof891f442004-09-14 13:54:30 +0000307 }
308 else
309 {
hassof7c43dc2004-09-26 16:24:14 +0000310 prefix2str (connected->address, (char *)buf, BUFSIZ);
Josh Bailey3f045a02012-03-24 08:35:20 -0700311 zlog_warn ("Nonexitant ip address %s removal attempt from \
312 circuit %d", buf, circuit->circuit_id);
Christian Frankeec874162015-11-10 18:33:12 +0100313 zlog_warn ("Current ip addresses on %s:", circuit->interface->name);
314 for (ALL_LIST_ELEMENTS_RO(circuit->ip_addrs, node, ip))
315 {
316 prefix2str((struct prefix*)ip, (char *)buf, BUFSIZ);
317 zlog_warn(" %s", buf);
318 }
319 zlog_warn("End of addresses");
hassof891f442004-09-14 13:54:30 +0000320 }
David Lampartere8aca322012-11-27 01:10:30 +0000321
322 prefix_ipv4_free (ipv4);
hassof891f442004-09-14 13:54:30 +0000323 }
324#ifdef HAVE_IPV6
325 if (connected->address->family == AF_INET6)
326 {
327 ipv6 = prefix_ipv6_new ();
328 ipv6->prefixlen = connected->address->prefixlen;
329 ipv6->prefix = connected->address->u.prefix6;
330
331 if (IN6_IS_ADDR_LINKLOCAL (&ipv6->prefix))
332 {
paul1eb8ef22005-04-07 07:30:20 +0000333 for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_link, node, ip6))
hassof891f442004-09-14 13:54:30 +0000334 {
hassof891f442004-09-14 13:54:30 +0000335 if (prefix_same ((struct prefix *) ip6, (struct prefix *) ipv6))
336 break;
337 }
338 if (ip6)
339 {
340 listnode_delete (circuit->ipv6_link, ip6);
341 found = 1;
342 }
343 }
344 else
345 {
paul1eb8ef22005-04-07 07:30:20 +0000346 for (ALL_LIST_ELEMENTS_RO (circuit->ipv6_non_link, node, ip6))
hassof891f442004-09-14 13:54:30 +0000347 {
hassof891f442004-09-14 13:54:30 +0000348 if (prefix_same ((struct prefix *) ip6, (struct prefix *) ipv6))
349 break;
350 }
351 if (ip6)
352 {
353 listnode_delete (circuit->ipv6_non_link, ip6);
354 found = 1;
355 }
356 }
357
358 if (!found)
359 {
hassof7c43dc2004-09-26 16:24:14 +0000360 prefix2str (connected->address, (char *)buf, BUFSIZ);
Josh Bailey3f045a02012-03-24 08:35:20 -0700361 zlog_warn ("Nonexitant ip address %s removal attempt from \
362 circuit %d", buf, circuit->circuit_id);
Christian Frankeec874162015-11-10 18:33:12 +0100363 zlog_warn ("Current ip addresses on %s:", circuit->interface->name);
364 for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_link, node, ip6))
365 {
366 prefix2str((struct prefix*)ip6, (char *)buf, BUFSIZ);
367 zlog_warn(" %s", buf);
368 }
369 zlog_warn(" -----");
370 for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, node, ip6))
371 {
372 prefix2str((struct prefix*)ip6, (char *)buf, BUFSIZ);
373 zlog_warn(" %s", buf);
374 }
375 zlog_warn("End of addresses");
hassof891f442004-09-14 13:54:30 +0000376 }
Josh Bailey3f045a02012-03-24 08:35:20 -0700377 else if (circuit->area)
378 lsp_regenerate_schedule (circuit->area, circuit->is_type, 0);
David Lampartere8aca322012-11-27 01:10:30 +0000379
380 prefix_ipv6_free (ipv6);
hassof891f442004-09-14 13:54:30 +0000381 }
382#endif /* HAVE_IPV6 */
383 return;
jardineb5d44e2003-12-23 08:09:43 +0000384}
385
Josh Bailey3f045a02012-03-24 08:35:20 -0700386static u_char
387isis_circuit_id_gen (struct interface *ifp)
388{
389 u_char id = 0;
390 char ifname[16];
391 unsigned int i;
392 int start = -1, end = -1;
393
394 /*
395 * Get a stable circuit id from ifname. This makes
396 * the ifindex from flapping when netdevs are created
397 * and deleted on the fly. Note that this circuit id
398 * is used in pseudo lsps so it is better to be stable.
399 * The following code works on any reasonanle ifname
400 * like: eth1 or trk-1.1 etc.
401 */
402 for (i = 0; i < strlen (ifp->name); i++)
403 {
David Lamparter52f02b42015-04-10 09:14:30 +0200404 if (isdigit((unsigned char)ifp->name[i]))
Josh Bailey3f045a02012-03-24 08:35:20 -0700405 {
406 if (start < 0)
407 {
408 start = i;
409 end = i + 1;
410 }
411 else
412 {
413 end = i + 1;
414 }
415 }
416 else if (start >= 0)
417 break;
418 }
419
420 if ((start >= 0) && (end >= start) && (end - start) < 16)
421 {
422 memset (ifname, 0, 16);
423 strncpy (ifname, &ifp->name[start], end - start);
424 id = (u_char)atoi(ifname);
425 }
426
427 /* Try to be unique. */
428 if (!id)
429 id = (u_char)((ifp->ifindex & 0xff) | 0x80);
430
431 return id;
432}
433
jardineb5d44e2003-12-23 08:09:43 +0000434void
435isis_circuit_if_add (struct isis_circuit *circuit, struct interface *ifp)
436{
paul1eb8ef22005-04-07 07:30:20 +0000437 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +0000438 struct connected *conn;
439
Josh Bailey3f045a02012-03-24 08:35:20 -0700440 circuit->circuit_id = isis_circuit_id_gen (ifp);
hassof390d2c2004-09-10 20:48:21 +0000441
Josh Bailey3f045a02012-03-24 08:35:20 -0700442 isis_circuit_if_bind (circuit, ifp);
jardineb5d44e2003-12-23 08:09:43 +0000443 /* isis_circuit_update_addrs (circuit, ifp); */
444
hassof390d2c2004-09-10 20:48:21 +0000445 if (if_is_broadcast (ifp))
446 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700447 if (circuit->circ_type_config == CIRCUIT_T_P2P)
448 circuit->circ_type = CIRCUIT_T_P2P;
hassof390d2c2004-09-10 20:48:21 +0000449 else
Josh Bailey3f045a02012-03-24 08:35:20 -0700450 circuit->circ_type = CIRCUIT_T_BROADCAST;
hassof390d2c2004-09-10 20:48:21 +0000451 }
452 else if (if_is_pointopoint (ifp))
453 {
454 circuit->circ_type = CIRCUIT_T_P2P;
455 }
Josh Bailey3f045a02012-03-24 08:35:20 -0700456 else if (if_is_loopback (ifp))
457 {
458 circuit->circ_type = CIRCUIT_T_LOOPBACK;
459 circuit->is_passive = 1;
460 }
hassof390d2c2004-09-10 20:48:21 +0000461 else
462 {
hassoc89c05d2005-09-04 21:36:36 +0000463 /* It's normal in case of loopback etc. */
464 if (isis->debugs & DEBUG_EVENTS)
Josh Bailey3f045a02012-03-24 08:35:20 -0700465 zlog_debug ("isis_circuit_if_add: unsupported media");
466 circuit->circ_type = CIRCUIT_T_UNKNOWN;
hassof390d2c2004-09-10 20:48:21 +0000467 }
468
Josh Bailey3f045a02012-03-24 08:35:20 -0700469 circuit->ip_addrs = list_new ();
470#ifdef HAVE_IPV6
471 circuit->ipv6_link = list_new ();
472 circuit->ipv6_non_link = list_new ();
473#endif /* HAVE_IPV6 */
474
paul1eb8ef22005-04-07 07:30:20 +0000475 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, conn))
476 isis_circuit_add_addr (circuit, conn);
jardineb5d44e2003-12-23 08:09:43 +0000477
478 return;
479}
480
481void
Josh Bailey3f045a02012-03-24 08:35:20 -0700482isis_circuit_if_del (struct isis_circuit *circuit, struct interface *ifp)
jardineb5d44e2003-12-23 08:09:43 +0000483{
Josh Bailey3f045a02012-03-24 08:35:20 -0700484 struct listnode *node, *nnode;
485 struct connected *conn;
hassof390d2c2004-09-10 20:48:21 +0000486
Josh Bailey3f045a02012-03-24 08:35:20 -0700487 assert (circuit->interface == ifp);
488
489 /* destroy addresses */
490 for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, conn))
491 isis_circuit_del_addr (circuit, conn);
492
493 if (circuit->ip_addrs)
hassof390d2c2004-09-10 20:48:21 +0000494 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700495 assert (listcount(circuit->ip_addrs) == 0);
496 list_delete (circuit->ip_addrs);
497 circuit->ip_addrs = NULL;
hassof390d2c2004-09-10 20:48:21 +0000498 }
jardineb5d44e2003-12-23 08:09:43 +0000499
Josh Bailey3f045a02012-03-24 08:35:20 -0700500#ifdef HAVE_IPV6
501 if (circuit->ipv6_link)
hassof390d2c2004-09-10 20:48:21 +0000502 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700503 assert (listcount(circuit->ipv6_link) == 0);
504 list_delete (circuit->ipv6_link);
505 circuit->ipv6_link = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000506 }
jardineb5d44e2003-12-23 08:09:43 +0000507
Josh Bailey3f045a02012-03-24 08:35:20 -0700508 if (circuit->ipv6_non_link)
hassof390d2c2004-09-10 20:48:21 +0000509 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700510 assert (listcount(circuit->ipv6_non_link) == 0);
511 list_delete (circuit->ipv6_non_link);
512 circuit->ipv6_non_link = NULL;
hassof390d2c2004-09-10 20:48:21 +0000513 }
Josh Bailey3f045a02012-03-24 08:35:20 -0700514#endif /* HAVE_IPV6 */
515
516 circuit->circ_type = CIRCUIT_T_UNKNOWN;
517 circuit->circuit_id = 0;
jardineb5d44e2003-12-23 08:09:43 +0000518
jardineb5d44e2003-12-23 08:09:43 +0000519 return;
520}
521
522void
Josh Bailey3f045a02012-03-24 08:35:20 -0700523isis_circuit_if_bind (struct isis_circuit *circuit, struct interface *ifp)
jardineb5d44e2003-12-23 08:09:43 +0000524{
Josh Bailey3f045a02012-03-24 08:35:20 -0700525 assert (circuit != NULL);
526 assert (ifp != NULL);
527 if (circuit->interface)
528 assert (circuit->interface == ifp);
529 else
530 circuit->interface = ifp;
531 if (ifp->info)
532 assert (ifp->info == circuit);
533 else
534 ifp->info = circuit;
Olivier Dugeon4f593572016-04-19 19:03:05 +0200535 isis_link_params_update (circuit, ifp);
Josh Bailey3f045a02012-03-24 08:35:20 -0700536}
537
538void
539isis_circuit_if_unbind (struct isis_circuit *circuit, struct interface *ifp)
540{
541 assert (circuit != NULL);
542 assert (ifp != NULL);
543 assert (circuit->interface == ifp);
544 assert (ifp->info == circuit);
jardineb5d44e2003-12-23 08:09:43 +0000545 circuit->interface = NULL;
Josh Bailey3f045a02012-03-24 08:35:20 -0700546 ifp->info = NULL;
jardineb5d44e2003-12-23 08:09:43 +0000547}
548
Josh Bailey3f045a02012-03-24 08:35:20 -0700549static void
550isis_circuit_update_all_srmflags (struct isis_circuit *circuit, int is_set)
551{
552 struct isis_area *area;
553 struct isis_lsp *lsp;
554 dnode_t *dnode, *dnode_next;
555 int level;
556
557 assert (circuit);
558 area = circuit->area;
559 assert (area);
560 for (level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++)
561 {
562 if (level & circuit->is_type)
563 {
564 if (area->lspdb[level - 1] &&
565 dict_count (area->lspdb[level - 1]) > 0)
566 {
567 for (dnode = dict_first (area->lspdb[level - 1]);
568 dnode != NULL; dnode = dnode_next)
569 {
570 dnode_next = dict_next (area->lspdb[level - 1], dnode);
571 lsp = dnode_get (dnode);
572 if (is_set)
573 {
574 ISIS_SET_FLAG (lsp->SRMflags, circuit);
575 }
576 else
577 {
578 ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
579 }
580 }
581 }
582 }
583 }
584}
585
Christian Frankef1fc1db2015-11-10 18:43:31 +0100586size_t
587isis_circuit_pdu_size(struct isis_circuit *circuit)
588{
589 return ISO_MTU(circuit);
590}
591
592void
593isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream)
594{
595 size_t stream_size = isis_circuit_pdu_size(circuit);
596
597 if (!*stream)
598 {
599 *stream = stream_new(stream_size);
600 }
601 else
602 {
603 if (STREAM_SIZE(*stream) != stream_size)
604 stream_resize(*stream, stream_size);
605 stream_reset(*stream);
606 }
607}
608
Josh Bailey3f045a02012-03-24 08:35:20 -0700609int
jardineb5d44e2003-12-23 08:09:43 +0000610isis_circuit_up (struct isis_circuit *circuit)
611{
Josh Bailey3f045a02012-03-24 08:35:20 -0700612 int retv;
613
614 /* Set the flags for all the lsps of the circuit. */
615 isis_circuit_update_all_srmflags (circuit, 1);
616
617 if (circuit->state == C_STATE_UP)
618 return ISIS_OK;
619
620 if (circuit->is_passive)
621 return ISIS_OK;
jardineb5d44e2003-12-23 08:09:43 +0000622
Christian Frankef1fc1db2015-11-10 18:43:31 +0100623 if (circuit->area->lsp_mtu > isis_circuit_pdu_size(circuit))
624 {
625 zlog_err("Interface MTU %zu on %s is too low to support area lsp mtu %u!",
626 isis_circuit_pdu_size(circuit), circuit->interface->name,
627 circuit->area->lsp_mtu);
Christian Franke8ed8d0b2016-04-03 12:46:26 -0300628 isis_circuit_update_all_srmflags(circuit, 0);
Christian Frankef1fc1db2015-11-10 18:43:31 +0100629 return ISIS_ERROR;
630 }
631
hassof390d2c2004-09-10 20:48:21 +0000632 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
633 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700634 /*
635 * Get the Hardware Address
636 */
Josh Bailey3f045a02012-03-24 08:35:20 -0700637 if (circuit->interface->hw_addr_len != ETH_ALEN)
638 {
639 zlog_warn ("unsupported link layer");
640 }
641 else
642 {
643 memcpy (circuit->u.bc.snpa, circuit->interface->hw_addr, ETH_ALEN);
644 }
645#ifdef EXTREME_DEGUG
646 zlog_debug ("isis_circuit_if_add: if_id %d, isomtu %d snpa %s",
647 circuit->interface->ifindex, ISO_MTU (circuit),
648 snpa_print (circuit->u.bc.snpa));
649#endif /* EXTREME_DEBUG */
Josh Bailey3f045a02012-03-24 08:35:20 -0700650
651 circuit->u.bc.adjdb[0] = list_new ();
652 circuit->u.bc.adjdb[1] = list_new ();
653
hassof390d2c2004-09-10 20:48:21 +0000654 /*
655 * ISO 10589 - 8.4.1 Enabling of broadcast circuits
656 */
jardineb5d44e2003-12-23 08:09:43 +0000657
hassof390d2c2004-09-10 20:48:21 +0000658 /* initilizing the hello sending threads
659 * for a broadcast IF
660 */
jardineb5d44e2003-12-23 08:09:43 +0000661
hassof390d2c2004-09-10 20:48:21 +0000662 /* 8.4.1 a) commence sending of IIH PDUs */
663
Josh Bailey3f045a02012-03-24 08:35:20 -0700664 if (circuit->is_type & IS_LEVEL_1)
665 {
666 thread_add_event (master, send_lan_l1_hello, circuit, 0);
667 circuit->u.bc.lan_neighs[0] = list_new ();
668 }
hassof390d2c2004-09-10 20:48:21 +0000669
Josh Bailey3f045a02012-03-24 08:35:20 -0700670 if (circuit->is_type & IS_LEVEL_2)
671 {
672 thread_add_event (master, send_lan_l2_hello, circuit, 0);
673 circuit->u.bc.lan_neighs[1] = list_new ();
674 }
hassof390d2c2004-09-10 20:48:21 +0000675
676 /* 8.4.1 b) FIXME: solicit ES - 8.4.6 */
677 /* 8.4.1 c) FIXME: listen for ESH PDUs */
678
679 /* 8.4.1 d) */
680 /* dr election will commence in... */
Josh Bailey3f045a02012-03-24 08:35:20 -0700681 if (circuit->is_type & IS_LEVEL_1)
682 THREAD_TIMER_ON (master, circuit->u.bc.t_run_dr[0], isis_run_dr_l1,
683 circuit, 2 * circuit->hello_interval[0]);
684 if (circuit->is_type & IS_LEVEL_2)
685 THREAD_TIMER_ON (master, circuit->u.bc.t_run_dr[1], isis_run_dr_l2,
686 circuit, 2 * circuit->hello_interval[1]);
jardineb5d44e2003-12-23 08:09:43 +0000687 }
hassof390d2c2004-09-10 20:48:21 +0000688 else
689 {
690 /* initializing the hello send threads
691 * for a ptp IF
692 */
Josh Bailey3f045a02012-03-24 08:35:20 -0700693 circuit->u.p2p.neighbor = NULL;
hassof390d2c2004-09-10 20:48:21 +0000694 thread_add_event (master, send_p2p_hello, circuit, 0);
jardineb5d44e2003-12-23 08:09:43 +0000695 }
696
jardineb5d44e2003-12-23 08:09:43 +0000697 /* initializing PSNP timers */
Josh Bailey3f045a02012-03-24 08:35:20 -0700698 if (circuit->is_type & IS_LEVEL_1)
699 THREAD_TIMER_ON (master, circuit->t_send_psnp[0], send_l1_psnp, circuit,
700 isis_jitter (circuit->psnp_interval[0], PSNP_JITTER));
701
702 if (circuit->is_type & IS_LEVEL_2)
703 THREAD_TIMER_ON (master, circuit->t_send_psnp[1], send_l2_psnp, circuit,
704 isis_jitter (circuit->psnp_interval[1], PSNP_JITTER));
705
706 /* unified init for circuits; ignore warnings below this level */
707 retv = isis_sock_init (circuit);
708 if (retv != ISIS_OK)
hassof390d2c2004-09-10 20:48:21 +0000709 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700710 isis_circuit_down (circuit);
711 return retv;
hassof390d2c2004-09-10 20:48:21 +0000712 }
713
Josh Bailey3f045a02012-03-24 08:35:20 -0700714 /* initialize the circuit streams after opening connection */
Christian Frankef1fc1db2015-11-10 18:43:31 +0100715 isis_circuit_stream(circuit, &circuit->rcv_stream);
716 isis_circuit_stream(circuit, &circuit->snd_stream);
jardineb5d44e2003-12-23 08:09:43 +0000717
jardineb5d44e2003-12-23 08:09:43 +0000718#ifdef GNU_LINUX
hassof390d2c2004-09-10 20:48:21 +0000719 THREAD_READ_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#else
hassof390d2c2004-09-10 20:48:21 +0000722 THREAD_TIMER_ON (master, circuit->t_read, isis_receive, circuit,
Josh Bailey3f045a02012-03-24 08:35:20 -0700723 circuit->fd);
jardineb5d44e2003-12-23 08:09:43 +0000724#endif
Josh Bailey3f045a02012-03-24 08:35:20 -0700725
726 circuit->lsp_queue = list_new ();
727 circuit->lsp_queue_last_cleared = time (NULL);
728
729 return ISIS_OK;
jardineb5d44e2003-12-23 08:09:43 +0000730}
731
732void
733isis_circuit_down (struct isis_circuit *circuit)
734{
Josh Bailey3f045a02012-03-24 08:35:20 -0700735 if (circuit->state != C_STATE_UP)
736 return;
737
738 /* Clear the flags for all the lsps of the circuit. */
739 isis_circuit_update_all_srmflags (circuit, 0);
740
hassof390d2c2004-09-10 20:48:21 +0000741 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
742 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700743 /* destroy neighbour lists */
744 if (circuit->u.bc.lan_neighs[0])
745 {
746 list_delete (circuit->u.bc.lan_neighs[0]);
747 circuit->u.bc.lan_neighs[0] = NULL;
748 }
749 if (circuit->u.bc.lan_neighs[1])
750 {
751 list_delete (circuit->u.bc.lan_neighs[1]);
752 circuit->u.bc.lan_neighs[1] = NULL;
753 }
754 /* destroy adjacency databases */
755 if (circuit->u.bc.adjdb[0])
756 {
757 circuit->u.bc.adjdb[0]->del = isis_delete_adj;
758 list_delete (circuit->u.bc.adjdb[0]);
759 circuit->u.bc.adjdb[0] = NULL;
760 }
761 if (circuit->u.bc.adjdb[1])
762 {
763 circuit->u.bc.adjdb[1]->del = isis_delete_adj;
764 list_delete (circuit->u.bc.adjdb[1]);
765 circuit->u.bc.adjdb[1] = NULL;
766 }
767 if (circuit->u.bc.is_dr[0])
768 {
769 isis_dr_resign (circuit, 1);
770 circuit->u.bc.is_dr[0] = 0;
771 }
772 memset (circuit->u.bc.l1_desig_is, 0, ISIS_SYS_ID_LEN + 1);
773 if (circuit->u.bc.is_dr[1])
774 {
775 isis_dr_resign (circuit, 2);
776 circuit->u.bc.is_dr[1] = 0;
777 }
778 memset (circuit->u.bc.l2_desig_is, 0, ISIS_SYS_ID_LEN + 1);
779 memset (circuit->u.bc.snpa, 0, ETH_ALEN);
780
hassof390d2c2004-09-10 20:48:21 +0000781 THREAD_TIMER_OFF (circuit->u.bc.t_send_lan_hello[0]);
782 THREAD_TIMER_OFF (circuit->u.bc.t_send_lan_hello[1]);
hassof891f442004-09-14 13:54:30 +0000783 THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[0]);
784 THREAD_TIMER_OFF (circuit->u.bc.t_run_dr[1]);
Josh Bailey3f045a02012-03-24 08:35:20 -0700785 THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[0]);
786 THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[1]);
Christian Franke61010c32015-11-10 18:43:34 +0100787 circuit->lsp_regenerate_pending[0] = 0;
788 circuit->lsp_regenerate_pending[1] = 0;
hassof390d2c2004-09-10 20:48:21 +0000789 }
790 else if (circuit->circ_type == CIRCUIT_T_P2P)
791 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700792 isis_delete_adj (circuit->u.p2p.neighbor);
793 circuit->u.p2p.neighbor = NULL;
hassof390d2c2004-09-10 20:48:21 +0000794 THREAD_TIMER_OFF (circuit->u.p2p.t_send_p2p_hello);
795 }
Josh Bailey3f045a02012-03-24 08:35:20 -0700796
797 /* Cancel all active threads */
798 THREAD_TIMER_OFF (circuit->t_send_csnp[0]);
799 THREAD_TIMER_OFF (circuit->t_send_csnp[1]);
800 THREAD_TIMER_OFF (circuit->t_send_psnp[0]);
801 THREAD_TIMER_OFF (circuit->t_send_psnp[1]);
802 THREAD_OFF (circuit->t_read);
803
804 if (circuit->lsp_queue)
805 {
806 circuit->lsp_queue->del = NULL;
807 list_delete (circuit->lsp_queue);
808 circuit->lsp_queue = NULL;
809 }
810
811 /* send one gratuitous hello to spead up convergence */
812 if (circuit->is_type & IS_LEVEL_1)
813 send_hello (circuit, IS_LEVEL_1);
814 if (circuit->is_type & IS_LEVEL_2)
815 send_hello (circuit, IS_LEVEL_2);
816
817 circuit->upadjcount[0] = 0;
818 circuit->upadjcount[1] = 0;
819
jardineb5d44e2003-12-23 08:09:43 +0000820 /* close the socket */
Josh Bailey3f045a02012-03-24 08:35:20 -0700821 if (circuit->fd)
822 {
823 close (circuit->fd);
824 circuit->fd = 0;
825 }
826
827 if (circuit->rcv_stream != NULL)
828 {
829 stream_free (circuit->rcv_stream);
830 circuit->rcv_stream = NULL;
831 }
832
833 if (circuit->snd_stream != NULL)
834 {
835 stream_free (circuit->snd_stream);
836 circuit->snd_stream = NULL;
837 }
838
839 thread_cancel_event (master, circuit);
jardineb5d44e2003-12-23 08:09:43 +0000840
841 return;
842}
843
844void
845circuit_update_nlpids (struct isis_circuit *circuit)
846{
847 circuit->nlpids.count = 0;
hassof390d2c2004-09-10 20:48:21 +0000848
849 if (circuit->ip_router)
850 {
851 circuit->nlpids.nlpids[0] = NLPID_IP;
852 circuit->nlpids.count++;
853 }
jardineb5d44e2003-12-23 08:09:43 +0000854#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000855 if (circuit->ipv6_router)
856 {
857 circuit->nlpids.nlpids[circuit->nlpids.count] = NLPID_IPV6;
858 circuit->nlpids.count++;
859 }
jardineb5d44e2003-12-23 08:09:43 +0000860#endif /* HAVE_IPV6 */
861 return;
862}
863
Josh Bailey3f045a02012-03-24 08:35:20 -0700864void
865isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty,
866 char detail)
867{
868 if (detail == ISIS_UI_LEVEL_BRIEF)
869 {
870 vty_out (vty, " %-12s", circuit->interface->name);
871 vty_out (vty, "0x%-7x", circuit->circuit_id);
872 vty_out (vty, "%-9s", circuit_state2string (circuit->state));
873 vty_out (vty, "%-9s", circuit_type2string (circuit->circ_type));
874 vty_out (vty, "%-9s", circuit_t2string (circuit->is_type));
875 vty_out (vty, "%s", VTY_NEWLINE);
876 }
877
878 if (detail == ISIS_UI_LEVEL_DETAIL)
879 {
Christian Frankecb32a192015-11-10 18:33:13 +0100880 struct listnode *node;
881 struct prefix *ip_addr;
882 u_char buf[BUFSIZ];
883
Josh Bailey3f045a02012-03-24 08:35:20 -0700884 vty_out (vty, " Interface: %s", circuit->interface->name);
885 vty_out (vty, ", State: %s", circuit_state2string (circuit->state));
886 if (circuit->is_passive)
887 vty_out (vty, ", Passive");
888 else
889 vty_out (vty, ", Active");
890 vty_out (vty, ", Circuit Id: 0x%x", circuit->circuit_id);
891 vty_out (vty, "%s", VTY_NEWLINE);
892 vty_out (vty, " Type: %s", circuit_type2string (circuit->circ_type));
893 vty_out (vty, ", Level: %s", circuit_t2string (circuit->is_type));
894 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
895 vty_out (vty, ", SNPA: %-10s", snpa_print (circuit->u.bc.snpa));
896 vty_out (vty, "%s", VTY_NEWLINE);
897 if (circuit->is_type & IS_LEVEL_1)
898 {
899 vty_out (vty, " Level-1 Information:%s", VTY_NEWLINE);
900 if (circuit->area->newmetric)
901 vty_out (vty, " Metric: %d", circuit->te_metric[0]);
902 else
903 vty_out (vty, " Metric: %d",
904 circuit->metrics[0].metric_default);
905 if (!circuit->is_passive)
906 {
907 vty_out (vty, ", Active neighbors: %u%s",
908 circuit->upadjcount[0], VTY_NEWLINE);
909 vty_out (vty, " Hello interval: %u, "
910 "Holddown count: %u %s%s",
911 circuit->hello_interval[0],
912 circuit->hello_multiplier[0],
913 (circuit->pad_hellos ? "(pad)" : "(no-pad)"),
914 VTY_NEWLINE);
915 vty_out (vty, " CNSP interval: %u, "
916 "PSNP interval: %u%s",
917 circuit->csnp_interval[0],
918 circuit->psnp_interval[0], VTY_NEWLINE);
919 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
920 vty_out (vty, " LAN Priority: %u, %s%s",
921 circuit->priority[0],
922 (circuit->u.bc.is_dr[0] ? \
923 "is DIS" : "is not DIS"), VTY_NEWLINE);
924 }
925 else
926 {
927 vty_out (vty, "%s", VTY_NEWLINE);
928 }
929 }
930 if (circuit->is_type & IS_LEVEL_2)
931 {
932 vty_out (vty, " Level-2 Information:%s", VTY_NEWLINE);
933 if (circuit->area->newmetric)
934 vty_out (vty, " Metric: %d", circuit->te_metric[1]);
935 else
936 vty_out (vty, " Metric: %d",
937 circuit->metrics[1].metric_default);
938 if (!circuit->is_passive)
939 {
940 vty_out (vty, ", Active neighbors: %u%s",
941 circuit->upadjcount[1], VTY_NEWLINE);
942 vty_out (vty, " Hello interval: %u, "
943 "Holddown count: %u %s%s",
944 circuit->hello_interval[1],
945 circuit->hello_multiplier[1],
946 (circuit->pad_hellos ? "(pad)" : "(no-pad)"),
947 VTY_NEWLINE);
948 vty_out (vty, " CNSP interval: %u, "
949 "PSNP interval: %u%s",
950 circuit->csnp_interval[1],
951 circuit->psnp_interval[1], VTY_NEWLINE);
952 if (circuit->circ_type == CIRCUIT_T_BROADCAST)
953 vty_out (vty, " LAN Priority: %u, %s%s",
954 circuit->priority[1],
955 (circuit->u.bc.is_dr[1] ? \
956 "is DIS" : "is not DIS"), VTY_NEWLINE);
957 }
958 else
959 {
960 vty_out (vty, "%s", VTY_NEWLINE);
961 }
962 }
963 if (circuit->ip_addrs && listcount (circuit->ip_addrs) > 0)
964 {
Josh Bailey3f045a02012-03-24 08:35:20 -0700965 vty_out (vty, " IP Prefix(es):%s", VTY_NEWLINE);
966 for (ALL_LIST_ELEMENTS_RO (circuit->ip_addrs, node, ip_addr))
967 {
968 prefix2str (ip_addr, (char*)buf, BUFSIZ),
969 vty_out (vty, " %s%s", buf, VTY_NEWLINE);
970 }
971 }
Christian Frankecb32a192015-11-10 18:33:13 +0100972 if (circuit->ipv6_link && listcount(circuit->ipv6_link) > 0)
973 {
974 vty_out(vty, " IPv6 Link-Locals:%s", VTY_NEWLINE);
975 for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_link, node, ip_addr))
976 {
977 prefix2str(ip_addr, (char*)buf, BUFSIZ),
978 vty_out(vty, " %s%s", buf, VTY_NEWLINE);
979 }
980 }
981 if (circuit->ipv6_link && listcount(circuit->ipv6_non_link) > 0)
982 {
983 vty_out(vty, " IPv6 Prefixes:%s", VTY_NEWLINE);
984 for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, node, ip_addr))
985 {
986 prefix2str(ip_addr, (char*)buf, BUFSIZ),
987 vty_out(vty, " %s%s", buf, VTY_NEWLINE);
988 }
989 }
990
Josh Bailey3f045a02012-03-24 08:35:20 -0700991 vty_out (vty, "%s", VTY_NEWLINE);
992 }
993 return;
994}
995
jardineb5d44e2003-12-23 08:09:43 +0000996int
hassof390d2c2004-09-10 20:48:21 +0000997isis_interface_config_write (struct vty *vty)
jardineb5d44e2003-12-23 08:09:43 +0000998{
jardineb5d44e2003-12-23 08:09:43 +0000999 int write = 0;
hasso3fdb2dd2005-09-28 18:45:54 +00001000 struct listnode *node, *node2;
jardineb5d44e2003-12-23 08:09:43 +00001001 struct interface *ifp;
1002 struct isis_area *area;
Josh Bailey3f045a02012-03-24 08:35:20 -07001003 struct isis_circuit *circuit;
jardineb5d44e2003-12-23 08:09:43 +00001004 int i;
jardineb5d44e2003-12-23 08:09:43 +00001005
hasso3fdb2dd2005-09-28 18:45:54 +00001006 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
jardineb5d44e2003-12-23 08:09:43 +00001007 {
Josh Bailey3f045a02012-03-24 08:35:20 -07001008 /* IF name */
1009 vty_out (vty, "interface %s%s", ifp->name, VTY_NEWLINE);
1010 write++;
1011 /* IF desc */
1012 if (ifp->desc)
1013 {
1014 vty_out (vty, " description %s%s", ifp->desc, VTY_NEWLINE);
1015 write++;
1016 }
1017 /* ISIS Circuit */
1018 for (ALL_LIST_ELEMENTS_RO (isis->area_list, node2, area))
1019 {
1020 circuit = circuit_lookup_by_ifp (ifp, area->circuit_list);
1021 if (circuit == NULL)
1022 continue;
1023 if (circuit->ip_router)
1024 {
1025 vty_out (vty, " ip router isis %s%s", area->area_tag,
1026 VTY_NEWLINE);
1027 write++;
1028 }
1029 if (circuit->is_passive)
1030 {
1031 vty_out (vty, " isis passive%s", VTY_NEWLINE);
1032 write++;
1033 }
1034 if (circuit->circ_type_config == CIRCUIT_T_P2P)
1035 {
1036 vty_out (vty, " isis network point-to-point%s", VTY_NEWLINE);
1037 write++;
1038 }
jardineb5d44e2003-12-23 08:09:43 +00001039#ifdef HAVE_IPV6
Josh Bailey3f045a02012-03-24 08:35:20 -07001040 if (circuit->ipv6_router)
1041 {
1042 vty_out (vty, " ipv6 router isis %s%s", area->area_tag,
1043 VTY_NEWLINE);
1044 write++;
1045 }
jardineb5d44e2003-12-23 08:09:43 +00001046#endif /* HAVE_IPV6 */
jardineb5d44e2003-12-23 08:09:43 +00001047
Josh Bailey3f045a02012-03-24 08:35:20 -07001048 /* ISIS - circuit type */
1049 if (circuit->is_type == IS_LEVEL_1)
1050 {
1051 vty_out (vty, " isis circuit-type level-1%s", VTY_NEWLINE);
1052 write++;
1053 }
1054 else
1055 {
1056 if (circuit->is_type == IS_LEVEL_2)
1057 {
1058 vty_out (vty, " isis circuit-type level-2-only%s",
1059 VTY_NEWLINE);
1060 write++;
1061 }
1062 }
jardineb5d44e2003-12-23 08:09:43 +00001063
Josh Bailey3f045a02012-03-24 08:35:20 -07001064 /* ISIS - CSNP interval */
1065 if (circuit->csnp_interval[0] == circuit->csnp_interval[1])
1066 {
1067 if (circuit->csnp_interval[0] != DEFAULT_CSNP_INTERVAL)
1068 {
1069 vty_out (vty, " isis csnp-interval %d%s",
1070 circuit->csnp_interval[0], VTY_NEWLINE);
1071 write++;
1072 }
1073 }
1074 else
1075 {
1076 for (i = 0; i < 2; i++)
1077 {
1078 if (circuit->csnp_interval[i] != DEFAULT_CSNP_INTERVAL)
1079 {
1080 vty_out (vty, " isis csnp-interval %d level-%d%s",
1081 circuit->csnp_interval[i], i + 1, VTY_NEWLINE);
1082 write++;
1083 }
1084 }
1085 }
jardineb5d44e2003-12-23 08:09:43 +00001086
Josh Bailey3f045a02012-03-24 08:35:20 -07001087 /* ISIS - PSNP interval */
1088 if (circuit->psnp_interval[0] == circuit->psnp_interval[1])
1089 {
1090 if (circuit->psnp_interval[0] != DEFAULT_PSNP_INTERVAL)
1091 {
1092 vty_out (vty, " isis psnp-interval %d%s",
1093 circuit->psnp_interval[0], VTY_NEWLINE);
1094 write++;
1095 }
1096 }
1097 else
1098 {
1099 for (i = 0; i < 2; i++)
1100 {
1101 if (circuit->psnp_interval[i] != DEFAULT_PSNP_INTERVAL)
1102 {
1103 vty_out (vty, " isis psnp-interval %d level-%d%s",
1104 circuit->psnp_interval[i], i + 1, VTY_NEWLINE);
1105 write++;
1106 }
1107 }
1108 }
jardineb5d44e2003-12-23 08:09:43 +00001109
Josh Bailey3f045a02012-03-24 08:35:20 -07001110 /* ISIS - Hello padding - Defaults to true so only display if false */
1111 if (circuit->pad_hellos == 0)
1112 {
1113 vty_out (vty, " no isis hello padding%s", VTY_NEWLINE);
1114 write++;
1115 }
jardineb5d44e2003-12-23 08:09:43 +00001116
Josh Bailey3f045a02012-03-24 08:35:20 -07001117 /* ISIS - Hello interval */
1118 if (circuit->hello_interval[0] == circuit->hello_interval[1])
1119 {
1120 if (circuit->hello_interval[0] != DEFAULT_HELLO_INTERVAL)
1121 {
1122 vty_out (vty, " isis hello-interval %d%s",
1123 circuit->hello_interval[0], VTY_NEWLINE);
1124 write++;
1125 }
1126 }
1127 else
1128 {
1129 for (i = 0; i < 2; i++)
1130 {
1131 if (circuit->hello_interval[i] != DEFAULT_HELLO_INTERVAL)
1132 {
1133 vty_out (vty, " isis hello-interval %d level-%d%s",
1134 circuit->hello_interval[i], i + 1, VTY_NEWLINE);
1135 write++;
1136 }
1137 }
1138 }
jardineb5d44e2003-12-23 08:09:43 +00001139
Josh Bailey3f045a02012-03-24 08:35:20 -07001140 /* ISIS - Hello Multiplier */
1141 if (circuit->hello_multiplier[0] == circuit->hello_multiplier[1])
1142 {
1143 if (circuit->hello_multiplier[0] != DEFAULT_HELLO_MULTIPLIER)
1144 {
1145 vty_out (vty, " isis hello-multiplier %d%s",
1146 circuit->hello_multiplier[0], VTY_NEWLINE);
1147 write++;
1148 }
1149 }
1150 else
1151 {
1152 for (i = 0; i < 2; i++)
1153 {
1154 if (circuit->hello_multiplier[i] != DEFAULT_HELLO_MULTIPLIER)
1155 {
1156 vty_out (vty, " isis hello-multiplier %d level-%d%s",
1157 circuit->hello_multiplier[i], i + 1,
1158 VTY_NEWLINE);
1159 write++;
1160 }
1161 }
1162 }
1163
1164 /* ISIS - Priority */
1165 if (circuit->priority[0] == circuit->priority[1])
1166 {
1167 if (circuit->priority[0] != DEFAULT_PRIORITY)
1168 {
1169 vty_out (vty, " isis priority %d%s",
1170 circuit->priority[0], VTY_NEWLINE);
1171 write++;
1172 }
1173 }
1174 else
1175 {
1176 for (i = 0; i < 2; i++)
1177 {
1178 if (circuit->priority[i] != DEFAULT_PRIORITY)
1179 {
1180 vty_out (vty, " isis priority %d level-%d%s",
1181 circuit->priority[i], i + 1, VTY_NEWLINE);
1182 write++;
1183 }
1184 }
1185 }
1186
1187 /* ISIS - Metric */
1188 if (circuit->te_metric[0] == circuit->te_metric[1])
1189 {
1190 if (circuit->te_metric[0] != DEFAULT_CIRCUIT_METRIC)
1191 {
1192 vty_out (vty, " isis metric %d%s", circuit->te_metric[0],
1193 VTY_NEWLINE);
1194 write++;
1195 }
1196 }
1197 else
1198 {
1199 for (i = 0; i < 2; i++)
1200 {
1201 if (circuit->te_metric[i] != DEFAULT_CIRCUIT_METRIC)
1202 {
1203 vty_out (vty, " isis metric %d level-%d%s",
1204 circuit->te_metric[i], i + 1, VTY_NEWLINE);
1205 write++;
1206 }
1207 }
1208 }
1209 if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5)
1210 {
1211 vty_out (vty, " isis password md5 %s%s", circuit->passwd.passwd,
1212 VTY_NEWLINE);
1213 write++;
1214 }
1215 else if (circuit->passwd.type == ISIS_PASSWD_TYPE_CLEARTXT)
1216 {
1217 vty_out (vty, " isis password clear %s%s", circuit->passwd.passwd,
1218 VTY_NEWLINE);
1219 write++;
1220 }
1221 }
1222 vty_out (vty, "!%s", VTY_NEWLINE);
jardineb5d44e2003-12-23 08:09:43 +00001223 }
hassof390d2c2004-09-10 20:48:21 +00001224
jardineb5d44e2003-12-23 08:09:43 +00001225 return write;
1226}
jardineb5d44e2003-12-23 08:09:43 +00001227
David Lamparter3732cba2016-07-29 16:19:40 +02001228struct isis_circuit *
1229isis_circuit_create (struct isis_area *area, struct interface *ifp)
jardineb5d44e2003-12-23 08:09:43 +00001230{
Josh Bailey3f045a02012-03-24 08:35:20 -07001231 struct isis_circuit *circuit;
David Lamparter3732cba2016-07-29 16:19:40 +02001232 circuit = isis_csm_state_change (ISIS_ENABLE, NULL, area);
1233 assert (circuit->state == C_STATE_CONF || circuit->state == C_STATE_UP);
1234 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;
1243 bool was_enabled = circuit->ip_router || circuit->ipv6_router;
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 +02001287void
1288isis_circuit_is_type_set (struct isis_circuit *circuit, int circ_type)
Josh Bailey3f045a02012-03-24 08:35:20 -07001289{
David Lamparter3732cba2016-07-29 16:19:40 +02001290 if (circuit->circ_type != circ_type)
1291 isis_event_circuit_type_change (circuit, circ_type);
Josh Bailey3f045a02012-03-24 08:35:20 -07001292}
1293
David Lamparter3732cba2016-07-29 16:19:40 +02001294int
1295isis_circuit_metric_set (struct isis_circuit *circuit, int level, int metric)
jardineb5d44e2003-12-23 08:09:43 +00001296{
David Lamparter3732cba2016-07-29 16:19:40 +02001297 assert (level == IS_LEVEL_1 || level == IS_LEVEL_2);
1298 if (metric > MAX_WIDE_LINK_METRIC)
1299 return -1;
1300 if (circuit->area && circuit->area->oldmetric
1301 && metric > MAX_NARROW_LINK_METRIC)
1302 return -1;
hassof390d2c2004-09-10 20:48:21 +00001303
David Lamparter3732cba2016-07-29 16:19:40 +02001304 circuit->te_metric[level - 1] = metric;
1305 circuit->metrics[level - 1].metric_default = metric;
hassof390d2c2004-09-10 20:48:21 +00001306
David Lamparter3732cba2016-07-29 16:19:40 +02001307 if (circuit->area)
1308 lsp_regenerate_schedule (circuit->area, level, 0);
1309 return 0;
jardineb5d44e2003-12-23 08:09:43 +00001310}
1311
Christian Frankef5fbfb22016-07-28 17:23:27 +02001312int
1313isis_circuit_passwd_unset (struct isis_circuit *circuit)
jardineb5d44e2003-12-23 08:09:43 +00001314{
Christian Frankef5fbfb22016-07-28 17:23:27 +02001315 memset(&circuit->passwd, 0, sizeof(circuit->passwd));
1316 return 0;
Josh Bailey3f045a02012-03-24 08:35:20 -07001317}
1318
Christian Frankef5fbfb22016-07-28 17:23:27 +02001319static int
1320isis_circuit_passwd_set (struct isis_circuit *circuit, u_char passwd_type, const char *passwd)
Josh Bailey3f045a02012-03-24 08:35:20 -07001321{
1322 int len;
Josh Bailey3f045a02012-03-24 08:35:20 -07001323
Christian Frankef5fbfb22016-07-28 17:23:27 +02001324 if (!passwd)
1325 return -1;
1326
1327 len = strlen(passwd);
Josh Bailey3f045a02012-03-24 08:35:20 -07001328 if (len > 254)
Christian Frankef5fbfb22016-07-28 17:23:27 +02001329 return -1;
hassof390d2c2004-09-10 20:48:21 +00001330
Christian Frankef5fbfb22016-07-28 17:23:27 +02001331 circuit->passwd.len = len;
1332 strncpy((char *)circuit->passwd.passwd, passwd, 255);
1333 circuit->passwd.type = passwd_type;
1334 return 0;
jardineb5d44e2003-12-23 08:09:43 +00001335}
1336
Christian Frankef5fbfb22016-07-28 17:23:27 +02001337int
1338isis_circuit_passwd_cleartext_set (struct isis_circuit *circuit, const char *passwd)
jardineb5d44e2003-12-23 08:09:43 +00001339{
Christian Frankef5fbfb22016-07-28 17:23:27 +02001340 return isis_circuit_passwd_set (circuit, ISIS_PASSWD_TYPE_CLEARTXT, passwd);
1341}
hassof390d2c2004-09-10 20:48:21 +00001342
Christian Frankef5fbfb22016-07-28 17:23:27 +02001343int
1344isis_circuit_passwd_hmac_md5_set (struct isis_circuit *circuit, const char *passwd)
1345{
1346 return isis_circuit_passwd_set (circuit, ISIS_PASSWD_TYPE_HMAC_MD5, passwd);
jardineb5d44e2003-12-23 08:09:43 +00001347}
Josh Bailey3f045a02012-03-24 08:35:20 -07001348struct cmd_node interface_node = {
jardineb5d44e2003-12-23 08:09:43 +00001349 INTERFACE_NODE,
1350 "%s(config-if)# ",
1351 1,
1352};
1353
David Lamparter3732cba2016-07-29 16:19:40 +02001354int
1355isis_circuit_circ_type_set(struct isis_circuit *circuit, int circ_type)
Josh Bailey3f045a02012-03-24 08:35:20 -07001356{
David Lamparter3732cba2016-07-29 16:19:40 +02001357 /* Changing the network type to/of loopback or unknown interfaces
1358 * is not supported. */
1359 if (circ_type == CIRCUIT_T_UNKNOWN
1360 || circ_type == CIRCUIT_T_LOOPBACK
1361 || circuit->circ_type == CIRCUIT_T_UNKNOWN
1362 || circuit->circ_type == CIRCUIT_T_LOOPBACK)
1363 {
1364 if (circuit->circ_type != circ_type)
1365 return -1;
1366 else
1367 return 0;
1368 }
Josh Bailey3f045a02012-03-24 08:35:20 -07001369
David Lamparter3732cba2016-07-29 16:19:40 +02001370 if (circuit->circ_type == circ_type)
1371 return 0;
Josh Bailey3f045a02012-03-24 08:35:20 -07001372
1373 if (circuit->state != C_STATE_UP)
1374 {
David Lamparter3732cba2016-07-29 16:19:40 +02001375 circuit->circ_type = circ_type;
1376 circuit->circ_type_config = circ_type;
Josh Bailey3f045a02012-03-24 08:35:20 -07001377 }
1378 else
1379 {
1380 struct isis_area *area = circuit->area;
David Lamparter3732cba2016-07-29 16:19:40 +02001381 if (circ_type == CIRCUIT_T_BROADCAST
1382 && !if_is_broadcast(circuit->interface))
1383 return -1;
Josh Bailey3f045a02012-03-24 08:35:20 -07001384
David Lamparter3732cba2016-07-29 16:19:40 +02001385 isis_csm_state_change(ISIS_DISABLE, circuit, area);
1386 circuit->circ_type = circ_type;
1387 circuit->circ_type_config = circ_type;
1388 isis_csm_state_change(ISIS_ENABLE, circuit, area);
Josh Bailey3f045a02012-03-24 08:35:20 -07001389 }
David Lamparter3732cba2016-07-29 16:19:40 +02001390 return 0;
Josh Bailey3f045a02012-03-24 08:35:20 -07001391}
1392
jardineb5d44e2003-12-23 08:09:43 +00001393int
1394isis_if_new_hook (struct interface *ifp)
1395{
jardineb5d44e2003-12-23 08:09:43 +00001396 return 0;
1397}
1398
1399int
1400isis_if_delete_hook (struct interface *ifp)
1401{
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001402 struct isis_circuit *circuit;
1403 /* Clean up the circuit data */
1404 if (ifp && ifp->info)
1405 {
1406 circuit = ifp->info;
1407 isis_csm_state_change (IF_DOWN_FROM_Z, circuit, circuit->area);
1408 isis_csm_state_change (ISIS_DISABLE, circuit, circuit->area);
1409 }
1410
jardineb5d44e2003-12-23 08:09:43 +00001411 return 0;
1412}
1413
jardineb5d44e2003-12-23 08:09:43 +00001414void
1415isis_circuit_init ()
1416{
jardineb5d44e2003-12-23 08:09:43 +00001417 /* Initialize Zebra interface data structure */
jardineb5d44e2003-12-23 08:09:43 +00001418 if_add_hook (IF_NEW_HOOK, isis_if_new_hook);
1419 if_add_hook (IF_DELETE_HOOK, isis_if_delete_hook);
1420
1421 /* Install interface node */
1422 install_node (&interface_node, isis_interface_config_write);
1423 install_element (CONFIG_NODE, &interface_cmd);
Subbaiah Venkatae38e0df2012-03-27 23:48:05 -07001424 install_element (CONFIG_NODE, &no_interface_cmd);
jardineb5d44e2003-12-23 08:09:43 +00001425
1426 install_default (INTERFACE_NODE);
1427 install_element (INTERFACE_NODE, &interface_desc_cmd);
1428 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
1429
David Lamparter3732cba2016-07-29 16:19:40 +02001430 isis_vty_init ();
jardineb5d44e2003-12-23 08:09:43 +00001431}