Line data Source code
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 12 : DEFINE_MTYPE_STATIC(LIB, SRV6_LOCATOR, "SRV6 locator");
14 12 : DEFINE_MTYPE_STATIC(LIB, SRV6_LOCATOR_CHUNK, "SRV6 locator chunk");
15 :
16 0 : const char *seg6local_action2str(uint32_t action)
17 : {
18 0 : switch (action) {
19 : case ZEBRA_SEG6_LOCAL_ACTION_END:
20 : 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 : }
54 : }
55 :
56 0 : int snprintf_seg6_segs(char *str,
57 : size_t size, const struct seg6_segs *segs)
58 : {
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 : }
68 0 : return strlen(str);
69 : }
70 :
71 0 : const char *seg6local_context2str(char *str, size_t size,
72 : const struct seg6local_context *ctx,
73 : uint32_t action)
74 : {
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 : 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 : case ZEBRA_SEG6_LOCAL_ACTION_END_DT6:
92 : case ZEBRA_SEG6_LOCAL_ACTION_END_DT4:
93 : 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 : case ZEBRA_SEG6_LOCAL_ACTION_END_B6:
99 : case ZEBRA_SEG6_LOCAL_ACTION_END_B6_ENCAP:
100 : case ZEBRA_SEG6_LOCAL_ACTION_END_BM:
101 : case ZEBRA_SEG6_LOCAL_ACTION_END_S:
102 : case ZEBRA_SEG6_LOCAL_ACTION_END_AS:
103 : case ZEBRA_SEG6_LOCAL_ACTION_END_AM:
104 : case ZEBRA_SEG6_LOCAL_ACTION_UNSPEC:
105 : default:
106 0 : snprintf(str, size, "unknown(%s)", __func__);
107 0 : return str;
108 : }
109 : }
110 :
111 0 : static void srv6_locator_chunk_list_free(void *data)
112 : {
113 0 : struct srv6_locator_chunk *chunk = data;
114 :
115 0 : srv6_locator_chunk_free(&chunk);
116 0 : }
117 :
118 0 : struct srv6_locator *srv6_locator_alloc(const char *name)
119 : {
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 : }
130 :
131 0 : struct srv6_locator_chunk *srv6_locator_chunk_alloc(void)
132 : {
133 0 : struct srv6_locator_chunk *chunk = NULL;
134 :
135 0 : chunk = XCALLOC(MTYPE_SRV6_LOCATOR_CHUNK,
136 : sizeof(struct srv6_locator_chunk));
137 0 : return chunk;
138 : }
139 :
140 0 : void srv6_locator_free(struct srv6_locator *locator)
141 : {
142 0 : if (locator) {
143 0 : QOBJ_UNREG(locator);
144 0 : list_delete(&locator->chunks);
145 :
146 0 : XFREE(MTYPE_SRV6_LOCATOR, locator);
147 : }
148 0 : }
149 :
150 0 : void srv6_locator_chunk_free(struct srv6_locator_chunk **chunk)
151 : {
152 0 : XFREE(MTYPE_SRV6_LOCATOR_CHUNK, *chunk);
153 0 : }
154 :
155 0 : json_object *srv6_locator_chunk_json(const struct srv6_locator_chunk *chunk)
156 : {
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 : }
166 :
167 : json_object *
168 0 : srv6_locator_chunk_detailed_json(const struct srv6_locator_chunk *chunk)
169 : {
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 : }
207 :
208 0 : json_object *srv6_locator_json(const struct srv6_locator *loc)
209 : {
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 : }
253 :
254 0 : return jo_root;
255 : }
256 :
257 0 : json_object *srv6_locator_detailed_json(const struct srv6_locator *loc)
258 : {
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 : }
304 :
305 0 : return jo_root;
306 : }
|