mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-25 12:18:43 +00:00
isisd: update struct isis_route_info has multiple sr info by algorithm
Before this commit, there was only one sr psid info included in route_info. In fact, in RFC8667, Algorithm ID, which is a property of Prefix-SID, has 8 bits of information. That is, each Prefix can hold up to 256 Prefix-SIDs. This commit implements it. The previously implemented single Prefix-SID will be continued as Algorithm 0. Signed-off-by: Hiroki Shirokura <hiroki.shirokura@linecorp.com> Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
This commit is contained in:
parent
bdaafbf834
commit
7153c3cabf
@ -39,6 +39,8 @@
|
||||
|
||||
DEFINE_MTYPE_STATIC(ISISD, ISIS_NEXTHOP, "ISIS nexthop");
|
||||
DEFINE_MTYPE_STATIC(ISISD, ISIS_ROUTE_INFO, "ISIS route info");
|
||||
DEFINE_MTYPE_STATIC(ISISD, ISIS_ROUTE_TABLE_INFO, "ISIS route table info");
|
||||
|
||||
|
||||
DEFINE_HOOK(isis_route_update_hook,
|
||||
(struct isis_area * area, struct prefix *prefix,
|
||||
@ -51,8 +53,25 @@ static void isis_route_update(struct isis_area *area, struct prefix *prefix,
|
||||
struct prefix_ipv6 *src_p,
|
||||
struct isis_route_info *route_info);
|
||||
|
||||
static struct isis_nexthop *isis_nexthop_create(int family, union g_addr *ip,
|
||||
ifindex_t ifindex)
|
||||
static struct mpls_label_stack *
|
||||
label_stack_dup(const struct mpls_label_stack *const orig)
|
||||
{
|
||||
struct mpls_label_stack *copy;
|
||||
int array_size;
|
||||
|
||||
if (orig == NULL)
|
||||
return NULL;
|
||||
|
||||
array_size = orig->num_labels * sizeof(mpls_label_t);
|
||||
copy = XCALLOC(MTYPE_ISIS_NEXTHOP_LABELS,
|
||||
sizeof(struct mpls_label_stack) + array_size);
|
||||
copy->num_labels = orig->num_labels;
|
||||
memcpy(copy->label, orig->label, array_size);
|
||||
return copy;
|
||||
}
|
||||
|
||||
static struct isis_nexthop *
|
||||
isis_nexthop_create(int family, const union g_addr *const ip, ifindex_t ifindex)
|
||||
{
|
||||
struct isis_nexthop *nexthop;
|
||||
|
||||
@ -65,12 +84,40 @@ static struct isis_nexthop *isis_nexthop_create(int family, union g_addr *ip,
|
||||
return nexthop;
|
||||
}
|
||||
|
||||
static struct isis_nexthop *
|
||||
isis_nexthop_dup(const struct isis_nexthop *const orig)
|
||||
{
|
||||
struct isis_nexthop *nexthop;
|
||||
|
||||
nexthop = isis_nexthop_create(orig->family, &orig->ip, orig->ifindex);
|
||||
memcpy(nexthop->sysid, orig->sysid, ISIS_SYS_ID_LEN);
|
||||
nexthop->sr = orig->sr;
|
||||
nexthop->label_stack = label_stack_dup(orig->label_stack);
|
||||
|
||||
return nexthop;
|
||||
}
|
||||
|
||||
void isis_nexthop_delete(struct isis_nexthop *nexthop)
|
||||
{
|
||||
XFREE(MTYPE_ISIS_NEXTHOP_LABELS, nexthop->label_stack);
|
||||
XFREE(MTYPE_ISIS_NEXTHOP, nexthop);
|
||||
}
|
||||
|
||||
static struct list *isis_nexthop_list_dup(const struct list *orig)
|
||||
{
|
||||
struct list *copy;
|
||||
struct listnode *node;
|
||||
struct isis_nexthop *nh;
|
||||
struct isis_nexthop *nhcopy;
|
||||
|
||||
copy = list_new();
|
||||
for (ALL_LIST_ELEMENTS_RO(orig, node, nh)) {
|
||||
nhcopy = isis_nexthop_dup(nh);
|
||||
listnode_add(copy, nhcopy);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
static struct isis_nexthop *nexthoplookup(struct list *nexthops, int family,
|
||||
union g_addr *ip, ifindex_t ifindex)
|
||||
{
|
||||
@ -238,9 +285,9 @@ isis_route_info_new(struct prefix *prefix, struct prefix_ipv6 *src_p,
|
||||
|
||||
rinfo->cost = cost;
|
||||
rinfo->depth = depth;
|
||||
rinfo->sr = *sr;
|
||||
rinfo->sr.nexthops = rinfo->nexthops;
|
||||
rinfo->sr.nexthops_backup =
|
||||
rinfo->sr_algo[sr->algorithm] = *sr;
|
||||
rinfo->sr_algo[sr->algorithm].nexthops = rinfo->nexthops;
|
||||
rinfo->sr_algo[sr->algorithm].nexthops_backup =
|
||||
rinfo->backup ? rinfo->backup->nexthops : NULL;
|
||||
|
||||
return rinfo;
|
||||
@ -248,6 +295,18 @@ isis_route_info_new(struct prefix *prefix, struct prefix_ipv6 *src_p,
|
||||
|
||||
static void isis_route_info_delete(struct isis_route_info *route_info)
|
||||
{
|
||||
for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
|
||||
if (!route_info->sr_algo[i].present)
|
||||
continue;
|
||||
|
||||
if (route_info->sr_algo[i].nexthops == route_info->nexthops)
|
||||
continue;
|
||||
|
||||
route_info->sr_algo[i].nexthops->del =
|
||||
(void (*)(void *))isis_nexthop_delete;
|
||||
list_delete(&route_info->sr_algo[i].nexthops);
|
||||
}
|
||||
|
||||
if (route_info->nexthops) {
|
||||
route_info->nexthops->del =
|
||||
(void (*)(void *))isis_nexthop_delete;
|
||||
@ -263,6 +322,27 @@ void isis_route_node_cleanup(struct route_table *table, struct route_node *node)
|
||||
isis_route_info_delete(node->info);
|
||||
}
|
||||
|
||||
struct isis_route_table_info *isis_route_table_info_alloc(uint8_t algorithm)
|
||||
{
|
||||
struct isis_route_table_info *info;
|
||||
|
||||
info = XCALLOC(MTYPE_ISIS_ROUTE_TABLE_INFO, sizeof(*info));
|
||||
info->algorithm = algorithm;
|
||||
return info;
|
||||
}
|
||||
|
||||
void isis_route_table_info_free(void *info)
|
||||
{
|
||||
XFREE(MTYPE_ISIS_ROUTE_TABLE_INFO, info);
|
||||
}
|
||||
|
||||
uint8_t isis_route_table_algorithm(const struct route_table *table)
|
||||
{
|
||||
const struct isis_route_table_info *info = table->info;
|
||||
|
||||
return info ? info->algorithm : 0;
|
||||
}
|
||||
|
||||
static bool isis_sr_psid_info_same(struct isis_sr_psid_info *new,
|
||||
struct isis_sr_psid_info *old)
|
||||
{
|
||||
@ -319,10 +399,22 @@ static int isis_route_info_same(struct isis_route_info *new,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!isis_sr_psid_info_same(&new->sr, &old->sr)) {
|
||||
if (buf)
|
||||
snprintf(buf, buf_size, "SR input label");
|
||||
return 0;
|
||||
for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
|
||||
struct isis_sr_psid_info new_sr_algo;
|
||||
struct isis_sr_psid_info old_sr_algo;
|
||||
|
||||
new_sr_algo = new->sr_algo[i];
|
||||
old_sr_algo = old->sr_algo[i];
|
||||
|
||||
if (!isis_sr_psid_info_same(&new_sr_algo, &old_sr_algo)) {
|
||||
if (buf)
|
||||
snprintf(
|
||||
buf, buf_size,
|
||||
"SR input label algo-%u (old: %s, new: %s)",
|
||||
i, old_sr_algo.present ? "yes" : "no",
|
||||
new_sr_algo.present ? "yes" : "no");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (new->nexthops->count != old->nexthops->count) {
|
||||
@ -411,7 +503,9 @@ isis_route_create(struct prefix *prefix, struct prefix_ipv6 *src_p,
|
||||
zlog_debug(
|
||||
"ISIS-Rte (%s): route changed: %pFX, change: %s",
|
||||
area->area_tag, prefix, change_buf);
|
||||
rinfo_new->sr_previous = rinfo_old->sr;
|
||||
for (int i = 0; i < SR_ALGORITHM_COUNT; i++)
|
||||
rinfo_new->sr_algo_previous[i] =
|
||||
rinfo_old->sr_algo[i];
|
||||
isis_route_info_delete(rinfo_old);
|
||||
route_info = rinfo_new;
|
||||
UNSET_FLAG(route_info->flag,
|
||||
@ -467,11 +561,42 @@ static void isis_route_remove_previous_sid(struct isis_area *area,
|
||||
* Explicitly uninstall previous Prefix-SID label if it has
|
||||
* changed or was removed.
|
||||
*/
|
||||
if (route_info->sr_previous.present &&
|
||||
(!route_info->sr.present ||
|
||||
route_info->sr_previous.label != route_info->sr.label))
|
||||
isis_zebra_prefix_sid_uninstall(area, prefix, route_info,
|
||||
&route_info->sr_previous);
|
||||
for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
|
||||
if (route_info->sr_algo_previous[i].present &&
|
||||
(!route_info->sr_algo[i].present ||
|
||||
route_info->sr_algo_previous[i].label !=
|
||||
route_info->sr_algo[i].label))
|
||||
isis_zebra_prefix_sid_uninstall(
|
||||
area, prefix, route_info,
|
||||
&route_info->sr_algo_previous[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_merge_route_info_sr_algo(struct isis_route_info *mrinfo,
|
||||
struct isis_route_info *rinfo)
|
||||
{
|
||||
for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
|
||||
if (rinfo->sr_algo[i].present) {
|
||||
assert(i == rinfo->sr_algo[i].algorithm);
|
||||
assert(rinfo->nexthops);
|
||||
assert(rinfo->backup ? rinfo->backup->nexthops != NULL
|
||||
: true);
|
||||
|
||||
if (mrinfo->sr_algo[i].nexthops != NULL &&
|
||||
mrinfo->sr_algo[i].nexthops != mrinfo->nexthops) {
|
||||
mrinfo->sr_algo[i].nexthops->del =
|
||||
(void (*)(void *))isis_nexthop_delete;
|
||||
list_delete(&mrinfo->sr_algo[i].nexthops);
|
||||
}
|
||||
|
||||
mrinfo->sr_algo[i] = rinfo->sr_algo[i];
|
||||
mrinfo->sr_algo[i].nexthops = isis_nexthop_list_dup(
|
||||
rinfo->sr_algo[i].nexthops);
|
||||
}
|
||||
}
|
||||
|
||||
UNSET_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
||||
UNSET_FLAG(mrinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
||||
}
|
||||
|
||||
static void isis_route_update(struct isis_area *area, struct prefix *prefix,
|
||||
@ -490,10 +615,22 @@ static void isis_route_update(struct isis_area *area, struct prefix *prefix,
|
||||
/* Install route. */
|
||||
isis_zebra_route_add_route(area->isis, prefix, src_p,
|
||||
route_info);
|
||||
/* Install/reinstall Prefix-SID label. */
|
||||
if (route_info->sr.present)
|
||||
isis_zebra_prefix_sid_install(area, prefix,
|
||||
&route_info->sr);
|
||||
|
||||
for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
|
||||
struct isis_sr_psid_info sr_algo;
|
||||
|
||||
sr_algo = route_info->sr_algo[i];
|
||||
|
||||
/*
|
||||
* Install/reinstall Prefix-SID label.
|
||||
*/
|
||||
if (sr_algo.present)
|
||||
isis_zebra_prefix_sid_install(area, prefix,
|
||||
&sr_algo);
|
||||
|
||||
hook_call(isis_route_update_hook, area, prefix,
|
||||
route_info);
|
||||
}
|
||||
|
||||
hook_call(isis_route_update_hook, area, prefix, route_info);
|
||||
|
||||
@ -501,9 +638,12 @@ static void isis_route_update(struct isis_area *area, struct prefix *prefix,
|
||||
UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
|
||||
} else {
|
||||
/* Uninstall Prefix-SID label. */
|
||||
if (route_info->sr.present)
|
||||
isis_zebra_prefix_sid_uninstall(
|
||||
area, prefix, route_info, &route_info->sr);
|
||||
for (int i = 0; i < SR_ALGORITHM_COUNT; i++)
|
||||
if (route_info->sr_algo[i].present)
|
||||
isis_zebra_prefix_sid_uninstall(
|
||||
area, prefix, route_info,
|
||||
&route_info->sr_algo[i]);
|
||||
|
||||
/* Uninstall route. */
|
||||
isis_zebra_route_del_route(area->isis, prefix, src_p,
|
||||
route_info);
|
||||
@ -523,6 +663,7 @@ static void _isis_route_verify_table(struct isis_area *area,
|
||||
#ifdef EXTREME_DEBUG
|
||||
char buff[SRCDEST2STR_BUFFER];
|
||||
#endif /* EXTREME_DEBUG */
|
||||
uint8_t algorithm = isis_route_table_algorithm(table);
|
||||
|
||||
for (rnode = route_top(table); rnode;
|
||||
rnode = srcdest_route_next(rnode)) {
|
||||
@ -545,13 +686,14 @@ static void _isis_route_verify_table(struct isis_area *area,
|
||||
src_p);
|
||||
if (rnode_bck) {
|
||||
rinfo->backup = rnode_bck->info;
|
||||
rinfo->sr.nexthops_backup =
|
||||
rinfo->sr_algo[algorithm].nexthops_backup =
|
||||
rinfo->backup->nexthops;
|
||||
UNSET_FLAG(rinfo->flag,
|
||||
ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
||||
} else if (rinfo->backup) {
|
||||
rinfo->backup = NULL;
|
||||
rinfo->sr.nexthops_backup = NULL;
|
||||
rinfo->sr_algo[algorithm].nexthops_backup =
|
||||
NULL;
|
||||
UNSET_FLAG(rinfo->flag,
|
||||
ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
||||
}
|
||||
@ -645,6 +787,8 @@ void isis_route_verify_merge(struct isis_area *area,
|
||||
merge = srcdest_table_init();
|
||||
|
||||
for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
|
||||
uint8_t algorithm =
|
||||
isis_route_table_algorithm(tables[level - 1]);
|
||||
for (rnode = route_top(tables[level - 1]); rnode;
|
||||
rnode = srcdest_route_next(rnode)) {
|
||||
struct isis_route_info *rinfo = rnode->info;
|
||||
@ -665,13 +809,14 @@ void isis_route_verify_merge(struct isis_area *area,
|
||||
tables_backup[level - 1], prefix, src_p);
|
||||
if (rnode_bck) {
|
||||
rinfo->backup = rnode_bck->info;
|
||||
rinfo->sr.nexthops_backup =
|
||||
rinfo->sr_algo[algorithm].nexthops_backup =
|
||||
rinfo->backup->nexthops;
|
||||
UNSET_FLAG(rinfo->flag,
|
||||
ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
||||
} else if (rinfo->backup) {
|
||||
rinfo->backup = NULL;
|
||||
rinfo->sr.nexthops_backup = NULL;
|
||||
rinfo->sr_algo[algorithm].nexthops_backup =
|
||||
NULL;
|
||||
UNSET_FLAG(rinfo->flag,
|
||||
ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
|
||||
}
|
||||
@ -680,6 +825,8 @@ void isis_route_verify_merge(struct isis_area *area,
|
||||
struct isis_route_info *mrinfo = mrnode->info;
|
||||
if (mrinfo) {
|
||||
route_unlock_node(mrnode);
|
||||
set_merge_route_info_sr_algo(mrinfo, rinfo);
|
||||
|
||||
if (CHECK_FLAG(mrinfo->flag,
|
||||
ISIS_ROUTE_FLAG_ACTIVE)) {
|
||||
/* Clear the ZEBRA_SYNCED flag on the
|
||||
@ -723,6 +870,7 @@ void isis_route_invalidate_table(struct isis_area *area,
|
||||
{
|
||||
struct route_node *rode;
|
||||
struct isis_route_info *rinfo;
|
||||
uint8_t algorithm = isis_route_table_algorithm(table);
|
||||
for (rode = route_top(table); rode; rode = srcdest_route_next(rode)) {
|
||||
if (rode->info == NULL)
|
||||
continue;
|
||||
@ -730,7 +878,7 @@ void isis_route_invalidate_table(struct isis_area *area,
|
||||
|
||||
if (rinfo->backup) {
|
||||
rinfo->backup = NULL;
|
||||
rinfo->sr.nexthops_backup = NULL;
|
||||
rinfo->sr_algo[algorithm].nexthops_backup = NULL;
|
||||
/*
|
||||
* For now, always force routes that have backup
|
||||
* nexthops to be reinstalled.
|
||||
|
@ -30,12 +30,16 @@ struct isis_route_info {
|
||||
uint8_t flag;
|
||||
uint32_t cost;
|
||||
uint32_t depth;
|
||||
struct isis_sr_psid_info sr;
|
||||
struct isis_sr_psid_info sr_previous;
|
||||
struct isis_sr_psid_info sr_algo[SR_ALGORITHM_COUNT];
|
||||
struct isis_sr_psid_info sr_algo_previous[SR_ALGORITHM_COUNT];
|
||||
struct list *nexthops;
|
||||
struct isis_route_info *backup;
|
||||
};
|
||||
|
||||
struct isis_route_table_info {
|
||||
uint8_t algorithm;
|
||||
};
|
||||
|
||||
DECLARE_HOOK(isis_route_update_hook,
|
||||
(struct isis_area * area, struct prefix *prefix,
|
||||
struct isis_route_info *route_info),
|
||||
@ -73,9 +77,14 @@ void isis_route_invalidate_table(struct isis_area *area,
|
||||
void isis_route_node_cleanup(struct route_table *table,
|
||||
struct route_node *node);
|
||||
|
||||
|
||||
void isis_route_switchover_nexthop(struct isis_area *area,
|
||||
struct route_table *table, int family,
|
||||
union g_addr *nexthop_addr,
|
||||
ifindex_t ifindex);
|
||||
|
||||
struct isis_route_table_info *isis_route_table_info_alloc(uint8_t algorithm);
|
||||
void isis_route_table_info_free(void *info);
|
||||
uint8_t isis_route_table_algorithm(const struct route_table *table);
|
||||
|
||||
#endif /* _ZEBRA_ISIS_ROUTE_H */
|
||||
|
@ -335,7 +335,9 @@ isis_spftree_new(struct isis_area *area, struct lspdb_head *lspdb,
|
||||
isis_vertex_queue_init(&tree->paths, "IS-IS SPF paths", false);
|
||||
tree->route_table = srcdest_table_init();
|
||||
tree->route_table->cleanup = isis_route_node_cleanup;
|
||||
tree->route_table->info = isis_route_table_info_alloc(algorithm);
|
||||
tree->route_table_backup = srcdest_table_init();
|
||||
tree->route_table_backup->info = isis_route_table_info_alloc(algorithm);
|
||||
tree->route_table_backup->cleanup = isis_route_node_cleanup;
|
||||
tree->area = area;
|
||||
tree->lspdb = lspdb;
|
||||
@ -380,6 +382,8 @@ void isis_spftree_del(struct isis_spftree *spftree)
|
||||
list_delete(&spftree->sadj_list);
|
||||
isis_vertex_queue_free(&spftree->tents);
|
||||
isis_vertex_queue_free(&spftree->paths);
|
||||
isis_route_table_info_free(spftree->route_table->info);
|
||||
isis_route_table_info_free(spftree->route_table_backup->info);
|
||||
route_table_finish(spftree->route_table);
|
||||
route_table_finish(spftree->route_table_backup);
|
||||
spftree->route_table = NULL;
|
||||
@ -1838,11 +1842,18 @@ void isis_spf_verify_routes(struct isis_area *area, struct isis_spftree **trees)
|
||||
|
||||
void isis_spf_invalidate_routes(struct isis_spftree *tree)
|
||||
{
|
||||
struct isis_route_table_info *backup_info;
|
||||
|
||||
isis_route_invalidate_table(tree->area, tree->route_table);
|
||||
|
||||
/* Delete backup routes. */
|
||||
|
||||
backup_info = tree->route_table_backup->info;
|
||||
route_table_finish(tree->route_table_backup);
|
||||
isis_route_table_info_free(backup_info);
|
||||
tree->route_table_backup = srcdest_table_init();
|
||||
tree->route_table_backup->info =
|
||||
isis_route_table_info_alloc(tree->algorithm);
|
||||
tree->route_table_backup->cleanup = isis_route_node_cleanup;
|
||||
}
|
||||
|
||||
@ -2242,8 +2253,10 @@ static void isis_print_route(struct ttable *tt, const struct prefix *prefix,
|
||||
if (nexthop->sr.present) {
|
||||
snprintf(buf_sid, sizeof(buf_sid), "%u",
|
||||
nexthop->sr.sid.value);
|
||||
sr_op2str(buf_lblop, sizeof(buf_lblop),
|
||||
rinfo->sr.label, nexthop->sr.label);
|
||||
sr_op2str(
|
||||
buf_lblop, sizeof(buf_lblop),
|
||||
rinfo->sr_algo[SR_ALGORITHM_SPF].label,
|
||||
nexthop->sr.label);
|
||||
} else {
|
||||
strlcpy(buf_sid, "-", sizeof(buf_sid));
|
||||
strlcpy(buf_lblop, "-", sizeof(buf_lblop));
|
||||
@ -2298,12 +2311,14 @@ static void isis_print_route(struct ttable *tt, const struct prefix *prefix,
|
||||
char buf_sid[BUFSIZ] = {};
|
||||
char buf_lblop[BUFSIZ] = {};
|
||||
|
||||
if (rinfo->sr.present) {
|
||||
if (rinfo->sr_algo[SR_ALGORITHM_SPF].present) {
|
||||
snprintf(buf_sid, sizeof(buf_sid), "%u",
|
||||
rinfo->sr.sid.value);
|
||||
sr_op2str(buf_lblop, sizeof(buf_lblop),
|
||||
rinfo->sr.label,
|
||||
MPLS_LABEL_IMPLICIT_NULL);
|
||||
rinfo->sr_algo[SR_ALGORITHM_SPF]
|
||||
.sid.value);
|
||||
sr_op2str(
|
||||
buf_lblop, sizeof(buf_lblop),
|
||||
rinfo->sr_algo[SR_ALGORITHM_SPF].label,
|
||||
MPLS_LABEL_IMPLICIT_NULL);
|
||||
} else {
|
||||
strlcpy(buf_sid, "-", sizeof(buf_sid));
|
||||
strlcpy(buf_lblop, "-", sizeof(buf_lblop));
|
||||
|
Loading…
Reference in New Issue
Block a user