]> git.proxmox.com Git - mirror_frr.git/blobdiff - ldpd/adjacency.c
Merge pull request #5259 from mjstapp/dplane_sample_plugin
[mirror_frr.git] / ldpd / adjacency.c
index 69031bdd758b14f3b2e9d1b573e4e68bee77b234..0bdd2423c7c1b47a7975ca0d44f17612d216fc6c 100644 (file)
 #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 *);
@@ -39,8 +41,18 @@ RB_GENERATE(ia_adj_head, adj, ia_entry, adj_compare)
 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)
@@ -48,21 +60,19 @@ adj_compare(struct adj *a, struct adj *b)
 
        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);
@@ -99,17 +109,19 @@ adj_new(struct in_addr lsr_id, struct hello_source *source,
        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);
@@ -120,15 +132,6 @@ adj_del_single(struct adj *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
@@ -136,23 +139,22 @@ adj_del(struct adj *adj, uint32_t notif_status)
         * 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:
@@ -183,7 +185,6 @@ adj_itimer(struct thread *thread)
                        tnbr_del(leconf, adj->source.target);
                        return (0);
                }
-               adj->source.target->adj = NULL;
        }
 
        adj_del(adj, S_HOLDTIME_EXP);
@@ -195,8 +196,9 @@ void
 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
@@ -208,7 +210,7 @@ adj_stop_itimer(struct adj *adj)
 /* 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);
@@ -236,9 +238,7 @@ tnbr_new(int af, union ldpd_addr *addr)
 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);
 }
@@ -264,6 +264,23 @@ tnbr_check(struct ldpd_conf *xconf, struct tnbr *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)
 {
@@ -283,16 +300,12 @@ 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);
        }
 }
 
@@ -344,8 +357,9 @@ static void
 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
@@ -366,13 +380,17 @@ adj_to_ctl(struct adj *adj)
        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);
 }