From 134970a2a183d5021a1de42e8eede2fc3aa32e56 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Wed, 28 Sep 2016 12:25:17 -0300 Subject: ldpd: fix processing of redistributed routes 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 --- ldpd/lde.c | 4 ++++ ldpd/lde.h | 3 +++ ldpd/lde_lib.c | 31 ++++++++++++++++++++++++++++++- ldpd/ldp_zebra.c | 4 ++++ ldpd/ldpd.h | 1 + 5 files changed, 42 insertions(+), 1 deletion(-) (limited to 'ldpd') diff --git a/ldpd/lde.c b/ldpd/lde.c index ae29ef6a7..904d0f8d9 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -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); diff --git a/ldpd/lde.h b/ldpd/lde.h index 0fce5565a..cf8f2129a 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -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 *); diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c index 568761bd6..c72a25985 100644 --- a/ldpd/lde_lib.c +++ b/ldpd/lde_lib.c @@ -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) { diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index 6c4137d30..b796b6f6d 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -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); } diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index 9601f25f7..b94794208 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -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, -- cgit v1.2.3