Merge pull request #13945 from pguibert6WIND/redistribute_isis_table

Redistribute isis table
This commit is contained in:
Russ White 2023-07-25 10:16:46 -04:00 committed by GitHub
commit 82d8e7d5fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 619 additions and 176 deletions

View File

@ -166,6 +166,11 @@ flavors (local LFA, Remote LFA and TI-LFA).
Configure a prefix-list to select eligible PQ nodes for remote LFA
backups (valid for all protected interfaces).
.. clicmd:: redistribute <ipv4 | ipv6> table (1-65535) <level-1 | level-2> [metric (0-16777215)|route-map WORD]
Redistribute routes from a given routing table into the given ISIS
level database.
.. _isis-region:
ISIS region

View File

@ -1430,20 +1430,99 @@ DEFPY_YANG(isis_redistribute, isis_redistribute_cmd,
level);
}
static void vty_print_redistribute(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults, const char *family)
/*
* XPath: /frr-isisd:isis/instance/redistribute/table
*/
DEFPY_YANG(isis_redistribute_table, isis_redistribute_table_cmd,
"[no] redistribute <ipv4|ipv6>$ip table (1-65535)$table"
"<level-1|level-2>$level [{metric (0-16777215)|route-map WORD}]",
NO_STR REDIST_STR "Redistribute IPv4 routes\n"
"Redistribute IPv6 routes\n"
"Non-main Kernel Routing Table\n"
"Table Id\n"
"Redistribute into level-1\n"
"Redistribute into level-2\n"
"Metric for redistributed routes\n"
"IS-IS default metric\n"
"Route map reference\n"
"Pointer to route-map entries\n")
{
const char *level = yang_dnode_get_string(dnode, "./level");
const char *protocol = yang_dnode_get_string(dnode, "./protocol");
struct isis_redist_table_present_args rtda = {};
char xpath[XPATH_MAXLEN];
char xpath_entry[XPATH_MAXLEN + 128];
int rv;
vty_out(vty, " redistribute %s %s %s", family, protocol, level);
rtda.rtda_table = table_str;
rtda.rtda_ip = ip;
rtda.rtda_level = level;
if (no) {
if (!isis_redist_table_is_present(vty, &rtda))
return CMD_WARNING_CONFIG_FAILED;
snprintf(xpath, sizeof(xpath), "./table[table='%s']", table_str);
nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
rv = nb_cli_apply_changes(vty,
"./redistribute/%s[protocol='table'][level='%s']",
ip, level);
if (rv == CMD_SUCCESS) {
if (isis_redist_table_get_first(vty, &rtda) > 0)
return CMD_SUCCESS;
nb_cli_enqueue_change(vty, "./table", NB_OP_DESTROY,
NULL);
nb_cli_apply_changes(vty,
"./redistribute/%s[protocol='table'][level='%s']",
ip, level);
}
return CMD_SUCCESS;
}
if (isis_redist_table_is_present(vty, &rtda))
return CMD_SUCCESS;
snprintf(xpath, sizeof(xpath), "./table[table='%s']", table_str);
nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_entry, sizeof(xpath_entry), "%s/route-map", xpath);
nb_cli_enqueue_change(vty, xpath_entry,
route_map ? NB_OP_MODIFY : NB_OP_DESTROY,
route_map ? route_map : NULL);
snprintf(xpath_entry, sizeof(xpath_entry), "%s/metric", xpath);
nb_cli_enqueue_change(vty, xpath_entry, NB_OP_MODIFY,
metric_str ? metric_str : NULL);
return nb_cli_apply_changes(vty,
"./redistribute/%s[protocol='table'][level='%s']",
ip, level);
}
static void vty_print_redistribute(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults, const char *family,
bool table)
{
const char *level;
const char *protocol = NULL;
const char *routemap = NULL;
uint16_t tableid;
if (table) {
level = yang_dnode_get_string(dnode, "../level");
tableid = yang_dnode_get_uint16(dnode, "./table");
vty_out(vty, " redistribute %s table %d ", family, tableid);
} else {
protocol = yang_dnode_get_string(dnode, "./protocol");
if (!table && strmatch(protocol, "table"))
return;
level = yang_dnode_get_string(dnode, "./level");
vty_out(vty, " redistribute %s %s ", family, protocol);
}
vty_out(vty, "%s", level);
if (show_defaults || !yang_dnode_is_default(dnode, "./metric"))
vty_out(vty, " metric %s",
yang_dnode_get_string(dnode, "./metric"));
yang_dnode_get_string(dnode, "%s", "./metric"));
if (yang_dnode_exists(dnode, "./route-map"))
vty_out(vty, " route-map %s",
yang_dnode_get_string(dnode, "./route-map"));
routemap = yang_dnode_get_string(dnode, "./route-map");
if (routemap)
vty_out(vty, " route-map %s", routemap);
vty_out(vty, "\n");
}
@ -1451,13 +1530,37 @@ void cli_show_isis_redistribute_ipv4(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults)
{
vty_print_redistribute(vty, dnode, show_defaults, "ipv4");
vty_print_redistribute(vty, dnode, show_defaults, "ipv4", false);
}
void cli_show_isis_redistribute_ipv6(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults)
{
vty_print_redistribute(vty, dnode, show_defaults, "ipv6");
vty_print_redistribute(vty, dnode, show_defaults, "ipv6", false);
}
void cli_show_isis_redistribute_ipv4_table(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults)
{
vty_print_redistribute(vty, dnode, show_defaults, "ipv4", true);
}
void cli_show_isis_redistribute_ipv6_table(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults)
{
vty_print_redistribute(vty, dnode, show_defaults, "ipv6", true);
}
int cli_cmp_isis_redistribute_table(const struct lyd_node *dnode1,
const struct lyd_node *dnode2)
{
uint16_t table1 = yang_dnode_get_uint16(dnode1, "./table");
uint16_t table2 = yang_dnode_get_uint16(dnode2, "./table");
return table1 - table2;
}
/*
@ -3681,6 +3784,7 @@ void isis_cli_init(void)
install_element(ISIS_NODE, &isis_default_originate_cmd);
install_element(ISIS_NODE, &isis_redistribute_cmd);
install_element(ISIS_NODE, &isis_redistribute_table_cmd);
install_element(ISIS_NODE, &isis_topology_cmd);

View File

@ -381,6 +381,29 @@ const struct frr_yang_module_info frr_isisd_info = {
},
{
.xpath = "/frr-isisd:isis/instance/redistribute/ipv4/metric",
.cbs = {
.destroy = isis_instance_redistribute_ipv4_metric_destroy,
.modify = isis_instance_redistribute_ipv4_metric_modify,
},
},
{
.xpath = "/frr-isisd:isis/instance/redistribute/ipv4/table",
.cbs = {
.cli_show = cli_show_isis_redistribute_ipv4_table,
.cli_cmp = cli_cmp_isis_redistribute_table,
.create = isis_instance_redistribute_ipv4_table_create,
.destroy = isis_instance_redistribute_ipv4_table_destroy,
},
},
{
.xpath = "/frr-isisd:isis/instance/redistribute/ipv4/table/route-map",
.cbs = {
.destroy = isis_instance_redistribute_ipv4_route_map_destroy,
.modify = isis_instance_redistribute_ipv4_route_map_modify,
},
},
{
.xpath = "/frr-isisd:isis/instance/redistribute/ipv4/table/metric",
.cbs = {
.modify = isis_instance_redistribute_ipv4_metric_modify,
},
@ -403,6 +426,29 @@ const struct frr_yang_module_info frr_isisd_info = {
},
{
.xpath = "/frr-isisd:isis/instance/redistribute/ipv6/metric",
.cbs = {
.destroy = isis_instance_redistribute_ipv6_metric_destroy,
.modify = isis_instance_redistribute_ipv6_metric_modify,
},
},
{
.xpath = "/frr-isisd:isis/instance/redistribute/ipv6/table",
.cbs = {
.cli_show = cli_show_isis_redistribute_ipv6_table,
.cli_cmp = cli_cmp_isis_redistribute_table,
.create = isis_instance_redistribute_ipv6_table_create,
.destroy = isis_instance_redistribute_ipv6_table_destroy,
},
},
{
.xpath = "/frr-isisd:isis/instance/redistribute/ipv6/table/route-map",
.cbs = {
.destroy = isis_instance_redistribute_ipv6_route_map_destroy,
.modify = isis_instance_redistribute_ipv6_route_map_modify,
},
},
{
.xpath = "/frr-isisd:isis/instance/redistribute/ipv6/table/metric",
.cbs = {
.modify = isis_instance_redistribute_ipv6_metric_modify,
},

View File

@ -121,6 +121,11 @@ int isis_instance_redistribute_ipv4_route_map_destroy(
struct nb_cb_destroy_args *args);
int isis_instance_redistribute_ipv4_metric_modify(
struct nb_cb_modify_args *args);
int isis_instance_redistribute_ipv4_metric_destroy(
struct nb_cb_destroy_args *args);
int isis_instance_redistribute_ipv4_table_create(struct nb_cb_create_args *args);
int isis_instance_redistribute_ipv4_table_destroy(
struct nb_cb_destroy_args *args);
int isis_instance_redistribute_ipv6_create(struct nb_cb_create_args *args);
int isis_instance_redistribute_ipv6_destroy(struct nb_cb_destroy_args *args);
int isis_instance_redistribute_ipv6_route_map_modify(
@ -129,6 +134,11 @@ int isis_instance_redistribute_ipv6_route_map_destroy(
struct nb_cb_destroy_args *args);
int isis_instance_redistribute_ipv6_metric_modify(
struct nb_cb_modify_args *args);
int isis_instance_redistribute_ipv6_metric_destroy(
struct nb_cb_destroy_args *args);
int isis_instance_redistribute_ipv6_table_create(struct nb_cb_create_args *args);
int isis_instance_redistribute_ipv6_table_destroy(
struct nb_cb_destroy_args *args);
int isis_instance_multi_topology_ipv4_multicast_create(
struct nb_cb_create_args *args);
int isis_instance_multi_topology_ipv4_multicast_destroy(
@ -587,6 +597,12 @@ void cli_show_isis_redistribute_ipv6(struct vty *vty,
void cli_show_isis_mt_ipv4_multicast(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults);
void cli_show_isis_redistribute_ipv4_table(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults);
void cli_show_isis_redistribute_ipv6_table(struct vty *vty,
const struct lyd_node *dnode,
bool show_defaults);
void cli_show_isis_mt_ipv4_mgmt(struct vty *vty, const struct lyd_node *dnode,
bool show_defaults);
void cli_show_isis_mt_ipv6_unicast(struct vty *vty,
@ -742,6 +758,9 @@ void isis_notif_seqno_skipped(const struct isis_circuit *circuit,
const uint8_t *lsp_id);
void isis_notif_own_lsp_purge(const struct isis_circuit *circuit,
const uint8_t *lsp_id);
/* cmp */
int cli_cmp_isis_redistribute_table(const struct lyd_node *dnode1,
const struct lyd_node *dnode2);
/* We also declare hook for every notification */

