srcdest_rnode_prefixes(rn, &dst_p, &src_p);
- if (IS_ZEBRA_DEBUG_EVENT)
+ if (IS_ZEBRA_DEBUG_RIB)
zlog_debug(
"%s: client %s %s(%u) checking: selected=%d, type=%d, distance=%d, metric=%d zebra_check_addr=%d",
__func__,
/* Either advertise a route for redistribution to registered clients or */
/* withdraw redistribution if add cannot be done for client */
void redistribute_update(const struct prefix *p, const struct prefix *src_p,
- struct route_entry *re, struct route_entry *prev_re)
+ const struct route_entry *re,
+ const struct route_entry *prev_re)
{
struct listnode *node, *nnode;
struct zserv *client;
__FUNCTION__);
return;
}
+ if (!zebra_check_addr(p)) {
+ if (IS_ZEBRA_DEBUG_RIB)
+ zlog_debug("Redist update filter prefix %s",
+ prefix2str(p, buf, sizeof(buf)));
+ return;
+ }
+
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
send_redistribute = 0;
send_redistribute = 1;
if (send_redistribute) {
- if (IS_ZEBRA_DEBUG_EVENT) {
+ if (IS_ZEBRA_DEBUG_RIB) {
zlog_debug(
"%s: client %s %s(%u), type=%d, distance=%d, metric=%d",
__func__,
}
}
+/*
+ * During a route delete, where 'new_re' is NULL, redist a delete to all
+ * clients registered for the type of 'old_re'.
+ * During a route update, redist a delete to any clients who will not see
+ * an update when the new route is installed. There are cases when a client
+ * may have seen a redist for 'old_re', but will not see
+ * the redist for 'new_re'.
+ */
void redistribute_delete(const struct prefix *p, const struct prefix *src_p,
- struct route_entry *re)
+ const struct route_entry *old_re,
+ const struct route_entry *new_re)
{
struct listnode *node, *nnode;
struct zserv *client;
- char buf[INET6_ADDRSTRLEN];
int afi;
+ char buf[PREFIX_STRLEN];
+ vrf_id_t vrfid;
+
+ if (old_re)
+ vrfid = old_re->vrf_id;
+ else if (new_re)
+ vrfid = new_re->vrf_id;
+ else
+ return;
if (IS_ZEBRA_DEBUG_RIB) {
- inet_ntop(p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN);
- zlog_debug("%u:%s/%d: Redist delete re %p (%s)",
- re->vrf_id, buf, p->prefixlen, re,
- zebra_route_string(re->type));
+ zlog_debug(
+ "%u:%s: Redist del: re %p (%s), new re %p (%s)",
+ vrfid, prefix2str(p, buf, sizeof(buf)),
+ old_re,
+ old_re ? zebra_route_string(old_re->type) : "None",
+ new_re,
+ new_re ? zebra_route_string(new_re->type) : "None");
}
/* Add DISTANCE_INFINITY check. */
- if (re->distance == DISTANCE_INFINITY)
+ if (old_re && (old_re->distance == DISTANCE_INFINITY)) {
+ if (IS_ZEBRA_DEBUG_RIB)
+ zlog_debug("\tSkipping due to Infinite Distance");
return;
+ }
afi = family2afi(p->family);
if (!afi) {
flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF,
"%s: Unknown AFI/SAFI prefix received\n",
- __FUNCTION__);
+ __func__);
+ return;
+ }
+
+ /* Skip invalid (e.g. linklocal) prefix */
+ if (!zebra_check_addr(p)) {
+ if (IS_ZEBRA_DEBUG_RIB) {
+ zlog_debug(
+ "%u:%s: Redist del old: skipping invalid prefix",
+ vrfid, prefix2str(p, buf, sizeof(buf)));
+ }
return;
}
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
- if ((is_default_prefix(p)
- && vrf_bitmap_check(client->redist_default[afi],
- re->vrf_id))
- || vrf_bitmap_check(client->redist[afi][ZEBRA_ROUTE_ALL],
- re->vrf_id)
- || (re->instance
- && redist_check_instance(
- &client->mi_redist[afi][re->type],
- re->instance))
- || vrf_bitmap_check(client->redist[afi][re->type],
- re->vrf_id)) {
+ if (new_re) {
+ /* Skip this client if it will receive an update for the
+ * 'new' re
+ */
+ if (is_default_prefix(p)
+ && vrf_bitmap_check(client->redist_default[afi],
+ new_re->vrf_id))
+ continue;
+ else if (vrf_bitmap_check(
+ client->redist[afi][ZEBRA_ROUTE_ALL],
+ new_re->vrf_id))
+ continue;
+ else if (new_re->instance
+ && redist_check_instance(
+ &client->mi_redist[afi][new_re->type],
+ new_re->instance))
+ continue;
+ else if (vrf_bitmap_check(
+ client->redist[afi][new_re->type],
+ new_re->vrf_id))
+ continue;
+ }
+
+ /* Send a delete for the 'old' re to any subscribed client. */
+ if (old_re
+ && (vrf_bitmap_check(client->redist[afi][ZEBRA_ROUTE_ALL],
+ old_re->vrf_id)
+ || (old_re->instance
+ && redist_check_instance(
+ &client->mi_redist[afi][old_re->type],
+ old_re->instance))
+ || vrf_bitmap_check(client->redist[afi][old_re->type],
+ old_re->vrf_id))) {
zsend_redistribute_route(ZEBRA_REDISTRIBUTE_ROUTE_DEL,
- client, p, src_p, re);
+ client, p, src_p, old_re);
}
}
}
struct route_entry *newre;
struct route_entry *same;
struct prefix p;
+ struct nexthop_group *ng;
route_map_result_t ret = RMAP_PERMITMATCH;
afi_t afi;
afi = family2afi(rn->p.family);
if (rmap_name)
ret = zebra_import_table_route_map_check(
- afi, re->type, re->instance, &rn->p, re->ng.nexthop,
+ afi, re->type, re->instance, &rn->p,
+ re->nhe->nhg->nexthop,
zvrf->vrf->vrf_id, re->tag, rmap_name);
if (ret != RMAP_PERMITMATCH) {
newre->metric = re->metric;
newre->mtu = re->mtu;
newre->table = zvrf->table_id;
- newre->nexthop_num = 0;
newre->uptime = monotime(NULL);
newre->instance = re->table;
- route_entry_copy_nexthops(newre, re->ng.nexthop);
- rib_add_multipath(afi, SAFI_UNICAST, &p, NULL, newre);
+ ng = nexthop_group_new();
+ copy_nexthops(&ng->nexthop, re->nhe->nhg->nexthop, NULL);
+
+ rib_add_multipath(afi, SAFI_UNICAST, &p, NULL, newre, ng);
return 0;
}
prefix_copy(&p, &rn->p);
rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_TABLE,
- re->table, re->flags, &p, NULL, re->ng.nexthop,
- zvrf->table_id, re->metric, re->distance, false);
+ re->table, re->flags, &p, NULL, re->nhe->nhg->nexthop,
+ re->nhe_id, zvrf->table_id, re->metric, re->distance,
+ false);
return 0;
}
if (!is_zebra_valid_kernel_table(table_id)
|| (table_id == RT_TABLE_MAIN))
- return (-1);
+ return -1;
if (afi >= AFI_MAX)
- return (-1);
+ return -1;
- table = zebra_vrf_table_with_table_id(afi, SAFI_UNICAST, vrf_id,
- table_id);
+ table = zebra_vrf_get_table_with_table_id(afi, SAFI_UNICAST, vrf_id,
+ table_id);
if (table == NULL) {
return 0;
} else if (IS_ZEBRA_DEBUG_RIB) {
if ((!rmap_name) || (strcmp(rmap_name, rmap) != 0))
return;
- table = zebra_vrf_table_with_table_id(afi, SAFI_UNICAST,
- zvrf->vrf->vrf_id, table_id);
+ table = zebra_vrf_get_table_with_table_id(afi, SAFI_UNICAST,
+ zvrf->vrf->vrf_id, table_id);
if (!table) {
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug("%s: Table id=%d not found", __func__,