summaryrefslogtreecommitdiffstats
path: root/zebra/zebra_rib.c
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2019-01-30 15:31:32 +0100
committerDonald Sharp <sharpd@cumulusnetworks.com>2019-01-30 15:52:13 +0100
commitb9f0e5ee2455868d6e9fa730c2b7c0082b0e611e (patch)
tree5b9da87baa350b40e21853fc2c108a8084868d58 /zebra/zebra_rib.c
parentMerge pull request #3414 from pguibert6WIND/iprule_any_flowspec_handling_2 (diff)
downloadfrr-b9f0e5ee2455868d6e9fa730c2b7c0082b0e611e.tar.xz
frr-b9f0e5ee2455868d6e9fa730c2b7c0082b0e611e.zip
zebra: On route update context is sometimes indeterminate in post-processing
When we get into rib_process_result and the operation we are handling is DPLANE_OP_ROUTE_UPDATE *and* the route entry being looked at is a route replace, we currently have no way to decode to the old_re and the re due to how we have stored context. As such they are the same pointer. As such the route replace for the same route type is causing the re to set the installed flag and then immediately unset the installed flag, leaving us in a state where the kernel has the route but the rib thinks we are not installed. Since the true old_re( the one being replaced by the update operation ) is going away( as that it zebra deletes the old one for us already ) this fix is not optimal but will get us moving forward. Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Diffstat (limited to 'zebra/zebra_rib.c')
-rw-r--r--zebra/zebra_rib.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 1eda55dca..3445136d1 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1933,7 +1933,16 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
UNSET_FLAG(re->status, ROUTE_ENTRY_FAILED);
SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
}
- if (old_re) {
+ /*
+ * On an update operation from the same route type
+ * context retrieval currently has no way to know
+ * which was the old and which was the new.
+ * So don't unset our flags that we just set.
+ * We know redistribution is ok because the
+ * old_re in this case is used for nothing
+ * more than knowing whom to contact if necessary.
+ */
+ if (old_re && old_re != re) {
UNSET_FLAG(old_re->status, ROUTE_ENTRY_FAILED);
UNSET_FLAG(old_re->status,
ROUTE_ENTRY_INSTALLED);