View File

@ -1088,7 +1088,7 @@ void default_info_origin_apply_finish(const struct lyd_node *dnode, int family)
routemap = yang_dnode_get_string(dnode, "./route-map");
isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap,
originate_type);
originate_type, 0);
}
void default_info_origin_ipv4_apply_finish(struct nb_cb_apply_finish_args *args)
@ -1119,7 +1119,7 @@ int isis_instance_default_information_originate_ipv4_destroy(
area = nb_running_get_entry(args->dnode, NULL, true);
level = yang_dnode_get_enum(args->dnode, "./level");
isis_redist_unset(area, level, AF_INET, DEFAULT_ROUTE);
isis_redist_unset(area, level, AF_INET, DEFAULT_ROUTE, 0);
return NB_OK;
}
@ -1182,7 +1182,7 @@ int isis_instance_default_information_originate_ipv6_destroy(
area = nb_running_get_entry(args->dnode, NULL, true);
level = yang_dnode_get_enum(args->dnode, "./level");
isis_redist_unset(area, level, AF_INET6, DEFAULT_ROUTE);
isis_redist_unset(area, level, AF_INET6, DEFAULT_ROUTE, 0);
return NB_OK;
}
@ -1244,7 +1244,7 @@ void redistribute_apply_finish(const struct lyd_node *dnode, int family)
if (yang_dnode_exists(dnode, "./route-map"))
routemap = yang_dnode_get_string(dnode, "./route-map");
isis_redist_set(area, level, family, type, metric, routemap, 0);
isis_redist_set(area, level, family, type, metric, routemap, 0, 0);
}
void redistribute_ipv4_apply_finish(struct nb_cb_apply_finish_args *args)
@ -1274,13 +1274,14 @@ int isis_instance_redistribute_ipv4_destroy(struct nb_cb_destroy_args *args)
area = nb_running_get_entry(args->dnode, NULL, true);
level = yang_dnode_get_enum(args->dnode, "./level");
type = yang_dnode_get_enum(args->dnode, "./protocol");
isis_redist_unset(area, level, AF_INET, type);
isis_redist_unset(area, level, AF_INET, type, 0);
return NB_OK;
}
/*
* XPath: /frr-isisd:isis/instance/redistribute/ipv4/route-map
* XPath: /frr-isisd:isis/instance/redistribute/ipv4/table/route-map
*/
int isis_instance_redistribute_ipv4_route_map_modify(
struct nb_cb_modify_args *args)
@ -1298,6 +1299,7 @@ int isis_instance_redistribute_ipv4_route_map_destroy(
/*
* XPath: /frr-isisd:isis/instance/redistribute/ipv4/metric
* XPath: /frr-isisd:isis/instance/redistribute/ipv4/table/metric
*/
int isis_instance_redistribute_ipv4_metric_modify(
struct nb_cb_modify_args *args)
@ -1306,6 +1308,58 @@ int isis_instance_redistribute_ipv4_metric_modify(
return NB_OK;
}
int isis_instance_redistribute_ipv4_metric_destroy(struct nb_cb_destroy_args *args)
{
/* It's all done by redistribute_apply_finish */
return NB_OK;
}
/*
* XPath: /frr-isisd:isis/instance/redistribute/ipv4/table
*/
int isis_instance_redistribute_ipv4_table_create(struct nb_cb_create_args *args)
{
uint16_t table;
int type, level;
unsigned long metric = 0;
const char *routemap = NULL;
struct isis_area *area;
if (args->event != NB_EV_APPLY)
return NB_OK;
type = yang_dnode_get_enum(args->dnode, "../protocol");
level = yang_dnode_get_enum(args->dnode, "../level");
area = nb_running_get_entry(args->dnode, "../.", true);
if (yang_dnode_exists(args->dnode, "./metric"))
metric = yang_dnode_get_uint32(args->dnode, "./metric");
if (yang_dnode_exists(args->dnode, "./route-map"))
routemap = yang_dnode_get_string(args->dnode, "./route-map");
table = yang_dnode_get_uint16(args->dnode, "./table");
isis_redist_set(area, level, AF_INET, type, metric, routemap, 0, table);
return NB_OK;
}
int isis_instance_redistribute_ipv4_table_destroy(struct nb_cb_destroy_args *args)
{
struct isis_area *area;
int level, type;
uint16_t table;
if (args->event != NB_EV_APPLY)
return NB_OK;
area = nb_running_get_entry(args->dnode, "../.", true);
level = yang_dnode_get_enum(args->dnode, "../level");
type = yang_dnode_get_enum(args->dnode, "../protocol");
table = yang_dnode_get_uint16(args->dnode, "./table");
isis_redist_unset(area, level, AF_INET, type, table);
return NB_OK;
}
/*
* XPath: /frr-isisd:isis/instance/redistribute/ipv6
*/
@ -1326,7 +1380,7 @@ int isis_instance_redistribute_ipv6_destroy(struct nb_cb_destroy_args *args)
area = nb_running_get_entry(args->dnode, NULL, true);
level = yang_dnode_get_enum(args->dnode, "./level");
type = yang_dnode_get_enum(args->dnode, "./protocol");
isis_redist_unset(area, level, AF_INET6, type);
isis_redist_unset(area, level, AF_INET6, type, 0);
return NB_OK;
}
@ -1358,6 +1412,33 @@ int isis_instance_redistribute_ipv6_metric_modify(
return NB_OK;
}
int isis_instance_redistribute_ipv6_metric_destroy(struct nb_cb_destroy_args *args)
{
/* It's all done by redistribute_apply_finish */
return NB_OK;
}
/*
* XPath: /frr-isisd:isis/instance/redistribute/ipv6/table
*/
int isis_instance_redistribute_ipv6_table_create(struct nb_cb_create_args *args)
{
if (args->event != NB_EV_APPLY)
return NB_OK;
/* TODO */
return NB_OK;
}
int isis_instance_redistribute_ipv6_table_destroy(struct nb_cb_destroy_args *args)
{
if (args->event != NB_EV_APPLY)
return NB_OK;
/* TODO */
return NB_OK;
}
/*
* XPath: /frr-isisd:isis/instance/multi-topology/ipv4-multicast
*/

