blob: 7cee89ee32c032bdeb37e62e84a58ab14c1c5f83 [file] [log] [blame]
jardineb5d44e2003-12-23 08:09:43 +00001/*
2 * IS-IS Rout(e)ing protocol - isis_route.c
3 * Copyright (C) 2001,2002 Sampo Saaristo
4 * Tampere University of Technology
5 * Institute of Communications Engineering
6 *
7 * based on ../ospf6d/ospf6_route.[ch]
8 * by Yasuhiro Ohara
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public Licenseas published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option)
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful,but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 * more details.
19
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 */
24
25#include <stdlib.h>
26#include <stdio.h>
27#include <zebra.h>
jardineb5d44e2003-12-23 08:09:43 +000028
29#include "thread.h"
30#include "linklist.h"
31#include "vty.h"
32#include "log.h"
33#include "memory.h"
34#include "prefix.h"
35#include "hash.h"
36#include "if.h"
37#include "table.h"
38
39#include "isis_constants.h"
40#include "isis_common.h"
41#include "dict.h"
42#include "isisd.h"
43#include "isis_misc.h"
44#include "isis_adjacency.h"
45#include "isis_circuit.h"
46#include "isis_tlv.h"
47#include "isis_pdu.h"
48#include "isis_lsp.h"
49#include "isis_spf.h"
50#include "isis_route.h"
51#include "isis_zebra.h"
52
53extern struct isis *isis;
54extern struct thread_master *master;
55
hasso92365882005-01-18 13:53:33 +000056static struct isis_nexthop *
jardineb5d44e2003-12-23 08:09:43 +000057isis_nexthop_create (struct in_addr *ip, unsigned int ifindex)
jardineb5d44e2003-12-23 08:09:43 +000058{
59 struct listnode *node;
60 struct isis_nexthop *nexthop;
jardineb5d44e2003-12-23 08:09:43 +000061
paul1eb8ef22005-04-07 07:30:20 +000062 for (ALL_LIST_ELEMENTS_RO (isis->nexthops, node, nexthop))
hassof390d2c2004-09-10 20:48:21 +000063 {
hassof390d2c2004-09-10 20:48:21 +000064 if (nexthop->ifindex != ifindex)
65 continue;
66 if (ip && memcmp (&nexthop->ip, ip, sizeof (struct in_addr)) != 0)
67 continue;
68
69 nexthop->lock++;
70 return nexthop;
71 }
72
jardineb5d44e2003-12-23 08:09:43 +000073 nexthop = XMALLOC (MTYPE_ISIS_NEXTHOP, sizeof (struct isis_nexthop));
hassof390d2c2004-09-10 20:48:21 +000074 if (!nexthop)
75 {
76 zlog_err ("ISIS-Rte: isis_nexthop_create: out of memory!");
77 }
78
jardineb5d44e2003-12-23 08:09:43 +000079 memset (nexthop, 0, sizeof (struct isis_nexthop));
80 nexthop->ifindex = ifindex;
81 memcpy (&nexthop->ip, ip, sizeof (struct in_addr));
82 listnode_add (isis->nexthops, nexthop);
83 nexthop->lock++;
84
85 return nexthop;
86}
87
hasso92365882005-01-18 13:53:33 +000088static void
jardineb5d44e2003-12-23 08:09:43 +000089isis_nexthop_delete (struct isis_nexthop *nexthop)
90{
91 nexthop->lock--;
hassof390d2c2004-09-10 20:48:21 +000092 if (nexthop->lock == 0)
93 {
94 listnode_delete (isis->nexthops, nexthop);
95 XFREE (MTYPE_ISIS_NEXTHOP, nexthop);
96 }
97
jardineb5d44e2003-12-23 08:09:43 +000098 return;
99}
100
hasso92365882005-01-18 13:53:33 +0000101static int
hassof390d2c2004-09-10 20:48:21 +0000102nexthoplookup (struct list *nexthops, struct in_addr *ip,
103 unsigned int ifindex)
jardineb5d44e2003-12-23 08:09:43 +0000104{
105 struct listnode *node;
106 struct isis_nexthop *nh;
107
paul1eb8ef22005-04-07 07:30:20 +0000108 for (ALL_LIST_ELEMENTS_RO (nexthops, node, nh))
hassof390d2c2004-09-10 20:48:21 +0000109 {
hassof390d2c2004-09-10 20:48:21 +0000110 if (!(memcmp (ip, &nh->ip, sizeof (struct in_addr))) &&
111 ifindex == nh->ifindex)
112 return 1;
113 }
jardineb5d44e2003-12-23 08:09:43 +0000114
115 return 0;
116}
117
hasso3d549272005-09-21 18:52:14 +0000118#ifdef EXTREME_DEBUG
hasso92365882005-01-18 13:53:33 +0000119static void
jardineb5d44e2003-12-23 08:09:43 +0000120nexthop_print (struct isis_nexthop *nh)
121{
122 u_char buf[BUFSIZ];
hassof390d2c2004-09-10 20:48:21 +0000123
hassof7c43dc2004-09-26 16:24:14 +0000124 inet_ntop (AF_INET, &nh->ip, (char *) buf, BUFSIZ);
hassof390d2c2004-09-10 20:48:21 +0000125
hasso529d65b2004-12-24 00:14:50 +0000126 zlog_debug (" %s %u", buf, nh->ifindex);
jardineb5d44e2003-12-23 08:09:43 +0000127}
128
hasso92365882005-01-18 13:53:33 +0000129static void
jardineb5d44e2003-12-23 08:09:43 +0000130nexthops_print (struct list *nhs)
131{
132 struct listnode *node;
hassof390d2c2004-09-10 20:48:21 +0000133
paul1eb8ef22005-04-07 07:30:20 +0000134 for (ALL_LIST_ELEMENTS_RO (nhs, node, nh))
135 nexthop_print (nh);
jardineb5d44e2003-12-23 08:09:43 +0000136}
hasso3d549272005-09-21 18:52:14 +0000137#endif /* EXTREME_DEBUG */
jardineb5d44e2003-12-23 08:09:43 +0000138
139#ifdef HAVE_IPV6
hasso92365882005-01-18 13:53:33 +0000140static struct isis_nexthop6 *
hassof390d2c2004-09-10 20:48:21 +0000141isis_nexthop6_new (struct in6_addr *ip6, unsigned int ifindex)
jardineb5d44e2003-12-23 08:09:43 +0000142{
hassof390d2c2004-09-10 20:48:21 +0000143
jardineb5d44e2003-12-23 08:09:43 +0000144 struct isis_nexthop6 *nexthop6;
hassof390d2c2004-09-10 20:48:21 +0000145
jardineb5d44e2003-12-23 08:09:43 +0000146 nexthop6 = XMALLOC (MTYPE_ISIS_NEXTHOP6, sizeof (struct isis_nexthop6));
hassof390d2c2004-09-10 20:48:21 +0000147 if (!nexthop6)
148 {
149 zlog_err ("ISIS-Rte: isis_nexthop_create6: out of memory!");
150 }
151
jardineb5d44e2003-12-23 08:09:43 +0000152 memset (nexthop6, 0, sizeof (struct isis_nexthop6));
153 nexthop6->ifindex = ifindex;
154 memcpy (&nexthop6->ip6, ip6, sizeof (struct in6_addr));
155 nexthop6->lock++;
156
157 return nexthop6;
158}
159
hasso92365882005-01-18 13:53:33 +0000160static struct isis_nexthop6 *
jardineb5d44e2003-12-23 08:09:43 +0000161isis_nexthop6_create (struct in6_addr *ip6, unsigned int ifindex)
jardineb5d44e2003-12-23 08:09:43 +0000162{
163 struct listnode *node;
164 struct isis_nexthop6 *nexthop6;
jardineb5d44e2003-12-23 08:09:43 +0000165
paul1eb8ef22005-04-07 07:30:20 +0000166 for (ALL_LIST_ELEMENTS_RO (isis->nexthops6, node, nexthop6))
hassof390d2c2004-09-10 20:48:21 +0000167 {
hassof390d2c2004-09-10 20:48:21 +0000168 if (nexthop6->ifindex != ifindex)
169 continue;
170 if (ip6 && memcmp (&nexthop6->ip6, ip6, sizeof (struct in6_addr)) != 0)
171 continue;
172
173 nexthop6->lock++;
174 return nexthop6;
175 }
176
jardineb5d44e2003-12-23 08:09:43 +0000177 nexthop6 = isis_nexthop6_new (ip6, ifindex);
178
179 return nexthop6;
180}
181
hasso92365882005-01-18 13:53:33 +0000182static void
jardineb5d44e2003-12-23 08:09:43 +0000183isis_nexthop6_delete (struct isis_nexthop6 *nexthop6)
184{
185
186 nexthop6->lock--;
hassof390d2c2004-09-10 20:48:21 +0000187 if (nexthop6->lock == 0)
188 {
189 listnode_delete (isis->nexthops6, nexthop6);
190 XFREE (MTYPE_ISIS_NEXTHOP6, nexthop6);
191 }
192
jardineb5d44e2003-12-23 08:09:43 +0000193 return;
194}
195
hasso92365882005-01-18 13:53:33 +0000196static int
hassof390d2c2004-09-10 20:48:21 +0000197nexthop6lookup (struct list *nexthops6, struct in6_addr *ip6,
198 unsigned int ifindex)
jardineb5d44e2003-12-23 08:09:43 +0000199{
200 struct listnode *node;
201 struct isis_nexthop6 *nh6;
202
paul1eb8ef22005-04-07 07:30:20 +0000203 for (ALL_LIST_ELEMENTS_RO (nexthops6, node, nh6))
hassof390d2c2004-09-10 20:48:21 +0000204 {
hassof390d2c2004-09-10 20:48:21 +0000205 if (!(memcmp (ip6, &nh6->ip6, sizeof (struct in6_addr))) &&
206 ifindex == nh6->ifindex)
207 return 1;
208 }
jardineb5d44e2003-12-23 08:09:43 +0000209
210 return 0;
211}
212
hasso92365882005-01-18 13:53:33 +0000213#ifdef EXTREME_DEBUG
214static void
jardineb5d44e2003-12-23 08:09:43 +0000215nexthop6_print (struct isis_nexthop6 *nh6)
216{
217 u_char buf[BUFSIZ];
hassof390d2c2004-09-10 20:48:21 +0000218
hassof7c43dc2004-09-26 16:24:14 +0000219 inet_ntop (AF_INET6, &nh6->ip6, (char *) buf, BUFSIZ);
hassof390d2c2004-09-10 20:48:21 +0000220
hasso529d65b2004-12-24 00:14:50 +0000221 zlog_debug (" %s %u", buf, nh6->ifindex);
jardineb5d44e2003-12-23 08:09:43 +0000222}
223
hasso92365882005-01-18 13:53:33 +0000224static void
jardineb5d44e2003-12-23 08:09:43 +0000225nexthops6_print (struct list *nhs6)
226{
227 struct listnode *node;
hassof390d2c2004-09-10 20:48:21 +0000228
paul1eb8ef22005-04-07 07:30:20 +0000229 for (ALL_LIST_ELEMENTS_RO (nhs6, node, nh6))
230 nexthop6_print (nh6);
jardineb5d44e2003-12-23 08:09:43 +0000231}
hasso92365882005-01-18 13:53:33 +0000232#endif /* EXTREME_DEBUG */
jardineb5d44e2003-12-23 08:09:43 +0000233#endif /* HAVE_IPV6 */
234
hasso92365882005-01-18 13:53:33 +0000235static void
jardineb5d44e2003-12-23 08:09:43 +0000236adjinfo2nexthop (struct list *nexthops, struct isis_adjacency *adj)
237{
238 struct isis_nexthop *nh;
paul1eb8ef22005-04-07 07:30:20 +0000239 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +0000240 struct in_addr *ipv4_addr;
241
242 if (adj->ipv4_addrs == NULL)
243 return;
paul1eb8ef22005-04-07 07:30:20 +0000244
245 for (ALL_LIST_ELEMENTS (adj->ipv4_addrs, node, nnode, ipv4_addr))
hassof390d2c2004-09-10 20:48:21 +0000246 {
hassof390d2c2004-09-10 20:48:21 +0000247 if (!nexthoplookup (nexthops, ipv4_addr,
248 adj->circuit->interface->ifindex))
249 {
250 nh = isis_nexthop_create (ipv4_addr,
251 adj->circuit->interface->ifindex);
252 listnode_add (nexthops, nh);
253 }
jardineb5d44e2003-12-23 08:09:43 +0000254 }
jardineb5d44e2003-12-23 08:09:43 +0000255}
256
257#ifdef HAVE_IPV6
hasso92365882005-01-18 13:53:33 +0000258static void
jardineb5d44e2003-12-23 08:09:43 +0000259adjinfo2nexthop6 (struct list *nexthops6, struct isis_adjacency *adj)
260{
paul1eb8ef22005-04-07 07:30:20 +0000261 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +0000262 struct in6_addr *ipv6_addr;
263 struct isis_nexthop6 *nh6;
hassof390d2c2004-09-10 20:48:21 +0000264
jardineb5d44e2003-12-23 08:09:43 +0000265 if (!adj->ipv6_addrs)
266 return;
267
paul1eb8ef22005-04-07 07:30:20 +0000268 for (ALL_LIST_ELEMENTS (adj->ipv6_addrs, node, nnode, ipv6_addr))
hassof390d2c2004-09-10 20:48:21 +0000269 {
hassof390d2c2004-09-10 20:48:21 +0000270 if (!nexthop6lookup (nexthops6, ipv6_addr,
271 adj->circuit->interface->ifindex))
272 {
273 nh6 = isis_nexthop6_create (ipv6_addr,
274 adj->circuit->interface->ifindex);
275 listnode_add (nexthops6, nh6);
276 }
jardineb5d44e2003-12-23 08:09:43 +0000277 }
jardineb5d44e2003-12-23 08:09:43 +0000278}
279#endif /* HAVE_IPV6 */
280
hasso92365882005-01-18 13:53:33 +0000281static struct isis_route_info *
hassof390d2c2004-09-10 20:48:21 +0000282isis_route_info_new (uint32_t cost, uint32_t depth, u_char family,
283 struct list *adjacencies)
jardineb5d44e2003-12-23 08:09:43 +0000284{
285 struct isis_route_info *rinfo;
286 struct isis_adjacency *adj;
paul1eb8ef22005-04-07 07:30:20 +0000287 struct listnode *node, *nnode;
hassof390d2c2004-09-10 20:48:21 +0000288
jardineb5d44e2003-12-23 08:09:43 +0000289 rinfo = XMALLOC (MTYPE_ISIS_ROUTE_INFO, sizeof (struct isis_route_info));
hassof390d2c2004-09-10 20:48:21 +0000290 if (!rinfo)
291 {
292 zlog_err ("ISIS-Rte: isis_route_info_new: out of memory!");
293 return NULL;
294 }
jardineb5d44e2003-12-23 08:09:43 +0000295 memset (rinfo, 0, sizeof (struct isis_route_info));
296
hassof390d2c2004-09-10 20:48:21 +0000297 if (family == AF_INET)
298 {
299 rinfo->nexthops = list_new ();
paul1eb8ef22005-04-07 07:30:20 +0000300 for (ALL_LIST_ELEMENTS (adjacencies, node, nnode, adj))
301 adjinfo2nexthop (rinfo->nexthops, adj);
jardineb5d44e2003-12-23 08:09:43 +0000302 }
jardineb5d44e2003-12-23 08:09:43 +0000303#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000304 if (family == AF_INET6)
305 {
306 rinfo->nexthops6 = list_new ();
paul1eb8ef22005-04-07 07:30:20 +0000307 for (ALL_LIST_ELEMENTS (adjacencies, node, nnode, adj))
308 adjinfo2nexthop6 (rinfo->nexthops6, adj);
jardineb5d44e2003-12-23 08:09:43 +0000309 }
hassof390d2c2004-09-10 20:48:21 +0000310
jardineb5d44e2003-12-23 08:09:43 +0000311#endif /* HAVE_IPV6 */
312
313 rinfo->cost = cost;
314 rinfo->depth = depth;
hassof390d2c2004-09-10 20:48:21 +0000315
jardineb5d44e2003-12-23 08:09:43 +0000316 return rinfo;
317}
318
hasso92365882005-01-18 13:53:33 +0000319static void
jardineb5d44e2003-12-23 08:09:43 +0000320isis_route_info_delete (struct isis_route_info *route_info)
321{
hassof390d2c2004-09-10 20:48:21 +0000322 if (route_info->nexthops)
323 {
hassof7c43dc2004-09-26 16:24:14 +0000324 route_info->nexthops->del = (void (*)(void *)) isis_nexthop_delete;
hassof390d2c2004-09-10 20:48:21 +0000325 list_delete (route_info->nexthops);
326 }
327
jardineb5d44e2003-12-23 08:09:43 +0000328#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000329 if (route_info->nexthops6)
330 {
hassof7c43dc2004-09-26 16:24:14 +0000331 route_info->nexthops6->del = (void (*)(void *)) isis_nexthop6_delete;
jardineb5d44e2003-12-23 08:09:43 +0000332 list_delete (route_info->nexthops6);
hassof390d2c2004-09-10 20:48:21 +0000333 }
jardineb5d44e2003-12-23 08:09:43 +0000334#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000335
jardineb5d44e2003-12-23 08:09:43 +0000336 XFREE (MTYPE_ISIS_ROUTE_INFO, route_info);
337}
338
hasso92365882005-01-18 13:53:33 +0000339static int
hassof390d2c2004-09-10 20:48:21 +0000340isis_route_info_same_attrib (struct isis_route_info *new,
341 struct isis_route_info *old)
jardineb5d44e2003-12-23 08:09:43 +0000342{
343 if (new->cost != old->cost)
344 return 0;
345 if (new->depth != old->depth)
346 return 0;
hassof390d2c2004-09-10 20:48:21 +0000347
jardineb5d44e2003-12-23 08:09:43 +0000348 return 1;
349}
350
hasso92365882005-01-18 13:53:33 +0000351static int
hassof390d2c2004-09-10 20:48:21 +0000352isis_route_info_same (struct isis_route_info *new,
353 struct isis_route_info *old, u_char family)
jardineb5d44e2003-12-23 08:09:43 +0000354{
paul1eb8ef22005-04-07 07:30:20 +0000355 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +0000356 struct isis_nexthop *nexthop;
357#ifdef HAVE_IPV6
358 struct isis_nexthop6 *nexthop6;
359#endif /* HAVE_IPV6 */
360 if (!isis_route_info_same_attrib (new, old))
361 return 0;
hassof390d2c2004-09-10 20:48:21 +0000362
363 if (family == AF_INET)
364 {
paul1eb8ef22005-04-07 07:30:20 +0000365 for (ALL_LIST_ELEMENTS (new->nexthops, node, nnode, nexthop))
366 if (nexthoplookup (old->nexthops, &nexthop->ip, nexthop->ifindex)
367 == 0)
368 return 0;
hassof390d2c2004-09-10 20:48:21 +0000369
paul1eb8ef22005-04-07 07:30:20 +0000370 for (ALL_LIST_ELEMENTS (old->nexthops, node, nnode, nexthop))
371 if (nexthoplookup (new->nexthops, &nexthop->ip, nexthop->ifindex)
372 == 0)
373 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000374 }
jardineb5d44e2003-12-23 08:09:43 +0000375#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000376 else if (family == AF_INET6)
377 {
paul1eb8ef22005-04-07 07:30:20 +0000378 for (ALL_LIST_ELEMENTS (new->nexthops6, node, nnode, nexthop6))
379 if (nexthop6lookup (old->nexthops6, &nexthop6->ip6,
380 nexthop6->ifindex) == 0)
381 return 0;
hassof390d2c2004-09-10 20:48:21 +0000382
paul1eb8ef22005-04-07 07:30:20 +0000383 for (ALL_LIST_ELEMENTS (old->nexthops6, node, nnode, nexthop6))
384 if (nexthop6lookup (new->nexthops6, &nexthop6->ip6,
385 nexthop6->ifindex) == 0)
386 return 0;
jardineb5d44e2003-12-23 08:09:43 +0000387 }
jardineb5d44e2003-12-23 08:09:43 +0000388#endif /* HAVE_IPV6 */
389
390 return 1;
391}
392
hasso92365882005-01-18 13:53:33 +0000393static void
jardineb5d44e2003-12-23 08:09:43 +0000394isis_nexthops_merge (struct list *new, struct list *old)
395{
paul1eb8ef22005-04-07 07:30:20 +0000396 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +0000397 struct isis_nexthop *nexthop;
398
paul1eb8ef22005-04-07 07:30:20 +0000399 for (ALL_LIST_ELEMENTS (new, node, nnode, nexthop))
hassof390d2c2004-09-10 20:48:21 +0000400 {
hassof390d2c2004-09-10 20:48:21 +0000401 if (nexthoplookup (old, &nexthop->ip, nexthop->ifindex))
402 continue;
403 listnode_add (old, nexthop);
404 nexthop->lock++;
405 }
jardineb5d44e2003-12-23 08:09:43 +0000406}
407
jardineb5d44e2003-12-23 08:09:43 +0000408#ifdef HAVE_IPV6
hasso92365882005-01-18 13:53:33 +0000409static void
jardineb5d44e2003-12-23 08:09:43 +0000410isis_nexthops6_merge (struct list *new, struct list *old)
411{
paul1eb8ef22005-04-07 07:30:20 +0000412 struct listnode *node, *nnode;
jardineb5d44e2003-12-23 08:09:43 +0000413 struct isis_nexthop6 *nexthop6;
414
paul1eb8ef22005-04-07 07:30:20 +0000415 for (ALL_LIST_ELEMENTS (new, node, nnode, nexthop6))
hassof390d2c2004-09-10 20:48:21 +0000416 {
hassof390d2c2004-09-10 20:48:21 +0000417 if (nexthop6lookup (old, &nexthop6->ip6, nexthop6->ifindex))
418 continue;
419 listnode_add (old, nexthop6);
420 nexthop6->lock++;
421 }
jardineb5d44e2003-12-23 08:09:43 +0000422}
423#endif /* HAVE_IPV6 */
424
hasso92365882005-01-18 13:53:33 +0000425static void
hassof390d2c2004-09-10 20:48:21 +0000426isis_route_info_merge (struct isis_route_info *new,
427 struct isis_route_info *old, u_char family)
jardineb5d44e2003-12-23 08:09:43 +0000428{
hassof390d2c2004-09-10 20:48:21 +0000429 if (family == AF_INET)
jardineb5d44e2003-12-23 08:09:43 +0000430 isis_nexthops_merge (new->nexthops, old->nexthops);
431#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000432 else if (family == AF_INET6)
jardineb5d44e2003-12-23 08:09:43 +0000433 isis_nexthops6_merge (new->nexthops6, old->nexthops6);
434#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000435
jardineb5d44e2003-12-23 08:09:43 +0000436 return;
437}
438
hasso92365882005-01-18 13:53:33 +0000439static int
hassof390d2c2004-09-10 20:48:21 +0000440isis_route_info_prefer_new (struct isis_route_info *new,
441 struct isis_route_info *old)
jardineb5d44e2003-12-23 08:09:43 +0000442{
jardineb5d44e2003-12-23 08:09:43 +0000443 if (!CHECK_FLAG (old->flag, ISIS_ROUTE_FLAG_ACTIVE))
444 return 1;
445
446 if (new->cost < old->cost)
447 return 1;
hassof390d2c2004-09-10 20:48:21 +0000448
jardineb5d44e2003-12-23 08:09:43 +0000449 return 0;
450}
451
jardineb5d44e2003-12-23 08:09:43 +0000452struct isis_route_info *
453isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth,
hassof390d2c2004-09-10 20:48:21 +0000454 struct list *adjacencies, struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +0000455{
456 struct route_node *route_node;
457 struct isis_route_info *rinfo_new, *rinfo_old, *route_info = NULL;
458 u_char buff[BUFSIZ];
459 u_char family;
hassof390d2c2004-09-10 20:48:21 +0000460
jardineb5d44e2003-12-23 08:09:43 +0000461 family = prefix->family;
462 /* for debugs */
hassof7c43dc2004-09-26 16:24:14 +0000463 prefix2str (prefix, (char *) buff, BUFSIZ);
hassof390d2c2004-09-10 20:48:21 +0000464
jardineb5d44e2003-12-23 08:09:43 +0000465 rinfo_new = isis_route_info_new (cost, depth, family, adjacencies);
hassof390d2c2004-09-10 20:48:21 +0000466 if (!rinfo_new)
467 {
468 zlog_err ("ISIS-Rte (%s): isis_route_create: out of memory!",
469 area->area_tag);
470 return NULL;
471 }
472
jardineb5d44e2003-12-23 08:09:43 +0000473 if (family == AF_INET)
hassof390d2c2004-09-10 20:48:21 +0000474 route_node = route_node_get (area->route_table, prefix);
jardineb5d44e2003-12-23 08:09:43 +0000475#ifdef HAVE_IPV6
476 else if (family == AF_INET6)
hassof390d2c2004-09-10 20:48:21 +0000477 route_node = route_node_get (area->route_table6, prefix);
jardineb5d44e2003-12-23 08:09:43 +0000478#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000479 else
jardineb5d44e2003-12-23 08:09:43 +0000480 return NULL;
hassof390d2c2004-09-10 20:48:21 +0000481 rinfo_old = route_node->info;
482 if (!rinfo_old)
483 {
484 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000485 zlog_debug ("ISIS-Rte (%s) route created: %s", area->area_tag, buff);
hassof390d2c2004-09-10 20:48:21 +0000486 SET_FLAG (rinfo_new->flag, ISIS_ROUTE_FLAG_ACTIVE);
487 route_node->info = rinfo_new;
488 return rinfo_new;
489 }
490
jardineb5d44e2003-12-23 08:09:43 +0000491 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000492 zlog_debug ("ISIS-Rte (%s) route already exists: %s", area->area_tag,
hassof390d2c2004-09-10 20:48:21 +0000493 buff);
494
495 if (isis_route_info_same (rinfo_new, rinfo_old, family))
496 {
jardineb5d44e2003-12-23 08:09:43 +0000497 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000498 zlog_debug ("ISIS-Rte (%s) route unchanged: %s", area->area_tag, buff);
jardineb5d44e2003-12-23 08:09:43 +0000499 isis_route_info_delete (rinfo_new);
500 route_info = rinfo_old;
501 }
hassof390d2c2004-09-10 20:48:21 +0000502 else if (isis_route_info_same_attrib (rinfo_new, rinfo_old))
503 {
504 /* merge the nexthop lists */
505 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000506 zlog_debug ("ISIS-Rte (%s) route changed (same attribs): %s",
hassof390d2c2004-09-10 20:48:21 +0000507 area->area_tag, buff);
508#ifdef EXTREME_DEBUG
hasso3d549272005-09-21 18:52:14 +0000509 if (family == AF_INET)
510 {
511 zlog_debug ("Old nexthops");
512 nexthops_print (rinfo_old->nexthops);
513 zlog_debug ("New nexthops");
514 nexthops_print (rinfo_new->nexthops);
515 }
516 else if (family == AF_INET6)
517 {
518 zlog_debug ("Old nexthops");
519 nexthops6_print (rinfo_old->nexthops6);
520 zlog_debug ("New nexthops");
521 nexthops6_print (rinfo_new->nexthops6);
522 }
hassof390d2c2004-09-10 20:48:21 +0000523#endif /* EXTREME_DEBUG */
524 isis_route_info_merge (rinfo_new, rinfo_old, family);
525 isis_route_info_delete (rinfo_new);
526 route_info = rinfo_old;
527 }
528 else
529 {
530 if (isis_route_info_prefer_new (rinfo_new, rinfo_old))
531 {
532 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000533 zlog_debug ("ISIS-Rte (%s) route changed: %s", area->area_tag,
534 buff);
hassof390d2c2004-09-10 20:48:21 +0000535 isis_route_info_delete (rinfo_old);
536 route_info = rinfo_new;
537 }
538 else
539 {
540 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000541 zlog_debug ("ISIS-Rte (%s) route rejected: %s", area->area_tag,
542 buff);
hassof390d2c2004-09-10 20:48:21 +0000543 isis_route_info_delete (rinfo_new);
544 route_info = rinfo_old;
545 }
546 }
547
jardineb5d44e2003-12-23 08:09:43 +0000548 SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE);
549 route_node->info = route_info;
hassof390d2c2004-09-10 20:48:21 +0000550
jardineb5d44e2003-12-23 08:09:43 +0000551 return route_info;
552}
553
hasso92365882005-01-18 13:53:33 +0000554static void
jardineb5d44e2003-12-23 08:09:43 +0000555isis_route_delete (struct prefix *prefix, struct route_table *table)
556{
557 struct route_node *rode;
558 struct isis_route_info *rinfo;
559 char buff[BUFSIZ];
560
561 /* for log */
562 prefix2str (prefix, buff, BUFSIZ);
563
564
565 rode = route_node_get (table, prefix);
566 rinfo = rode->info;
567
hassof390d2c2004-09-10 20:48:21 +0000568 if (rinfo == NULL)
569 {
570 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000571 zlog_debug ("ISIS-Rte: tried to delete non-existant route %s", buff);
hassof390d2c2004-09-10 20:48:21 +0000572 return;
573 }
jardineb5d44e2003-12-23 08:09:43 +0000574
hassof390d2c2004-09-10 20:48:21 +0000575 if (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
576 {
577 UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
578 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000579 zlog_debug ("ISIS-Rte: route delete %s", buff);
hassof390d2c2004-09-10 20:48:21 +0000580 isis_zebra_route_update (prefix, rinfo);
581 }
jardineb5d44e2003-12-23 08:09:43 +0000582 isis_route_info_delete (rinfo);
583 rode->info = NULL;
hassof390d2c2004-09-10 20:48:21 +0000584
jardineb5d44e2003-12-23 08:09:43 +0000585 return;
586}
587
588int
589isis_route_validate (struct thread *thread)
590{
591 struct isis_area *area;
592 struct route_table *table;
593 struct route_node *rode;
594 struct isis_route_info *rinfo;
595 u_char buff[BUFSIZ];
596#ifdef HAVE_IPV6
597 int v6done = 0;
598#endif
599 area = THREAD_ARG (thread);
600 table = area->route_table;
601#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000602again:
jardineb5d44e2003-12-23 08:09:43 +0000603#endif
hassof390d2c2004-09-10 20:48:21 +0000604 for (rode = route_top (table); rode; rode = route_next (rode))
605 {
606 if (rode->info == NULL)
607 continue;
608 rinfo = rode->info;
609
610 if (isis->debugs & DEBUG_RTE_EVENTS)
611 {
hassof7c43dc2004-09-26 16:24:14 +0000612 prefix2str (&rode->p, (char *) buff, BUFSIZ);
hasso529d65b2004-12-24 00:14:50 +0000613 zlog_debug ("ISIS-Rte (%s): route validate: %s %s %s",
614 area->area_tag,
615 (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC) ?
hassof390d2c2004-09-10 20:48:21 +0000616 "sync'ed" : "nosync"),
hasso529d65b2004-12-24 00:14:50 +0000617 (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE) ?
hassof390d2c2004-09-10 20:48:21 +0000618 "active" : "inactive"), buff);
619 }
620
621 isis_zebra_route_update (&rode->p, rinfo);
622 if (!CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE))
623 isis_route_delete (&rode->p, area->route_table);
jardineb5d44e2003-12-23 08:09:43 +0000624 }
jardineb5d44e2003-12-23 08:09:43 +0000625#ifdef HAVE_IPV6
626 if (v6done)
627 return ISIS_OK;
628 table = area->route_table6;
629 v6done = 1;
630 goto again;
631#endif
632
633 return ISIS_OK;
634}