diff options
Diffstat (limited to 'zebra/redistribute.c')
| -rw-r--r-- | zebra/redistribute.c | 147 |
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) |
