Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | | /********************************************************************* |
3 | | * Copyright 2022 Hiroki Shirokura, LINE Corporation |
4 | | * Copyright 2022 Masakazu Asama |
5 | | * Copyright 2022 6WIND S.A. |
6 | | * |
7 | | * flex_algo.c: Flexible Algorithm library |
8 | | * |
9 | | * Authors |
10 | | * ------- |
11 | | * Hiroki Shirokura |
12 | | * Masakazu Asama |
13 | | * Louis Scalbert |
14 | | */ |
15 | | |
16 | | #include "zebra.h" |
17 | | |
18 | | #include "flex_algo.h" |
19 | | |
20 | 8 | DEFINE_MTYPE_STATIC(LIB, FLEX_ALGO_DATABASE, "Flex-Algo database"); |
21 | 8 | DEFINE_MTYPE_STATIC(LIB, FLEX_ALGO, "Flex-Algo algorithm information"); |
22 | 8 | |
23 | 8 | static void _flex_algo_delete(struct flex_algos *flex_algos, |
24 | 8 | struct flex_algo *fa); |
25 | 8 | |
26 | 8 | struct flex_algos *flex_algos_alloc(flex_algo_allocator_t allocator, |
27 | 8 | flex_algo_releaser_t releaser) |
28 | 8 | { |
29 | 0 | struct flex_algos *flex_algos; |
30 | |
|
31 | 0 | flex_algos = |
32 | 0 | XCALLOC(MTYPE_FLEX_ALGO_DATABASE, sizeof(struct flex_algos)); |
33 | 0 | flex_algos->flex_algos = list_new(); |
34 | 0 | flex_algos->allocator = allocator; |
35 | 0 | flex_algos->releaser = releaser; |
36 | 0 | return flex_algos; |
37 | 0 | } |
38 | | |
39 | | void flex_algos_free(struct flex_algos *flex_algos) |
40 | 0 | { |
41 | 0 | struct listnode *node, *nnode; |
42 | 0 | struct flex_algo *fa; |
43 | |
|
44 | 0 | for (ALL_LIST_ELEMENTS(flex_algos->flex_algos, node, nnode, fa)) |
45 | 0 | _flex_algo_delete(flex_algos, fa); |
46 | 0 | list_delete(&flex_algos->flex_algos); |
47 | 0 | XFREE(MTYPE_FLEX_ALGO_DATABASE, flex_algos); |
48 | 0 | } |
49 | | |
50 | | struct flex_algo *flex_algo_alloc(struct flex_algos *flex_algos, |
51 | | uint8_t algorithm, void *arg) |
52 | 0 | { |
53 | 0 | struct flex_algo *fa; |
54 | |
|
55 | 0 | fa = XCALLOC(MTYPE_FLEX_ALGO, sizeof(struct flex_algo)); |
56 | 0 | fa->algorithm = algorithm; |
57 | 0 | if (flex_algos->allocator) |
58 | 0 | fa->data = flex_algos->allocator(arg); |
59 | 0 | admin_group_init(&fa->admin_group_exclude_any); |
60 | 0 | admin_group_init(&fa->admin_group_include_any); |
61 | 0 | admin_group_init(&fa->admin_group_include_all); |
62 | 0 | listnode_add(flex_algos->flex_algos, fa); |
63 | 0 | return fa; |
64 | 0 | } |
65 | | |
66 | | static void _flex_algo_delete(struct flex_algos *flex_algos, |
67 | | struct flex_algo *fa) |
68 | 0 | { |
69 | 0 | if (flex_algos->releaser) |
70 | 0 | flex_algos->releaser(fa->data); |
71 | 0 | admin_group_term(&fa->admin_group_exclude_any); |
72 | 0 | admin_group_term(&fa->admin_group_include_any); |
73 | 0 | admin_group_term(&fa->admin_group_include_all); |
74 | 0 | listnode_delete(flex_algos->flex_algos, fa); |
75 | 0 | XFREE(MTYPE_FLEX_ALGO, fa); |
76 | 0 | } |
77 | | |
78 | | |
79 | | void flex_algo_delete(struct flex_algos *flex_algos, uint8_t algorithm) |
80 | 0 | { |
81 | 0 | struct listnode *node, *nnode; |
82 | 0 | struct flex_algo *fa; |
83 | |
|
84 | 0 | for (ALL_LIST_ELEMENTS(flex_algos->flex_algos, node, nnode, fa)) { |
85 | 0 | if (fa->algorithm != algorithm) |
86 | 0 | continue; |
87 | 0 | _flex_algo_delete(flex_algos, fa); |
88 | 0 | } |
89 | 0 | } |
90 | | |
91 | | /** |
92 | | * @brief Look up the local flex-algo object by its algorithm number. |
93 | | * @param algorithm flex-algo algorithm number |
94 | | * @param area area pointer of flex-algo |
95 | | * @return local flex-algo object if exist, else NULL |
96 | | */ |
97 | | struct flex_algo *flex_algo_lookup(struct flex_algos *flex_algos, |
98 | | uint8_t algorithm) |
99 | 0 | { |
100 | 0 | struct listnode *node; |
101 | 0 | struct flex_algo *fa; |
102 | |
|
103 | 0 | for (ALL_LIST_ELEMENTS_RO(flex_algos->flex_algos, node, fa)) |
104 | 0 | if (fa->algorithm == algorithm) |
105 | 0 | return fa; |
106 | 0 | return NULL; |
107 | 0 | } |
108 | | |
109 | | /** |
110 | | * @brief Compare two Flex-Algo Definitions (FAD) |
111 | | * @param Flex algo 1 |
112 | | * @param Flex algo 2 |
113 | | * @return true if the definition is equal, else false |
114 | | */ |
115 | | bool flex_algo_definition_cmp(struct flex_algo *fa1, struct flex_algo *fa2) |
116 | 0 | { |
117 | 0 | if (fa1->algorithm != fa2->algorithm) |
118 | 0 | return false; |
119 | 0 | if (fa1->calc_type != fa2->calc_type) |
120 | 0 | return false; |
121 | 0 | if (fa1->metric_type != fa2->metric_type) |
122 | 0 | return false; |
123 | 0 | if (fa1->exclude_srlg != fa2->exclude_srlg) |
124 | 0 | return false; |
125 | 0 | if (fa1->flags != fa2->flags) |
126 | 0 | return false; |
127 | 0 | if (fa1->unsupported_subtlv != fa2->unsupported_subtlv) |
128 | 0 | return false; |
129 | | |
130 | 0 | if (!admin_group_cmp(&fa1->admin_group_exclude_any, |
131 | 0 | &fa2->admin_group_exclude_any)) |
132 | 0 | return false; |
133 | 0 | if (!admin_group_cmp(&fa1->admin_group_include_all, |
134 | 0 | &fa2->admin_group_include_all)) |
135 | 0 | return false; |
136 | 0 | if (!admin_group_cmp(&fa1->admin_group_include_any, |
137 | 0 | &fa2->admin_group_include_any)) |
138 | 0 | return false; |
139 | | |
140 | 0 | return true; |
141 | 0 | } |
142 | | |
143 | | /** |
144 | | * Check SR Algorithm is Flex-Algo |
145 | | * according to RFC9350 section 4 |
146 | | * |
147 | | * @param algorithm SR Algorithm |
148 | | */ |
149 | | bool flex_algo_id_valid(uint16_t algorithm) |
150 | 0 | { |
151 | 0 | return algorithm >= SR_ALGORITHM_FLEX_MIN && |
152 | 0 | algorithm <= SR_ALGORITHM_FLEX_MAX; |
153 | 0 | } |
154 | | |
155 | | char *flex_algo_metric_type_print(char *type_str, size_t sz, |
156 | | enum flex_algo_metric_type metric_type) |
157 | 0 | { |
158 | 0 | switch (metric_type) { |
159 | 0 | case MT_IGP: |
160 | 0 | snprintf(type_str, sz, "igp"); |
161 | 0 | break; |
162 | 0 | case MT_MIN_UNI_LINK_DELAY: |
163 | 0 | snprintf(type_str, sz, "delay"); |
164 | 0 | break; |
165 | 0 | case MT_TE_DEFAULT: |
166 | 0 | snprintf(type_str, sz, "te"); |
167 | 0 | break; |
168 | 0 | } |
169 | 0 | return type_str; |
170 | 0 | } |
171 | | |
172 | | bool flex_algo_get_state(struct flex_algos *flex_algos, uint8_t algorithm) |
173 | 0 | { |
174 | 0 | struct flex_algo *fa = flex_algo_lookup(flex_algos, algorithm); |
175 | |
|
176 | 0 | if (!fa) |
177 | 0 | return false; |
178 | | |
179 | 0 | return fa->state; |
180 | 0 | } |
181 | | |
182 | | void flex_algo_set_state(struct flex_algos *flex_algos, uint8_t algorithm, |
183 | | bool state) |
184 | 0 | { |
185 | 0 | struct flex_algo *fa = flex_algo_lookup(flex_algos, algorithm); |
186 | |
|
187 | 0 | if (!fa) |
188 | 0 | return; |
189 | | |
190 | 0 | fa->state = state; |
191 | 0 | } |