]>
git.proxmox.com Git - mirror_frr.git/blob - ldpd/adjacency.c
4 * Copyright (c) 2013, 2015 Renato Westphal <renato@openbsd.org>
5 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
6 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
7 * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 static __inline
int adj_compare(struct adj
*, struct adj
*);
29 static int adj_itimer(struct thread
*);
30 static __inline
int tnbr_compare(struct tnbr
*, struct tnbr
*);
31 static void tnbr_del(struct ldpd_conf
*, struct tnbr
*);
32 static int tnbr_hello_timer(struct thread
*);
33 static void tnbr_start_hello_timer(struct tnbr
*);
34 static void tnbr_stop_hello_timer(struct tnbr
*);
36 RB_GENERATE(global_adj_head
, adj
, global_entry
, adj_compare
)
37 RB_GENERATE(nbr_adj_head
, adj
, nbr_entry
, adj_compare
)
38 RB_GENERATE(ia_adj_head
, adj
, ia_entry
, adj_compare
)
39 RB_GENERATE(tnbr_head
, tnbr
, entry
, tnbr_compare
)
42 adj_compare(struct adj
*a
, struct adj
*b
)
44 if (adj_get_af(a
) < adj_get_af(b
))
46 if (adj_get_af(a
) > adj_get_af(b
))
49 if (ntohl(a
->lsr_id
.s_addr
) < ntohl(b
->lsr_id
.s_addr
))
51 if (ntohl(a
->lsr_id
.s_addr
) > ntohl(b
->lsr_id
.s_addr
))
54 if (a
->source
.type
< b
->source
.type
)
56 if (a
->source
.type
> b
->source
.type
)
59 switch (a
->source
.type
) {
61 if (strcmp(a
->source
.link
.ia
->iface
->name
,
62 b
->source
.link
.ia
->iface
->name
) < 0)
64 if (strcmp(a
->source
.link
.ia
->iface
->name
,
65 b
->source
.link
.ia
->iface
->name
) > 0)
67 return (ldp_addrcmp(a
->source
.link
.ia
->af
,
68 &a
->source
.link
.src_addr
, &b
->source
.link
.src_addr
));
70 return (ldp_addrcmp(a
->source
.target
->af
,
71 &a
->source
.target
->addr
, &b
->source
.target
->addr
));
73 fatalx("adj_compare: unknown hello type");
80 adj_new(struct in_addr lsr_id
, struct hello_source
*source
,
81 union ldpd_addr
*addr
)
85 log_debug("%s: lsr-id %s, %s", __func__
, inet_ntoa(lsr_id
),
86 log_hello_src(source
));
88 if ((adj
= calloc(1, sizeof(*adj
))) == NULL
)
93 adj
->source
= *source
;
94 adj
->trans_addr
= *addr
;
96 RB_INSERT(global_adj_head
, &global
.adj_tree
, adj
);
98 switch (source
->type
) {
100 RB_INSERT(ia_adj_head
, &source
->link
.ia
->adj_tree
, adj
);
103 source
->target
->adj
= adj
;
111 adj_del_single(struct adj
*adj
)
113 log_debug("%s: lsr-id %s, %s (%s)", __func__
, inet_ntoa(adj
->lsr_id
),
114 log_hello_src(&adj
->source
), af_name(adj_get_af(adj
)));
116 adj_stop_itimer(adj
);
118 RB_REMOVE(global_adj_head
, &global
.adj_tree
, adj
);
120 RB_REMOVE(nbr_adj_head
, &adj
->nbr
->adj_tree
, adj
);
121 switch (adj
->source
.type
) {
123 RB_REMOVE(ia_adj_head
, &adj
->source
.link
.ia
->adj_tree
, adj
);
126 adj
->source
.target
->adj
= NULL
;
134 adj_del(struct adj
*adj
, uint32_t notif_status
)
136 struct nbr
*nbr
= adj
->nbr
;
142 * If the neighbor still exists but none of its remaining
143 * adjacencies (if any) are from the preferred address-family,
146 if (nbr
&& nbr_adj_count(nbr
, nbr
->af
) == 0) {
147 RB_FOREACH_SAFE(adj
, nbr_adj_head
, &nbr
->adj_tree
, atmp
)
149 session_shutdown(nbr
, notif_status
, 0, 0);
155 adj_find(struct in_addr lsr_id
, struct hello_source
*source
)
159 adj
.source
= *source
;
160 return (RB_FIND(global_adj_head
, &global
.adj_tree
, &adj
));
164 adj_get_af(struct adj
*adj
)
166 switch (adj
->source
.type
) {
168 return (adj
->source
.link
.ia
->af
);
170 return (adj
->source
.target
->af
);
172 fatalx("adj_get_af: unknown hello type");
176 /* adjacency timers */
180 adj_itimer(struct thread
*thread
)
182 struct adj
*adj
= THREAD_ARG(thread
);
184 adj
->inactivity_timer
= NULL
;
186 log_debug("%s: lsr-id %s", __func__
, inet_ntoa(adj
->lsr_id
));
188 if (adj
->source
.type
== HELLO_TARGETED
) {
189 if (!(adj
->source
.target
->flags
& F_TNBR_CONFIGURED
) &&
190 adj
->source
.target
->pw_count
== 0) {
191 /* remove dynamic targeted neighbor */
192 tnbr_del(leconf
, adj
->source
.target
);
195 adj
->source
.target
->adj
= NULL
;
198 adj_del(adj
, S_HOLDTIME_EXP
);
204 adj_start_itimer(struct adj
*adj
)
206 THREAD_TIMER_OFF(adj
->inactivity_timer
);
207 adj
->inactivity_timer
= thread_add_timer(master
, adj_itimer
, adj
,
212 adj_stop_itimer(struct adj
*adj
)
214 THREAD_TIMER_OFF(adj
->inactivity_timer
);
217 /* targeted neighbors */
220 tnbr_compare(struct tnbr
*a
, struct tnbr
*b
)
227 return (ldp_addrcmp(a
->af
, &a
->addr
, &b
->addr
));
231 tnbr_new(int af
, union ldpd_addr
*addr
)
235 if ((tnbr
= calloc(1, sizeof(*tnbr
))) == NULL
)
240 tnbr
->state
= TNBR_STA_DOWN
;
246 tnbr_del(struct ldpd_conf
*xconf
, struct tnbr
*tnbr
)
248 tnbr_stop_hello_timer(tnbr
);
250 adj_del(tnbr
->adj
, S_SHUTDOWN
);
251 RB_REMOVE(tnbr_head
, &xconf
->tnbr_tree
, tnbr
);
256 tnbr_find(struct ldpd_conf
*xconf
, int af
, union ldpd_addr
*addr
)
261 return (RB_FIND(tnbr_head
, &xconf
->tnbr_tree
, &tnbr
));
265 tnbr_check(struct ldpd_conf
*xconf
, struct tnbr
*tnbr
)
267 if (!(tnbr
->flags
& (F_TNBR_CONFIGURED
|F_TNBR_DYNAMIC
)) &&
268 tnbr
->pw_count
== 0) {
269 tnbr_del(xconf
, tnbr
);
277 tnbr_update(struct tnbr
*tnbr
)
279 int socket_ok
, rtr_id_ok
;
281 if ((ldp_af_global_get(&global
, tnbr
->af
))->ldp_edisc_socket
!= -1)
286 if (ldp_rtr_id_get(leconf
) != INADDR_ANY
)
291 if (tnbr
->state
== TNBR_STA_DOWN
) {
292 if (!socket_ok
|| !rtr_id_ok
)
295 tnbr
->state
= TNBR_STA_ACTIVE
;
296 send_hello(HELLO_TARGETED
, NULL
, tnbr
);
298 tnbr_start_hello_timer(tnbr
);
299 } else if (tnbr
->state
== TNBR_STA_ACTIVE
) {
300 if (socket_ok
&& rtr_id_ok
)
303 tnbr
->state
= TNBR_STA_DOWN
;
304 tnbr_stop_hello_timer(tnbr
);
309 tnbr_update_all(int af
)
313 /* update targeted neighbors */
314 RB_FOREACH(tnbr
, tnbr_head
, &leconf
->tnbr_tree
)
315 if (tnbr
->af
== af
|| af
== AF_UNSPEC
)
320 tnbr_get_hello_holdtime(struct tnbr
*tnbr
)
322 if ((ldp_af_conf_get(leconf
, tnbr
->af
))->thello_holdtime
!= 0)
323 return ((ldp_af_conf_get(leconf
, tnbr
->af
))->thello_holdtime
);
325 return (leconf
->thello_holdtime
);
329 tnbr_get_hello_interval(struct tnbr
*tnbr
)
331 if ((ldp_af_conf_get(leconf
, tnbr
->af
))->thello_interval
!= 0)
332 return ((ldp_af_conf_get(leconf
, tnbr
->af
))->thello_interval
);
334 return (leconf
->thello_interval
);
337 /* target neighbors timers */
341 tnbr_hello_timer(struct thread
*thread
)
343 struct tnbr
*tnbr
= THREAD_ARG(thread
);
345 tnbr
->hello_timer
= NULL
;
346 send_hello(HELLO_TARGETED
, NULL
, tnbr
);
347 tnbr_start_hello_timer(tnbr
);
353 tnbr_start_hello_timer(struct tnbr
*tnbr
)
355 THREAD_TIMER_OFF(tnbr
->hello_timer
);
356 tnbr
->hello_timer
= thread_add_timer(master
, tnbr_hello_timer
, tnbr
,
357 tnbr_get_hello_interval(tnbr
));
361 tnbr_stop_hello_timer(struct tnbr
*tnbr
)
363 THREAD_TIMER_OFF(tnbr
->hello_timer
);
367 adj_to_ctl(struct adj
*adj
)
369 static struct ctl_adj actl
;
371 actl
.af
= adj_get_af(adj
);
372 actl
.id
= adj
->lsr_id
;
373 actl
.type
= adj
->source
.type
;
374 switch (adj
->source
.type
) {
376 memcpy(actl
.ifname
, adj
->source
.link
.ia
->iface
->name
,
377 sizeof(actl
.ifname
));
378 actl
.src_addr
= adj
->source
.link
.src_addr
;
381 actl
.src_addr
= adj
->source
.target
->addr
;
384 actl
.holdtime
= adj
->holdtime
;
385 actl
.holdtime_remaining
=
386 thread_timer_remain_second(adj
->inactivity_timer
);
387 actl
.trans_addr
= adj
->trans_addr
;
388 actl
.ds_tlv
= adj
->ds_tlv
;