Coverage Report

Created: 2025-11-11 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/lib/srv6.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * SRv6 definitions
4
 * Copyright (C) 2020  Hiroki Shirokura, LINE Corporation
5
 */
6
7
#include "zebra.h"
8
9
#include "srv6.h"
10
#include "log.h"
11
12
DEFINE_QOBJ_TYPE(srv6_locator);
13
8
DEFINE_MTYPE_STATIC(LIB, SRV6_LOCATOR, "SRV6 locator");
14
8
DEFINE_MTYPE_STATIC(LIB, SRV6_LOCATOR_CHUNK, "SRV6 locator chunk");
15
8
16
8
const char *seg6local_action2str(uint32_t action)
17
8
{
18
0
  switch (action) {
19
0
  case ZEBRA_SEG6_LOCAL_ACTION_END:
20
0
    return "End";
21
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_X:
22
0
    return "End.X";
23
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_T:
24
0
    return "End.T";
25
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_DX2:
26
0
    return "End.DX2";
27
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_DX6:
28
0
    return "End.DX6";
29
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_DX4:
30
0
    return "End.DX4";
31
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_DT6:
32
0
    return "End.DT6";
33
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_DT4:
34
0
    return "End.DT4";
35
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_B6:
36
0
    return "End.B6";
37
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_B6_ENCAP:
38
0
    return "End.B6.Encap";
39
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_BM:
40
0
    return "End.BM";
41
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_S:
42
0
    return "End.S";
43
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_AS:
44
0
    return "End.AS";
45
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_AM:
46
0
    return "End.AM";
47
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_DT46:
48
0
    return "End.DT46";
49
0
  case ZEBRA_SEG6_LOCAL_ACTION_UNSPEC:
50
0
    return "unspec";
51
0
  default:
52
0
    return "unknown";
53
0
  }
54
0
}
55
56
int snprintf_seg6_segs(char *str,
57
    size_t size, const struct seg6_segs *segs)
58
0
{
59
0
  str[0] = '\0';
60
0
  for (size_t i = 0; i < segs->num_segs; i++) {
61
0
    char addr[INET6_ADDRSTRLEN];
62
0
    bool not_last = (i + 1) < segs->num_segs;
63
64
0
    inet_ntop(AF_INET6, &segs->segs[i], addr, sizeof(addr));
65
0
    strlcat(str, addr, size);
66
0
    strlcat(str, not_last ? "," : "", size);
67
0
  }
68
0
  return strlen(str);
69
0
}
70
71
const char *seg6local_context2str(char *str, size_t size,
72
          const struct seg6local_context *ctx,
73
          uint32_t action)