View File

@ -31,6 +31,7 @@
DEFINE_MTYPE_STATIC(ISISD, ISIS_EXT_ROUTE, "ISIS redistributed route");
DEFINE_MTYPE_STATIC(ISISD, ISIS_EXT_INFO, "ISIS redistributed route info");
DEFINE_MTYPE_STATIC(ISISD, ISIS_RMAP_NAME, "ISIS redistribute route-map name");
DEFINE_MTYPE_STATIC(ISISD, ISIS_REDISTRIBUTE, "ISIS redistribute");
static int redist_protocol(int family)
{
@ -61,12 +62,43 @@ static struct route_table *get_ext_info(struct isis *i, int family)
return i->ext_info[protocol];
}
static struct isis_redist *get_redist_settings(struct isis_area *area,
int family, int type, int level)
static struct isis_redist *isis_redist_lookup(struct isis_area *area,
int family, int type, int level,
uint16_t table)
{
int protocol = redist_protocol(family);
struct listnode *node;
struct isis_redist *red;
return &area->redist_settings[protocol][type][level - 1];
if (area->redist_settings[protocol][type][level - 1]) {
for (ALL_LIST_ELEMENTS_RO(area->redist_settings[protocol][type]
[level - 1],
node, red))
if (red->table == table)
return red;
}
return NULL;
}
static struct isis_redist *isis_redist_get(struct isis_area *area, int family,
int type, int level, uint16_t table)
{
struct isis_redist *red;
int protocol;
red = isis_redist_lookup(area, family, type, level, table);
if (red)
return red;
protocol = redist_protocol(family);
if (area->redist_settings[protocol][type][level - 1] == NULL)
area->redist_settings[protocol][type][level - 1] = list_new();
red = XCALLOC(MTYPE_ISIS_REDISTRIBUTE, sizeof(struct isis_redist));
red->table = table;
listnode_add(area->redist_settings[protocol][type][level - 1], red);
return red;
}
struct route_table *get_ext_reach(struct isis_area *area, int family, int level)
@ -206,10 +238,57 @@ static void isis_redist_ensure_default(struct isis *isis, int family)
info->metric = MAX_WIDE_PATH_METRIC;
}
static int _isis_redist_table_is_present(const struct lyd_node *dnode, void *arg)
{
struct isis_redist_table_present_args *rtda = arg;
/* This entry is the caller, so skip it. */
if (yang_dnode_get_uint16(dnode, "table") !=
(uint16_t)atoi(rtda->rtda_table))
return YANG_ITER_CONTINUE;
/* found */
rtda->rtda_found = true;
return YANG_ITER_CONTINUE;
}
static int _isis_redist_table_get_first_cb(const struct lyd_node *dnode,
void *arg)
{
uint16_t *table = arg;
*table = yang_dnode_get_uint16(dnode, "table");
return YANG_ITER_STOP;
}
uint16_t isis_redist_table_get_first(const struct vty *vty,
struct isis_redist_table_present_args *rtda)
{
uint16_t table = 0;
yang_dnode_iterate(_isis_redist_table_get_first_cb, &table,
vty->candidate_config->dnode,
"%s/redistribute/%s[protocol='table'][level='%s']/table",
VTY_CURR_XPATH, rtda->rtda_ip, rtda->rtda_level);
return table;
}
bool isis_redist_table_is_present(const struct vty *vty,
struct isis_redist_table_present_args *rtda)
{
rtda->rtda_found = false;
yang_dnode_iterate(_isis_redist_table_is_present, rtda,
vty->candidate_config->dnode,
"%s/redistribute/%s[protocol='table'][level='%s']/table",
VTY_CURR_XPATH, rtda->rtda_ip, rtda->rtda_level);
return rtda->rtda_found;
}
/* Handle notification about route being added */
void isis_redist_add(struct isis *isis, int type, struct prefix *p,
struct prefix_ipv6 *src_p, uint8_t distance,
uint32_t metric, const route_tag_t tag)
uint32_t metric, const route_tag_t tag, uint16_t table)
{
int family = p->family;
struct route_table *ei_table = get_ext_info(isis, family);
@ -249,8 +328,9 @@ void isis_redist_add(struct isis *isis, int type, struct prefix *p,
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
for (level = 1; level <= ISIS_LEVELS; level++) {
redist = get_redist_settings(area, family, type, level);
if (!redist->redist)
redist = isis_redist_lookup(area, family, type, level,
table);
if (!redist || !redist->redist)
continue;
isis_redist_update_ext_reach(area, level, redist, p,
@ -259,7 +339,7 @@ void isis_redist_add(struct isis *isis, int type, struct prefix *p,
}
void isis_redist_delete(struct isis *isis, int type, struct prefix *p,
struct prefix_ipv6 *src_p)
struct prefix_ipv6 *src_p, uint16_t table)
{
int family = p->family;
struct route_table *ei_table = get_ext_info(isis, family);
@ -279,7 +359,7 @@ void isis_redist_delete(struct isis *isis, int type, struct prefix *p,
* "always" setting will ignore routes with origin
* DEFAULT_ROUTE. */
isis_redist_add(isis, DEFAULT_ROUTE, p, NULL, 254,
MAX_WIDE_PATH_METRIC, 0);
MAX_WIDE_PATH_METRIC, 0, table);
return;
}
@ -302,8 +382,9 @@ void isis_redist_delete(struct isis *isis, int type, struct prefix *p,
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
for (level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
redist = get_redist_settings(area, family, type, level);
if (!redist->redist)
redist = isis_redist_lookup(area, family, type, level,
table);
if (!redist || !redist->redist)
continue;
isis_redist_uninstall(area, level, p, src_p);
@ -329,53 +410,6 @@ static void isis_redist_routemap_set(struct isis_redist *redist,
}
}
static void isis_redist_update_zebra_subscriptions(struct isis *isis)
{
struct listnode *node;
struct isis_area *area;
int type;
int level;
int protocol;
if (isis->vrf_id == VRF_UNKNOWN)
return;
char do_subscribe[REDIST_PROTOCOL_COUNT][ZEBRA_ROUTE_MAX + 1];
memset(do_subscribe, 0, sizeof(do_subscribe));
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++)
for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++)
for (level = 0; level < ISIS_LEVELS; level++)
if (area->redist_settings[protocol]
[type][level]
.redist
== 1)
do_subscribe[protocol][type] =
1;
for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++)
for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) {
/* This field is actually controlling transmission of
* the IS-IS
* routes to Zebra and has nothing to do with
* redistribution,
* so skip it. */
if (type == PROTO_TYPE)
continue;
afi_t afi = afi_for_redist_protocol(protocol);
if (do_subscribe[protocol][type])
isis_zebra_redistribute_set(afi, type,
isis->vrf_id);
else
isis_zebra_redistribute_unset(afi, type,
isis->vrf_id);
}
}
void isis_redist_free(struct isis *isis)
{
struct route_node *rn;
@ -397,11 +431,12 @@ void isis_redist_free(struct isis *isis)
}
void isis_redist_set(struct isis_area *area, int level, int family, int type,
uint32_t metric, const char *routemap, int originate_type)
uint32_t metric, const char *routemap, int originate_type,
uint16_t table)
{
int protocol = redist_protocol(family);
struct isis_redist *redist =
get_redist_settings(area, family, type, level);
struct isis_redist *redist = isis_redist_get(area, family, type, level,
table);
int i;
struct route_table *ei_table;
struct route_node *rn;
@ -421,7 +456,8 @@ void isis_redist_set(struct isis_area *area, int level, int family, int type,
}
}
isis_redist_update_zebra_subscriptions(area->isis);
isis_zebra_redistribute_set(afi_for_redist_protocol(protocol), type,
area->isis->vrf_id, redist->table);
if (type == DEFAULT_ROUTE && originate_type == DEFAULT_ORIGINATE_ALWAYS)
isis_redist_ensure_default(area->isis, family);
@ -452,18 +488,26 @@ void isis_redist_set(struct isis_area *area, int level, int family, int type,
}
}
void isis_redist_unset(struct isis_area *area, int level, int family, int type)
void isis_redist_unset(struct isis_area *area, int level, int family, int type,
uint16_t table)
{
struct isis_redist *redist =
get_redist_settings(area, family, type, level);
struct isis_redist *redist = isis_redist_lookup(area, family, type,
level, table);
struct route_table *er_table = get_ext_reach(area, family, level);
struct route_node *rn;
struct isis_ext_info *info;
struct list *redist_list;
int protocol = redist_protocol(family);
if (!redist->redist)
if (!redist || !redist->redist)
return;
redist->redist = 0;
redist_list = area->redist_settings[protocol][type][level - 1];
listnode_delete(redist_list, redist);
XFREE(MTYPE_ISIS_REDISTRIBUTE, redist);
if (!er_table) {
zlog_warn("%s: External reachability table uninitialized.",
__func__);
@ -493,7 +537,8 @@ void isis_redist_unset(struct isis_area *area, int level, int family, int type)
}
lsp_regenerate_schedule(area, level, 0);
isis_redist_update_zebra_subscriptions(area->isis);
isis_zebra_redistribute_unset(afi_for_redist_protocol(protocol), type,
area->isis->vrf_id, table);
}
void isis_redist_area_finish(struct isis_area *area)
@ -502,16 +547,30 @@ void isis_redist_area_finish(struct isis_area *area)
int protocol;
int level;
int type;
struct isis_redist *redist;
struct listnode *node, *nnode;
struct list *redist_list;
for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++)
for (level = 0; level < ISIS_LEVELS; level++) {
for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) {
struct isis_redist *redist;
redist = &area->redist_settings[protocol][type]
[level];
redist->redist = 0;
XFREE(MTYPE_ISIS_RMAP_NAME, redist->map_name);
redist_list = area->redist_settings[protocol]
[type][level];
if (!redist_list)
continue;
for (ALL_LIST_ELEMENTS(redist_list, node, nnode,
redist)) {
redist->redist = 0;
XFREE(MTYPE_ISIS_RMAP_NAME,
redist->map_name);
isis_zebra_redistribute_unset(
afi_for_redist_protocol(protocol),
type, area->isis->vrf_id,
redist->table);
listnode_delete(redist_list, redist);
XFREE(MTYPE_ISIS_REDISTRIBUTE, redist);
}
list_delete(&redist_list);
}
if (!area->ext_reach[protocol][level])
continue;
@ -523,8 +582,6 @@ void isis_redist_area_finish(struct isis_area *area)
route_table_finish(area->ext_reach[protocol][level]);
area->ext_reach[protocol][level] = NULL;
}
isis_redist_update_zebra_subscriptions(area->isis);
}
#ifdef FABRICD
@ -581,7 +638,7 @@ DEFUN (isis_redistribute,
routemap = argv[idx_metric_rmap + 1]->arg;
}
isis_redist_set(area, level, family, type, metric, routemap, 0);
isis_redist_set(area, level, family, type, metric, routemap, 0, 0);
return 0;
}
@ -617,7 +674,7 @@ DEFUN (no_isis_redistribute,
level = 2;
isis_redist_unset(area, level, family, type);
isis_redist_unset(area, level, family, type, 0);
return 0;
}
@ -677,7 +734,7 @@ DEFUN (isis_default_originate,
}
isis_redist_set(area, level, family, DEFAULT_ROUTE, metric, routemap,
originate_type);
originate_type, 0);
return 0;
}
@ -701,7 +758,7 @@ DEFUN (no_isis_default_originate,
level = 2;
isis_redist_unset(area, level, family, DEFAULT_ROUTE);
isis_redist_unset(area, level, family, DEFAULT_ROUTE, 0);
return 0;
}
#endif /* ifdef FABRICD */
@ -713,7 +770,9 @@ int isis_redist_config_write(struct vty *vty, struct isis_area *area,
int level;
int write = 0;
struct isis_redist *redist;
struct list *redist_list;
const char *family_str;
struct listnode *node;
if (family == AF_INET)
family_str = "ipv4";
@ -727,25 +786,36 @@ int isis_redist_config_write(struct vty *vty, struct isis_area *area,
continue;
for (level = 1; level <= ISIS_LEVELS; level++) {
redist = get_redist_settings(area, family, type, level);
if (!redist->redist)
redist_list = area->redist_settings[redist_protocol(
family)][type][level - 1];
if (!redist_list)
continue;
vty_out(vty, " redistribute %s %s", family_str,
zebra_route_string(type));
if (!fabricd)
vty_out(vty, " level-%d", level);
if (redist->metric)
vty_out(vty, " metric %u", redist->metric);
if (redist->map_name)
vty_out(vty, " route-map %s", redist->map_name);
vty_out(vty, "\n");
write++;
for (ALL_LIST_ELEMENTS_RO(redist_list, node, redist)) {
if (!redist->redist)
continue;
vty_out(vty, " redistribute %s %s", family_str,
zebra_route_string(type));
if (type == ZEBRA_ROUTE_TABLE)
vty_out(vty, " %u", redist->table);
if (!fabricd)
vty_out(vty, " level-%d", level);
if (redist->metric)
vty_out(vty, " metric %u",
redist->metric);
if (redist->map_name)
vty_out(vty, " route-map %s",
redist->map_name);
vty_out(vty, "\n");
write++;
}
}
}
for (level = 1; level <= ISIS_LEVELS; level++) {
redist =
get_redist_settings(area, family, DEFAULT_ROUTE, level);
redist = isis_redist_lookup(area, family, DEFAULT_ROUTE, level,
0);
if (!redist)
continue;
if (!redist->redist)
continue;
vty_out(vty, " default-information originate %s",

View File

@ -26,6 +26,15 @@ struct isis_redist {
uint32_t metric;
char *map_name;
struct route_map *map;
uint16_t table;
};
struct isis_redist_table_present_args {
/* from filter.h, struct acl_dup_args */
const char *rtda_ip;
const char *rtda_level;
const char *rtda_table;
bool rtda_found;
};
struct isis;
@ -40,17 +49,24 @@ struct route_table *get_ext_reach(struct isis_area *area, int family,
int level);
void isis_redist_add(struct isis *isis, int type, struct prefix *p,
struct prefix_ipv6 *src_p, uint8_t distance,
uint32_t metric, route_tag_t tag);
uint32_t metric, route_tag_t tag, uint16_t instance);
void isis_redist_delete(struct isis *isis, int type, struct prefix *p,
struct prefix_ipv6 *src_p);
struct prefix_ipv6 *src_p, uint16_t tableid);
int isis_redist_config_write(struct vty *vty, struct isis_area *area,
int family);
void isis_redist_init(void);
void isis_redist_area_finish(struct isis_area *area);
void isis_redist_set(struct isis_area *area, int level, int family, int type,
uint32_t metric, const char *routemap, int originate_type);
void isis_redist_unset(struct isis_area *area, int level, int family, int type);
uint32_t metric, const char *routemap, int originate_type,
uint16_t table);
void isis_redist_unset(struct isis_area *area, int level, int family, int type,
uint16_t table);
void isis_redist_free(struct isis *isis);
bool isis_redist_table_is_present(const struct vty *vty,
struct isis_redist_table_present_args *rtda);
uint16_t isis_redist_table_get_first(const struct vty *vty,
struct isis_redist_table_present_args *rtda);
#endif

