]>
git.proxmox.com Git - mirror_frr.git/blob - ldpd/adjacency.c
1 // SPDX-License-Identifier: ISC
5 * Copyright (c) 2013, 2015 Renato Westphal <renato@openbsd.org>
6 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
7 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
8 * Copyright (c) 2004, 2005, 2008 Esben Norby <norby@openbsd.org>
17 static __inline
int adj_compare(const struct adj
*, const struct adj
*);
18 static void adj_itimer(struct thread
*);
19 static __inline
int tnbr_compare(const struct tnbr
*, const struct tnbr
*);
20 static void tnbr_del(struct ldpd_conf
*, struct tnbr
*);
21 static void tnbr_start(struct tnbr
*);
22 static void tnbr_stop(struct tnbr
*);
23 static void tnbr_hello_timer(struct thread
*);
24 static void tnbr_start_hello_timer(struct tnbr
*);
25 static void tnbr_stop_hello_timer(struct tnbr
*);
27 RB_GENERATE(global_adj_head
, adj
, global_entry
, adj_compare
)
28 RB_GENERATE(nbr_adj_head
, adj
, nbr_entry
, adj_compare
)
29 RB_GENERATE(ia_adj_head
, adj
, ia_entry
, adj_compare
)
30 RB_GENERATE(tnbr_head
, tnbr
, entry
, tnbr_compare
)
33 adj_compare(const struct adj
*a
, const struct adj
*b
)
35 if (adj_get_af(a
) < adj_get_af(b
))
37 if (adj_get_af(a
) > adj_get_af(b
))
40 if (ntohl(a
->lsr_id
.s_addr
) < ntohl(b
->lsr_id
.s_addr
))
42 if (ntohl(a
->lsr_id
.s_addr
) > ntohl(b
->lsr_id
.s_addr
))
45 if (a
->source
.type
< b
->source
.type
)
47 if (a
->source
.type
> b
->source
.type
)
50 switch (a
->source
.type
) {
52 if (if_cmp_name_func(a
->source
.link
.ia
->iface
->name
,
53 b
->source
.link
.ia
->iface
->name
) < 0)
55 if (if_cmp_name_func(a
->source
.link
.ia
->iface
->name
,
56 b
->source
.link
.ia
->iface
->name
) > 0)
58 return (ldp_addrcmp(a
->source
.link
.ia
->af
,
59 &a
->source
.link
.src_addr
, &b
->source
.link
.src_addr
));
61 return (ldp_addrcmp(a
->source
.target
->af
,
62 &a
->source
.target
->addr
, &b
->source
.target
->addr
));
64 fatalx("adj_compare: unknown hello type");
71 adj_new(struct in_addr lsr_id
, struct hello_source
*source
,
72 union ldpd_addr
*addr
)
76 log_debug("%s: lsr-id %pI4, %s", __func__
, &lsr_id
,
77 log_hello_src(source
));
79 if ((adj
= calloc(1, sizeof(*adj
))) == NULL
)
84 adj
->source
= *source
;
85 adj
->trans_addr
= *addr
;
87 RB_INSERT(global_adj_head
, &global
.adj_tree
, adj
);
89 switch (source
->type
) {
91 RB_INSERT(ia_adj_head
, &source
->link
.ia
->adj_tree
, adj
);
94 source
->target
->adj
= adj
;
102 adj_del(struct adj
*adj
, uint32_t notif_status
)
104 struct nbr
*nbr
= adj
->nbr
;
106 log_debug("%s: lsr-id %pI4, %s (%s)", __func__
, &adj
->lsr_id
,
107 log_hello_src(&adj
->source
), af_name(adj_get_af(adj
)));
109 adj_stop_itimer(adj
);
111 RB_REMOVE(global_adj_head
, &global
.adj_tree
, adj
);
113 RB_REMOVE(nbr_adj_head
, &nbr
->adj_tree
, adj
);
114 switch (adj
->source
.type
) {
116 RB_REMOVE(ia_adj_head
, &adj
->source
.link
.ia
->adj_tree
, adj
);
119 ldp_sync_fsm_adj_event(adj
, LDP_SYNC_EVT_ADJ_DEL
);
122 adj
->source
.target
->adj
= NULL
;
129 * If the neighbor still exists but none of its remaining
130 * adjacencies (if any) are from the preferred address-family,
133 if (nbr
&& nbr_adj_count(nbr
, nbr
->af
) == 0) {
134 session_shutdown(nbr
, notif_status
, 0, 0);
140 adj_find(struct in_addr lsr_id
, struct hello_source
*source
)
144 adj
.source
= *source
;
145 return (RB_FIND(global_adj_head
, &global
.adj_tree
, &adj
));
149 adj_get_af(const struct adj
*adj
)
151 switch (adj
->source
.type
) {
153 return (adj
->source
.link
.ia
->af
);
155 return (adj
->source
.target
->af
);
157 fatalx("adj_get_af: unknown hello type");
161 /* adjacency timers */
164 static void adj_itimer(struct thread
*thread
)
166 struct adj
*adj
= THREAD_ARG(thread
);
168 adj
->inactivity_timer
= NULL
;
170 log_debug("%s: lsr-id %pI4", __func__
, &adj
->lsr_id
);
172 if (adj
->source
.type
== HELLO_TARGETED
) {
173 if (!(adj
->source
.target
->flags
& F_TNBR_CONFIGURED
) &&
174 adj
->source
.target
->pw_count
== 0 &&
175 adj
->source
.target
->rlfa_count
== 0) {
176 /* remove dynamic targeted neighbor */
177 tnbr_del(leconf
, adj
->source
.target
);
182 adj_del(adj
, S_HOLDTIME_EXP
);
186 adj_start_itimer(struct adj
*adj
)
188 THREAD_OFF(adj
->inactivity_timer
);
189 adj
->inactivity_timer
= NULL
;
190 thread_add_timer(master
, adj_itimer
, adj
, adj
->holdtime
,
191 &adj
->inactivity_timer
);
195 adj_stop_itimer(struct adj
*adj
)
197 THREAD_OFF(adj
->inactivity_timer
);
200 /* targeted neighbors */
203 tnbr_compare(const struct tnbr
*a
, const struct tnbr
*b
)
210 return (ldp_addrcmp(a
->af
, &a
->addr
, &b
->addr
));
214 tnbr_new(int af
, union ldpd_addr
*addr
)
218 if ((tnbr
= calloc(1, sizeof(*tnbr
))) == NULL
)
223 tnbr
->state
= TNBR_STA_DOWN
;
229 tnbr_del(struct ldpd_conf
*xconf
, struct tnbr
*tnbr
)
232 RB_REMOVE(tnbr_head
, &xconf
->tnbr_tree
, tnbr
);
237 tnbr_find(struct ldpd_conf
*xconf
, int af
, union ldpd_addr
*addr
)
242 return (RB_FIND(tnbr_head
, &xconf
->tnbr_tree
, &tnbr
));
246 tnbr_check(struct ldpd_conf
*xconf
, struct tnbr
*tnbr
)
248 if (!(tnbr
->flags
& (F_TNBR_CONFIGURED
|F_TNBR_DYNAMIC
)) &&
249 tnbr
->pw_count
== 0 && tnbr
->rlfa_count
== 0) {
250 tnbr_del(xconf
, tnbr
);
258 tnbr_start(struct tnbr
*tnbr
)
260 send_hello(HELLO_TARGETED
, NULL
, tnbr
);
261 tnbr_start_hello_timer(tnbr
);
262 tnbr
->state
= TNBR_STA_ACTIVE
;
266 tnbr_stop(struct tnbr
*tnbr
)
268 tnbr_stop_hello_timer(tnbr
);
270 adj_del(tnbr
->adj
, S_SHUTDOWN
);
271 tnbr
->state
= TNBR_STA_DOWN
;
275 tnbr_update(struct tnbr
*tnbr
)
277 int socket_ok
, rtr_id_ok
;
279 if ((ldp_af_global_get(&global
, tnbr
->af
))->ldp_edisc_socket
!= -1)
284 if (ldp_rtr_id_get(leconf
) != INADDR_ANY
)
289 if (tnbr
->state
== TNBR_STA_DOWN
) {
290 if (!socket_ok
|| !rtr_id_ok
)
294 } else if (tnbr
->state
== TNBR_STA_ACTIVE
) {
295 if (socket_ok
&& rtr_id_ok
)
303 tnbr_update_all(int af
)
307 /* update targeted neighbors */
308 RB_FOREACH(tnbr
, tnbr_head
, &leconf
->tnbr_tree
)
309 if (tnbr
->af
== af
|| af
== AF_UNSPEC
)
314 tnbr_get_hello_holdtime(struct tnbr
*tnbr
)
316 if ((ldp_af_conf_get(leconf
, tnbr
->af
))->thello_holdtime
!= 0)
317 return ((ldp_af_conf_get(leconf
, tnbr
->af
))->thello_holdtime
);
319 return (leconf
->thello_holdtime
);
323 tnbr_get_hello_interval(struct tnbr
*tnbr
)
325 if ((ldp_af_conf_get(leconf
, tnbr
->af
))->thello_interval
!= 0)
326 return ((ldp_af_conf_get(leconf
, tnbr
->af
))->thello_interval
);
328 return (leconf
->thello_interval
);
331 /* target neighbors timers */
334 static void tnbr_hello_timer(struct thread
*thread
)
336 struct tnbr
*tnbr
= THREAD_ARG(thread
);
338 tnbr
->hello_timer
= NULL
;
339 send_hello(HELLO_TARGETED
, NULL
, tnbr
);
340 tnbr_start_hello_timer(tnbr
);
344 tnbr_start_hello_timer(struct tnbr
*tnbr
)
346 THREAD_OFF(tnbr
->hello_timer
);
347 tnbr
->hello_timer
= NULL
;
348 thread_add_timer(master
, tnbr_hello_timer
, tnbr
, tnbr_get_hello_interval(tnbr
),
353 tnbr_stop_hello_timer(struct tnbr
*tnbr
)
355 THREAD_OFF(tnbr
->hello_timer
);
359 adj_to_ctl(struct adj
*adj
)
361 static struct ctl_adj actl
;
363 actl
.af
= adj_get_af(adj
);
364 actl
.id
= adj
->lsr_id
;
365 actl
.type
= adj
->source
.type
;
366 switch (adj
->source
.type
) {
368 memcpy(actl
.ifname
, adj
->source
.link
.ia
->iface
->name
,
369 sizeof(actl
.ifname
));
370 actl
.src_addr
= adj
->source
.link
.src_addr
;
373 actl
.src_addr
= adj
->source
.target
->addr
;
376 actl
.holdtime
= adj
->holdtime
;
377 actl
.holdtime_remaining
=
378 thread_timer_remain_second(adj
->inactivity_timer
);
379 actl
.trans_addr
= adj
->trans_addr
;
380 actl
.ds_tlv
= adj
->ds_tlv
;