#include "ldpe.h"
#include "log.h"
-static __inline int adj_compare(struct adj *, struct adj *);
+static __inline int adj_compare(const struct adj *, const struct adj *);
static int adj_itimer(struct thread *);
-static __inline int tnbr_compare(struct tnbr *, struct tnbr *);
+static __inline int tnbr_compare(const struct tnbr *, const struct tnbr *);
static void tnbr_del(struct ldpd_conf *, struct tnbr *);
+static void tnbr_start(struct tnbr *);
+static void tnbr_stop(struct tnbr *);
static int tnbr_hello_timer(struct thread *);
static void tnbr_start_hello_timer(struct tnbr *);
static void tnbr_stop_hello_timer(struct tnbr *);
RB_GENERATE(tnbr_head, tnbr, entry, tnbr_compare)
static __inline int
-adj_compare(struct adj *a, struct adj *b)
+adj_compare(const struct adj *a, const struct adj *b)
{
+ if (adj_get_af(a) < adj_get_af(b))
+ return (-1);
+ if (adj_get_af(a) > adj_get_af(b))
+ return (1);
+
+ if (ntohl(a->lsr_id.s_addr) < ntohl(b->lsr_id.s_addr))
+ return (-1);
+ if (ntohl(a->lsr_id.s_addr) > ntohl(b->lsr_id.s_addr))
+ return (1);
+
if (a->source.type < b->source.type)
return (-1);
if (a->source.type > b->source.type)
switch (a->source.type) {
case HELLO_LINK:
- if (a->source.link.ia->af < b->source.link.ia->af)
+ if (if_cmp_name_func(a->source.link.ia->iface->name,
+ b->source.link.ia->iface->name) < 0)
return (-1);
- if (a->source.link.ia->af > b->source.link.ia->af)
+ if (if_cmp_name_func(a->source.link.ia->iface->name,
+ b->source.link.ia->iface->name) > 0)
return (1);
return (ldp_addrcmp(a->source.link.ia->af,
&a->source.link.src_addr, &b->source.link.src_addr));
case HELLO_TARGETED:
- if (a->source.target->af < b->source.target->af)
- return (-1);
- if (a->source.target->af > b->source.target->af)
- return (1);
return (ldp_addrcmp(a->source.target->af,
&a->source.target->addr, &b->source.target->addr));
default:
- fatalx("adj_get_af: unknown hello type");
+ fatalx("adj_compare: unknown hello type");
}
return (0);
return (adj);
}
-static void
-adj_del_single(struct adj *adj)
+void
+adj_del(struct adj *adj, uint32_t notif_status)
{
+ struct nbr *nbr = adj->nbr;
+
log_debug("%s: lsr-id %s, %s (%s)", __func__, inet_ntoa(adj->lsr_id),
log_hello_src(&adj->source), af_name(adj_get_af(adj)));
adj_stop_itimer(adj);
RB_REMOVE(global_adj_head, &global.adj_tree, adj);
- if (adj->nbr)
- RB_REMOVE(nbr_adj_head, &adj->nbr->adj_tree, adj);
+ if (nbr)
+ RB_REMOVE(nbr_adj_head, &nbr->adj_tree, adj);
switch (adj->source.type) {
case HELLO_LINK:
RB_REMOVE(ia_adj_head, &adj->source.link.ia->adj_tree, adj);
}
free(adj);
-}
-
-void
-adj_del(struct adj *adj, uint32_t notif_status)
-{
- struct nbr *nbr = adj->nbr;
- struct adj *atmp;
-
- adj_del_single(adj);
/*
* If the neighbor still exists but none of its remaining
* then delete it.
*/
if (nbr && nbr_adj_count(nbr, nbr->af) == 0) {
- RB_FOREACH_SAFE(adj, nbr_adj_head, &nbr->adj_tree, atmp)
- adj_del_single(adj);
session_shutdown(nbr, notif_status, 0, 0);
nbr_del(nbr);
}
}
struct adj *
-adj_find(struct hello_source *source)
+adj_find(struct in_addr lsr_id, struct hello_source *source)
{
struct adj adj;
+ adj.lsr_id = lsr_id;
adj.source = *source;
return (RB_FIND(global_adj_head, &global.adj_tree, &adj));
}
int
-adj_get_af(struct adj *adj)
+adj_get_af(const struct adj *adj)
{
switch (adj->source.type) {
case HELLO_LINK:
tnbr_del(leconf, adj->source.target);
return (0);
}
- adj->source.target->adj = NULL;
}
adj_del(adj, S_HOLDTIME_EXP);
adj_start_itimer(struct adj *adj)
{
THREAD_TIMER_OFF(adj->inactivity_timer);
- adj->inactivity_timer = thread_add_timer(master, adj_itimer, adj,
- adj->holdtime);
+ adj->inactivity_timer = NULL;
+ thread_add_timer(master, adj_itimer, adj, adj->holdtime,
+ &adj->inactivity_timer);
}
void
/* targeted neighbors */
static __inline int
-tnbr_compare(struct tnbr *a, struct tnbr *b)
+tnbr_compare(const struct tnbr *a, const struct tnbr *b)
{
if (a->af < b->af)
return (-1);
static void
tnbr_del(struct ldpd_conf *xconf, struct tnbr *tnbr)
{
- tnbr_stop_hello_timer(tnbr);
- if (tnbr->adj)
- adj_del(tnbr->adj, S_SHUTDOWN);
+ tnbr_stop(tnbr);
RB_REMOVE(tnbr_head, &xconf->tnbr_tree, tnbr);
free(tnbr);
}
return (tnbr);
}
+static void
+tnbr_start(struct tnbr *tnbr)
+{
+ send_hello(HELLO_TARGETED, NULL, tnbr);
+ tnbr_start_hello_timer(tnbr);
+ tnbr->state = TNBR_STA_ACTIVE;
+}
+
+static void
+tnbr_stop(struct tnbr *tnbr)
+{
+ tnbr_stop_hello_timer(tnbr);
+ if (tnbr->adj)
+ adj_del(tnbr->adj, S_SHUTDOWN);
+ tnbr->state = TNBR_STA_DOWN;
+}
+
void
tnbr_update(struct tnbr *tnbr)
{
if (!socket_ok || !rtr_id_ok)
return;
- tnbr->state = TNBR_STA_ACTIVE;
- send_hello(HELLO_TARGETED, NULL, tnbr);
-
- tnbr_start_hello_timer(tnbr);
+ tnbr_start(tnbr);
} else if (tnbr->state == TNBR_STA_ACTIVE) {
if (socket_ok && rtr_id_ok)
return;
- tnbr->state = TNBR_STA_DOWN;
- tnbr_stop_hello_timer(tnbr);
+ tnbr_stop(tnbr);
}
}
tnbr_start_hello_timer(struct tnbr *tnbr)
{
THREAD_TIMER_OFF(tnbr->hello_timer);
- tnbr->hello_timer = thread_add_timer(master, tnbr_hello_timer, tnbr,
- tnbr_get_hello_interval(tnbr));
+ tnbr->hello_timer = NULL;
+ thread_add_timer(master, tnbr_hello_timer, tnbr, tnbr_get_hello_interval(tnbr),
+ &tnbr->hello_timer);
}
static void
case HELLO_LINK:
memcpy(actl.ifname, adj->source.link.ia->iface->name,
sizeof(actl.ifname));
+ actl.src_addr = adj->source.link.src_addr;
break;
case HELLO_TARGETED:
actl.src_addr = adj->source.target->addr;
break;
}
actl.holdtime = adj->holdtime;
+ actl.holdtime_remaining =
+ thread_timer_remain_second(adj->inactivity_timer);
actl.trans_addr = adj->trans_addr;
+ actl.ds_tlv = adj->ds_tlv;
return (&actl);
}