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