summaryrefslogtreecommitdiff
path: root/zebra/redistribute.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/redistribute.c')
-rw-r--r--zebra/redistribute.c147
1 files changed, 102 insertions, 45 deletions
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index d2fa85eb64..11c1330398 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"
@@ -28,6 +29,7 @@
#include "zebra/zapi_msg.h"
#include "zebra/zebra_vxlan.h"
#include "zebra/zebra_errors.h"
+#include "zebra/zebra_neigh.h"
#define ZEBRA_PTM_SUPPORT
@@ -60,7 +62,7 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id)
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
- if (!vrf_bitmap_check(client->redist_default[afi], vrf_id))
+ if (!vrf_bitmap_check(&client->redist_default[afi], vrf_id))
continue;
/* Lookup table. */
@@ -77,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);
@@ -88,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;
@@ -125,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.
*/
@@ -146,16 +174,27 @@ 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) &&
- vrf_bitmap_check(client->redist_default[afi], re->vrf_id))
+ vrf_bitmap_check(&client->redist_default[afi], re->vrf_id))
return true;
/* If redistribute in enabled for zebra route all */
- if (vrf_bitmap_check(client->redist[afi][ZEBRA_ROUTE_ALL], re->vrf_id))
+ if (vrf_bitmap_check(&client->redist[afi][ZEBRA_ROUTE_ALL], re->vrf_id))
return true;
/*
@@ -171,7 +210,7 @@ static bool zebra_redistribute_check(const struct route_node *rn,
}
/* If redistribution is enabled for give route type. */
- if (vrf_bitmap_check(client->redist[afi][re->type], re->vrf_id))
+ if (vrf_bitmap_check(&client->redist[afi][re->type], re->vrf_id))
return true;
return false;
@@ -185,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(
@@ -210,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);
+ }
}
}
@@ -233,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;
@@ -256,12 +302,11 @@ void redistribute_delete(const struct route_node *rn,
table = new_re->table;
}
- zlog_debug(
- "%u:%u%pRN: Redist del: re %p (%u:%s), new re %p (%u:%s)",
- vrfid, table, rn, old_re, old_inst,
- old_re ? zebra_route_string(old_re->type) : "None",
- new_re, new_inst,
- new_re ? zebra_route_string(new_re->type) : "None");
+ zlog_debug("(%u:%u):%pRN: Redist del: re %p (%u:%s), new re %p (%u:%s)",
+ vrfid, table, rn, old_re, old_inst,
+ old_re ? zebra_route_string(old_re->type) : "None",
+ new_re, new_inst,
+ new_re ? zebra_route_string(new_re->type) : "None");
}
/* Skip invalid (e.g. linklocal) prefix */
@@ -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,20 +383,19 @@ 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],
+ if (!vrf_bitmap_check(&client->redist[afi][type],
zvrf_id(zvrf))) {
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug(
"%s: setting vrf %s(%u) redist bitmap",
__func__, VRF_LOGNAME(zvrf->vrf),
zvrf_id(zvrf));
- vrf_bitmap_set(client->redist[afi][type],
+ 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);
}
}
@@ -387,7 +442,7 @@ void zebra_redistribute_delete(ZAPI_HANDLER_ARGS)
if (instance)
redist_del_instance(&client->mi_redist[afi][type], instance);
else
- vrf_bitmap_unset(client->redist[afi][type], zvrf_id(zvrf));
+ vrf_bitmap_unset(&client->redist[afi][type], zvrf_id(zvrf));
stream_failure:
return;
@@ -405,7 +460,7 @@ void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS)
return;
}
- vrf_bitmap_set(client->redist_default[afi], zvrf_id(zvrf));
+ vrf_bitmap_set(&client->redist_default[afi], zvrf_id(zvrf));
zebra_redistribute_default(client, zvrf_id(zvrf));
stream_failure:
@@ -424,7 +479,7 @@ void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS)
return;
}
- vrf_bitmap_unset(client->redist_default[afi], zvrf_id(zvrf));
+ vrf_bitmap_unset(&client->redist_default[afi], zvrf_id(zvrf));
stream_failure:
return;
@@ -473,6 +528,8 @@ void zebra_interface_down_update(struct interface *ifp)
zsend_interface_update(ZEBRA_INTERFACE_DOWN, client, ifp);
}
+
+ zebra_neigh_del_all(ifp);
}
/* Interface information update. */
@@ -589,9 +646,8 @@ void zebra_interface_vrf_update_del(struct interface *ifp, vrf_id_t new_vrf_id)
struct zserv *client;
if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug(
- "MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/DEL %s VRF Id %u -> %u",
- ifp->name, ifp->vrf->vrf_id, new_vrf_id);
+ zlog_debug("MESSAGE: ZEBRA_INTERFACE_DELETE %s VRF Id %u -> %u",
+ ifp->name, ifp->vrf->vrf_id, new_vrf_id);
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
/* Do not send unsolicited messages to synchronous clients. */
@@ -603,7 +659,6 @@ void zebra_interface_vrf_update_del(struct interface *ifp, vrf_id_t new_vrf_id)
zsend_interface_update(ZEBRA_INTERFACE_DOWN, client, ifp);
client->ifdel_cnt++;
zsend_interface_delete(client, ifp);
- zsend_interface_vrf_update(client, ifp, new_vrf_id);
}
}
@@ -616,9 +671,8 @@ void zebra_interface_vrf_update_add(struct interface *ifp, vrf_id_t old_vrf_id)
struct zserv *client;
if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug(
- "MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/ADD %s VRF Id %u -> %u",
- ifp->name, old_vrf_id, ifp->vrf->vrf_id);
+ zlog_debug("MESSAGE: ZEBRA_INTERFACE_ADD %s VRF Id %u -> %u",
+ ifp->name, old_vrf_id, ifp->vrf->vrf_id);
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
/* Do not send unsolicited messages to synchronous clients. */
@@ -644,10 +698,9 @@ int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn,
afi = family2afi(rn->p.family);
if (rmap_name)
- ret = zebra_import_table_route_map_check(
- afi, re->type, re->instance, &rn->p,
- re->nhe->nhg.nexthop,
- zvrf->vrf->vrf_id, re->tag, rmap_name);
+ ret = zebra_import_table_route_map_check(afi, re, &rn->p,
+ re->nhe->nhg.nexthop,
+ rmap_name);
if (ret != RMAP_PERMITMATCH) {
UNSET_FLAG(re->flags, ZEBRA_FLAG_SELECTED);
@@ -661,9 +714,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;
}
@@ -672,6 +726,8 @@ int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn,
zebra_del_import_table_entry(zvrf, rn, same);
}
+ UNSET_FLAG(re->flags, ZEBRA_FLAG_RR_USE_DISTANCE);
+
newre = zebra_rib_route_entry_new(
0, ZEBRA_ROUTE_TABLE, re->table, re->flags, re->nhe_id,
zvrf->table_id, re->metric, re->mtu,
@@ -681,6 +737,7 @@ int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn,
copy_nexthops(&ng->nexthop, re->nhe->nhg.nexthop, NULL);
rib_add_multipath(afi, SAFI_UNICAST, &p, NULL, newre, ng, false);
+ nexthop_group_delete(&ng);
return 0;
}
@@ -712,7 +769,7 @@ int zebra_import_table(afi_t afi, vrf_id_t vrf_id, uint32_t table_id,
struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(vrf_id);
if (!is_zebra_valid_kernel_table(table_id)
- || (table_id == RT_TABLE_MAIN))
+ || (table_id == rt_table_main_id))
return -1;
if (afi >= AFI_MAX)