]> git.puffer.fish Git - matthieu/frr.git/commitdiff
ldpd: fix processing of redistributed routes
authorRenato Westphal <renatowestphal@gmail.com>
Wed, 28 Sep 2016 15:25:17 +0000 (12:25 -0300)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 28 Sep 2016 20:05:39 +0000 (16:05 -0400)
Commit 5048fe changed the way zebra behave when a route is updated. Now,
whenever a route is changed, zebra advertises its new version without
withdrawing the old one. This patch adapts ldpd to understand this new
behavior. After processing a ZEBRA_REDISTRIBUTE_IPV[46]_ADD message,
we need to check for nexthops that were removed and, for each of them
(if any), withdraw the associated labels from zebra.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
ldpd/lde.c
ldpd/lde.h
ldpd/lde_lib.c
ldpd/ldp_zebra.c
ldpd/ldpd.h

index ae29ef6a7dab43d6bc1f543ae8d7d8f830c18c28..904d0f8d9ac450366b82c757fc6d0d97aed55b1a 100644 (file)
@@ -406,6 +406,7 @@ lde_dispatch_parent(struct thread *thread)
 
                switch (imsg.hdr.type) {
                case IMSG_NETWORK_ADD:
+               case IMSG_NETWORK_ADD_END:
                case IMSG_NETWORK_DEL:
                        if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(kr)) {
                                log_warnx("%s: wrong imsg len", __func__);
@@ -433,6 +434,9 @@ lde_dispatch_parent(struct thread *thread)
                                lde_kernel_insert(&fec, kr.af, &kr.nexthop,
                                    kr.priority, kr.flags & F_CONNECTED, NULL);
                                break;
+                       case IMSG_NETWORK_ADD_END:
+                               lde_kernel_reevaluate(&fec);
+                               break;
                        case IMSG_NETWORK_DEL:
                                lde_kernel_remove(&fec, kr.af, &kr.nexthop,
                                    kr.priority);
index 0fce5565a2ae21acec8bc394e51a13128b48dfda..cf8f2129af9173e15f2fc284c445e925fdaf85ca 100644 (file)
@@ -102,7 +102,9 @@ struct fec_nh {
        union ldpd_addr          nexthop;
        uint32_t                 remote_label;
        uint8_t                  priority;
+       uint8_t                  flags;
 };
+#define F_FEC_NH_NEW           0x01
 
 struct fec_node {
        struct fec               fec;
@@ -167,6 +169,7 @@ void                 lde_kernel_insert(struct fec *, int, union ldpd_addr *,
                    uint8_t, int, void *);
 void            lde_kernel_remove(struct fec *, int, union ldpd_addr *,
                    uint8_t);
+void            lde_kernel_reevaluate(struct fec *);
 void            lde_check_mapping(struct map *, struct lde_nbr *);
 void            lde_check_request(struct map *, struct lde_nbr *);
 void            lde_check_release(struct map *, struct lde_nbr *);
index 568761bd613f0626cdd17f543f93ca7a26ffc070..c72a25985d3c7b22ea041e3dc45fe78fbd8c401a 100644 (file)
@@ -334,8 +334,11 @@ lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop,
        fn = (struct fec_node *)fec_find(&ft, fec);
        if (fn == NULL)
                fn = fec_add(fec);
-       if (fec_nh_find(fn, af, nexthop, priority) != NULL)
+       fnh = fec_nh_find(fn, af, nexthop, priority);
+       if (fnh != NULL) {
+               fnh->flags |= F_FEC_NH_NEW;
                return;
+       }
 
        if (fn->fec.type == FEC_TYPE_PWID)
                fn->data = data;
@@ -352,6 +355,7 @@ lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop,
        }
 
        fnh = fec_nh_add(fn, af, nexthop, priority);
+       fnh->flags |= F_FEC_NH_NEW;
        lde_send_change_klabel(fn, fnh);
 
        switch (fn->fec.type) {
@@ -402,6 +406,31 @@ lde_kernel_remove(struct fec *fec, int af, union ldpd_addr *nexthop,
        }
 }
 
+/*
+ * Whenever a route is changed, zebra advertises its new version without
+ * withdrawing the old one. So, after processing a ZEBRA_REDISTRIBUTE_IPV[46]_ADD
+ * message, we need to check for nexthops that were removed and, for each of
+ * them (if any), withdraw the associated labels from zebra.
+ */
+void
+lde_kernel_reevaluate(struct fec *fec)
+{
+       struct fec_node         *fn;
+       struct fec_nh           *fnh, *safe;
+
+       fn = (struct fec_node *)fec_find(&ft, fec);
+       if (fn == NULL)
+               return;
+
+       LIST_FOREACH_SAFE(fnh, &fn->nexthops, entry, safe) {
+               if (fnh->flags & F_FEC_NH_NEW)
+                       fnh->flags &= ~F_FEC_NH_NEW;
+               else
+                       lde_kernel_remove(fec, fnh->af, &fnh->nexthop,
+                           fnh->priority);
+       }
+}
+
 void
 lde_check_mapping(struct map *map, struct lde_nbr *ln)
 {
index 6c4137d3051d720e2c25d09db512d551ee5d6fa1..b796b6f6d6fc6b5b6694f0854b2531629192d720 100644 (file)
@@ -438,6 +438,10 @@ ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length,
                }
        }
 
+       if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD ||
+           command == ZEBRA_REDISTRIBUTE_IPV6_ADD)
+               main_imsg_compose_lde(IMSG_NETWORK_ADD_END, 0, &kr, sizeof(kr));
+
        return (0);
 }
 
index 9601f25f70e05aa7265d3020f08c35e65ec59c8e..b94794208a2cc57e01bbfd9383ff541d395abf8c 100644 (file)
@@ -117,6 +117,7 @@ enum imsg_type {
        IMSG_NEIGHBOR_UP,
        IMSG_NEIGHBOR_DOWN,
        IMSG_NETWORK_ADD,
+       IMSG_NETWORK_ADD_END,
        IMSG_NETWORK_DEL,
        IMSG_SOCKET_IPC,
        IMSG_SOCKET_NET,