Coverage Report

Created: 2026-04-27 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/lib/flex_algo.c
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
}