summaryrefslogtreecommitdiffstats
path: root/zebra/zebra_rnh.c
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2018-03-26 17:05:52 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2018-04-06 19:22:43 +0200
commitd61d5d888cc0e9f8526eff39de7e3aa4949fe322 (patch)
treea43575e3fcb34e83bf7ffabd6d59ffae6166ddf7 /zebra/zebra_rnh.c
parentpbrd: Do not use vrf_frame for pbrms display (diff)
downloadfrr-d61d5d888cc0e9f8526eff39de7e3aa4949fe322.tar.xz
frr-d61d5d888cc0e9f8526eff39de7e3aa4949fe322.zip
zebra: Add code to notice nexthop changes for pbr tables
When we have a PBR installed as a table, we need to notice when a nexthop changes and rethink the routes for the pbr tables. Add code to nexthop tracking to notice the pbr watched nexthop has changed in some manner. If it is a pbr route that depends on the nexthop then just enqueue it for rethinking. This is a bit of a hammer, we know that only pbr routes are going to be installing routes in weird non-standard tables as such we need to only handle nexthop changes for nexthops that are actually changing that we care about and to only requeue for route nodes we have route entries for from PBR Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Diffstat (limited to 'zebra/zebra_rnh.c')
-rw-r--r--zebra/zebra_rnh.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 65df4e15a..879da092f 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -514,6 +514,59 @@ static void zebra_rnh_notify_protocol_clients(vrf_id_t vrfid, int family,
}
}
+static void zebra_rnh_process_pbr_tables(int family,
+ struct route_node *nrn,
+ struct rnh *rnh,
+ struct route_node *prn,
+ struct route_entry *re)
+{
+ struct zebra_ns_table *znst;
+ struct route_entry *o_re;
+ struct route_node *o_rn;
+ struct listnode *node;
+ struct zserv *client;
+ struct zebra_ns *zns;
+ afi_t afi = AFI_IP;
+
+ if (family == AF_INET6)
+ afi = AFI_IP6;
+
+ /*
+ * We are only concerned about nexthops that change for
+ * anyone using PBR
+ */
+ for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) {
+ if (client->proto == ZEBRA_ROUTE_PBR)
+ break;
+ }
+
+ if (!client)
+ return;
+
+ zns = zebra_ns_lookup(NS_DEFAULT);
+ RB_FOREACH (znst, zebra_ns_table_head, &zns->ns_tables) {
+ if (afi != znst->afi)
+ continue;
+
+ for (o_rn = route_top(znst->table);
+ o_rn; o_rn = srcdest_route_next(o_rn)) {
+ RNODE_FOREACH_RE (o_rn, o_re) {
+ if (o_re->type == ZEBRA_ROUTE_PBR)
+ break;
+
+ }
+
+ /*
+ * If we have a PBR route and a nexthop changes
+ * just rethink it. Yes this is a hammer, but
+ * a small one
+ */
+ if (o_re)
+ rib_queue_add(o_rn);
+ }
+ }
+}
+
static void zebra_rnh_process_static_routes(vrf_id_t vrfid, int family,
struct route_node *nrn,
struct rnh *rnh,
@@ -752,6 +805,9 @@ static void zebra_rnh_eval_nexthop_entry(vrf_id_t vrfid, int family, int force,
zebra_rnh_process_static_routes(vrfid, family, nrn, rnh, prn,
rnh->state);
+ zebra_rnh_process_pbr_tables(family, nrn, rnh, prn,
+ rnh->state);
+
/* Process pseudowires attached to this nexthop */
zebra_rnh_process_pseudowires(vrfid, rnh);
}