View File

@ -498,10 +498,10 @@ static int isis_zebra_read(ZAPI_CALLBACK_ARGS)
if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
isis_redist_add(isis, api.type, &api.prefix, &api.src_prefix,
api.distance, api.metric, api.tag);
api.distance, api.metric, api.tag, api.instance);
else
isis_redist_delete(isis, api.type, &api.prefix,
&api.src_prefix);
isis_redist_delete(isis, api.type, &api.prefix, &api.src_prefix,
api.instance);
return 0;
}
@ -511,24 +511,26 @@ int isis_distribute_list_update(int routetype)
return 0;
}
void isis_zebra_redistribute_set(afi_t afi, int type, vrf_id_t vrf_id)
void isis_zebra_redistribute_set(afi_t afi, int type, vrf_id_t vrf_id,
uint16_t tableid)
{
if (type == DEFAULT_ROUTE)
zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
zclient, afi, vrf_id);
else
zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type,
0, vrf_id);
tableid, vrf_id);
}
void isis_zebra_redistribute_unset(afi_t afi, int type, vrf_id_t vrf_id)
void isis_zebra_redistribute_unset(afi_t afi, int type, vrf_id_t vrf_id,
uint16_t tableid)
{
if (type == DEFAULT_ROUTE)
zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
zclient, afi, vrf_id);
else
zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi,
type, 0, vrf_id);
type, tableid, vrf_id);
}
/**

View File

@ -43,8 +43,10 @@ void isis_zebra_prefix_sid_uninstall(struct isis_area *area,
struct isis_sr_psid_info *psid);
void isis_zebra_send_adjacency_sid(int cmd, const struct sr_adjacency *sra);
int isis_distribute_list_update(int routetype);
void isis_zebra_redistribute_set(afi_t afi, int type, vrf_id_t vrf_id);
void isis_zebra_redistribute_unset(afi_t afi, int type, vrf_id_t vrf_id);
void isis_zebra_redistribute_set(afi_t afi, int type, vrf_id_t vrf_id,
uint16_t tableid);
void isis_zebra_redistribute_unset(afi_t afi, int type, vrf_id_t vrf_id,
uint16_t tableid);
int isis_zebra_rlfa_register(struct isis_spftree *spftree, struct rlfa *rlfa);
void isis_zebra_rlfa_unregister_all(struct isis_spftree *spftree);
bool isis_zebra_label_manager_ready(void);

View File

@ -599,64 +599,66 @@ static int isis_vrf_delete(struct vrf *vrf)
static void isis_set_redist_vrf_bitmaps(struct isis *isis, bool set)
{
struct listnode *node;
struct listnode *node, *lnode;
struct isis_area *area;
int type;
int level;
int protocol;
char do_subscribe[REDIST_PROTOCOL_COUNT][ZEBRA_ROUTE_MAX + 1];
memset(do_subscribe, 0, sizeof(do_subscribe));
struct isis_redist *redist;
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++)
for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++)
for (level = 0; level < ISIS_LEVELS; level++)
if (area->redist_settings[protocol]
[type][level]
.redist
== 1)
do_subscribe[protocol][type] =
1;
for (level = 0; level < ISIS_LEVELS; level++) {
if (area->redist_settings[protocol][type]
[level] == NULL)
continue;
for (ALL_LIST_ELEMENTS_RO(area->redist_settings
[protocol]
[type]
[level],
lnode,
redist)) {
if (redist->redist == 0)
continue;
/* This field is actually
* controlling transmission of
* the IS-IS
* routes to Zebra and has
* nothing to do with
* redistribution,
* so skip it. */
afi_t afi =
afi_for_redist_protocol(
protocol);
for (protocol = 0; protocol < REDIST_PROTOCOL_COUNT; protocol++)
for (type = 0; type < ZEBRA_ROUTE_MAX + 1; type++) {
/* This field is actually controlling transmission of
* the IS-IS
* routes to Zebra and has nothing to do with
* redistribution,
* so skip it. */
if (type == PROTO_TYPE)
continue;
if (!do_subscribe[protocol][type])
continue;
afi_t afi = afi_for_redist_protocol(protocol);
if (type == DEFAULT_ROUTE) {
if (set)
vrf_bitmap_set(
&zclient->default_information
[afi],
isis->vrf_id);
else
vrf_bitmap_unset(
&zclient->default_information
[afi],
isis->vrf_id);
} else {
if (set)
vrf_bitmap_set(
&zclient->redist[afi][type],
isis->vrf_id);
else
vrf_bitmap_unset(
&zclient->redist[afi][type],
isis->vrf_id);
}
}
if (type == DEFAULT_ROUTE) {
if (set)
vrf_bitmap_set(
&zclient->default_information
[afi],
isis->vrf_id);
else
vrf_bitmap_unset(
&zclient->default_information
[afi],
isis->vrf_id);
} else {
if (set)
vrf_bitmap_set(
&zclient->redist
[afi]
[type],
isis->vrf_id);
else
vrf_bitmap_unset(
&zclient->redist
[afi]
[type],
isis->vrf_id);
}
}
}
}
static int isis_vrf_enable(struct vrf *vrf)

