]>
Commit | Line | Data |
---|---|---|
eb5d44eb | 1 | /* |
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> | |
eb5d44eb | 28 | |
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 | ||
53 | extern struct isis *isis; | |
54 | extern struct thread_master *master; | |
55 | ||
92365889 | 56 | static struct isis_nexthop * |
eb5d44eb | 57 | isis_nexthop_create (struct in_addr *ip, unsigned int ifindex) |
eb5d44eb | 58 | { |
59 | struct listnode *node; | |
60 | struct isis_nexthop *nexthop; | |
f390d2c7 | 61 | |
1eb8ef25 | 62 | for (ALL_LIST_ELEMENTS_RO (isis->nexthops, node, nexthop)) |
f390d2c7 | 63 | { |
f390d2c7 | 64 | 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 | ||
eb5d44eb | 73 | nexthop = XMALLOC (MTYPE_ISIS_NEXTHOP, sizeof (struct isis_nexthop)); |
f390d2c7 | 74 | if (!nexthop) |
75 | { | |
76 | zlog_err ("ISIS-Rte: isis_nexthop_create: out of memory!"); | |
77 | } | |
78 | ||
eb5d44eb | 79 | 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 | ||
92365889 | 88 | static void |
eb5d44eb | 89 | isis_nexthop_delete (struct isis_nexthop *nexthop) |
90 | { | |
91 | nexthop->lock--; | |
f390d2c7 | 92 | if (nexthop->lock == 0) |
93 | { | |
94 | listnode_delete (isis->nexthops, nexthop); | |
95 | XFREE (MTYPE_ISIS_NEXTHOP, nexthop); | |
96 | } | |
97 | ||
eb5d44eb | 98 | return; |
99 | } | |
100 | ||
92365889 | 101 | static int |
f390d2c7 | 102 | nexthoplookup (struct list *nexthops, struct in_addr *ip, |
103 | unsigned int ifindex) | |
eb5d44eb | 104 | { |
105 | struct listnode *node; | |
106 | struct isis_nexthop *nh; | |
107 | ||
1eb8ef25 | 108 | for (ALL_LIST_ELEMENTS_RO (nexthops, node, nh)) |
f390d2c7 | 109 | { |
f390d2c7 | 110 | if (!(memcmp (ip, &nh->ip, sizeof (struct in_addr))) && |
111 | ifindex == nh->ifindex) | |
112 | return 1; | |
113 | } | |
eb5d44eb | 114 | |
115 | return 0; | |
116 | } | |
117 | ||
92365889 | 118 | #if 0 /* Old or new code? */ |
119 | static void | |
eb5d44eb | 120 | nexthop_print (struct isis_nexthop *nh) |
121 | { | |
122 | u_char buf[BUFSIZ]; | |
f390d2c7 | 123 | |
f7c43dcb | 124 | inet_ntop (AF_INET, &nh->ip, (char *) buf, BUFSIZ); |
f390d2c7 | 125 | |
529d65b3 | 126 | zlog_debug (" %s %u", buf, nh->ifindex); |
eb5d44eb | 127 | } |
128 | ||
92365889 | 129 | static void |
eb5d44eb | 130 | nexthops_print (struct list *nhs) |
131 | { | |
132 | struct listnode *node; | |
f390d2c7 | 133 | |
1eb8ef25 | 134 | for (ALL_LIST_ELEMENTS_RO (nhs, node, nh)) |
135 | nexthop_print (nh); | |
eb5d44eb | 136 | } |
92365889 | 137 | #endif /* 0 */ |
eb5d44eb | 138 | |
139 | #ifdef HAVE_IPV6 | |
92365889 | 140 | static struct isis_nexthop6 * |
f390d2c7 | 141 | isis_nexthop6_new (struct in6_addr *ip6, unsigned int ifindex) |
eb5d44eb | 142 | { |
f390d2c7 | 143 | |
eb5d44eb | 144 | struct isis_nexthop6 *nexthop6; |
f390d2c7 | 145 | |
eb5d44eb | 146 | nexthop6 = XMALLOC (MTYPE_ISIS_NEXTHOP6, sizeof (struct isis_nexthop6)); |
f390d2c7 | 147 | if (!nexthop6) |
148 | { | |
149 | zlog_err ("ISIS-Rte: isis_nexthop_create6: out of memory!"); | |
150 | } | |
151 | ||
eb5d44eb | 152 | 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 | ||
92365889 | 160 | static struct isis_nexthop6 * |
eb5d44eb | 161 | isis_nexthop6_create (struct in6_addr *ip6, unsigned int ifindex) |
eb5d44eb | 162 | { |
163 | struct listnode *node; | |
164 | struct isis_nexthop6 *nexthop6; | |
f390d2c7 | 165 | |
1eb8ef25 | 166 | for (ALL_LIST_ELEMENTS_RO (isis->nexthops6, node, nexthop6)) |
f390d2c7 | 167 | { |
f390d2c7 | 168 | 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 | ||
eb5d44eb | 177 | nexthop6 = isis_nexthop6_new (ip6, ifindex); |
178 | ||
179 | return nexthop6; | |
180 | } | |
181 | ||
92365889 | 182 | static void |
eb5d44eb | 183 | isis_nexthop6_delete (struct isis_nexthop6 *nexthop6) |
184 | { | |
185 | ||
186 | nexthop6->lock--; | |
f390d2c7 | 187 | if (nexthop6->lock == 0) |
188 | { | |
189 | listnode_delete (isis->nexthops6, nexthop6); | |
190 | XFREE (MTYPE_ISIS_NEXTHOP6, nexthop6); | |
191 | } | |
192 | ||
eb5d44eb | 193 | return; |
194 | } | |
195 | ||
92365889 | 196 | static int |
f390d2c7 | 197 | nexthop6lookup (struct list *nexthops6, struct in6_addr *ip6, |
198 | unsigned int ifindex) | |
eb5d44eb | 199 | { |
200 | struct listnode *node; | |
201 | struct isis_nexthop6 *nh6; | |
202 | ||
1eb8ef25 | 203 | for (ALL_LIST_ELEMENTS_RO (nexthops6, node, nh6)) |
f390d2c7 | 204 | { |
f390d2c7 | 205 | if (!(memcmp (ip6, &nh6->ip6, sizeof (struct in6_addr))) && |
206 | ifindex == nh6->ifindex) | |
207 | return 1; | |
208 | } | |
eb5d44eb | 209 | |
210 | return 0; | |
211 | } | |
212 | ||
92365889 | 213 | #ifdef EXTREME_DEBUG |
214 | static void | |
eb5d44eb | 215 | nexthop6_print (struct isis_nexthop6 *nh6) |
216 | { | |
217 | u_char buf[BUFSIZ]; | |
f390d2c7 | 218 | |
f7c43dcb | 219 | inet_ntop (AF_INET6, &nh6->ip6, (char *) buf, BUFSIZ); |
f390d2c7 | 220 | |
529d65b3 | 221 | zlog_debug (" %s %u", buf, nh6->ifindex); |
eb5d44eb | 222 | } |
223 | ||
92365889 | 224 | static void |
eb5d44eb | 225 | nexthops6_print (struct list *nhs6) |
226 | { | |
227 | struct listnode *node; | |
f390d2c7 | 228 | |
1eb8ef25 | 229 | for (ALL_LIST_ELEMENTS_RO (nhs6, node, nh6)) |
230 | nexthop6_print (nh6); | |
eb5d44eb | 231 | } |
92365889 | 232 | #endif /* EXTREME_DEBUG */ |
eb5d44eb | 233 | #endif /* HAVE_IPV6 */ |
234 | ||
92365889 | 235 | static void |
eb5d44eb | 236 | adjinfo2nexthop (struct list *nexthops, struct isis_adjacency *adj) |
237 | { | |
238 | struct isis_nexthop *nh; | |
1eb8ef25 | 239 | struct listnode *node, *nnode; |
eb5d44eb | 240 | struct in_addr *ipv4_addr; |
241 | ||
242 | if (adj->ipv4_addrs == NULL) | |
243 | return; | |
1eb8ef25 | 244 | |
245 | for (ALL_LIST_ELEMENTS (adj->ipv4_addrs, node, nnode, ipv4_addr)) | |
f390d2c7 | 246 | { |
f390d2c7 | 247 | 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 | } | |
eb5d44eb | 254 | } |
eb5d44eb | 255 | } |
256 | ||
257 | #ifdef HAVE_IPV6 | |
92365889 | 258 | static void |
eb5d44eb | 259 | adjinfo2nexthop6 (struct list *nexthops6, struct isis_adjacency *adj) |
260 | { | |
1eb8ef25 | 261 | struct listnode *node, *nnode; |
eb5d44eb | 262 | struct in6_addr *ipv6_addr; |
263 | struct isis_nexthop6 *nh6; | |
f390d2c7 | 264 | |
eb5d44eb | 265 | if (!adj->ipv6_addrs) |
266 | return; | |
267 | ||
1eb8ef25 | 268 | for (ALL_LIST_ELEMENTS (adj->ipv6_addrs, node, nnode, ipv6_addr)) |
f390d2c7 | 269 | { |
f390d2c7 | 270 | 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 | } | |
eb5d44eb | 277 | } |
eb5d44eb | 278 | } |
279 | #endif /* HAVE_IPV6 */ | |
280 | ||
92365889 | 281 | static struct isis_route_info * |
f390d2c7 | 282 | isis_route_info_new (uint32_t cost, uint32_t depth, u_char family, |
283 | struct list *adjacencies) | |
eb5d44eb | 284 | { |
285 | struct isis_route_info *rinfo; | |
286 | struct isis_adjacency *adj; | |
1eb8ef25 | 287 | struct listnode *node, *nnode; |
f390d2c7 | 288 | |
eb5d44eb | 289 | rinfo = XMALLOC (MTYPE_ISIS_ROUTE_INFO, sizeof (struct isis_route_info)); |
f390d2c7 | 290 | if (!rinfo) |
291 | { | |
292 | zlog_err ("ISIS-Rte: isis_route_info_new: out of memory!"); | |
293 | return NULL; | |
294 | } | |
eb5d44eb | 295 | memset (rinfo, 0, sizeof (struct isis_route_info)); |
296 | ||
f390d2c7 | 297 | if (family == AF_INET) |
298 | { | |
299 | rinfo->nexthops = list_new (); | |
1eb8ef25 | 300 | for (ALL_LIST_ELEMENTS (adjacencies, node, nnode, adj)) |
301 | adjinfo2nexthop (rinfo->nexthops, adj); | |
eb5d44eb | 302 | } |
eb5d44eb | 303 | #ifdef HAVE_IPV6 |
f390d2c7 | 304 | if (family == AF_INET6) |
305 | { | |
306 | rinfo->nexthops6 = list_new (); | |
1eb8ef25 | 307 | for (ALL_LIST_ELEMENTS (adjacencies, node, nnode, adj)) |
308 | adjinfo2nexthop6 (rinfo->nexthops6, adj); | |
eb5d44eb | 309 | } |
f390d2c7 | 310 | |
eb5d44eb | 311 | #endif /* HAVE_IPV6 */ |
312 | ||
313 | rinfo->cost = cost; | |
314 | rinfo->depth = depth; | |
f390d2c7 | 315 | |
eb5d44eb | 316 | return rinfo; |
317 | } | |
318 | ||
92365889 | 319 | static void |
eb5d44eb | 320 | isis_route_info_delete (struct isis_route_info *route_info) |
321 | { | |
f390d2c7 | 322 | if (route_info->nexthops) |
323 | { | |
f7c43dcb | 324 | route_info->nexthops->del = (void (*)(void *)) isis_nexthop_delete; |
f390d2c7 | 325 | list_delete (route_info->nexthops); |
326 | } | |
327 | ||
eb5d44eb | 328 | #ifdef HAVE_IPV6 |
f390d2c7 | 329 | if (route_info->nexthops6) |
330 | { | |
f7c43dcb | 331 | route_info->nexthops6->del = (void (*)(void *)) isis_nexthop6_delete; |
eb5d44eb | 332 | list_delete (route_info->nexthops6); |
f390d2c7 | 333 | } |
eb5d44eb | 334 | #endif /* HAVE_IPV6 */ |
f390d2c7 | 335 | |
eb5d44eb | 336 | XFREE (MTYPE_ISIS_ROUTE_INFO, route_info); |
337 | } | |
338 | ||
92365889 | 339 | static int |
f390d2c7 | 340 | isis_route_info_same_attrib (struct isis_route_info *new, |
341 | struct isis_route_info *old) | |
eb5d44eb | 342 | { |
343 | if (new->cost != old->cost) | |
344 | return 0; | |
345 | if (new->depth != old->depth) | |
346 | return 0; | |
f390d2c7 | 347 | |
eb5d44eb | 348 | return 1; |
349 | } | |
350 | ||
92365889 | 351 | static int |
f390d2c7 | 352 | isis_route_info_same (struct isis_route_info *new, |
353 | struct isis_route_info *old, u_char family) | |
eb5d44eb | 354 | { |
1eb8ef25 | 355 | struct listnode *node, *nnode; |
eb5d44eb | 356 | 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; | |
f390d2c7 | 362 | |
363 | if (family == AF_INET) | |
364 | { | |
1eb8ef25 | 365 | for (ALL_LIST_ELEMENTS (new->nexthops, node, nnode, nexthop)) |
366 | if (nexthoplookup (old->nexthops, &nexthop->ip, nexthop->ifindex) | |
367 | == 0) | |
368 | return 0; | |
369 | ||
370 | for (ALL_LIST_ELEMENTS (old->nexthops, node, nnode, nexthop)) | |
371 | if (nexthoplookup (new->nexthops, &nexthop->ip, nexthop->ifindex) | |
372 | == 0) | |
373 | return 0; | |
eb5d44eb | 374 | } |
eb5d44eb | 375 | #ifdef HAVE_IPV6 |
f390d2c7 | 376 | else if (family == AF_INET6) |
377 | { | |
1eb8ef25 | 378 | for (ALL_LIST_ELEMENTS (new->nexthops6, node, nnode, nexthop6)) |
379 | if (nexthop6lookup (old->nexthops6, &nexthop6->ip6, | |
380 | nexthop6->ifindex) == 0) | |
381 | return 0; | |
382 | ||
383 | for (ALL_LIST_ELEMENTS (old->nexthops6, node, nnode, nexthop6)) | |
384 | if (nexthop6lookup (new->nexthops6, &nexthop6->ip6, | |
385 | nexthop6->ifindex) == 0) | |
386 | return 0; | |
eb5d44eb | 387 | } |
eb5d44eb | 388 | #endif /* HAVE_IPV6 */ |
389 | ||
390 | return 1; | |
391 | } | |
392 | ||
92365889 | 393 | static void |
eb5d44eb | 394 | isis_nexthops_merge (struct list *new, struct list *old) |
395 | { | |
1eb8ef25 | 396 | struct listnode *node, *nnode; |
eb5d44eb | 397 | struct isis_nexthop *nexthop; |
398 | ||
1eb8ef25 | 399 | for (ALL_LIST_ELEMENTS (new, node, nnode, nexthop)) |
f390d2c7 | 400 | { |
f390d2c7 | 401 | if (nexthoplookup (old, &nexthop->ip, nexthop->ifindex)) |
402 | continue; | |
403 | listnode_add (old, nexthop); | |
404 | nexthop->lock++; | |
405 | } | |
eb5d44eb | 406 | } |
407 | ||
eb5d44eb | 408 | #ifdef HAVE_IPV6 |
92365889 | 409 | static void |
eb5d44eb | 410 | isis_nexthops6_merge (struct list *new, struct list *old) |
411 | { | |
1eb8ef25 | 412 | struct listnode *node, *nnode; |
eb5d44eb | 413 | struct isis_nexthop6 *nexthop6; |
414 | ||
1eb8ef25 | 415 | for (ALL_LIST_ELEMENTS (new, node, nnode, nexthop6)) |
f390d2c7 | 416 | { |
f390d2c7 | 417 | if (nexthop6lookup (old, &nexthop6->ip6, nexthop6->ifindex)) |
418 | continue; | |
419 | listnode_add (old, nexthop6); | |
420 | nexthop6->lock++; | |
421 | } | |
eb5d44eb | 422 | } |
423 | #endif /* HAVE_IPV6 */ | |
424 | ||
92365889 | 425 | static void |
f390d2c7 | 426 | isis_route_info_merge (struct isis_route_info *new, |
427 | struct isis_route_info *old, u_char family) | |
eb5d44eb | 428 | { |
f390d2c7 | 429 | if (family == AF_INET) |
eb5d44eb | 430 | isis_nexthops_merge (new->nexthops, old->nexthops); |
431 | #ifdef HAVE_IPV6 | |
f390d2c7 | 432 | else if (family == AF_INET6) |
eb5d44eb | 433 | isis_nexthops6_merge (new->nexthops6, old->nexthops6); |
434 | #endif /* HAVE_IPV6 */ | |
f390d2c7 | 435 | |
eb5d44eb | 436 | return; |
437 | } | |
438 | ||
92365889 | 439 | static int |
f390d2c7 | 440 | isis_route_info_prefer_new (struct isis_route_info *new, |
441 | struct isis_route_info *old) | |
eb5d44eb | 442 | { |
eb5d44eb | 443 | if (!CHECK_FLAG (old->flag, ISIS_ROUTE_FLAG_ACTIVE)) |
444 | return 1; | |
445 | ||
446 | if (new->cost < old->cost) | |
447 | return 1; | |
f390d2c7 | 448 | |
eb5d44eb | 449 | return 0; |
450 | } | |
451 | ||
eb5d44eb | 452 | struct isis_route_info * |
453 | isis_route_create (struct prefix *prefix, u_int32_t cost, u_int32_t depth, | |
f390d2c7 | 454 | struct list *adjacencies, struct isis_area *area) |
eb5d44eb | 455 | { |
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; | |
f390d2c7 | 460 | |
eb5d44eb | 461 | family = prefix->family; |
462 | /* for debugs */ | |
f7c43dcb | 463 | prefix2str (prefix, (char *) buff, BUFSIZ); |
f390d2c7 | 464 | |
eb5d44eb | 465 | rinfo_new = isis_route_info_new (cost, depth, family, adjacencies); |
f390d2c7 | 466 | 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 | ||
eb5d44eb | 473 | if (family == AF_INET) |
f390d2c7 | 474 | route_node = route_node_get (area->route_table, prefix); |
eb5d44eb | 475 | #ifdef HAVE_IPV6 |
476 | else if (family == AF_INET6) | |
f390d2c7 | 477 | route_node = route_node_get (area->route_table6, prefix); |
eb5d44eb | 478 | #endif /* HAVE_IPV6 */ |
f390d2c7 | 479 | else |
eb5d44eb | 480 | return NULL; |
f390d2c7 | 481 | rinfo_old = route_node->info; |
482 | if (!rinfo_old) | |
483 | { | |
484 | if (isis->debugs & DEBUG_RTE_EVENTS) | |
529d65b3 | 485 | zlog_debug ("ISIS-Rte (%s) route created: %s", area->area_tag, buff); |
f390d2c7 | 486 | SET_FLAG (rinfo_new->flag, ISIS_ROUTE_FLAG_ACTIVE); |
487 | route_node->info = rinfo_new; | |
488 | return rinfo_new; | |
489 | } | |
490 | ||
eb5d44eb | 491 | if (isis->debugs & DEBUG_RTE_EVENTS) |
529d65b3 | 492 | zlog_debug ("ISIS-Rte (%s) route already exists: %s", area->area_tag, |
f390d2c7 | 493 | buff); |
494 | ||
495 | if (isis_route_info_same (rinfo_new, rinfo_old, family)) | |
496 | { | |
eb5d44eb | 497 | if (isis->debugs & DEBUG_RTE_EVENTS) |
529d65b3 | 498 | zlog_debug ("ISIS-Rte (%s) route unchanged: %s", area->area_tag, buff); |
f390d2c7 | 499 | isis_route_info_delete (rinfo_new); |
500 | route_info = rinfo_old; | |
501 | } | |
502 | else if (isis_route_info_same_attrib (rinfo_new, rinfo_old)) | |
503 | { | |
504 | /* merge the nexthop lists */ | |
eb5d44eb | 505 | if (isis->debugs & DEBUG_RTE_EVENTS) |
529d65b3 | 506 | zlog_debug ("ISIS-Rte (%s) route changed (same attribs): %s", |
f390d2c7 | 507 | area->area_tag, buff); |
508 | #ifdef EXTREME_DEBUG | |
529d65b3 | 509 | zlog_debug ("Old nexthops"); |
f390d2c7 | 510 | nexthops6_print (rinfo_old->nexthops6); |
529d65b3 | 511 | zlog_debug ("New nexthops"); |
f390d2c7 | 512 | nexthops6_print (rinfo_new->nexthops6); |
513 | #endif /* EXTREME_DEBUG */ | |
514 | isis_route_info_merge (rinfo_new, rinfo_old, family); | |
eb5d44eb | 515 | isis_route_info_delete (rinfo_new); |
516 | route_info = rinfo_old; | |
517 | } | |
f390d2c7 | 518 | else |
519 | { | |
520 | if (isis_route_info_prefer_new (rinfo_new, rinfo_old)) | |
521 | { | |
522 | if (isis->debugs & DEBUG_RTE_EVENTS) | |
529d65b3 | 523 | zlog_debug ("ISIS-Rte (%s) route changed: %s", area->area_tag, |
524 | buff); | |
f390d2c7 | 525 | isis_route_info_delete (rinfo_old); |
526 | route_info = rinfo_new; | |
527 | } | |
528 | else | |
529 | { | |
530 | if (isis->debugs & DEBUG_RTE_EVENTS) | |
529d65b3 | 531 | zlog_debug ("ISIS-Rte (%s) route rejected: %s", area->area_tag, |
532 | buff); | |
f390d2c7 | 533 | isis_route_info_delete (rinfo_new); |
534 | route_info = rinfo_old; | |
535 | } | |
536 | } | |
537 | ||
eb5d44eb | 538 | SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE); |
539 | route_node->info = route_info; | |
f390d2c7 | 540 | |
eb5d44eb | 541 | return route_info; |
542 | } | |
543 | ||
92365889 | 544 | static void |
eb5d44eb | 545 | isis_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 | ||
f390d2c7 | 558 | if (rinfo == NULL) |
559 | { | |
560 | if (isis->debugs & DEBUG_RTE_EVENTS) | |
529d65b3 | 561 | zlog_debug ("ISIS-Rte: tried to delete non-existant route %s", buff); |
f390d2c7 | 562 | return; |
563 | } | |
564 | ||
565 | 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) | |
529d65b3 | 569 | zlog_debug ("ISIS-Rte: route delete %s", buff); |
f390d2c7 | 570 | isis_zebra_route_update (prefix, rinfo); |
571 | } | |
eb5d44eb | 572 | isis_route_info_delete (rinfo); |
573 | rode->info = NULL; | |
f390d2c7 | 574 | |
eb5d44eb | 575 | return; |
576 | } | |
577 | ||
578 | int | |
579 | isis_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 | |
f390d2c7 | 592 | again: |
eb5d44eb | 593 | #endif |
f390d2c7 | 594 | 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 | { | |
f7c43dcb | 602 | prefix2str (&rode->p, (char *) buff, BUFSIZ); |
529d65b3 | 603 | zlog_debug ("ISIS-Rte (%s): route validate: %s %s %s", |
604 | area->area_tag, | |
605 | (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC) ? | |
f390d2c7 | 606 | "sync'ed" : "nosync"), |
529d65b3 | 607 | (CHECK_FLAG (rinfo->flag, ISIS_ROUTE_FLAG_ACTIVE) ? |
f390d2c7 | 608 | "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); | |
eb5d44eb | 614 | } |
eb5d44eb | 615 | #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 | } |