]> git.proxmox.com Git - mirror_frr.git/blob - lib/flex_algo.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / lib / flex_algo.c
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 DEFINE_MTYPE_STATIC(LIB, FLEX_ALGO_DATABASE, "Flex-Algo database");
21 DEFINE_MTYPE_STATIC(LIB, FLEX_ALGO, "Flex-Algo algorithm information");
22
23 static void _flex_algo_delete(struct flex_algos *flex_algos,
24 struct flex_algo *fa);
25
26 struct flex_algos *flex_algos_alloc(flex_algo_allocator_t allocator,
27 flex_algo_releaser_t releaser)
28 {
29 struct flex_algos *flex_algos;
30
31 flex_algos =
32 XCALLOC(MTYPE_FLEX_ALGO_DATABASE, sizeof(struct flex_algos));
33 flex_algos->flex_algos = list_new();
34 flex_algos->allocator = allocator;
35 flex_algos->releaser = releaser;
36 return flex_algos;
37 }
38
39 void flex_algos_free(struct flex_algos *flex_algos)
40 {
41 struct listnode *node, *nnode;
42 struct flex_algo *fa;
43
44 for (ALL_LIST_ELEMENTS(flex_algos->flex_algos, node, nnode, fa))
45 _flex_algo_delete(flex_algos, fa);
46 list_delete(&flex_algos->flex_algos);
47 XFREE(MTYPE_FLEX_ALGO_DATABASE, flex_algos);
48 }
49
50 struct flex_algo *flex_algo_alloc(struct flex_algos *flex_algos,
51 uint8_t algorithm, void *arg)
52 {
53 struct flex_algo *fa;
54
55 fa = XCALLOC(MTYPE_FLEX_ALGO, sizeof(struct flex_algo));
56 fa->algorithm = algorithm;
57 if (flex_algos->allocator)
58 fa->data = flex_algos->allocator(arg);
59 admin_group_init(&fa->admin_group_exclude_any);
60 admin_group_init(&fa->admin_group_include_any);
61 admin_group_init(&fa->admin_group_include_all);
62 listnode_add(flex_algos->flex_algos, fa);
63 return fa;
64 }
65
66 static void _flex_algo_delete(struct flex_algos *flex_algos,
67 struct flex_algo *fa)
68 {
69 if (flex_algos->releaser)
70 flex_algos->releaser(fa->data);
71 admin_group_term(&fa->admin_group_exclude_any);
72 admin_group_term(&fa->admin_group_include_any);
73 admin_group_term(&fa->admin_group_include_all);
74 listnode_delete(flex_algos->flex_algos, fa);
75 XFREE(MTYPE_FLEX_ALGO, fa);
76 }
77
78
79 void flex_algo_delete(struct flex_algos *flex_algos, uint8_t algorithm)
80 {
81 struct listnode *node, *nnode;
82 struct flex_algo *fa;
83
84 for (ALL_LIST_ELEMENTS(flex_algos->flex_algos, node, nnode, fa)) {
85 if (fa->algorithm != algorithm)
86 continue;
87 _flex_algo_delete(flex_algos, fa);
88 }
89 }
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 {
100 struct listnode *node;
101 struct flex_algo *fa;
102
103 for (ALL_LIST_ELEMENTS_RO(flex_algos->flex_algos, node, fa))
104 if (fa->algorithm == algorithm)
105 return fa;
106 return NULL;
107 }
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 {
117 if (fa1->algorithm != fa2->algorithm)
118 return false;
119 if (fa1->calc_type != fa2->calc_type)
120 return false;
121 if (fa1->metric_type != fa2->metric_type)
122 return false;
123 if (fa1->exclude_srlg != fa2->exclude_srlg)
124 return false;
125 if (fa1->flags != fa2->flags)
126 return false;
127 if (fa1->unsupported_subtlv != fa2->unsupported_subtlv)
128 return false;
129
130 if (!admin_group_cmp(&fa1->admin_group_exclude_any,
131 &fa2->admin_group_exclude_any))
132 return false;
133 if (!admin_group_cmp(&fa1->admin_group_include_all,
134 &fa2->admin_group_include_all))
135 return false;
136 if (!admin_group_cmp(&fa1->admin_group_include_any,
137 &fa2->admin_group_include_any))
138 return false;
139
140 return true;
141 }
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 {
151 return algorithm >= SR_ALGORITHM_FLEX_MIN &&
152 algorithm <= SR_ALGORITHM_FLEX_MAX;
153 }
154
155 char *flex_algo_metric_type_print(char *type_str, size_t sz,
156 enum flex_algo_metric_type metric_type)
157 {
158 switch (metric_type) {
159 case MT_IGP:
160 snprintf(type_str, sz, "igp");
161 break;
162 case MT_MIN_UNI_LINK_DELAY:
163 snprintf(type_str, sz, "delay");
164 break;
165 case MT_TE_DEFAULT:
166 snprintf(type_str, sz, "te");
167 break;
168 }
169 return type_str;
170 }
171
172 bool flex_algo_get_state(struct flex_algos *flex_algos, uint8_t algorithm)
173 {
174 struct flex_algo *fa = flex_algo_lookup(flex_algos, algorithm);
175
176 if (!fa)
177 return false;
178
179 return fa->state;
180 }
181
182 void flex_algo_set_state(struct flex_algos *flex_algos, uint8_t algorithm,
183 bool state)
184 {
185 struct flex_algo *fa = flex_algo_lookup(flex_algos, algorithm);
186
187 if (!fa)
188 return;
189
190 fa->state = state;
191 }