]>
git.proxmox.com Git - mirror_frr.git/blob - isisd/isis_adjacency.c
2 * IS-IS Rout(e)ing protocol - isis_adjacency.c
3 * handling of IS-IS adjacencies
5 * Copyright (C) 2001,2002 Sampo Saaristo
6 * Tampere University of Technology
7 * Institute of Communications Engineering
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)
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
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.
38 #include "isisd/dict.h"
39 #include "isisd/include-netbsd/iso.h"
40 #include "isisd/isis_constants.h"
41 #include "isisd/isis_common.h"
42 #include "isisd/isisd.h"
43 #include "isisd/isis_circuit.h"
44 #include "isisd/isis_adjacency.h"
45 #include "isisd/isis_misc.h"
46 #include "isisd/isis_dr.h"
47 #include "isisd/isis_dynhn.h"
48 #include "isisd/isis_pdu.h"
50 extern struct isis
*isis
;
52 static struct isis_adjacency
*
53 adj_alloc (u_char
* id
)
55 struct isis_adjacency
*adj
;
57 adj
= XMALLOC (MTYPE_ISIS_ADJACENCY
, sizeof (struct isis_adjacency
));
58 memset (adj
, 0, sizeof (struct isis_adjacency
));
59 memcpy (adj
->sysid
, id
, ISIS_SYS_ID_LEN
);
64 struct isis_adjacency
*
65 isis_new_adj (u_char
* id
, u_char
* snpa
, int level
,
66 struct isis_circuit
*circuit
)
68 struct isis_adjacency
*adj
;
71 adj
= adj_alloc (id
); /* P2P kludge */
75 zlog_err ("Out of memory!");
79 memcpy (adj
->snpa
, snpa
, 6);
80 adj
->circuit
= circuit
;
83 adj
->last_flap
= time (NULL
);
84 if (circuit
->circ_type
== CIRCUIT_T_BROADCAST
)
86 listnode_add (circuit
->u
.bc
.adjdb
[level
- 1], adj
);
87 adj
->dischanges
[level
- 1] = 0;
88 for (i
= 0; i
< DIS_RECORDS
; i
++) /* clear N DIS state change records */
90 adj
->dis_record
[(i
* ISIS_LEVELS
) + level
- 1].dis
92 adj
->dis_record
[(i
* ISIS_LEVELS
) + level
- 1].last_dis_change
100 struct isis_adjacency
*
101 isis_adj_lookup (u_char
* sysid
, struct list
*adjdb
)
103 struct isis_adjacency
*adj
;
104 struct listnode
*node
;
106 for (ALL_LIST_ELEMENTS_RO (adjdb
, node
, adj
))
107 if (memcmp (adj
->sysid
, sysid
, ISIS_SYS_ID_LEN
) == 0)
114 struct isis_adjacency
*
115 isis_adj_lookup_snpa (u_char
* ssnpa
, struct list
*adjdb
)
117 struct listnode
*node
;
118 struct isis_adjacency
*adj
;
120 for (ALL_LIST_ELEMENTS_RO (adjdb
, node
, adj
))
121 if (memcmp (adj
->snpa
, ssnpa
, ETH_ALEN
) == 0)
128 * When we recieve a NULL list, we will know its p2p
131 isis_delete_adj (struct isis_adjacency
*adj
, struct list
*adjdb
)
133 struct isis_adjacency
*adj2
= NULL
;
134 struct listnode
*node
;
138 for (ALL_LIST_ELEMENTS_RO (adjdb
, node
, adj2
))
142 listnode_delete (adjdb
, adj
);
146 list_delete (adj
->ipv4_addrs
);
149 list_delete (adj
->ipv6_addrs
);
153 XFREE (MTYPE_ISIS_ADJACENCY
, adj
);
157 zlog_warn ("tried to delete a non-existent adjacency");
164 isis_adj_state_change (struct isis_adjacency
*adj
, enum isis_adj_state state
,
168 int level
= adj
->level
;
169 struct isis_circuit
*circuit
;
171 old_state
= adj
->adj_state
;
172 adj
->adj_state
= state
;
174 circuit
= adj
->circuit
;
176 if (isis
->debugs
& DEBUG_ADJ_PACKETS
)
178 zlog_debug ("ISIS-Adj (%s): Adjacency state change %d->%d: %s",
179 circuit
->area
->area_tag
,
180 old_state
, state
, reason
? reason
: "unspecified");
183 if (circuit
->circ_type
== CIRCUIT_T_BROADCAST
)
185 if (state
== ISIS_ADJ_UP
)
186 circuit
->upadjcount
[level
- 1]++;
187 if (state
== ISIS_ADJ_DOWN
)
189 isis_delete_adj (adj
, adj
->circuit
->u
.bc
.adjdb
[level
- 1]);
190 circuit
->upadjcount
[level
- 1]--;
193 list_delete_all_node (circuit
->u
.bc
.lan_neighs
[level
- 1]);
194 isis_adj_build_neigh_list (circuit
->u
.bc
.adjdb
[level
- 1],
195 circuit
->u
.bc
.lan_neighs
[level
- 1]);
197 else if (state
== ISIS_ADJ_UP
)
198 { /* p2p interface */
199 if (adj
->sys_type
== ISIS_SYSTYPE_UNKNOWN
)
200 send_hello (circuit
, 1);
202 /* update counter & timers for debugging purposes */
203 adj
->last_flap
= time (NULL
);
206 /* 7.3.17 - going up on P2P -> send CSNP */
207 /* FIXME: yup, I know its wrong... but i will do it! (for now) */
208 send_csnp (circuit
, 1);
209 send_csnp (circuit
, 2);
211 else if (state
== ISIS_ADJ_DOWN
)
212 { /* p2p interface */
213 adj
->circuit
->u
.p2p
.neighbor
= NULL
;
214 isis_delete_adj (adj
, NULL
);
221 isis_adj_print (struct isis_adjacency
*adj
)
223 struct isis_dynhn
*dyn
;
224 struct listnode
*node
;
225 struct in_addr
*ipv4_addr
;
227 struct in6_addr
*ipv6_addr
;
228 u_char ip6
[INET6_ADDRSTRLEN
];
229 #endif /* HAVE_IPV6 */
233 dyn
= dynhn_find_by_id (adj
->sysid
);
235 zlog_debug ("%s", dyn
->name
.name
);
237 zlog_debug ("SystemId %20s SNPA %s, level %d\nHolding Time %d",
238 adj
->sysid
? sysid_print (adj
->sysid
) : "unknown",
239 snpa_print (adj
->snpa
), adj
->level
, adj
->hold_time
);
240 if (adj
->ipv4_addrs
&& listcount (adj
->ipv4_addrs
) > 0)
242 zlog_debug ("IPv4 Addresses:");
244 for (ALL_LIST_ELEMENTS_RO (adj
->ipv4_addrs
, node
, ipv4_addr
))
245 zlog_debug ("%s", inet_ntoa (*ipv4_addr
));
249 if (adj
->ipv6_addrs
&& listcount (adj
->ipv6_addrs
) > 0)
251 zlog_debug ("IPv6 Addresses:");
252 for (ALL_LIST_ELEMENTS_RO (adj
->ipv6_addrs
, node
, ipv6_addr
))
254 inet_ntop (AF_INET6
, ipv6_addr
, (char *)ip6
, INET6_ADDRSTRLEN
);
255 zlog_debug ("%s", ip6
);
258 #endif /* HAVE_IPV6 */
259 zlog_debug ("Speaks: %s", nlpid2string (&adj
->nlpids
));
265 isis_adj_expire (struct thread
*thread
)
267 struct isis_adjacency
*adj
;
273 adj
= THREAD_ARG (thread
);
276 adj
->t_expire
= NULL
;
278 /* trigger the adj expire event */
279 isis_adj_state_change (adj
, ISIS_ADJ_DOWN
, "holding time expired");
285 adj_state2string (int state
)
290 case ISIS_ADJ_INITIALIZING
:
291 return "Initializing";
300 return NULL
; /* not reached */
304 * show clns/isis neighbor (detail)
307 isis_adj_print_vty2 (struct isis_adjacency
*adj
, struct vty
*vty
, char detail
)
311 struct in6_addr
*ipv6_addr
;
312 u_char ip6
[INET6_ADDRSTRLEN
];
313 #endif /* HAVE_IPV6 */
314 struct in_addr
*ip_addr
;
316 struct isis_dynhn
*dyn
;
318 struct listnode
*node
;
320 dyn
= dynhn_find_by_id (adj
->sysid
);
322 vty_out (vty
, " %-20s", dyn
->name
.name
);
325 vty_out (vty
, " %-20s", sysid_print (adj
->sysid
));
329 vty_out (vty
, " unknown ");
332 if (detail
== ISIS_UI_LEVEL_BRIEF
)
335 vty_out (vty
, "%-12s", adj
->circuit
->interface
->name
);
337 vty_out (vty
, "NULL circuit!");
338 vty_out (vty
, "%-3u", adj
->level
); /* level */
339 vty_out (vty
, "%-13s", adj_state2string (adj
->adj_state
));
342 vty_out (vty
, "%-9lu", adj
->last_upd
+ adj
->hold_time
- now
);
345 vty_out (vty
, "%-10s", snpa_print (adj
->snpa
));
346 vty_out (vty
, "%s", VTY_NEWLINE
);
349 if (detail
== ISIS_UI_LEVEL_DETAIL
)
353 vty_out (vty
, "%s Interface: %s", VTY_NEWLINE
, adj
->circuit
->interface
->name
); /* interface name */
355 vty_out (vty
, "NULL circuit!%s", VTY_NEWLINE
);
356 vty_out (vty
, ", Level: %u", adj
->level
); /* level */
357 vty_out (vty
, ", State: %s", adj_state2string (adj
->adj_state
));
360 vty_out (vty
, ", Expires in %s",
361 time2string (adj
->last_upd
+ adj
->hold_time
- now
));
363 vty_out (vty
, ", Expires in %s", time2string (adj
->hold_time
));
364 vty_out (vty
, "%s Adjacency flaps: %u", VTY_NEWLINE
, adj
->flaps
);
365 vty_out (vty
, ", Last: %s ago", time2string (now
- adj
->last_flap
));
366 vty_out (vty
, "%s Circuit type: %s",
367 VTY_NEWLINE
, circuit_t2string (adj
->circuit_t
));
368 vty_out (vty
, ", Speaks: %s", nlpid2string (&adj
->nlpids
));
369 vty_out (vty
, "%s SNPA: %s", VTY_NEWLINE
, snpa_print (adj
->snpa
));
370 dyn
= dynhn_find_by_id (adj
->lanid
);
372 vty_out (vty
, ", LAN id: %s.%02x",
373 dyn
->name
.name
, adj
->lanid
[ISIS_SYS_ID_LEN
]);
375 vty_out (vty
, ", LAN id: %s.%02x",
376 sysid_print (adj
->lanid
), adj
->lanid
[ISIS_SYS_ID_LEN
]);
378 vty_out (vty
, "%s Priority: %u",
379 VTY_NEWLINE
, adj
->prio
[adj
->level
- 1]);
381 vty_out (vty
, ", %s, DIS flaps: %u, Last: %s ago%s",
382 isis_disflag2string (adj
->dis_record
[ISIS_LEVELS
+ level
- 1].
383 dis
), adj
->dischanges
[level
- 1],
385 (adj
->dis_record
[ISIS_LEVELS
+ level
- 1].
386 last_dis_change
)), VTY_NEWLINE
);
388 if (adj
->ipv4_addrs
&& listcount (adj
->ipv4_addrs
) > 0)
390 vty_out (vty
, " IPv4 Addresses:%s", VTY_NEWLINE
);
391 for (ALL_LIST_ELEMENTS_RO (adj
->ipv4_addrs
, node
, ip_addr
))
392 vty_out (vty
, " %s%s", inet_ntoa (*ip_addr
), VTY_NEWLINE
);
395 if (adj
->ipv6_addrs
&& listcount (adj
->ipv6_addrs
) > 0)
397 vty_out (vty
, " IPv6 Addresses:%s", VTY_NEWLINE
);
398 for (ALL_LIST_ELEMENTS_RO (adj
->ipv4_addrs
, node
, ipv6_addr
))
400 inet_ntop (AF_INET6
, ipv6_addr
, (char *)ip6
, INET6_ADDRSTRLEN
);
401 vty_out (vty
, " %s%s", ip6
, VTY_NEWLINE
);
404 #endif /* HAVE_IPV6 */
405 vty_out (vty
, "%s", VTY_NEWLINE
);
411 isis_adj_print_vty (struct isis_adjacency
*adj
, struct vty
*vty
)
413 isis_adj_print_vty2 (adj
, vty
, ISIS_UI_LEVEL_BRIEF
);
417 isis_adj_print_vty_detail (struct isis_adjacency
*adj
, struct vty
*vty
)
419 isis_adj_print_vty2 (adj
, vty
, ISIS_UI_LEVEL_DETAIL
);
423 isis_adj_print_vty_extensive (struct isis_adjacency
*adj
, struct vty
*vty
)
425 isis_adj_print_vty2 (adj
, vty
, ISIS_UI_LEVEL_EXTENSIVE
);
429 isis_adj_p2p_print_vty (struct isis_adjacency
*adj
, struct vty
*vty
)
431 isis_adj_print_vty2 (adj
, vty
, ISIS_UI_LEVEL_BRIEF
);
435 isis_adj_p2p_print_vty_detail (struct isis_adjacency
*adj
, struct vty
*vty
)
437 isis_adj_print_vty2 (adj
, vty
, ISIS_UI_LEVEL_DETAIL
);
441 isis_adj_p2p_print_vty_extensive (struct isis_adjacency
*adj
, struct vty
*vty
)
443 isis_adj_print_vty2 (adj
, vty
, ISIS_UI_LEVEL_EXTENSIVE
);
447 isis_adjdb_iterate (struct list
*adjdb
, void (*func
) (struct isis_adjacency
*,
450 struct listnode
*node
, *nnode
;
451 struct isis_adjacency
*adj
;
453 for (ALL_LIST_ELEMENTS (adjdb
, node
, nnode
, adj
))
458 isis_adj_build_neigh_list (struct list
*adjdb
, struct list
*list
)
460 struct isis_adjacency
*adj
;
461 struct listnode
*node
;
465 zlog_warn ("isis_adj_build_neigh_list(): NULL list");
469 for (ALL_LIST_ELEMENTS_RO (adjdb
, node
, adj
))
473 zlog_warn ("isis_adj_build_neigh_list(): NULL adj");
477 if ((adj
->adj_state
== ISIS_ADJ_UP
||
478 adj
->adj_state
== ISIS_ADJ_INITIALIZING
))
479 listnode_add (list
, adj
->snpa
);
485 isis_adj_build_up_list (struct list
*adjdb
, struct list
*list
)
487 struct isis_adjacency
*adj
;
488 struct listnode
*node
;
492 zlog_warn ("isis_adj_build_up_list(): NULL list");
496 for (ALL_LIST_ELEMENTS_RO (adjdb
, node
, adj
))
500 zlog_warn ("isis_adj_build_up_list(): NULL adj");
504 if (adj
->adj_state
== ISIS_ADJ_UP
)
505 listnode_add (list
, adj
);