summaryrefslogtreecommitdiffstats
path: root/zebra/redistribute.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--zebra/redistribute.c92
1 files changed, 74 insertions, 18 deletions
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 7559e31..70ace35 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -16,6 +16,7 @@
#include "log.h"
#include "vrf.h"
#include "srcdest_table.h"
+#include "frrdistance.h"
#include "zebra/rib.h"
#include "zebra/zebra_router.h"
@@ -78,9 +79,8 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id)
RNODE_FOREACH_RE (rn, newre) {
if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED))
- zsend_redistribute_route(
- ZEBRA_REDISTRIBUTE_ROUTE_ADD, client,
- rn, newre);
+ zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
+ client, rn, newre, false);
}
route_unlock_node(rn);
@@ -89,14 +89,26 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id)
/* Redistribute routes. */
static void zebra_redistribute(struct zserv *client, int type,
- unsigned short instance, vrf_id_t vrf_id,
+ unsigned short instance, struct zebra_vrf *zvrf,
int afi)
{
struct route_entry *newre;
struct route_table *table;
struct route_node *rn;
+ bool is_table_direct = false;
+ vrf_id_t vrf_id = zvrf_id(zvrf);
+
+ if (type == ZEBRA_ROUTE_TABLE_DIRECT) {
+ if (vrf_id == VRF_DEFAULT) {
+ table = zebra_router_find_table(zvrf, instance, afi,
+ SAFI_UNICAST);
+ type = ZEBRA_ROUTE_ALL;
+ is_table_direct = true;
+ } else
+ return;
+ } else
+ table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
- table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
if (!table)
return;
@@ -126,11 +138,26 @@ static void zebra_redistribute(struct zserv *client, int type,
continue;
zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
- client, rn, newre);
+ client, rn, newre, is_table_direct);
}
}
/*
+ * Function to return a valid table id value if table-direct is used
+ * return 0 otherwise
+ * This function can be called only if zebra_redistribute_check returns TRUE
+ */
+static bool zebra_redistribute_is_table_direct(const struct route_entry *re)
+{
+ struct zebra_vrf *zvrf;
+
+ zvrf = zebra_vrf_lookup_by_id(re->vrf_id);
+ if (re->vrf_id == VRF_DEFAULT && zvrf->table_id != re->table)
+ return true;
+ return false;
+}
+
+/*
* Function to check if prefix is candidate for
* redistribute.
*/
@@ -147,8 +174,19 @@ static bool zebra_redistribute_check(const struct route_node *rn,
afi = family2afi(rn->p.family);
zvrf = zebra_vrf_lookup_by_id(re->vrf_id);
- if (re->vrf_id == VRF_DEFAULT && zvrf->table_id != re->table)
+ if (re->vrf_id == VRF_DEFAULT && zvrf->table_id != re->table) {
+ if (re->table &&
+ redist_check_instance(&client->mi_redist
+ [afi][ZEBRA_ROUTE_TABLE_DIRECT],
+ re->table)) {
+ /* table-direct redistribution only for route entries which
+ * are on the default vrf, and that have table id different
+ * from the default table.
+ */
+ return true;
+ }
return false;
+ }
/* If default route and redistributed */
if (is_default_prefix(&rn->p) &&
@@ -186,6 +224,7 @@ void redistribute_update(const struct route_node *rn,
{
struct listnode *node, *nnode;
struct zserv *client;
+ bool is_table_direct;
if (IS_ZEBRA_DEBUG_RIB)
zlog_debug(
@@ -211,11 +250,16 @@ void redistribute_update(const struct route_node *rn,
re->vrf_id, re->table, re->type,
re->distance, re->metric);
}
+ is_table_direct = zebra_redistribute_is_table_direct(re);
zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_ADD,
- client, rn, re);
- } else if (zebra_redistribute_check(rn, prev_re, client))
+ client, rn, re,
+ is_table_direct);
+ } else if (zebra_redistribute_check(rn, prev_re, client)) {
+ is_table_direct = zebra_redistribute_is_table_direct(prev_re);
zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
- client, rn, prev_re);
+ client, rn, prev_re,
+ is_table_direct);
+ }
}
}
@@ -234,6 +278,7 @@ void redistribute_delete(const struct route_node *rn,
struct listnode *node, *nnode;
struct zserv *client;
vrf_id_t vrfid;
+ bool is_table_direct;
if (old_re)
vrfid = old_re->vrf_id;
@@ -286,9 +331,20 @@ void redistribute_delete(const struct route_node *rn,
continue;
/* Send a delete for the 'old' re to any subscribed client. */
- if (zebra_redistribute_check(rn, old_re, client))
+ if (zebra_redistribute_check(rn, old_re, client)) {
+ /*
+ * SA is complaining that old_re could be false
+ * SA is wrong because old_re is checked for NULL
+ * in zebra_redistribute_check and false is
+ * returned in that case. Let's just make SA
+ * happy.
+ */
+ assert(old_re);
+ is_table_direct = zebra_redistribute_is_table_direct(old_re);
zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
- client, rn, old_re);
+ client, rn, old_re,
+ is_table_direct);
+ }
}
}
@@ -327,8 +383,7 @@ void zebra_redistribute_add(ZAPI_HANDLER_ARGS)
instance)) {
redist_add_instance(&client->mi_redist[afi][type],
instance);
- zebra_redistribute(client, type, instance,
- zvrf_id(zvrf), afi);
+ zebra_redistribute(client, type, instance, zvrf, afi);
}
} else {
if (!vrf_bitmap_check(&client->redist[afi][type],
@@ -340,7 +395,7 @@ void zebra_redistribute_add(ZAPI_HANDLER_ARGS)
zvrf_id(zvrf));
vrf_bitmap_set(&client->redist[afi][type],
zvrf_id(zvrf));
- zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi);
+ zebra_redistribute(client, type, 0, zvrf, afi);
}
}
@@ -663,9 +718,10 @@ int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn,
if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED))
continue;
- if (same->type == re->type && same->instance == re->instance
- && same->table == re->table
- && same->type != ZEBRA_ROUTE_CONNECT)
+ if (same->type == re->type && same->instance == re->instance &&
+ same->table == re->table &&
+ (same->type != ZEBRA_ROUTE_CONNECT &&
+ same->type != ZEBRA_ROUTE_LOCAL))
break;
}