diff options
author | Renato Westphal <renatowestphal@gmail.com> | 2016-09-28 17:25:17 +0200 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2016-09-28 22:05:39 +0200 |
commit | 134970a2a183d5021a1de42e8eede2fc3aa32e56 (patch) | |
tree | b5c1edc17d6b49d0d0ebab59776454a1354c48d3 /ldpd | |
parent | ldpd: make route flags a 32bit field (diff) | |
download | frr-134970a2a183d5021a1de42e8eede2fc3aa32e56.tar.xz frr-134970a2a183d5021a1de42e8eede2fc3aa32e56.zip |
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 <renato@opensourcerouting.org>
Diffstat (limited to 'ldpd')
-rw-r--r-- | ldpd/lde.c | 4 | ||||
-rw-r--r-- | ldpd/lde.h | 3 | ||||
-rw-r--r-- | ldpd/lde_lib.c | 31 | ||||
-rw-r--r-- | ldpd/ldp_zebra.c | 4 | ||||
-rw-r--r-- | ldpd/ldpd.h | 1 |
5 files changed, 42 insertions, 1 deletions
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, |