Skip to content

Commit

Permalink
isisd: update struct isis_route_info has multiple sr info by algorithm
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
slankdev authored and louis-6wind committed Apr 18, 2023
1 parent bdaafbf commit 7153c3c
Show file tree
Hide file tree
Showing 3 changed files with 208 additions and 36 deletions.
202 changes: 175 additions & 27 deletions isisd/isis_route.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;

Expand All @@ -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)
{
Expand Down Expand Up @@ -238,16 +285,28 @@ 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;
}

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;
Expand All @@ -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)
{
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -490,20 +615,35 @@ 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);

SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
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);
Expand All @@ -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)) {
Expand All @@ -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);
}
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}
Expand All @@ -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
Expand Down Expand Up @@ -723,14 +870,15 @@ 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;
rinfo = rode->info;

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.
Expand Down
13 changes: 11 additions & 2 deletions isisd/isis_route.h
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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 */
Loading

0 comments on commit 7153c3c

Please sign in to comment.