3939
4040DEFINE_MTYPE_STATIC (ISISD , ISIS_NEXTHOP , "ISIS nexthop" );
4141DEFINE_MTYPE_STATIC (ISISD , ISIS_ROUTE_INFO , "ISIS route info" );
42+ DEFINE_MTYPE_STATIC (ISISD , ISIS_ROUTE_TABLE_INFO , "ISIS route table info" );
43+
4244
4345DEFINE_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+
68100void 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+
74121static 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
249296static 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+
266346static 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
477602static 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.
0 commit comments