]>
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 int adj_itimer(struct thread
*);
29 static void tnbr_del(struct tnbr
*);
30 static int tnbr_hello_timer(struct thread
*);
31 static void tnbr_start_hello_timer(struct tnbr
*);
32 static void tnbr_stop_hello_timer(struct tnbr
*);
35 adj_new(struct in_addr lsr_id
, struct hello_source
*source
,
36 union ldpd_addr
*addr
)
40 log_debug("%s: lsr-id %s, %s", __func__
, inet_ntoa(lsr_id
),
41 log_hello_src(source
));
43 if ((adj
= calloc(1, sizeof(*adj
))) == NULL
)
48 adj
->source
= *source
;
49 adj
->trans_addr
= *addr
;
51 LIST_INSERT_HEAD(&global
.adj_list
, adj
, global_entry
);
53 switch (source
->type
) {
55 LIST_INSERT_HEAD(&source
->link
.ia
->adj_list
, adj
, ia_entry
);
58 source
->target
->adj
= adj
;
66 adj_del_single(struct adj
*adj
)
68 log_debug("%s: lsr-id %s, %s (%s)", __func__
, inet_ntoa(adj
->lsr_id
),
69 log_hello_src(&adj
->source
), af_name(adj_get_af(adj
)));
73 LIST_REMOVE(adj
, global_entry
);
75 LIST_REMOVE(adj
, nbr_entry
);
76 switch (adj
->source
.type
) {
78 LIST_REMOVE(adj
, ia_entry
);
81 adj
->source
.target
->adj
= NULL
;
89 adj_del(struct adj
*adj
, uint32_t notif_status
)
91 struct nbr
*nbr
= adj
->nbr
;
97 * If the neighbor still exists but none of its remaining
98 * adjacencies (if any) are from the preferred address-family,
101 if (nbr
&& nbr_adj_count(nbr
, nbr
->af
) == 0) {
102 LIST_FOREACH_SAFE(adj
, &nbr
->adj_list
, nbr_entry
, atmp
)
104 session_shutdown(nbr
, notif_status
, 0, 0);
110 adj_find(struct hello_source
*source
)
114 LIST_FOREACH(adj
, &global
.adj_list
, global_entry
) {
115 if (adj
->source
.type
!= source
->type
)
118 switch (source
->type
) {
120 if (ldp_addrcmp(source
->link
.ia
->af
,
121 &adj
->source
.link
.src_addr
,
122 &source
->link
.src_addr
) == 0)
126 if (adj
->source
.target
== source
->target
)
136 adj_get_af(struct adj
*adj
)
138 switch (adj
->source
.type
) {
140 return (adj
->source
.link
.ia
->af
);
142 return (adj
->source
.target
->af
);
144 fatalx("adj_get_af: unknown hello type");
148 /* adjacency timers */
152 adj_itimer(struct thread
*thread
)
154 struct adj
*adj
= THREAD_ARG(thread
);
156 adj
->inactivity_timer
= NULL
;
158 log_debug("%s: lsr-id %s", __func__
, inet_ntoa(adj
->lsr_id
));
160 if (adj
->source
.type
== HELLO_TARGETED
) {
161 if (!(adj
->source
.target
->flags
& F_TNBR_CONFIGURED
) &&
162 adj
->source
.target
->pw_count
== 0) {
163 /* remove dynamic targeted neighbor */
164 tnbr_del(adj
->source
.target
);
167 adj
->source
.target
->adj
= NULL
;
170 adj_del(adj
, S_HOLDTIME_EXP
);
176 adj_start_itimer(struct adj
*adj
)
178 THREAD_TIMER_OFF(adj
->inactivity_timer
);
179 adj
->inactivity_timer
= thread_add_timer(master
, adj_itimer
, adj
,
184 adj_stop_itimer(struct adj
*adj
)
186 THREAD_TIMER_OFF(adj
->inactivity_timer
);
189 /* targeted neighbors */
192 tnbr_new(int af
, union ldpd_addr
*addr
)
196 if ((tnbr
= calloc(1, sizeof(*tnbr
))) == NULL
)
201 tnbr
->state
= TNBR_STA_DOWN
;
207 tnbr_del(struct tnbr
*tnbr
)
209 tnbr_stop_hello_timer(tnbr
);
211 adj_del(tnbr
->adj
, S_SHUTDOWN
);
212 LIST_REMOVE(tnbr
, entry
);
217 tnbr_find(struct ldpd_conf
*xconf
, int af
, union ldpd_addr
*addr
)
221 LIST_FOREACH(tnbr
, &xconf
->tnbr_list
, entry
)
222 if (af
== tnbr
->af
&&
223 ldp_addrcmp(af
, addr
, &tnbr
->addr
) == 0)
230 tnbr_check(struct tnbr
*tnbr
)
232 if (!(tnbr
->flags
& (F_TNBR_CONFIGURED
|F_TNBR_DYNAMIC
)) &&
233 tnbr
->pw_count
== 0) {
242 tnbr_update(struct tnbr
*tnbr
)
244 int socket_ok
, rtr_id_ok
;
246 if ((ldp_af_global_get(&global
, tnbr
->af
))->ldp_edisc_socket
!= -1)
251 if (ldp_rtr_id_get(leconf
) != INADDR_ANY
)
256 if (tnbr
->state
== TNBR_STA_DOWN
) {
257 if (!socket_ok
|| !rtr_id_ok
)
260 tnbr
->state
= TNBR_STA_ACTIVE
;
261 send_hello(HELLO_TARGETED
, NULL
, tnbr
);
263 tnbr_start_hello_timer(tnbr
);
264 } else if (tnbr
->state
== TNBR_STA_ACTIVE
) {
265 if (socket_ok
&& rtr_id_ok
)
268 tnbr
->state
= TNBR_STA_DOWN
;
269 tnbr_stop_hello_timer(tnbr
);
274 tnbr_update_all(int af
)
278 /* update targeted neighbors */
279 LIST_FOREACH(tnbr
, &leconf
->tnbr_list
, entry
)
280 if (tnbr
->af
== af
|| af
== AF_UNSPEC
)
285 tnbr_get_hello_holdtime(struct tnbr
*tnbr
)
287 if ((ldp_af_conf_get(leconf
, tnbr
->af
))->thello_holdtime
!= 0)
288 return ((ldp_af_conf_get(leconf
, tnbr
->af
))->thello_holdtime
);
290 return (leconf
->thello_holdtime
);
294 tnbr_get_hello_interval(struct tnbr
*tnbr
)
296 if ((ldp_af_conf_get(leconf
, tnbr
->af
))->thello_interval
!= 0)
297 return ((ldp_af_conf_get(leconf
, tnbr
->af
))->thello_interval
);
299 return (leconf
->thello_interval
);
302 /* target neighbors timers */
306 tnbr_hello_timer(struct thread
*thread
)
308 struct tnbr
*tnbr
= THREAD_ARG(thread
);
310 tnbr
->hello_timer
= NULL
;
311 send_hello(HELLO_TARGETED
, NULL
, tnbr
);
312 tnbr_start_hello_timer(tnbr
);
318 tnbr_start_hello_timer(struct tnbr
*tnbr
)
320 THREAD_TIMER_OFF(tnbr
->hello_timer
);
321 tnbr
->hello_timer
= thread_add_timer(master
, tnbr_hello_timer
, tnbr
,
322 tnbr_get_hello_interval(tnbr
));
326 tnbr_stop_hello_timer(struct tnbr
*tnbr
)
328 THREAD_TIMER_OFF(tnbr
->hello_timer
);
332 adj_to_ctl(struct adj
*adj
)
334 static struct ctl_adj actl
;
336 actl
.af
= adj_get_af(adj
);
337 actl
.id
= adj
->lsr_id
;
338 actl
.type
= adj
->source
.type
;
339 switch (adj
->source
.type
) {
341 memcpy(actl
.ifname
, adj
->source
.link
.ia
->iface
->name
,
342 sizeof(actl
.ifname
));
345 actl
.src_addr
= adj
->source
.target
->addr
;
348 actl
.holdtime
= adj
->holdtime
;
349 actl
.trans_addr
= adj
->trans_addr
;