74
0
{
75
0
  switch (action) {
76
77
0
  case ZEBRA_SEG6_LOCAL_ACTION_END:
78
0
    snprintf(str, size, "USP");
79
0
    return str;
80
81
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_X:
82
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_DX6:
83
0
    snprintfrr(str, size, "nh6 %pI6", &ctx->nh6);
84
0
    return str;
85
86
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_DX4:
87
0
    snprintfrr(str, size, "nh4 %pI4", &ctx->nh4);
88
0
    return str;
89
90
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_T:
91
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_DT6:
92
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_DT4:
93
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_DT46:
94
0
    snprintf(str, size, "table %u", ctx->table);
95
0
    return str;
96
97
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_DX2:
98
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_B6:
99
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_B6_ENCAP:
100
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_BM:
101
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_S:
102
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_AS:
103
0
  case ZEBRA_SEG6_LOCAL_ACTION_END_AM:
104
0
  case ZEBRA_SEG6_LOCAL_ACTION_UNSPEC:
105
0
  default:
106
0
    snprintf(str, size, "unknown(%s)", __func__);
107
0
    return str;
108
0
  }
109
0
}
110
111
static void srv6_locator_chunk_list_free(void *data)
112
0
{
113
0
  struct srv6_locator_chunk *chunk = data;
114
115
0
  srv6_locator_chunk_free(&chunk);
116
0
}
117
118
struct srv6_locator *srv6_locator_alloc(const char *name)
119
0
{
120
0
  struct srv6_locator *locator = NULL;
121
122
0
  locator = XCALLOC(MTYPE_SRV6_LOCATOR, sizeof(struct srv6_locator));
123
0
  strlcpy(locator->name, name, sizeof(locator->name));
124
0
  locator->chunks = list_new();
125
0
  locator->chunks->del = srv6_locator_chunk_list_free;
126
127
0
  QOBJ_REG(locator, srv6_locator);
128
0
  return locator;
129
0
}
130
131
struct srv6_locator_chunk *srv6_locator_chunk_alloc(void)
132
0
{
133
0
  struct srv6_locator_chunk *chunk = NULL;
134
135
0
  chunk = XCALLOC(MTYPE_SRV6_LOCATOR_CHUNK,
136
0
      sizeof(struct srv6_locator_chunk));
137
0
  return chunk;
138
0
}
139
140
void srv6_locator_free(struct srv6_locator *locator)
141
0
{
142
0
  if (locator) {
143
0
    QOBJ_UNREG(locator);
144
0
    list_delete(&locator->chunks);
145
146
0
    XFREE(MTYPE_SRV6_LOCATOR, locator);
147
0
  }
148
0
}
149
150
void srv6_locator_chunk_free(struct srv6_locator_chunk **chunk)
151
0
{
152
0
  XFREE(MTYPE_SRV6_LOCATOR_CHUNK, *chunk);
153
0
}
154
155
json_object *srv6_locator_chunk_json(const struct srv6_locator_chunk *chunk)
156
0
{
157
0
  json_object *jo_root = NULL;
158
159
0
  jo_root = json_object_new_object();
160
0
  json_object_string_addf(jo_root, "prefix", "%pFX", &chunk->prefix);
161
0
  json_object_string_add(jo_root, "proto",
162
0
             zebra_route_string(chunk->proto));
163
164
0
  return jo_root;
165
0
}
166
167
json_object *
168
srv6_locator_chunk_detailed_json(const struct srv6_locator_chunk *chunk)
169
0
{
170
0
  json_object *jo_root = NULL;
171
172
0
  jo_root = json_object_new_object();
173
174
  /* set prefix */
175
0
  json_object_string_addf(jo_root, "prefix", "%pFX", &chunk->prefix);
176
177
  /* set block_bits_length */
178
0
  json_object_int_add(jo_root, "blockBitsLength",
179
0
          chunk->block_bits_length);
180
181
  /* set node_bits_length */
182
0
  json_object_int_add(jo_root, "nodeBitsLength", chunk->node_bits_length);
183
184
  /* set function_bits_length */
185
0
  json_object_int_add(jo_root, "functionBitsLength",
186
0
          chunk->function_bits_length);
187
188
  /* set argument_bits_length */
189
0
  json_object_int_add(jo_root, "argumentBitsLength",
190
0
          chunk->argument_bits_length);
191
192
  /* set keep */
193
0
  json_object_int_add(jo_root, "keep", chunk->keep);
194
195
  /* set proto */
196
0
  json_object_string_add(jo_root, "proto",
197
0
             zebra_route_string(chunk->proto));
198
199
  /* set instance */
200
0
  json_object_int_add(jo_root, "instance", chunk->instance);
201
202
  /* set session_id */
203
0
  json_object_int_add(jo_root, "sessionId", chunk->session_id);
204
205
0
  return jo_root;
206
0
}
207
208
json_object *srv6_locator_json(const struct srv6_locator *loc)
209
0
{
210
0
  struct listnode *node;
211
0
  struct srv6_locator_chunk *chunk;
212
0
  json_object *jo_root = NULL;
213
0
  json_object *jo_chunk = NULL;
214
0
  json_object *jo_chunks = NULL;
215
216
0
  jo_root = json_object_new_object();
217
218
  /* set name */
219
0
  json_object_string_add(jo_root, "name", loc->name);
220
221
  /* set prefix */
222
0
  json_object_string_addf(jo_root, "prefix", "%pFX", &loc->prefix);
223
224
  /* set block_bits_length */
225
0
  json_object_int_add(jo_root, "blockBitsLength", loc->block_bits_length);
226
227
  /* set node_bits_length */
228
0
  json_object_int_add(jo_root, "nodeBitsLength", loc->node_bits_length);
229
230
  /* set function_bits_length */
231
0
  json_object_int_add(jo_root, "functionBitsLength",
232
0
          loc->function_bits_length);
233
234
  /* set argument_bits_length */
235
0
  json_object_int_add(jo_root, "argumentBitsLength",
236
0
          loc->argument_bits_length);
237
238
  /* set true if the locator is a Micro-segment (uSID) locator */
239
0
  if (CHECK_FLAG(loc->flags, SRV6_LOCATOR_USID))
240
0
    json_object_string_add(jo_root, "behavior", "usid");
241
242
  /* set status_up */
243
0
  json_object_boolean_add(jo_root, "statusUp",
244
0
        loc->status_up);
245
246
  /* set chunks */
247
0
  jo_chunks = json_object_new_array();
248
0
  json_object_object_add(jo_root, "chunks", jo_chunks);
249
0
  for (ALL_LIST_ELEMENTS_RO((struct list *)loc->chunks, node, chunk)) {
250
0
    jo_chunk = srv6_locator_chunk_json(chunk);
251
0
    json_object_array_add(jo_chunks, jo_chunk);
252
0
  }
253
254
0
  return jo_root;
255
0
}
256
257
json_object *srv6_locator_detailed_json(const struct srv6_locator *loc)
258
0
{
259
0
  struct listnode *node;
260
0
  struct srv6_locator_chunk *chunk;
261
0
  json_object *jo_root = NULL;
262
0
  json_object *jo_chunk = NULL;
263
0
  json_object *jo_chunks = NULL;
264
265
0
  jo_root = json_object_new_object();
266
267
  /* set name */
268
0
  json_object_string_add(jo_root, "name", loc->name);
269
270
  /* set prefix */
271
0
  json_object_string_addf(jo_root, "prefix", "%pFX", &loc->prefix);
272
273
  /* set block_bits_length */
274
0
  json_object_int_add(jo_root, "blockBitsLength", loc->block_bits_length);
275
276
  /* set node_bits_length */
277
0
  json_object_int_add(jo_root, "nodeBitsLength", loc->node_bits_length);
278
279
  /* set function_bits_length */
280
0
  json_object_int_add(jo_root, "functionBitsLength",
281
0
          loc->function_bits_length);
282
283
  /* set argument_bits_length */
284
0
  json_object_int_add(jo_root, "argumentBitsLength",
285
0
          loc->argument_bits_length);
286
287
  /* set true if the locator is a Micro-segment (uSID) locator */
288
0
  if (CHECK_FLAG(loc->flags, SRV6_LOCATOR_USID))
289
0
    json_object_string_add(jo_root, "behavior", "usid");
290
291
  /* set algonum */
292
0
  json_object_int_add(jo_root, "algoNum", loc->algonum);
293
294
  /* set status_up */
295
0
  json_object_boolean_add(jo_root, "statusUp", loc->status_up);
296
297
  /* set chunks */
298
0
  jo_chunks = json_object_new_array();
299
0
  json_object_object_add(jo_root, "chunks", jo_chunks);
300
0
  for (ALL_LIST_ELEMENTS_RO((struct list *)loc->chunks, node, chunk)) {
301
0
    jo_chunk = srv6_locator_chunk_detailed_json(chunk);
302
0
    json_object_array_add(jo_chunks, jo_chunk);
303
0
  }
304
305
0
  return jo_root;
306
0
}