39
39
40
40
DEFINE_MTYPE_STATIC (ISISD , ISIS_NEXTHOP , "ISIS nexthop" );
41
41
DEFINE_MTYPE_STATIC (ISISD , ISIS_ROUTE_INFO , "ISIS route info" );
42
+ DEFINE_MTYPE_STATIC (ISISD , ISIS_ROUTE_TABLE_INFO , "ISIS route table info" );
43
+
42
44
43
45
DEFINE_HOOK (isis_route_update_hook ,
44
46
(struct isis_area * area , struct prefix * prefix ,
@@ -51,8 +53,25 @@ static void isis_route_update(struct isis_area *area, struct prefix *prefix,
51
53
struct prefix_ipv6 * src_p ,
52
54
struct isis_route_info * route_info );
53
55
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 )
56
75
{
57
76
struct isis_nexthop * nexthop ;
58
77
@@ -65,12 +84,40 @@ static struct isis_nexthop *isis_nexthop_create(int family, union g_addr *ip,
65
84
return nexthop ;
66
85
}
67
86
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
+
68
100
void isis_nexthop_delete (struct isis_nexthop * nexthop )
69
101
{
70
102
XFREE (MTYPE_ISIS_NEXTHOP_LABELS , nexthop -> label_stack );
71
103
XFREE (MTYPE_ISIS_NEXTHOP , nexthop );
72
104
}
73
105
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
+
74
121
static struct isis_nexthop * nexthoplookup (struct list * nexthops , int family ,
75
122
union g_addr * ip , ifindex_t ifindex )
76
123
{
@@ -238,16 +285,28 @@ isis_route_info_new(struct prefix *prefix, struct prefix_ipv6 *src_p,
238
285
239
286
rinfo -> cost = cost ;
240
287
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 =
244
291
rinfo -> backup ? rinfo -> backup -> nexthops : NULL ;
245
292
246
293
return rinfo ;
247
294
}
248
295
249
296
static void isis_route_info_delete (struct isis_route_info * route_info )
250
297
{
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
+
251
310
if (route_info -> nexthops ) {
252
311
route_info -> nexthops -> del =
253
312
(void (* )(void * ))isis_nexthop_delete ;
@@ -263,6 +322,27 @@ void isis_route_node_cleanup(struct route_table *table, struct route_node *node)
263
322
isis_route_info_delete (node -> info );
264
323
}
265
324
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
+
266
346
static bool isis_sr_psid_info_same (struct isis_sr_psid_info * new ,
267
347
struct isis_sr_psid_info * old )
268
348
{
@@ -319,10 +399,22 @@ static int isis_route_info_same(struct isis_route_info *new,
319
399
return 0 ;
320
400
}
321
401
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
+ }
326
418
}
327
419
328
420
if (new -> nexthops -> count != old -> nexthops -> count ) {
@@ -411,7 +503,9 @@ isis_route_create(struct prefix *prefix, struct prefix_ipv6 *src_p,
411
503
zlog_debug (
412
504
"ISIS-Rte (%s): route changed: %pFX, change: %s" ,
413
505
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 ];
415
509
isis_route_info_delete (rinfo_old );
416
510
route_info = rinfo_new ;
417
511
UNSET_FLAG (route_info -> flag ,
@@ -467,11 +561,42 @@ static void isis_route_remove_previous_sid(struct isis_area *area,
467
561
* Explicitly uninstall previous Prefix-SID label if it has
468
562
* changed or was removed.
469
563
*/
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 );
475
600
}
476
601
477
602
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,
490
615
/* Install route. */
491
616
isis_zebra_route_add_route (area -> isis , prefix , src_p ,
492
617
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
+ }
497
634
498
635
hook_call (isis_route_update_hook , area , prefix , route_info );
499
636
500
637
SET_FLAG (route_info -> flag , ISIS_ROUTE_FLAG_ZEBRA_SYNCED );
501
638
UNSET_FLAG (route_info -> flag , ISIS_ROUTE_FLAG_ZEBRA_RESYNC );
502
639
} else {
503
640
/* 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
+
507
647
/* Uninstall route. */
508
648
isis_zebra_route_del_route (area -> isis , prefix , src_p ,
509
649
route_info );
@@ -523,6 +663,7 @@ static void _isis_route_verify_table(struct isis_area *area,
523
663
#ifdef EXTREME_DEBUG
524
664
char buff [SRCDEST2STR_BUFFER ];
525
665
#endif /* EXTREME_DEBUG */
666
+ uint8_t algorithm = isis_route_table_algorithm (table );
526
667
527
668
for (rnode = route_top (table ); rnode ;
528
669
rnode = srcdest_route_next (rnode )) {
@@ -545,13 +686,14 @@ static void _isis_route_verify_table(struct isis_area *area,
545
686
src_p );
546
687
if (rnode_bck ) {
547
688
rinfo -> backup = rnode_bck -> info ;
548
- rinfo -> sr .nexthops_backup =
689
+ rinfo -> sr_algo [ algorithm ] .nexthops_backup =
549
690
rinfo -> backup -> nexthops ;
550
691
UNSET_FLAG (rinfo -> flag ,
551
692
ISIS_ROUTE_FLAG_ZEBRA_SYNCED );
552
693
} else if (rinfo -> backup ) {
553
694
rinfo -> backup = NULL ;
554
- rinfo -> sr .nexthops_backup = NULL ;
695
+ rinfo -> sr_algo [algorithm ].nexthops_backup =
696
+ NULL ;
555
697
UNSET_FLAG (rinfo -> flag ,
556
698
ISIS_ROUTE_FLAG_ZEBRA_SYNCED );
557
699
}
@@ -645,6 +787,8 @@ void isis_route_verify_merge(struct isis_area *area,
645
787
merge = srcdest_table_init ();
646
788
647
789
for (int level = ISIS_LEVEL1 ; level <= ISIS_LEVEL2 ; level ++ ) {
790
+ uint8_t algorithm =
791
+ isis_route_table_algorithm (tables [level - 1 ]);
648
792
for (rnode = route_top (tables [level - 1 ]); rnode ;
649
793
rnode = srcdest_route_next (rnode )) {
650
794
struct isis_route_info * rinfo = rnode -> info ;
@@ -665,13 +809,14 @@ void isis_route_verify_merge(struct isis_area *area,
665
809
tables_backup [level - 1 ], prefix , src_p );
666
810
if (rnode_bck ) {
667
811
rinfo -> backup = rnode_bck -> info ;
668
- rinfo -> sr .nexthops_backup =
812
+ rinfo -> sr_algo [ algorithm ] .nexthops_backup =
669
813
rinfo -> backup -> nexthops ;
670
814
UNSET_FLAG (rinfo -> flag ,
671
815
ISIS_ROUTE_FLAG_ZEBRA_SYNCED );
672
816
} else if (rinfo -> backup ) {
673
817
rinfo -> backup = NULL ;
674
- rinfo -> sr .nexthops_backup = NULL ;
818
+ rinfo -> sr_algo [algorithm ].nexthops_backup =
819
+ NULL ;
675
820
UNSET_FLAG (rinfo -> flag ,
676
821
ISIS_ROUTE_FLAG_ZEBRA_SYNCED );
677
822
}
@@ -680,6 +825,8 @@ void isis_route_verify_merge(struct isis_area *area,
680
825
struct isis_route_info * mrinfo = mrnode -> info ;
681
826
if (mrinfo ) {
682
827
route_unlock_node (mrnode );
828
+ set_merge_route_info_sr_algo (mrinfo , rinfo );
829
+
683
830
if (CHECK_FLAG (mrinfo -> flag ,
684
831
ISIS_ROUTE_FLAG_ACTIVE )) {
685
832
/* Clear the ZEBRA_SYNCED flag on the
@@ -723,14 +870,15 @@ void isis_route_invalidate_table(struct isis_area *area,
723
870
{
724
871
struct route_node * rode ;
725
872
struct isis_route_info * rinfo ;
873
+ uint8_t algorithm = isis_route_table_algorithm (table );
726
874
for (rode = route_top (table ); rode ; rode = srcdest_route_next (rode )) {
727
875
if (rode -> info == NULL )
728
876
continue ;
729
877
rinfo = rode -> info ;
730
878
731
879
if (rinfo -> backup ) {
732
880
rinfo -> backup = NULL ;
733
- rinfo -> sr .nexthops_backup = NULL ;
881
+ rinfo -> sr_algo [ algorithm ] .nexthops_backup = NULL ;
734
882
/*
735
883
* For now, always force routes that have backup
736
884
* nexthops to be reinstalled.
0 commit comments