summaryrefslogtreecommitdiffstats
path: root/ldpd
diff options
context:
space:
mode:
authorRenato Westphal <renatowestphal@gmail.com>2016-09-28 17:25:17 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2016-09-28 22:05:39 +0200
commit134970a2a183d5021a1de42e8eede2fc3aa32e56 (patch)
treeb5c1edc17d6b49d0d0ebab59776454a1354c48d3 /ldpd
parentldpd: make route flags a 32bit field (diff)
downloadfrr-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.c4
-rw-r--r--ldpd/lde.h3
-rw-r--r--ldpd/lde_lib.c31
-rw-r--r--ldpd/ldp_zebra.c4
-rw-r--r--ldpd/ldpd.h1
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,