blob: 3ef903808f47c49182da5418ac03fc7b25673604 [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
hassof390d2c2004-09-10 20:48:21 +000062 for (node = listhead (isis->nexthops); node; nextnode (node))
63 {
64 nexthop = getdata (node);
65 if (nexthop->ifindex != ifindex)
66 continue;
67 if (ip && memcmp (&nexthop->ip, ip, sizeof (struct in_addr)) != 0)
68 continue;
69
70 nexthop->lock++;
71 return nexthop;
72 }
73
jardineb5d44e2003-12-23 08:09:43 +000074 nexthop = XMALLOC (MTYPE_ISIS_NEXTHOP, sizeof (struct isis_nexthop));
hassof390d2c2004-09-10 20:48:21 +000075 if (!nexthop)
76 {
77 zlog_err ("ISIS-Rte: isis_nexthop_create: out of memory!");
78 }
79
jardineb5d44e2003-12-23 08:09:43 +000080 memset (nexthop, 0, sizeof (struct isis_nexthop));
81 nexthop->ifindex = ifindex;
82 memcpy (&nexthop->ip, ip, sizeof (struct in_addr));
83 listnode_add (isis->nexthops, nexthop);
84 nexthop->lock++;
85
86 return nexthop;
87}
88
hasso92365882005-01-18 13:53:33 +000089static void
jardineb5d44e2003-12-23 08:09:43 +000090isis_nexthop_delete (struct isis_nexthop *nexthop)
91{
92 nexthop->lock--;
hassof390d2c2004-09-10 20:48:21 +000093 if (nexthop->lock == 0)
94 {
95 listnode_delete (isis->nexthops, nexthop);
96 XFREE (MTYPE_ISIS_NEXTHOP, nexthop);
97 }
98
jardineb5d44e2003-12-23 08:09:43 +000099 return;
100}
101
hasso92365882005-01-18 13:53:33 +0000102static int
hassof390d2c2004-09-10 20:48:21 +0000103nexthoplookup (struct list *nexthops, struct in_addr *ip,
104 unsigned int ifindex)
jardineb5d44e2003-12-23 08:09:43 +0000105{
106 struct listnode *node;
107 struct isis_nexthop *nh;
108
hassof390d2c2004-09-10 20:48:21 +0000109 for (node = listhead (nexthops); node; nextnode (node))
110 {
111 nh = getdata (node);
112 if (!(memcmp (ip, &nh->ip, sizeof (struct in_addr))) &&
113 ifindex == nh->ifindex)
114 return 1;
115 }
jardineb5d44e2003-12-23 08:09:43 +0000116
117 return 0;
118}
119
hasso92365882005-01-18 13:53:33 +0000120#if 0 /* Old or new code? */
121static void
jardineb5d44e2003-12-23 08:09:43 +0000122nexthop_print (struct isis_nexthop *nh)
123{
124 u_char buf[BUFSIZ];
hassof390d2c2004-09-10 20:48:21 +0000125
hassof7c43dc2004-09-26 16:24:14 +0000126 inet_ntop (AF_INET, &nh->ip, (char *) buf, BUFSIZ);
hassof390d2c2004-09-10 20:48:21 +0000127
hasso529d65b2004-12-24 00:14:50 +0000128 zlog_debug (" %s %u", buf, nh->ifindex);
jardineb5d44e2003-12-23 08:09:43 +0000129}
130
hasso92365882005-01-18 13:53:33 +0000131static void
jardineb5d44e2003-12-23 08:09:43 +0000132nexthops_print (struct list *nhs)
133{
134 struct listnode *node;
hassof390d2c2004-09-10 20:48:21 +0000135
136 for (node = listhead (nhs); node; nextnode (node))
jardineb5d44e2003-12-23 08:09:43 +0000137 nexthop_print (getdata (node));
138}
hasso92365882005-01-18 13:53:33 +0000139#endif /* 0 */
jardineb5d44e2003-12-23 08:09:43 +0000140
141#ifdef HAVE_IPV6
hasso92365882005-01-18 13:53:33 +0000142static struct isis_nexthop6 *
hassof390d2c2004-09-10 20:48:21 +0000143isis_nexthop6_new (struct in6_addr *ip6, unsigned int ifindex)
jardineb5d44e2003-12-23 08:09:43 +0000144{
hassof390d2c2004-09-10 20:48:21 +0000145
jardineb5d44e2003-12-23 08:09:43 +0000146 struct isis_nexthop6 *nexthop6;
hassof390d2c2004-09-10 20:48:21 +0000147
jardineb5d44e2003-12-23 08:09:43 +0000148 nexthop6 = XMALLOC (MTYPE_ISIS_NEXTHOP6, sizeof (struct isis_nexthop6));
hassof390d2c2004-09-10 20:48:21 +0000149 if (!nexthop6)
150 {
151 zlog_err ("ISIS-Rte: isis_nexthop_create6: out of memory!");
152 }
153
jardineb5d44e2003-12-23 08:09:43 +0000154 memset (nexthop6, 0, sizeof (struct isis_nexthop6));
155 nexthop6->ifindex = ifindex;
156 memcpy (&nexthop6->ip6, ip6, sizeof (struct in6_addr));
157 nexthop6->lock++;
158
159 return nexthop6;
160}
161
hasso92365882005-01-18 13:53:33 +0000162static struct isis_nexthop6 *
jardineb5d44e2003-12-23 08:09:43 +0000163isis_nexthop6_create (struct in6_addr *ip6, unsigned int ifindex)
jardineb5d44e2003-12-23 08:09:43 +0000164{
165 struct listnode *node;
166 struct isis_nexthop6 *nexthop6;
jardineb5d44e2003-12-23 08:09:43 +0000167
hassof390d2c2004-09-10 20:48:21 +0000168 for (node = listhead (isis->nexthops6); node; nextnode (node))
169 {
170 nexthop6 = getdata (node);
171 if (nexthop6->ifindex != ifindex)
172 continue;
173 if (ip6 && memcmp (&nexthop6->ip6, ip6, sizeof (struct in6_addr)) != 0)
174 continue;
175
176 nexthop6->lock++;
177 return nexthop6;
178 }
179
jardineb5d44e2003-12-23 08:09:43 +0000180 nexthop6 = isis_nexthop6_new (ip6, ifindex);
181
182 return nexthop6;
183}
184
hasso92365882005-01-18 13:53:33 +0000185static void
jardineb5d44e2003-12-23 08:09:43 +0000186isis_nexthop6_delete (struct isis_nexthop6 *nexthop6)
187{
188
189 nexthop6->lock--;
hassof390d2c2004-09-10 20:48:21 +0000190 if (nexthop6->lock == 0)
191 {
192 listnode_delete (isis->nexthops6, nexthop6);
193 XFREE (MTYPE_ISIS_NEXTHOP6, nexthop6);
194 }
195
jardineb5d44e2003-12-23 08:09:43 +0000196 return;
197}
198
hasso92365882005-01-18 13:53:33 +0000199static int
hassof390d2c2004-09-10 20:48:21 +0000200nexthop6lookup (struct list *nexthops6, struct in6_addr *ip6,
201 unsigned int ifindex)
jardineb5d44e2003-12-23 08:09:43 +0000202{
203 struct listnode *node;
204 struct isis_nexthop6 *nh6;
205
hassof390d2c2004-09-10 20:48:21 +0000206 for (node = listhead (nexthops6); node; nextnode (node))
207 {
208 nh6 = getdata (node);
209 if (!(memcmp (ip6, &nh6->ip6, sizeof (struct in6_addr))) &&
210 ifindex == nh6->ifindex)
211 return 1;
212 }
jardineb5d44e2003-12-23 08:09:43 +0000213
214 return 0;
215}
216
hasso92365882005-01-18 13:53:33 +0000217#ifdef EXTREME_DEBUG
218static void
jardineb5d44e2003-12-23 08:09:43 +0000219nexthop6_print (struct isis_nexthop6 *nh6)
220{
221 u_char buf[BUFSIZ];
hassof390d2c2004-09-10 20:48:21 +0000222
hassof7c43dc2004-09-26 16:24:14 +0000223 inet_ntop (AF_INET6, &nh6->ip6, (char *) buf, BUFSIZ);
hassof390d2c2004-09-10 20:48:21 +0000224
hasso529d65b2004-12-24 00:14:50 +0000225 zlog_debug (" %s %u", buf, nh6->ifindex);
jardineb5d44e2003-12-23 08:09:43 +0000226}
227
hasso92365882005-01-18 13:53:33 +0000228static void
jardineb5d44e2003-12-23 08:09:43 +0000229nexthops6_print (struct list *nhs6)
230{
231 struct listnode *node;
hassof390d2c2004-09-10 20:48:21 +0000232
233 for (node = listhead (nhs6); node; nextnode (node))
jardineb5d44e2003-12-23 08:09:43 +0000234 nexthop6_print (getdata (node));
235}
hasso92365882005-01-18 13:53:33 +0000236#endif /* EXTREME_DEBUG */
jardineb5d44e2003-12-23 08:09:43 +0000237#endif /* HAVE_IPV6 */
238
hasso92365882005-01-18 13:53:33 +0000239static void
jardineb5d44e2003-12-23 08:09:43 +0000240adjinfo2nexthop (struct list *nexthops, struct isis_adjacency *adj)
241{
242 struct isis_nexthop *nh;
243 struct listnode *node;
244 struct in_addr *ipv4_addr;
245
246 if (adj->ipv4_addrs == NULL)
247 return;
hassof390d2c2004-09-10 20:48:21 +0000248 for (node = listhead (adj->ipv4_addrs); node; nextnode (node))
249 {
250 ipv4_addr = getdata (node);
251 if (!nexthoplookup (nexthops, ipv4_addr,
252 adj->circuit->interface->ifindex))
253 {
254 nh = isis_nexthop_create (ipv4_addr,
255 adj->circuit->interface->ifindex);
256 listnode_add (nexthops, nh);
257 }
jardineb5d44e2003-12-23 08:09:43 +0000258 }
jardineb5d44e2003-12-23 08:09:43 +0000259}
260
261#ifdef HAVE_IPV6
hasso92365882005-01-18 13:53:33 +0000262static void
jardineb5d44e2003-12-23 08:09:43 +0000263adjinfo2nexthop6 (struct list *nexthops6, struct isis_adjacency *adj)
264{
265 struct listnode *node;
266 struct in6_addr *ipv6_addr;
267 struct isis_nexthop6 *nh6;
hassof390d2c2004-09-10 20:48:21 +0000268
jardineb5d44e2003-12-23 08:09:43 +0000269 if (!adj->ipv6_addrs)
270 return;
271
hassof390d2c2004-09-10 20:48:21 +0000272 for (node = listhead (adj->ipv6_addrs); node; nextnode (node))
273 {
274 ipv6_addr = getdata (node);
275 if (!nexthop6lookup (nexthops6, ipv6_addr,
276 adj->circuit->interface->ifindex))
277 {
278 nh6 = isis_nexthop6_create (ipv6_addr,
279 adj->circuit->interface->ifindex);
280 listnode_add (nexthops6, nh6);
281 }
jardineb5d44e2003-12-23 08:09:43 +0000282 }
jardineb5d44e2003-12-23 08:09:43 +0000283}
284#endif /* HAVE_IPV6 */
285
hasso92365882005-01-18 13:53:33 +0000286static struct isis_route_info *
hassof390d2c2004-09-10 20:48:21 +0000287isis_route_info_new (uint32_t cost, uint32_t depth, u_char family,
288 struct list *adjacencies)
jardineb5d44e2003-12-23 08:09:43 +0000289{
290 struct isis_route_info *rinfo;
291 struct isis_adjacency *adj;
292 struct listnode *node;
hassof390d2c2004-09-10 20:48:21 +0000293
jardineb5d44e2003-12-23 08:09:43 +0000294 rinfo = XMALLOC (MTYPE_ISIS_ROUTE_INFO, sizeof (struct isis_route_info));
hassof390d2c2004-09-10 20:48:21 +0000295 if (!rinfo)
296 {
297 zlog_err ("ISIS-Rte: isis_route_info_new: out of memory!");
298 return NULL;
299 }
jardineb5d44e2003-12-23 08:09:43 +0000300 memset (rinfo, 0, sizeof (struct isis_route_info));
301
hassof390d2c2004-09-10 20:48:21 +0000302 if (family == AF_INET)
303 {
304 rinfo->nexthops = list_new ();
305 for (node = listhead (adjacencies); node; nextnode (node))
306 {
307 adj = getdata (node);
308 adjinfo2nexthop (rinfo->nexthops, adj);
309 }
jardineb5d44e2003-12-23 08:09:43 +0000310 }
jardineb5d44e2003-12-23 08:09:43 +0000311#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000312 if (family == AF_INET6)
313 {
314 rinfo->nexthops6 = list_new ();
315 for (node = listhead (adjacencies); node; nextnode (node))
316 {
317 adj = getdata (node);
318 adjinfo2nexthop6 (rinfo->nexthops6, adj);
319 }
jardineb5d44e2003-12-23 08:09:43 +0000320 }
hassof390d2c2004-09-10 20:48:21 +0000321
jardineb5d44e2003-12-23 08:09:43 +0000322#endif /* HAVE_IPV6 */
323
324 rinfo->cost = cost;
325 rinfo->depth = depth;
hassof390d2c2004-09-10 20:48:21 +0000326
jardineb5d44e2003-12-23 08:09:43 +0000327 return rinfo;
328}
329
hasso92365882005-01-18 13:53:33 +0000330static void
jardineb5d44e2003-12-23 08:09:43 +0000331isis_route_info_delete (struct isis_route_info *route_info)
332{
hassof390d2c2004-09-10 20:48:21 +0000333 if (route_info->nexthops)
334 {
hassof7c43dc2004-09-26 16:24:14 +0000335 route_info->nexthops->del = (void (*)(void *)) isis_nexthop_delete;
hassof390d2c2004-09-10 20:48:21 +0000336 list_delete (route_info->nexthops);
337 }
338
jardineb5d44e2003-12-23 08:09:43 +0000339#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000340 if (route_info->nexthops6)
341 {
hassof7c43dc2004-09-26 16:24:14 +0000342 route_info->nexthops6->del = (void (*)(void *)) isis_nexthop6_delete;
jardineb5d44e2003-12-23 08:09:43 +0000343 list_delete (route_info->nexthops6);
hassof390d2c2004-09-10 20:48:21 +0000344 }
jardineb5d44e2003-12-23 08:09:43 +0000345#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000346
jardineb5d44e2003-12-23 08:09:43 +0000347 XFREE (MTYPE_ISIS_ROUTE_INFO, route_info);
348}
349
hasso92365882005-01-18 13:53:33 +0000350static int
hassof390d2c2004-09-10 20:48:21 +0000351isis_route_info_same_attrib (struct isis_route_info *new,
352 struct isis_route_info *old)
jardineb5d44e2003-12-23 08:09:43 +0000353{
354 if (new->cost != old->cost)
355 return 0;
356 if (new->depth != old->depth)
357 return 0;
hassof390d2c2004-09-10 20:48:21 +0000358
jardineb5d44e2003-12-23 08:09:43 +0000359 return 1;
360}
361
hasso92365882005-01-18 13:53:33 +0000362static int
hassof390d2c2004-09-10 20:48:21 +0000363isis_route_info_same (struct isis_route_info *new,
364 struct isis_route_info *old, u_char family)
jardineb5d44e2003-12-23 08:09:43 +0000365{
hassof390d2c2004-09-10 20:48:21 +0000366 struct listnode *node;
jardineb5d44e2003-12-23 08:09:43 +0000367 struct isis_nexthop *nexthop;
368#ifdef HAVE_IPV6
369 struct isis_nexthop6 *nexthop6;
370#endif /* HAVE_IPV6 */
371 if (!isis_route_info_same_attrib (new, old))
372 return 0;
hassof390d2c2004-09-10 20:48:21 +0000373
374 if (family == AF_INET)
375 {
376 for (node = listhead (new->nexthops); node; nextnode (node))
377 {
378 nexthop = (struct isis_nexthop *) getdata (node);
379 if (nexthoplookup (old->nexthops, &nexthop->ip, nexthop->ifindex) ==
380 0)
381 return 0;
382 }
383
384 for (node = listhead (old->nexthops); node; nextnode (node))
385 {
386 nexthop = (struct isis_nexthop *) getdata (node);
387 if (nexthoplookup (new->nexthops, &nexthop->ip, nexthop->ifindex) ==
388 0)
389 return 0;
390 }
jardineb5d44e2003-12-23 08:09:43 +0000391 }
jardineb5d44e2003-12-23 08:09:43 +0000392#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000393 else if (family == AF_INET6)
394 {
395 for (node = listhead (new->nexthops6); node; nextnode (node))
396 {
397 nexthop6 = (struct isis_nexthop6 *) getdata (node);
398 if (nexthop6lookup (old->nexthops6, &nexthop6->ip6,
399 nexthop6->ifindex) == 0)
400 return 0;
401 }
402
403 for (node = listhead (old->nexthops6); node; nextnode (node))
404 {
405 nexthop6 = (struct isis_nexthop6 *) getdata (node);
406 if (nexthop6lookup (new->nexthops6, &nexthop6->ip6,
407 nexthop6->ifindex) == 0)
408 return 0;
409 }
jardineb5d44e2003-12-23 08:09:43 +0000410 }
jardineb5d44e2003-12-23 08:09:43 +0000411#endif /* HAVE_IPV6 */
412
413 return 1;
414}
415
hasso92365882005-01-18 13:53:33 +0000416static void
jardineb5d44e2003-12-23 08:09:43 +0000417isis_nexthops_merge (struct list *new, struct list *old)
418{
419 struct listnode *node;
420 struct isis_nexthop *nexthop;
421
hassof390d2c2004-09-10 20:48:21 +0000422 for (node = listhead (new); node; nextnode (node))
423 {
424 nexthop = (struct isis_nexthop *) getdata (node);
425 if (nexthoplookup (old, &nexthop->ip, nexthop->ifindex))
426 continue;
427 listnode_add (old, nexthop);
428 nexthop->lock++;
429 }
jardineb5d44e2003-12-23 08:09:43 +0000430}
431
jardineb5d44e2003-12-23 08:09:43 +0000432#ifdef HAVE_IPV6
hasso92365882005-01-18 13:53:33 +0000433static void
jardineb5d44e2003-12-23 08:09:43 +0000434isis_nexthops6_merge (struct list *new, struct list *old)
435{
436 struct listnode *node;
437 struct isis_nexthop6 *nexthop6;
438
hassof390d2c2004-09-10 20:48:21 +0000439 for (node = listhead (new); node; nextnode (node))
440 {
441 nexthop6 = (struct isis_nexthop6 *) getdata (node);
442 if (nexthop6lookup (old, &nexthop6->ip6, nexthop6->ifindex))
443 continue;
444 listnode_add (old, nexthop6);
445 nexthop6->lock++;
446 }
jardineb5d44e2003-12-23 08:09:43 +0000447}
448#endif /* HAVE_IPV6 */
449
hasso92365882005-01-18 13:53:33 +0000450static void
hassof390d2c2004-09-10 20:48:21 +0000451isis_route_info_merge (struct isis_route_info *new,
452 struct isis_route_info *old, u_char family)
jardineb5d44e2003-12-23 08:09:43 +0000453{
hassof390d2c2004-09-10 20:48:21 +0000454 if (family == AF_INET)
jardineb5d44e2003-12-23 08:09:43 +0000455 isis_nexthops_merge (new->nexthops, old->nexthops);
456#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000457 else if (family == AF_INET6)
jardineb5d44e2003-12-23 08:09:43 +0000458 isis_nexthops6_merge (new->nexthops6, old->nexthops6);
459#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000460
jardineb5d44e2003-12-23 08:09:43 +0000461 return;
462}
463
hasso92365882005-01-18 13:53:33 +0000464static int
hassof390d2c2004-09-10 20:48:21 +0000465isis_route_info_prefer_new (struct isis_route_info *new,
466 struct isis_route_info *old)
jardineb5d44e2003-12-23 08:09:43 +0000467{
jardineb5d44e2003-12-23 08:09:43 +0000468 if (!CHECK_FLAG (old->flag, ISIS_ROUTE_FLAG_ACTIVE))
469 return 1;
470
471 if (new->cost < old->cost)
472 return 1;
hassof390d2c2004-09-10 20:48:21 +0000473
jardineb5d44e2003-12-23 08:09:43 +0000474 return 0;
475}
476
jardineb5d44e2003-12-23 08:09:43 +0000477struct isis_route_info *
478isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth,
hassof390d2c2004-09-10 20:48:21 +0000479 struct list *adjacencies, struct isis_area *area)
jardineb5d44e2003-12-23 08:09:43 +0000480{
481 struct route_node *route_node;
482 struct isis_route_info *rinfo_new, *rinfo_old, *route_info = NULL;
483 u_char buff[BUFSIZ];
484 u_char family;
hassof390d2c2004-09-10 20:48:21 +0000485
jardineb5d44e2003-12-23 08:09:43 +0000486 family = prefix->family;
487 /* for debugs */
hassof7c43dc2004-09-26 16:24:14 +0000488 prefix2str (prefix, (char *) buff, BUFSIZ);
hassof390d2c2004-09-10 20:48:21 +0000489
jardineb5d44e2003-12-23 08:09:43 +0000490 rinfo_new = isis_route_info_new (cost, depth, family, adjacencies);
hassof390d2c2004-09-10 20:48:21 +0000491 if (!rinfo_new)
492 {
493 zlog_err ("ISIS-Rte (%s): isis_route_create: out of memory!",
494 area->area_tag);
495 return NULL;
496 }
497
jardineb5d44e2003-12-23 08:09:43 +0000498 if (family == AF_INET)
hassof390d2c2004-09-10 20:48:21 +0000499 route_node = route_node_get (area->route_table, prefix);
jardineb5d44e2003-12-23 08:09:43 +0000500#ifdef HAVE_IPV6
501 else if (family == AF_INET6)
hassof390d2c2004-09-10 20:48:21 +0000502 route_node = route_node_get (area->route_table6, prefix);
jardineb5d44e2003-12-23 08:09:43 +0000503#endif /* HAVE_IPV6 */
hassof390d2c2004-09-10 20:48:21 +0000504 else
jardineb5d44e2003-12-23 08:09:43 +0000505 return NULL;
hassof390d2c2004-09-10 20:48:21 +0000506 rinfo_old = route_node->info;
507 if (!rinfo_old)
508 {
509 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000510 zlog_debug ("ISIS-Rte (%s) route created: %s", area->area_tag, buff);
hassof390d2c2004-09-10 20:48:21 +0000511 SET_FLAG (rinfo_new->flag, ISIS_ROUTE_FLAG_ACTIVE);
512 route_node->info = rinfo_new;
513 return rinfo_new;
514 }
515
jardineb5d44e2003-12-23 08:09:43 +0000516 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000517 zlog_debug ("ISIS-Rte (%s) route already exists: %s", area->area_tag,
hassof390d2c2004-09-10 20:48:21 +0000518 buff);
519
520 if (isis_route_info_same (rinfo_new, rinfo_old, family))
521 {
jardineb5d44e2003-12-23 08:09:43 +0000522 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000523 zlog_debug ("ISIS-Rte (%s) route unchanged: %s", area->area_tag, buff);
jardineb5d44e2003-12-23 08:09:43 +0000524 isis_route_info_delete (rinfo_new);
525 route_info = rinfo_old;
526 }
hassof390d2c2004-09-10 20:48:21 +0000527 else if (isis_route_info_same_attrib (rinfo_new, rinfo_old))
528 {
529 /* merge the nexthop lists */
530 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000531 zlog_debug ("ISIS-Rte (%s) route changed (same attribs): %s",
hassof390d2c2004-09-10 20:48:21 +0000532 area->area_tag, buff);
533#ifdef EXTREME_DEBUG
hasso529d65b2004-12-24 00:14:50 +0000534 zlog_debug ("Old nexthops");
hassof390d2c2004-09-10 20:48:21 +0000535 nexthops6_print (rinfo_old->nexthops6);
hasso529d65b2004-12-24 00:14:50 +0000536 zlog_debug ("New nexthops");
hassof390d2c2004-09-10 20:48:21 +0000537 nexthops6_print (rinfo_new->nexthops6);
538#endif /* EXTREME_DEBUG */
539 isis_route_info_merge (rinfo_new, rinfo_old, family);
540 isis_route_info_delete (rinfo_new);
541 route_info = rinfo_old;
542 }
543 else
544 {
545 if (isis_route_info_prefer_new (rinfo_new, rinfo_old))
546 {
547 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000548 zlog_debug ("ISIS-Rte (%s) route changed: %s", area->area_tag,
549 buff);
hassof390d2c2004-09-10 20:48:21 +0000550 isis_route_info_delete (rinfo_old);
551 route_info = rinfo_new;
552 }
553 else
554 {
555 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000556 zlog_debug ("ISIS-Rte (%s) route rejected: %s", area->area_tag,
557 buff);
hassof390d2c2004-09-10 20:48:21 +0000558 isis_route_info_delete (rinfo_new);
559 route_info = rinfo_old;
560 }
561 }
562
jardineb5d44e2003-12-23 08:09:43 +0000563 SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE);
564 route_node->info = route_info;
hassof390d2c2004-09-10 20:48:21 +0000565
jardineb5d44e2003-12-23 08:09:43 +0000566 return route_info;
567}
568
hasso92365882005-01-18 13:53:33 +0000569static void
jardineb5d44e2003-12-23 08:09:43 +0000570isis_route_delete (struct prefix *prefix, struct route_table *table)
571{
572 struct route_node *rode;
573 struct isis_route_info *rinfo;
574 char buff[BUFSIZ];
575
576 /* for log */
577 prefix2str (prefix, buff, BUFSIZ);
578
579
580 rode = route_node_get (table, prefix);
581 rinfo = rode->info;
582
hassof390d2c2004-09-10 20:48:21 +0000583 if (rinfo == NULL)
584 {
585 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000586 zlog_debug ("ISIS-Rte: tried to delete non-existant route %s", buff);
hassof390d2c2004-09-10 20:48:21 +0000587 return;
588 }
jardineb5d44e2003-12-23 08:09:43 +0000589
hassof390d2c2004-09-10 20:48:21 +0000590 if (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
591 {
592 UNSET_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE);
593 if (isis->debugs & DEBUG_RTE_EVENTS)
hasso529d65b2004-12-24 00:14:50 +0000594 zlog_debug ("ISIS-Rte: route delete %s", buff);
hassof390d2c2004-09-10 20:48:21 +0000595 isis_zebra_route_update (prefix, rinfo);
596 }
jardineb5d44e2003-12-23 08:09:43 +0000597 isis_route_info_delete (rinfo);
598 rode->info = NULL;
hassof390d2c2004-09-10 20:48:21 +0000599
jardineb5d44e2003-12-23 08:09:43 +0000600 return;
601}
602
603int
604isis_route_validate (struct thread *thread)
605{
606 struct isis_area *area;
607 struct route_table *table;
608 struct route_node *rode;
609 struct isis_route_info *rinfo;
610 u_char buff[BUFSIZ];
611#ifdef HAVE_IPV6
612 int v6done = 0;
613#endif
614 area = THREAD_ARG (thread);
615 table = area->route_table;
616#ifdef HAVE_IPV6
hassof390d2c2004-09-10 20:48:21 +0000617again:
jardineb5d44e2003-12-23 08:09:43 +0000618#endif
hassof390d2c2004-09-10 20:48:21 +0000619 for (rode = route_top (table); rode; rode = route_next (rode))
620 {
621 if (rode->info == NULL)
622 continue;
623 rinfo = rode->info;
624
625 if (isis->debugs & DEBUG_RTE_EVENTS)
626 {
hassof7c43dc2004-09-26 16:24:14 +0000627 prefix2str (&rode->p, (char *) buff, BUFSIZ);
hasso529d65b2004-12-24 00:14:50 +0000628 zlog_debug ("ISIS-Rte (%s): route validate: %s %s %s",
629 area->area_tag,
630 (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC) ?
hassof390d2c2004-09-10 20:48:21 +0000631 "sync'ed" : "nosync"),
hasso529d65b2004-12-24 00:14:50 +0000632 (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE) ?
hassof390d2c2004-09-10 20:48:21 +0000633 "active" : "inactive"), buff);
634 }
635
636 isis_zebra_route_update (&rode->p, rinfo);
637 if (!CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE))
638 isis_route_delete (&rode->p, area->route_table);
jardineb5d44e2003-12-23 08:09:43 +0000639 }
jardineb5d44e2003-12-23 08:09:43 +0000640#ifdef HAVE_IPV6
641 if (v6done)
642 return ISIS_OK;
643 table = area->route_table6;
644 v6done = 1;
645 goto again;
646#endif
647
648 return ISIS_OK;
649}