]>
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.
22 #include <sys/types.h>
23 #include <arpa/inet.h>
31 static void adj_del_single(struct adj
*);
32 static void adj_itimer(int, short, void *);
33 static void tnbr_del(struct tnbr
*);
34 static void tnbr_hello_timer(int, short, void *);
35 static void tnbr_start_hello_timer(struct tnbr
*);
36 static void tnbr_stop_hello_timer(struct tnbr
*);
39 adj_new(struct in_addr lsr_id
, struct hello_source
*source
,
40 union ldpd_addr
*addr
)
44 log_debug("%s: lsr-id %s, %s", __func__
, inet_ntoa(lsr_id
),
45 log_hello_src(source
));
47 if ((adj
= calloc(1, sizeof(*adj
))) == NULL
)
52 adj
->source
= *source
;
53 adj
->trans_addr
= *addr
;
55 evtimer_set(&adj
->inactivity_timer
, adj_itimer
, adj
);
57 LIST_INSERT_HEAD(&global
.adj_list
, adj
, global_entry
);
59 switch (source
->type
) {
61 LIST_INSERT_HEAD(&source
->link
.ia
->adj_list
, adj
, ia_entry
);
64 source
->target
->adj
= adj
;
72 adj_del_single(struct adj
*adj
)
74 log_debug("%s: lsr-id %s, %s (%s)", __func__
, inet_ntoa(adj
->lsr_id
),
75 log_hello_src(&adj
->source
), af_name(adj_get_af(adj
)));
79 LIST_REMOVE(adj
, global_entry
);
81 LIST_REMOVE(adj
, nbr_entry
);
82 switch (adj
->source
.type
) {
84 LIST_REMOVE(adj
, ia_entry
);
87 adj
->source
.target
->adj
= NULL
;
95 adj_del(struct adj
*adj
, uint32_t notif_status
)
97 struct nbr
*nbr
= adj
->nbr
;
103 * If the neighbor still exists but none of its remaining
104 * adjacencies (if any) are from the preferred address-family,
107 if (nbr
&& nbr_adj_count(nbr
, nbr
->af
) == 0) {
108 LIST_FOREACH_SAFE(adj
, &nbr
->adj_list
, nbr_entry
, atmp
)
110 session_shutdown(nbr
, notif_status
, 0, 0);
116 adj_find(struct hello_source
*source
)
120 LIST_FOREACH(adj
, &global
.adj_list
, global_entry
) {
121 if (adj
->source
.type
!= source
->type
)
124 switch (source
->type
) {
126 if (ldp_addrcmp(source
->link
.ia
->af
,
127 &adj
->source
.link
.src_addr
,
128 &source
->link
.src_addr
) == 0)
132 if (adj
->source
.target
== source
->target
)
142 adj_get_af(struct adj
*adj
)
144 switch (adj
->source
.type
) {
146 return (adj
->source
.link
.ia
->af
);
148 return (adj
->source
.target
->af
);
150 fatalx("adj_get_af: unknown hello type");
154 /* adjacency timers */
158 adj_itimer(int fd
, short event
, void *arg
)
160 struct adj
*adj
= arg
;
162 log_debug("%s: lsr-id %s", __func__
, inet_ntoa(adj
->lsr_id
));
164 if (adj
->source
.type
== HELLO_TARGETED
) {
165 if (!(adj
->source
.target
->flags
& F_TNBR_CONFIGURED
) &&
166 adj
->source
.target
->pw_count
== 0) {
167 /* remove dynamic targeted neighbor */
168 tnbr_del(adj
->source
.target
);
171 adj
->source
.target
->adj
= NULL
;
174 adj_del(adj
, S_HOLDTIME_EXP
);
178 adj_start_itimer(struct adj
*adj
)
183 tv
.tv_sec
= adj
->holdtime
;
184 if (evtimer_add(&adj
->inactivity_timer
, &tv
) == -1)
189 adj_stop_itimer(struct adj
*adj
)
191 if (evtimer_pending(&adj
->inactivity_timer
, NULL
) &&
192 evtimer_del(&adj
->inactivity_timer
) == -1)
196 /* targeted neighbors */
199 tnbr_new(struct ldpd_conf
*xconf
, int af
, union ldpd_addr
*addr
)
203 if ((tnbr
= calloc(1, sizeof(*tnbr
))) == NULL
)
208 tnbr
->state
= TNBR_STA_DOWN
;
209 tnbr
->hello_holdtime
= (ldp_af_conf_get(xconf
, af
))->thello_holdtime
;
210 tnbr
->hello_interval
= (ldp_af_conf_get(xconf
, af
))->thello_interval
;
216 tnbr_del(struct tnbr
*tnbr
)
218 tnbr_stop_hello_timer(tnbr
);
220 adj_del(tnbr
->adj
, S_SHUTDOWN
);
221 LIST_REMOVE(tnbr
, entry
);
226 tnbr_find(struct ldpd_conf
*xconf
, int af
, union ldpd_addr
*addr
)
230 LIST_FOREACH(tnbr
, &xconf
->tnbr_list
, entry
)
231 if (af
== tnbr
->af
&&
232 ldp_addrcmp(af
, addr
, &tnbr
->addr
) == 0)
239 tnbr_check(struct tnbr
*tnbr
)
241 if (!(tnbr
->flags
& (F_TNBR_CONFIGURED
|F_TNBR_DYNAMIC
)) &&
242 tnbr
->pw_count
== 0) {
251 tnbr_update(struct tnbr
*tnbr
)
253 int socket_ok
, rtr_id_ok
;
255 if ((ldp_af_global_get(&global
, tnbr
->af
))->ldp_edisc_socket
!= -1)
260 if (leconf
->rtr_id
.s_addr
!= INADDR_ANY
)
265 if (tnbr
->state
== TNBR_STA_DOWN
) {
266 if (!socket_ok
|| !rtr_id_ok
)
269 tnbr
->state
= TNBR_STA_ACTIVE
;
270 send_hello(HELLO_TARGETED
, NULL
, tnbr
);
272 evtimer_set(&tnbr
->hello_timer
, tnbr_hello_timer
, tnbr
);
273 tnbr_start_hello_timer(tnbr
);
274 } else if (tnbr
->state
== TNBR_STA_ACTIVE
) {
275 if (socket_ok
&& rtr_id_ok
)
278 tnbr
->state
= TNBR_STA_DOWN
;
279 tnbr_stop_hello_timer(tnbr
);
284 tnbr_update_all(int af
)
288 /* update targeted neighbors */
289 LIST_FOREACH(tnbr
, &leconf
->tnbr_list
, entry
)
290 if (tnbr
->af
== af
|| af
== AF_UNSPEC
)
294 /* target neighbors timers */
298 tnbr_hello_timer(int fd
, short event
, void *arg
)
300 struct tnbr
*tnbr
= arg
;
302 send_hello(HELLO_TARGETED
, NULL
, tnbr
);
303 tnbr_start_hello_timer(tnbr
);
307 tnbr_start_hello_timer(struct tnbr
*tnbr
)
312 tv
.tv_sec
= tnbr
->hello_interval
;
313 if (evtimer_add(&tnbr
->hello_timer
, &tv
) == -1)
318 tnbr_stop_hello_timer(struct tnbr
*tnbr
)
320 if (evtimer_pending(&tnbr
->hello_timer
, NULL
) &&
321 evtimer_del(&tnbr
->hello_timer
) == -1)
326 adj_to_ctl(struct adj
*adj
)
328 static struct ctl_adj actl
;
330 actl
.af
= adj_get_af(adj
);
331 actl
.id
= adj
->lsr_id
;
332 actl
.type
= adj
->source
.type
;
333 switch (adj
->source
.type
) {
335 memcpy(actl
.ifname
, adj
->source
.link
.ia
->iface
->name
,
336 sizeof(actl
.ifname
));
339 actl
.src_addr
= adj
->source
.target
->addr
;
342 actl
.holdtime
= adj
->holdtime
;
343 actl
.trans_addr
= adj
->trans_addr
;