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