blob: 04346d4acbd0803d762c043f70d6f11a97838d41 [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
hasso92365882005-01-18 13:53:33 +0000118#if 0 /* Old or new code? */
119static 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}
hasso92365882005-01-18 13:53:33 +0000137#endif /* 0 */
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
hasso529d65b2004-12-24 00:14:50 +0000509 zlog_debug ("Old nexthops");
hassof390d2c2004-09-10 20:48:21 +0000510 nexthops6_print (rinfo_old->nexthops6);
hasso529d65b2004-12-24 00:14:50 +0000511 zlog_debug ("New nexthops");
hassof390d2c2004-09-10 20:48:21 +0000512 nexthops6_print (rinfo_new->nexthops6);
513#endif /* EXTREME_DEBUG */
514 isis_route_info_merge (rinfo_new, rinfo_old, family);
515 isis_route_info_delete (rinfo_new);
516 route_info = rinfo_old;
517 }
518 else
519 {
520 if (isis_route_info_prefer_new (rinfo_new, rinfo_old))
521 {
522 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000523 zlog_debug ("ISIS-Rte (%s) route changed: %s", area->area_tag,
524 buff);
hassof390d2c2004-09-10 20:48:21 +0000525 isis_route_info_delete (rinfo_old);
526 route_info = rinfo_new;
527 }
528 else
529 {
530 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000531 zlog_debug ("ISIS-Rte (%s) route rejected: %s", area->area_tag,
532 buff);
hassof390d2c2004-09-10 20:48:21 +0000533 isis_route_info_delete (rinfo_new);
534 route_info = rinfo_old;
535 }
536 }
537
jardineb5d44e2003-12-23 08:09:43 +0000538 SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE);
539 route_node->info = route_info;
hassof390d2c2004-09-10 20:48:21 +0000540
jardineb5d44e2003-12-23 08:09:43 +0000541 return route_info;
542}
543
hasso92365882005-01-18 13:53:33 +0000544static void
jardineb5d44e2003-12-23 08:09:43 +0000545isis_route_delete (struct prefix *prefix, struct route_table *table)
546{
547 struct route_node *rode;
548 struct isis_route_info *rinfo;
549 char buff[BUFSIZ];
550
551 /* for log */
552 prefix2str (prefix, buff, BUFSIZ);
553
554
555 rode = route_node_get (table, prefix);
556 rinfo = rode->info;
557
hassof390d2c2004-09-10 20:48:21 +0000558 if (rinfo == NULL)
559 {
560 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000561 zlog_debug ("ISIS-Rte: tried to delete non-existant route %s", buff);
hassof390d2c2004-09-10 20:48:21 +0000562 return;
563 }
jardineb5d44e2003-12-23 08:09:43 +0000564
hassof390d2c2004-09-10 20:48:21 +0000565 if (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
566 {
567 UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
568 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000569 zlog_debug ("ISIS-Rte: route delete %s", buff);
hassof390d2c2004-09-10 20:48:21 +0000570 isis_zebra_route_update (prefix, rinfo);
571 }
jardineb5d44e2003-12-23 08:09:43 +0000572 isis_route_info_delete (rinfo);
573 rode->info = NULL;
hassof390d2c2004-09-10 20:48:21 +0000574
jardineb5d44e2003-12-23 08:09:43 +0000575 return;
576}
577
578int
579isis_route_validate (struct thread *thread)
580{
581 struct isis_area *area;
582 struct route_table *table;
583 struct route_node *rode;
584 struct isis_route_info *rinfo;
585 u_char buff[BUFSIZ];
586#ifdef HAVE_IPV6
587 int v6done = 0;
588#endif
589 area = THREAD_ARG (thread);
590 table = area->route_table;
591#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000592again:
jardineb5d44e2003-12-23 08:09:43 +0000593#endif
hassof390d2c2004-09-10 20:48:21 +0000594 for (rode = route_top (table); rode; rode = route_next (rode))
595 {
596 if (rode->info == NULL)
597 continue;
598 rinfo = rode->info;
599
600 if (isis->debugs & DEBUG_RTE_EVENTS)
601 {
hassof7c43dc2004-09-26 16:24:14 +0000602 prefix2str (&rode->p, (char *) buff, BUFSIZ);
hasso529d65b2004-12-24 00:14:50 +0000603 zlog_debug ("ISIS-Rte (%s): route validate: %s %s %s",
604 area->area_tag,
605 (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC) ?
hassof390d2c2004-09-10 20:48:21 +0000606 "sync'ed" : "nosync"),
hasso529d65b2004-12-24 00:14:50 +0000607 (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE) ?
hassof390d2c2004-09-10 20:48:21 +0000608 "active" : "inactive"), buff);
609 }
610
611 isis_zebra_route_update (&rode->p, rinfo);
612 if (!CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE))
613 isis_route_delete (&rode->p, area->route_table);
jardineb5d44e2003-12-23 08:09:43 +0000614 }
jardineb5d44e2003-12-23 08:09:43 +0000615#ifdef HAVE_IPV6
616 if (v6done)
617 return ISIS_OK;
618 table = area->route_table6;
619 v6done = 1;
620 goto again;
621#endif
622
623 return ISIS_OK;
624}