Skip to content

Commit 7153c3c

Browse files
slankdevlouis-6wind
authored andcommitted
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 <[email protected]> Signed-off-by: Louis Scalbert <[email protected]>
1 parent bdaafbf commit 7153c3c

File tree

3 files changed

+208
-36
lines changed

3 files changed

+208
-36
lines changed

isisd/isis_route.c

+175-27
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939

4040
DEFINE_MTYPE_STATIC(ISISD, ISIS_NEXTHOP, "ISIS nexthop");
4141
DEFINE_MTYPE_STATIC(ISISD, ISIS_ROUTE_INFO, "ISIS route info");
42+
DEFINE_MTYPE_STATIC(ISISD, ISIS_ROUTE_TABLE_INFO, "ISIS route table info");
43+
4244

4345
DEFINE_HOOK(isis_route_update_hook,
4446
(struct isis_area * area, struct prefix *prefix,
@@ -51,8 +53,25 @@ static void isis_route_update(struct isis_area *area, struct prefix *prefix,
5153
struct prefix_ipv6 *src_p,
5254
struct isis_route_info *route_info);
5355

54-
static struct isis_nexthop *isis_nexthop_create(int family, union g_addr *ip,
55-
ifindex_t ifindex)
56+
static struct mpls_label_stack *
57+
label_stack_dup(const struct mpls_label_stack *const orig)
58+
{
59+
struct mpls_label_stack *copy;
60+
int array_size;
61+
62+
if (orig == NULL)
63+
return NULL;
64+
65+
array_size = orig->num_labels * sizeof(mpls_label_t);
66+
copy = XCALLOC(MTYPE_ISIS_NEXTHOP_LABELS,
67+
sizeof(struct mpls_label_stack) + array_size);
68+
copy->num_labels = orig->num_labels;
69+
memcpy(copy->label, orig->label, array_size);
70+
return copy;
71+
}
72+
73+
static struct isis_nexthop *
74+
isis_nexthop_create(int family, const union g_addr *const ip, ifindex_t ifindex)
5675
{
5776
struct isis_nexthop *nexthop;
5877

@@ -65,12 +84,40 @@ static struct isis_nexthop *isis_nexthop_create(int family, union g_addr *ip,
6584
return nexthop;
6685
}
6786

87+
static struct isis_nexthop *
88+
isis_nexthop_dup(const struct isis_nexthop *const orig)
89+
{
90+
struct isis_nexthop *nexthop;
91+
92+
nexthop = isis_nexthop_create(orig->family, &orig->ip, orig->ifindex);
93+
memcpy(nexthop->sysid, orig->sysid, ISIS_SYS_ID_LEN);
94+
nexthop->sr = orig->sr;
95+
nexthop->label_stack = label_stack_dup(orig->label_stack);
96+
97+
return nexthop;
98+
}
99+
68100
void isis_nexthop_delete(struct isis_nexthop *nexthop)
69101
{
70102
XFREE(MTYPE_ISIS_NEXTHOP_LABELS, nexthop->label_stack);
71103
XFREE(MTYPE_ISIS_NEXTHOP, nexthop);
72104
}
73105

106+
static struct list *isis_nexthop_list_dup(const struct list *orig)
107+
{
108+
struct list *copy;
109+
struct listnode *node;
110+
struct isis_nexthop *nh;
111+
struct isis_nexthop *nhcopy;
112+
113+
copy = list_new();
114+
for (ALL_LIST_ELEMENTS_RO(orig, node, nh)) {
115+
nhcopy = isis_nexthop_dup(nh);
116+
listnode_add(copy, nhcopy);
117+
}
118+
return copy;
119+
}
120+
74121
static struct isis_nexthop *nexthoplookup(struct list *nexthops, int family,
75122
union g_addr *ip, ifindex_t ifindex)
76123
{
@@ -238,16 +285,28 @@ isis_route_info_new(struct prefix *prefix, struct prefix_ipv6 *src_p,
238285

239286
rinfo->cost = cost;
240287
rinfo->depth = depth;
241-
rinfo->sr = *sr;
242-
rinfo->sr.nexthops = rinfo->nexthops;
243-
rinfo->sr.nexthops_backup =
288+
rinfo->sr_algo[sr->algorithm] = *sr;
289+
rinfo->sr_algo[sr->algorithm].nexthops = rinfo->nexthops;
290+
rinfo->sr_algo[sr->algorithm].nexthops_backup =
244291
rinfo->backup ? rinfo->backup->nexthops : NULL;
245292

246293
return rinfo;
247294
}
248295

249296
static void isis_route_info_delete(struct isis_route_info *route_info)
250297
{
298+
for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
299+
if (!route_info->sr_algo[i].present)
300+
continue;
301+
302+
if (route_info->sr_algo[i].nexthops == route_info->nexthops)
303+
continue;
304+
305+
route_info->sr_algo[i].nexthops->del =
306+
(void (*)(void *))isis_nexthop_delete;
307+
list_delete(&route_info->sr_algo[i].nexthops);
308+
}
309+
251310
if (route_info->nexthops) {
252311
route_info->nexthops->del =
253312
(void (*)(void *))isis_nexthop_delete;
@@ -263,6 +322,27 @@ void isis_route_node_cleanup(struct route_table *table, struct route_node *node)
263322
isis_route_info_delete(node->info);
264323
}
265324

325+
struct isis_route_table_info *isis_route_table_info_alloc(uint8_t algorithm)
326+
{
327+
struct isis_route_table_info *info;
328+
329+
info = XCALLOC(MTYPE_ISIS_ROUTE_TABLE_INFO, sizeof(*info));
330+
info->algorithm = algorithm;
331+
return info;
332+
}
333+
334+
void isis_route_table_info_free(void *info)
335+
{
336+
XFREE(MTYPE_ISIS_ROUTE_TABLE_INFO, info);
337+
}
338+
339+
uint8_t isis_route_table_algorithm(const struct route_table *table)
340+
{
341+
const struct isis_route_table_info *info = table->info;
342+
343+
return info ? info->algorithm : 0;
344+
}
345+
266346
static bool isis_sr_psid_info_same(struct isis_sr_psid_info *new,
267347
struct isis_sr_psid_info *old)
268348
{
@@ -319,10 +399,22 @@ static int isis_route_info_same(struct isis_route_info *new,
319399
return 0;
320400
}
321401

322-
if (!isis_sr_psid_info_same(&new->sr, &old->sr)) {
323-
if (buf)
324-
snprintf(buf, buf_size, "SR input label");
325-
return 0;
402+
for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
403+
struct isis_sr_psid_info new_sr_algo;
404+
struct isis_sr_psid_info old_sr_algo;
405+
406+
new_sr_algo = new->sr_algo[i];
407+
old_sr_algo = old->sr_algo[i];
408+
409+
if (!isis_sr_psid_info_same(&new_sr_algo, &old_sr_algo)) {
410+
if (buf)
411+
snprintf(
412+
buf, buf_size,
413+
"SR input label algo-%u (old: %s, new: %s)",
414+
i, old_sr_algo.present ? "yes" : "no",
415+
new_sr_algo.present ? "yes" : "no");
416+
return 0;
417+
}
326418
}
327419

328420
if (new->nexthops->count != old->nexthops->count) {
@@ -411,7 +503,9 @@ isis_route_create(struct prefix *prefix, struct prefix_ipv6 *src_p,
411503
zlog_debug(
412504
"ISIS-Rte (%s): route changed: %pFX, change: %s",
413505
area->area_tag, prefix, change_buf);
414-
rinfo_new->sr_previous = rinfo_old->sr;
506+
for (int i = 0; i < SR_ALGORITHM_COUNT; i++)
507+
rinfo_new->sr_algo_previous[i] =
508+
rinfo_old->sr_algo[i];
415509
isis_route_info_delete(rinfo_old);
416510
route_info = rinfo_new;
417511
UNSET_FLAG(route_info->flag,
@@ -467,11 +561,42 @@ static void isis_route_remove_previous_sid(struct isis_area *area,
467561
* Explicitly uninstall previous Prefix-SID label if it has
468562
* changed or was removed.
469563
*/
470-
if (route_info->sr_previous.present &&
471-
(!route_info->sr.present ||
472-
route_info->sr_previous.label != route_info->sr.label))
473-
isis_zebra_prefix_sid_uninstall(area, prefix, route_info,
474-
&route_info->sr_previous);
564+
for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
565+
if (route_info->sr_algo_previous[i].present &&
566+
(!route_info->sr_algo[i].present ||
567+
route_info->sr_algo_previous[i].label !=
568+
route_info->sr_algo[i].label))
569+
isis_zebra_prefix_sid_uninstall(
570+
area, prefix, route_info,
571+
&route_info->sr_algo_previous[i]);
572+
}
573+
}
574+
575+
static void set_merge_route_info_sr_algo(struct isis_route_info *mrinfo,
576+
struct isis_route_info *rinfo)
577+
{
578+
for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
579+
if (rinfo->sr_algo[i].present) {
580+
assert(i == rinfo->sr_algo[i].algorithm);
581+
assert(rinfo->nexthops);
582+
assert(rinfo->backup ? rinfo->backup->nexthops != NULL
583+
: true);
584+
585+
if (mrinfo->sr_algo[i].nexthops != NULL &&
586+
mrinfo->sr_algo[i].nexthops != mrinfo->nexthops) {
587+
mrinfo->sr_algo[i].nexthops->del =
588+
(void (*)(void *))isis_nexthop_delete;
589+
list_delete(&mrinfo->sr_algo[i].nexthops);
590+
}
591+
592+
mrinfo->sr_algo[i] = rinfo->sr_algo[i];
593+
mrinfo->sr_algo[i].nexthops = isis_nexthop_list_dup(
594+
rinfo->sr_algo[i].nexthops);
595+
}
596+
}
597+
598+
UNSET_FLAG(rinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
599+
UNSET_FLAG(mrinfo->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
475600
}
476601

477602
static void isis_route_update(struct isis_area *area, struct prefix *prefix,
@@ -490,20 +615,35 @@ static void isis_route_update(struct isis_area *area, struct prefix *prefix,
490615
/* Install route. */
491616
isis_zebra_route_add_route(area->isis, prefix, src_p,
492617
route_info);
493-
/* Install/reinstall Prefix-SID label. */
494-
if (route_info->sr.present)
495-
isis_zebra_prefix_sid_install(area, prefix,
496-
&route_info->sr);
618+
619+
for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
620+
struct isis_sr_psid_info sr_algo;
621+
622+
sr_algo = route_info->sr_algo[i];
623+
624+
/*
625+
* Install/reinstall Prefix-SID label.
626+
*/
627+
if (sr_algo.present)
628+
isis_zebra_prefix_sid_install(area, prefix,
629+
&sr_algo);
630+
631+
hook_call(isis_route_update_hook, area, prefix,
632+
route_info);
633+
}
497634

498635
hook_call(isis_route_update_hook, area, prefix, route_info);
499636

500637
SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
501638
UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
502639
} else {
503640
/* Uninstall Prefix-SID label. */
504-
if (route_info->sr.present)
505-
isis_zebra_prefix_sid_uninstall(
506-
area, prefix, route_info, &route_info->sr);
641+
for (int i = 0; i < SR_ALGORITHM_COUNT; i++)
642+
if (route_info->sr_algo[i].present)
643+
isis_zebra_prefix_sid_uninstall(
644+
area, prefix, route_info,
645+
&route_info->sr_algo[i]);
646+
507647
/* Uninstall route. */
508648
isis_zebra_route_del_route(area->isis, prefix, src_p,
509649
route_info);
@@ -523,6 +663,7 @@ static void _isis_route_verify_table(struct isis_area *area,
523663
#ifdef EXTREME_DEBUG
524664
char buff[SRCDEST2STR_BUFFER];
525665
#endif /* EXTREME_DEBUG */
666+
uint8_t algorithm = isis_route_table_algorithm(table);
526667

527668
for (rnode = route_top(table); rnode;
528669
rnode = srcdest_route_next(rnode)) {
@@ -545,13 +686,14 @@ static void _isis_route_verify_table(struct isis_area *area,
545686
src_p);
546687
if (rnode_bck) {
547688
rinfo->backup = rnode_bck->info;
548-
rinfo->sr.nexthops_backup =
689+
rinfo->sr_algo[algorithm].nexthops_backup =
549690
rinfo->backup->nexthops;
550691
UNSET_FLAG(rinfo->flag,
551692
ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
552693
} else if (rinfo->backup) {
553694
rinfo->backup = NULL;
554-
rinfo->sr.nexthops_backup = NULL;
695+
rinfo->sr_algo[algorithm].nexthops_backup =
696+
NULL;
555697
UNSET_FLAG(rinfo->flag,
556698
ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
557699
}
@@ -645,6 +787,8 @@ void isis_route_verify_merge(struct isis_area *area,
645787
merge = srcdest_table_init();
646788

647789
for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) {
790+
uint8_t algorithm =
791+
isis_route_table_algorithm(tables[level - 1]);
648792
for (rnode = route_top(tables[level - 1]); rnode;
649793
rnode = srcdest_route_next(rnode)) {
650794
struct isis_route_info *rinfo = rnode->info;
@@ -665,13 +809,14 @@ void isis_route_verify_merge(struct isis_area *area,
665809
tables_backup[level - 1], prefix, src_p);
666810
if (rnode_bck) {
667811
rinfo->backup = rnode_bck->info;
668-
rinfo->sr.nexthops_backup =
812+
rinfo->sr_algo[algorithm].nexthops_backup =
669813
rinfo->backup->nexthops;
670814
UNSET_FLAG(rinfo->flag,
671815
ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
672816
} else if (rinfo->backup) {
673817
rinfo->backup = NULL;
674-
rinfo->sr.nexthops_backup = NULL;
818+
rinfo->sr_algo[algorithm].nexthops_backup =
819+
NULL;
675820
UNSET_FLAG(rinfo->flag,
676821
ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
677822
}
@@ -680,6 +825,8 @@ void isis_route_verify_merge(struct isis_area *area,
680825
struct isis_route_info *mrinfo = mrnode->info;
681826
if (mrinfo) {
682827
route_unlock_node(mrnode);
828+
set_merge_route_info_sr_algo(mrinfo, rinfo);
829+
683830
if (CHECK_FLAG(mrinfo->flag,
684831
ISIS_ROUTE_FLAG_ACTIVE)) {
685832
/* Clear the ZEBRA_SYNCED flag on the
@@ -723,14 +870,15 @@ void isis_route_invalidate_table(struct isis_area *area,
723870
{
724871
struct route_node *rode;
725872
struct isis_route_info *rinfo;
873+
uint8_t algorithm = isis_route_table_algorithm(table);
726874
for (rode = route_top(table); rode; rode = srcdest_route_next(rode)) {
727875
if (rode->info == NULL)
728876
continue;
729877
rinfo = rode->info;
730878

731879
if (rinfo->backup) {
732880
rinfo->backup = NULL;
733-
rinfo->sr.nexthops_backup = NULL;
881+
rinfo->sr_algo[algorithm].nexthops_backup = NULL;
734882
/*
735883
* For now, always force routes that have backup
736884
* nexthops to be reinstalled.

isisd/isis_route.h

+11-2
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,16 @@ struct isis_route_info {
3030
uint8_t flag;
3131
uint32_t cost;
3232
uint32_t depth;
33-
struct isis_sr_psid_info sr;
34-
struct isis_sr_psid_info sr_previous;
33+
struct isis_sr_psid_info sr_algo[SR_ALGORITHM_COUNT];
34+
struct isis_sr_psid_info sr_algo_previous[SR_ALGORITHM_COUNT];
3535
struct list *nexthops;
3636
struct isis_route_info *backup;
3737
};
3838

39+
struct isis_route_table_info {
40+
uint8_t algorithm;
41+
};
42+
3943
DECLARE_HOOK(isis_route_update_hook,
4044
(struct isis_area * area, struct prefix *prefix,
4145
struct isis_route_info *route_info),
@@ -73,9 +77,14 @@ void isis_route_invalidate_table(struct isis_area *area,
7377
void isis_route_node_cleanup(struct route_table *table,
7478
struct route_node *node);
7579

80+
7681
void isis_route_switchover_nexthop(struct isis_area *area,
7782
struct route_table *table, int family,
7883
union g_addr *nexthop_addr,
7984
ifindex_t ifindex);
8085

86+
struct isis_route_table_info *isis_route_table_info_alloc(uint8_t algorithm);
87+
void isis_route_table_info_free(void *info);
88+
uint8_t isis_route_table_algorithm(const struct route_table *table);
89+
8190
#endif /* _ZEBRA_ISIS_ROUTE_H */

0 commit comments

Comments
 (0)