View File

@ -230,8 +230,8 @@ struct isis_area {
#endif /* ifndef FABRICD */
/* Counters */
uint32_t circuit_state_changes;
struct isis_redist redist_settings[REDIST_PROTOCOL_COUNT]
[ZEBRA_ROUTE_MAX + 1][ISIS_LEVELS];
struct list *redist_settings[REDIST_PROTOCOL_COUNT][ZEBRA_ROUTE_MAX + 1]
[ISIS_LEVELS];
struct route_table *ext_reach[REDIST_PROTOCOL_COUNT][ISIS_LEVELS];
struct spf_backoff *spf_delay_ietf[ISIS_LEVELS]; /*Structure with IETF

View File

@ -146,5 +146,20 @@
"protocol": "isis",
"selected": true
}
],
"192.0.2.6/32": [
{
"nexthops": [
{
"active": true,
"fib": true,
"ip": "10.0.10.1",
"interfaceName": "r3-eth1"
}
],
"prefix": "192.0.2.6/32",
"protocol": "isis",
"selected": true
}
]
}

View File

@ -61,5 +61,20 @@
"protocol": "connected",
"selected": true
}
],
"192.0.2.6/32": [
{
"nexthops": [
{
"active": true,
"fib": true,
"ip": "10.0.11.1",
"interfaceName": "r4-eth1"
}
],
"prefix": "192.0.2.6/32",
"protocol": "isis",
"selected": true
}
]
}

View File

@ -20,4 +20,5 @@ router isis 1
is-type level-1
redistribute ipv4 connected level-1
redistribute ipv6 connected level-1
redistribute ipv4 table 20 level-1
!

View File

@ -141,5 +141,21 @@
"protocol": "connected",
"selected": true
}
],
"192.0.2.6/32": [
{
"nexthops": [
{
"active": true,
"fib": true,
"ip": "10.0.10.6",
"interfaceName": "r5-eth0"
}
],
"prefix": "192.0.2.6/32",
"protocol": "table",
"instance": 20,
"selected": true
}
]
}

View File

@ -1,4 +1,6 @@
hostname r5
ip route 192.0.2.6/32 10.0.10.6 table 20
ip import 20
interface r5-eth0
ip address 10.0.10.1/24
ipv6 address 2001:db8:2:1::1/64

View File

@ -1495,9 +1495,32 @@ module frr-isisd {
"IS-IS level into which the routes should be redistributed.";
}
uses redistribute-attributes;
}
choice protocol-type {
case protocol-table {
when "./protocol = \"table\"";
list table {
key "table";
when "../protocol = \"table\"";
description
"Routing table number";
leaf table {
type uint16 {
range "1..65535";
}
description
"Routing table number.";
}
uses redistribute-attributes;
}
}
case protocol-other {
uses redistribute-attributes;
}
}
}
list ipv6 {
key "protocol level";
description
@ -1516,7 +1539,29 @@ module frr-isisd {
"IS-IS level into which the routes should be redistributed.";
}
uses redistribute-attributes;
choice protocol-type {
case protocol-table {
when "./protocol = \"table\"";
list table {
key "table";
when "../protocol = \"table\"";
leaf table {
type uint16 {
range "1..65535";
}
description
"Routing table number.";
}
uses redistribute-attributes;
}
}
case protocol-other {
uses redistribute-attributes;
}
}
}
}

View File

@ -675,6 +675,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,