]>
Commit | Line | Data |
---|---|---|
eb5d44eb | 1 | /* |
2 | * IS-IS Rout(e)ing protocol - isis_adjacency.c | |
3 | * handling of IS-IS adjacencies | |
4 | * | |
5 | * Copyright (C) 2001,2002 Sampo Saaristo | |
6 | * Tampere University of Technology | |
7 | * Institute of Communications Engineering | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify it | |
10 | * under the terms of the GNU General Public Licenseas published by the Free | |
11 | * Software Foundation; either version 2 of the License, or (at your option) | |
12 | * any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful,but WITHOUT | |
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
17 | * more details. | |
18 | ||
19 | * You should have received a copy of the GNU General Public License along | |
20 | * with this program; if not, write to the Free Software Foundation, Inc., | |
21 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
22 | */ | |
23 | ||
eb5d44eb | 24 | #include <zebra.h> |
eb5d44eb | 25 | |
26 | #include "log.h" | |
27 | #include "memory.h" | |
28 | #include "hash.h" | |
29 | #include "vty.h" | |
30 | #include "linklist.h" | |
31 | #include "thread.h" | |
32 | #include "if.h" | |
33 | #include "stream.h" | |
34 | ||
35 | #include "isisd/dict.h" | |
eb5d44eb | 36 | #include "isisd/isis_constants.h" |
37 | #include "isisd/isis_common.h" | |
3f045a08 | 38 | #include "isisd/isis_flags.h" |
eb5d44eb | 39 | #include "isisd/isisd.h" |
40 | #include "isisd/isis_circuit.h" | |
41 | #include "isisd/isis_adjacency.h" | |
42 | #include "isisd/isis_misc.h" | |
43 | #include "isisd/isis_dr.h" | |
44 | #include "isisd/isis_dynhn.h" | |
45 | #include "isisd/isis_pdu.h" | |
3f045a08 JB |
46 | #include "isisd/isis_tlv.h" |
47 | #include "isisd/isis_lsp.h" | |
48 | #include "isisd/isis_spf.h" | |
49 | #include "isisd/isis_events.h" | |
eb5d44eb | 50 | |
eb5d44eb | 51 | extern struct isis *isis; |
52 | ||
92365889 | 53 | static struct isis_adjacency * |
02e33d3e | 54 | adj_alloc (const u_char *id) |
eb5d44eb | 55 | { |
f390d2c7 | 56 | struct isis_adjacency *adj; |
eb5d44eb | 57 | |
aac372f4 | 58 | adj = XCALLOC (MTYPE_ISIS_ADJACENCY, sizeof (struct isis_adjacency)); |
f390d2c7 | 59 | memcpy (adj->sysid, id, ISIS_SYS_ID_LEN); |
60 | ||
61 | return adj; | |
eb5d44eb | 62 | } |
63 | ||
64 | struct isis_adjacency * | |
02e33d3e | 65 | isis_new_adj (const u_char * id, const u_char * snpa, int level, |
eb5d44eb | 66 | struct isis_circuit *circuit) |
67 | { | |
eb5d44eb | 68 | struct isis_adjacency *adj; |
f390d2c7 | 69 | int i; |
70 | ||
71 | adj = adj_alloc (id); /* P2P kludge */ | |
eb5d44eb | 72 | |
f390d2c7 | 73 | if (adj == NULL) |
74 | { | |
75 | zlog_err ("Out of memory!"); | |
76 | return NULL; | |
77 | } | |
eb5d44eb | 78 | |
41b36e90 | 79 | if (snpa) { |
3f045a08 | 80 | memcpy (adj->snpa, snpa, ETH_ALEN); |
41b36e90 | 81 | } else { |
3f045a08 | 82 | memset (adj->snpa, ' ', ETH_ALEN); |
41b36e90 PJ |
83 | } |
84 | ||
eb5d44eb | 85 | adj->circuit = circuit; |
86 | adj->level = level; | |
87 | adj->flaps = 0; | |
88 | adj->last_flap = time (NULL); | |
f390d2c7 | 89 | if (circuit->circ_type == CIRCUIT_T_BROADCAST) |
90 | { | |
91 | listnode_add (circuit->u.bc.adjdb[level - 1], adj); | |
92 | adj->dischanges[level - 1] = 0; | |
93 | for (i = 0; i < DIS_RECORDS; i++) /* clear N DIS state change records */ | |
eb5d44eb | 94 | { |
f390d2c7 | 95 | adj->dis_record[(i * ISIS_LEVELS) + level - 1].dis |
eb5d44eb | 96 | = ISIS_UNKNOWN_DIS; |
f390d2c7 | 97 | adj->dis_record[(i * ISIS_LEVELS) + level - 1].last_dis_change |
98 | = time (NULL); | |
eb5d44eb | 99 | } |
f390d2c7 | 100 | } |
eb5d44eb | 101 | |
102 | return adj; | |
103 | } | |
104 | ||
105 | struct isis_adjacency * | |
02e33d3e | 106 | isis_adj_lookup (const u_char * sysid, struct list *adjdb) |
eb5d44eb | 107 | { |
108 | struct isis_adjacency *adj; | |
109 | struct listnode *node; | |
110 | ||
1eb8ef25 | 111 | for (ALL_LIST_ELEMENTS_RO (adjdb, node, adj)) |
112 | if (memcmp (adj->sysid, sysid, ISIS_SYS_ID_LEN) == 0) | |
113 | return adj; | |
f390d2c7 | 114 | |
eb5d44eb | 115 | return NULL; |
116 | } | |
117 | ||
eb5d44eb | 118 | struct isis_adjacency * |
02e33d3e | 119 | isis_adj_lookup_snpa (const u_char * ssnpa, struct list *adjdb) |
eb5d44eb | 120 | { |
121 | struct listnode *node; | |
122 | struct isis_adjacency *adj; | |
123 | ||
1eb8ef25 | 124 | for (ALL_LIST_ELEMENTS_RO (adjdb, node, adj)) |
125 | if (memcmp (adj->snpa, ssnpa, ETH_ALEN) == 0) | |
126 | return adj; | |
f390d2c7 | 127 | |
eb5d44eb | 128 | return NULL; |
129 | } | |
130 | ||
f390d2c7 | 131 | void |
3f045a08 | 132 | isis_delete_adj (void *arg) |
eb5d44eb | 133 | { |
3f045a08 JB |
134 | struct isis_adjacency *adj = arg; |
135 | ||
3fdb2dd9 | 136 | if (!adj) |
137 | return; | |
f390d2c7 | 138 | |
3f045a08 JB |
139 | THREAD_TIMER_OFF (adj->t_expire); |
140 | ||
141 | /* remove from SPF trees */ | |
142 | spftree_area_adj_del (adj->circuit->area, adj); | |
13fb40ac | 143 | |
3f045a08 JB |
144 | if (adj->area_addrs) |
145 | list_delete (adj->area_addrs); | |
eb5d44eb | 146 | if (adj->ipv4_addrs) |
147 | list_delete (adj->ipv4_addrs); | |
eb5d44eb | 148 | if (adj->ipv6_addrs) |
149 | list_delete (adj->ipv6_addrs); | |
3f045a08 | 150 | |
d8fba7d9 CF |
151 | adj_mt_finish(adj); |
152 | ||
3fdb2dd9 | 153 | XFREE (MTYPE_ISIS_ADJACENCY, adj); |
eb5d44eb | 154 | return; |
155 | } | |
156 | ||
3f045a08 JB |
157 | static const char * |
158 | adj_state2string (int state) | |
159 | { | |
160 | ||
161 | switch (state) | |
162 | { | |
163 | case ISIS_ADJ_INITIALIZING: | |
164 | return "Initializing"; | |
165 | case ISIS_ADJ_UP: | |
166 | return "Up"; | |
167 | case ISIS_ADJ_DOWN: | |
168 | return "Down"; | |
169 | default: | |
170 | return "Unknown"; | |
171 | } | |
172 | ||
173 | return NULL; /* not reached */ | |
174 | } | |
175 | ||
f390d2c7 | 176 | void |
3f045a08 | 177 | isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state new_state, |
1cd80845 | 178 | const char *reason) |
eb5d44eb | 179 | { |
180 | int old_state; | |
3f045a08 | 181 | int level; |
eb5d44eb | 182 | struct isis_circuit *circuit; |
f390d2c7 | 183 | |
eb5d44eb | 184 | old_state = adj->adj_state; |
3f045a08 | 185 | adj->adj_state = new_state; |
eb5d44eb | 186 | |
187 | circuit = adj->circuit; | |
f390d2c7 | 188 | |
189 | if (isis->debugs & DEBUG_ADJ_PACKETS) | |
190 | { | |
529d65b3 | 191 | zlog_debug ("ISIS-Adj (%s): Adjacency state change %d->%d: %s", |
f390d2c7 | 192 | circuit->area->area_tag, |
3f045a08 | 193 | old_state, new_state, reason ? reason : "unspecified"); |
eb5d44eb | 194 | } |
195 | ||
3f045a08 | 196 | if (circuit->area->log_adj_changes) |
f390d2c7 | 197 | { |
3f045a08 JB |
198 | const char *adj_name; |
199 | struct isis_dynhn *dyn; | |
f390d2c7 | 200 | |
3f045a08 JB |
201 | dyn = dynhn_find_by_id (adj->sysid); |
202 | if (dyn) | |
203 | adj_name = (const char *)dyn->name.name; | |
204 | else | |
85b123a4 | 205 | adj_name = sysid_print (adj->sysid); |
3f045a08 JB |
206 | |
207 | zlog_info ("%%ADJCHANGE: Adjacency to %s (%s) changed from %s to %s, %s", | |
208 | adj_name, | |
e8aca32f | 209 | adj->circuit->interface->name, |
3f045a08 JB |
210 | adj_state2string (old_state), |
211 | adj_state2string (new_state), | |
212 | reason ? reason : "unspecified"); | |
f390d2c7 | 213 | } |
3f045a08 JB |
214 | |
215 | if (circuit->circ_type == CIRCUIT_T_BROADCAST) | |
216 | { | |
217 | for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) | |
218 | { | |
219 | if ((adj->level & level) == 0) | |
220 | continue; | |
221 | if (new_state == ISIS_ADJ_UP) | |
e38e0df0 SV |
222 | { |
223 | circuit->upadjcount[level - 1]++; | |
224 | isis_event_adjacency_state_change (adj, new_state); | |
225 | /* update counter & timers for debugging purposes */ | |
226 | adj->last_flap = time (NULL); | |
227 | adj->flaps++; | |
228 | } | |
3f045a08 | 229 | else if (new_state == ISIS_ADJ_DOWN) |
e38e0df0 SV |
230 | { |
231 | listnode_delete (circuit->u.bc.adjdb[level - 1], adj); | |
232 | circuit->upadjcount[level - 1]--; | |
233 | if (circuit->upadjcount[level - 1] == 0) | |
234 | { | |
235 | /* Clean lsp_queue when no adj is up. */ | |
236 | if (circuit->lsp_queue) | |
237 | list_delete_all_node (circuit->lsp_queue); | |
238 | } | |
239 | isis_event_adjacency_state_change (adj, new_state); | |
240 | isis_delete_adj (adj); | |
241 | } | |
242 | ||
243 | if (circuit->u.bc.lan_neighs[level - 1]) | |
244 | { | |
245 | list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]); | |
246 | isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1], | |
247 | circuit->u.bc.lan_neighs[level - 1]); | |
248 | } | |
3f045a08 JB |
249 | |
250 | /* On adjacency state change send new pseudo LSP if we are the DR */ | |
251 | if (circuit->u.bc.is_dr[level - 1]) | |
252 | lsp_regenerate_schedule_pseudo (circuit, level); | |
253 | } | |
f390d2c7 | 254 | } |
3f045a08 JB |
255 | else if (circuit->circ_type == CIRCUIT_T_P2P) |
256 | { | |
257 | for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) | |
258 | { | |
259 | if ((adj->level & level) == 0) | |
260 | continue; | |
261 | if (new_state == ISIS_ADJ_UP) | |
e38e0df0 SV |
262 | { |
263 | circuit->upadjcount[level - 1]++; | |
264 | isis_event_adjacency_state_change (adj, new_state); | |
3f045a08 | 265 | |
e38e0df0 SV |
266 | if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN) |
267 | send_hello (circuit, level); | |
3f045a08 | 268 | |
e38e0df0 SV |
269 | /* update counter & timers for debugging purposes */ |
270 | adj->last_flap = time (NULL); | |
271 | adj->flaps++; | |
3f045a08 | 272 | |
e38e0df0 SV |
273 | /* 7.3.17 - going up on P2P -> send CSNP */ |
274 | /* FIXME: yup, I know its wrong... but i will do it! (for now) */ | |
275 | send_csnp (circuit, level); | |
276 | } | |
3f045a08 | 277 | else if (new_state == ISIS_ADJ_DOWN) |
e38e0df0 SV |
278 | { |
279 | if (adj->circuit->u.p2p.neighbor == adj) | |
280 | adj->circuit->u.p2p.neighbor = NULL; | |
281 | circuit->upadjcount[level - 1]--; | |
282 | if (circuit->upadjcount[level - 1] == 0) | |
283 | { | |
284 | /* Clean lsp_queue when no adj is up. */ | |
285 | if (circuit->lsp_queue) | |
286 | list_delete_all_node (circuit->lsp_queue); | |
287 | } | |
288 | isis_event_adjacency_state_change (adj, new_state); | |
289 | isis_delete_adj (adj); | |
290 | } | |
3f045a08 | 291 | } |
f390d2c7 | 292 | } |
3f045a08 | 293 | |
eb5d44eb | 294 | return; |
295 | } | |
296 | ||
297 | ||
298 | void | |
299 | isis_adj_print (struct isis_adjacency *adj) | |
300 | { | |
301 | struct isis_dynhn *dyn; | |
302 | struct listnode *node; | |
303 | struct in_addr *ipv4_addr; | |
eb5d44eb | 304 | struct in6_addr *ipv6_addr; |
f390d2c7 | 305 | u_char ip6[INET6_ADDRSTRLEN]; |
f390d2c7 | 306 | |
307 | if (!adj) | |
eb5d44eb | 308 | return; |
309 | dyn = dynhn_find_by_id (adj->sysid); | |
310 | if (dyn) | |
529d65b3 | 311 | zlog_debug ("%s", dyn->name.name); |
f390d2c7 | 312 | |
529d65b3 | 313 | zlog_debug ("SystemId %20s SNPA %s, level %d\nHolding Time %d", |
85b123a4 CF |
314 | sysid_print (adj->sysid), snpa_print (adj->snpa), |
315 | adj->level, adj->hold_time); | |
f390d2c7 | 316 | if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0) |
317 | { | |
3f045a08 | 318 | zlog_debug ("IPv4 Address(es):"); |
f390d2c7 | 319 | |
1eb8ef25 | 320 | for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ipv4_addr)) |
321 | zlog_debug ("%s", inet_ntoa (*ipv4_addr)); | |
eb5d44eb | 322 | } |
f390d2c7 | 323 | |
f390d2c7 | 324 | if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0) |
325 | { | |
3f045a08 | 326 | zlog_debug ("IPv6 Address(es):"); |
1eb8ef25 | 327 | for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr)) |
f390d2c7 | 328 | { |
f7c43dcb | 329 | inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN); |
529d65b3 | 330 | zlog_debug ("%s", ip6); |
f390d2c7 | 331 | } |
eb5d44eb | 332 | } |
529d65b3 | 333 | zlog_debug ("Speaks: %s", nlpid2string (&adj->nlpids)); |
eb5d44eb | 334 | |
335 | return; | |
336 | } | |
337 | ||
f390d2c7 | 338 | int |
eb5d44eb | 339 | isis_adj_expire (struct thread *thread) |
340 | { | |
341 | struct isis_adjacency *adj; | |
eb5d44eb | 342 | |
343 | /* | |
344 | * Get the adjacency | |
345 | */ | |
346 | adj = THREAD_ARG (thread); | |
347 | assert (adj); | |
83fe45e3 | 348 | adj->t_expire = NULL; |
eb5d44eb | 349 | |
350 | /* trigger the adj expire event */ | |
351 | isis_adj_state_change (adj, ISIS_ADJ_DOWN, "holding time expired"); | |
352 | ||
353 | return 0; | |
354 | } | |
355 | ||
eb5d44eb | 356 | /* |
3f045a08 | 357 | * show isis neighbor [detail] |
eb5d44eb | 358 | */ |
3f045a08 JB |
359 | void |
360 | isis_adj_print_vty (struct isis_adjacency *adj, struct vty *vty, char detail) | |
eb5d44eb | 361 | { |
eb5d44eb | 362 | struct in6_addr *ipv6_addr; |
f390d2c7 | 363 | u_char ip6[INET6_ADDRSTRLEN]; |
eb5d44eb | 364 | struct in_addr *ip_addr; |
365 | time_t now; | |
366 | struct isis_dynhn *dyn; | |
367 | int level; | |
368 | struct listnode *node; | |
369 | ||
370 | dyn = dynhn_find_by_id (adj->sysid); | |
371 | if (dyn) | |
372 | vty_out (vty, " %-20s", dyn->name.name); | |
f390d2c7 | 373 | else |
0bffa929 | 374 | vty_out (vty, " %-20s", sysid_print (adj->sysid)); |
f390d2c7 | 375 | |
376 | if (detail == ISIS_UI_LEVEL_BRIEF) | |
377 | { | |
378 | if (adj->circuit) | |
379 | vty_out (vty, "%-12s", adj->circuit->interface->name); | |
380 | else | |
381 | vty_out (vty, "NULL circuit!"); | |
382 | vty_out (vty, "%-3u", adj->level); /* level */ | |
383 | vty_out (vty, "%-13s", adj_state2string (adj->adj_state)); | |
384 | now = time (NULL); | |
385 | if (adj->last_upd) | |
8f2c16aa DL |
386 | vty_out (vty, "%-9llu", |
387 | (unsigned long long)adj->last_upd + adj->hold_time - now); | |
f390d2c7 | 388 | else |
389 | vty_out (vty, "- "); | |
390 | vty_out (vty, "%-10s", snpa_print (adj->snpa)); | |
391 | vty_out (vty, "%s", VTY_NEWLINE); | |
392 | } | |
393 | ||
394 | if (detail == ISIS_UI_LEVEL_DETAIL) | |
395 | { | |
396 | level = adj->level; | |
3f045a08 | 397 | vty_out (vty, "%s", VTY_NEWLINE); |
f390d2c7 | 398 | if (adj->circuit) |
3f045a08 | 399 | vty_out (vty, " Interface: %s", adj->circuit->interface->name); |
f390d2c7 | 400 | else |
3f045a08 | 401 | vty_out (vty, " Interface: NULL circuit"); |
f390d2c7 | 402 | vty_out (vty, ", Level: %u", adj->level); /* level */ |
403 | vty_out (vty, ", State: %s", adj_state2string (adj->adj_state)); | |
404 | now = time (NULL); | |
405 | if (adj->last_upd) | |
406 | vty_out (vty, ", Expires in %s", | |
407 | time2string (adj->last_upd + adj->hold_time - now)); | |
408 | else | |
409 | vty_out (vty, ", Expires in %s", time2string (adj->hold_time)); | |
3f045a08 JB |
410 | vty_out (vty, "%s", VTY_NEWLINE); |
411 | vty_out (vty, " Adjacency flaps: %u", adj->flaps); | |
f390d2c7 | 412 | vty_out (vty, ", Last: %s ago", time2string (now - adj->last_flap)); |
3f045a08 JB |
413 | vty_out (vty, "%s", VTY_NEWLINE); |
414 | vty_out (vty, " Circuit type: %s", circuit_t2string (adj->circuit_t)); | |
f390d2c7 | 415 | vty_out (vty, ", Speaks: %s", nlpid2string (&adj->nlpids)); |
3f045a08 JB |
416 | vty_out (vty, "%s", VTY_NEWLINE); |
417 | vty_out (vty, " SNPA: %s", snpa_print (adj->snpa)); | |
e8aca32f | 418 | if (adj->circuit && (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) |
3f045a08 JB |
419 | { |
420 | dyn = dynhn_find_by_id (adj->lanid); | |
421 | if (dyn) | |
422 | vty_out (vty, ", LAN id: %s.%02x", | |
423 | dyn->name.name, adj->lanid[ISIS_SYS_ID_LEN]); | |
424 | else | |
425 | vty_out (vty, ", LAN id: %s.%02x", | |
426 | sysid_print (adj->lanid), adj->lanid[ISIS_SYS_ID_LEN]); | |
427 | ||
428 | vty_out (vty, "%s", VTY_NEWLINE); | |
429 | vty_out (vty, " LAN Priority: %u", adj->prio[adj->level - 1]); | |
430 | ||
431 | vty_out (vty, ", %s, DIS flaps: %u, Last: %s ago", | |
432 | isis_disflag2string (adj->dis_record[ISIS_LEVELS + level - 1]. | |
433 | dis), adj->dischanges[level - 1], | |
434 | time2string (now - | |
435 | (adj->dis_record[ISIS_LEVELS + level - 1]. | |
436 | last_dis_change))); | |
437 | } | |
438 | vty_out (vty, "%s", VTY_NEWLINE); | |
f390d2c7 | 439 | |
3f045a08 JB |
440 | if (adj->area_addrs && listcount (adj->area_addrs) > 0) |
441 | { | |
442 | struct area_addr *area_addr; | |
443 | vty_out (vty, " Area Address(es):%s", VTY_NEWLINE); | |
444 | for (ALL_LIST_ELEMENTS_RO (adj->area_addrs, node, area_addr)) | |
445 | vty_out (vty, " %s%s", isonet_print (area_addr->area_addr, | |
446 | area_addr->addr_len), VTY_NEWLINE); | |
447 | } | |
f390d2c7 | 448 | if (adj->ipv4_addrs && listcount (adj->ipv4_addrs) > 0) |
449 | { | |
3f045a08 | 450 | vty_out (vty, " IPv4 Address(es):%s", VTY_NEWLINE); |
1eb8ef25 | 451 | for (ALL_LIST_ELEMENTS_RO (adj->ipv4_addrs, node, ip_addr)) |
452 | vty_out (vty, " %s%s", inet_ntoa (*ip_addr), VTY_NEWLINE); | |
f390d2c7 | 453 | } |
f390d2c7 | 454 | if (adj->ipv6_addrs && listcount (adj->ipv6_addrs) > 0) |
455 | { | |
3f045a08 | 456 | vty_out (vty, " IPv6 Address(es):%s", VTY_NEWLINE); |
5d6e2691 | 457 | for (ALL_LIST_ELEMENTS_RO (adj->ipv6_addrs, node, ipv6_addr)) |
f390d2c7 | 458 | { |
f7c43dcb | 459 | inet_ntop (AF_INET6, ipv6_addr, (char *)ip6, INET6_ADDRSTRLEN); |
f390d2c7 | 460 | vty_out (vty, " %s%s", ip6, VTY_NEWLINE); |
461 | } | |
462 | } | |
f390d2c7 | 463 | vty_out (vty, "%s", VTY_NEWLINE); |
464 | } | |
eb5d44eb | 465 | return; |
466 | } | |
467 | ||
eb5d44eb | 468 | void |
469 | isis_adj_build_neigh_list (struct list *adjdb, struct list *list) | |
eb5d44eb | 470 | { |
471 | struct isis_adjacency *adj; | |
472 | struct listnode *node; | |
f390d2c7 | 473 | |
474 | if (!list) | |
475 | { | |
476 | zlog_warn ("isis_adj_build_neigh_list(): NULL list"); | |
eb5d44eb | 477 | return; |
478 | } | |
f390d2c7 | 479 | |
1eb8ef25 | 480 | for (ALL_LIST_ELEMENTS_RO (adjdb, node, adj)) |
f390d2c7 | 481 | { |
f390d2c7 | 482 | if (!adj) |
483 | { | |
484 | zlog_warn ("isis_adj_build_neigh_list(): NULL adj"); | |
485 | return; | |
486 | } | |
487 | ||
488 | if ((adj->adj_state == ISIS_ADJ_UP || | |
489 | adj->adj_state == ISIS_ADJ_INITIALIZING)) | |
490 | listnode_add (list, adj->snpa); | |
491 | } | |
eb5d44eb | 492 | return; |
493 | } | |
494 | ||
495 | void | |
496 | isis_adj_build_up_list (struct list *adjdb, struct list *list) | |
497 | { | |
498 | struct isis_adjacency *adj; | |
499 | struct listnode *node; | |
500 | ||
cd4ab724 | 501 | if (adjdb == NULL) { |
502 | zlog_warn ("isis_adj_build_up_list(): adjacency DB is empty"); | |
503 | return; | |
504 | } | |
505 | ||
f390d2c7 | 506 | if (!list) |
507 | { | |
508 | zlog_warn ("isis_adj_build_up_list(): NULL list"); | |
eb5d44eb | 509 | return; |
510 | } | |
511 | ||
1eb8ef25 | 512 | for (ALL_LIST_ELEMENTS_RO (adjdb, node, adj)) |
f390d2c7 | 513 | { |
f390d2c7 | 514 | if (!adj) |
515 | { | |
516 | zlog_warn ("isis_adj_build_up_list(): NULL adj"); | |
517 | return; | |
518 | } | |
519 | ||
520 | if (adj->adj_state == ISIS_ADJ_UP) | |
521 | listnode_add (list, adj); | |
522 | } | |
523 | ||
eb5d44eb | 524 | return; |
525 | } | |
d8fba7d9 CF |
526 | |
527 | int | |
528 | isis_adj_usage2levels(enum isis_adj_usage usage) | |
529 | { | |
530 | switch (usage) | |
531 | { | |
532 | case ISIS_ADJ_LEVEL1: | |
533 | return IS_LEVEL_1; | |
534 | case ISIS_ADJ_LEVEL2: | |
535 | return IS_LEVEL_2; | |
536 | case ISIS_ADJ_LEVEL1AND2: | |
537 | return IS_LEVEL_1 | IS_LEVEL_2; | |
538 | default: | |
539 | break; | |
540 | } | |
541 | return 0; | |
542 | } |