2 * Zebra SRv6 definitions
3 * Copyright (C) 2020 Hiroki Shirokura, LINE Corporation
4 * Copyright (C) 2020 Masakazu Asama
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "zebra/debug.h"
28 #include "zebra/zapi_msg.h"
29 #include "zebra/zserv.h"
30 #include "zebra/zebra_router.h"
31 #include "zebra/zebra_srv6.h"
32 #include "zebra/zebra_errors.h"
36 #include <arpa/inet.h>
37 #include <netinet/in.h>
42 #include <arpa/inet.h>
43 #include <netinet/in.h>
46 DEFINE_MGROUP(SRV6_MGR
, "SRv6 Manager");
47 DEFINE_MTYPE_STATIC(SRV6_MGR
, SRV6M_CHUNK
, "SRv6 Manager Chunk");
49 /* define hooks for the basic API, so that it can be specialized or served
53 DEFINE_HOOK(srv6_manager_client_connect
,
54 (struct zserv
*client
, vrf_id_t vrf_id
),
56 DEFINE_HOOK(srv6_manager_client_disconnect
,
57 (struct zserv
*client
), (client
));
58 DEFINE_HOOK(srv6_manager_get_chunk
,
59 (struct srv6_locator
**loc
,
61 const char *locator_name
,
63 (loc
, client
, locator_name
, vrf_id
));
64 DEFINE_HOOK(srv6_manager_release_chunk
,
65 (struct zserv
*client
,
66 const char *locator_name
,
68 (client
, locator_name
, vrf_id
));
70 /* define wrappers to be called in zapi_msg.c (as hooks must be called in
71 * source file where they were defined)
74 void srv6_manager_client_connect_call(struct zserv
*client
, vrf_id_t vrf_id
)
76 hook_call(srv6_manager_client_connect
, client
, vrf_id
);
79 void srv6_manager_get_locator_chunk_call(struct srv6_locator
**loc
,
81 const char *locator_name
,
84 hook_call(srv6_manager_get_chunk
, loc
, client
, locator_name
, vrf_id
);
87 void srv6_manager_release_locator_chunk_call(struct zserv
*client
,
88 const char *locator_name
,
91 hook_call(srv6_manager_release_chunk
, client
, locator_name
, vrf_id
);
94 int srv6_manager_client_disconnect_cb(struct zserv
*client
)
96 hook_call(srv6_manager_client_disconnect
, client
);
100 static int zebra_srv6_cleanup(struct zserv
*client
)
105 void zebra_srv6_locator_add(struct srv6_locator
*locator
)
107 struct zebra_srv6
*srv6
= zebra_srv6_get_default();
108 struct srv6_locator
*tmp
;
110 tmp
= zebra_srv6_locator_lookup(locator
->name
);
112 listnode_add(srv6
->locators
, locator
);
115 void zebra_srv6_locator_delete(struct srv6_locator
*locator
)
117 struct zebra_srv6
*srv6
= zebra_srv6_get_default();
119 listnode_delete(srv6
->locators
, locator
);
122 struct srv6_locator
*zebra_srv6_locator_lookup(const char *name
)
124 struct zebra_srv6
*srv6
= zebra_srv6_get_default();
125 struct srv6_locator
*locator
;
126 struct listnode
*node
;
128 for (ALL_LIST_ELEMENTS_RO(srv6
->locators
, node
, locator
))
129 if (!strncmp(name
, locator
->name
, SRV6_LOCNAME_SIZE
))
134 struct zebra_srv6
*zebra_srv6_get_default(void)
136 static struct zebra_srv6 srv6
;
137 static bool first_execution
= true;
139 if (first_execution
) {
140 first_execution
= false;
141 srv6
.locators
= list_new();
147 * Core function, assigns srv6-locator chunks
149 * It first searches through the list to check if there's one available
150 * (previously released). Otherwise it creates and assigns a new one
152 * @param proto Daemon protocol of client, to identify the owner
153 * @param instance Instance, to identify the owner
154 * @param session_id SessionID of client
155 * @param name Name of SRv6-locator
156 * @return Pointer to the assigned srv6-locator chunk,
157 * or NULL if the request could not be satisfied
159 static struct srv6_locator
*
160 assign_srv6_locator_chunk(uint8_t proto
,
163 const char *locator_name
)
165 bool chunk_found
= false;
166 struct listnode
*node
= NULL
;
167 struct srv6_locator
*loc
= NULL
;
168 struct srv6_locator_chunk
*chunk
= NULL
;
170 loc
= zebra_srv6_locator_lookup(locator_name
);
172 zlog_info("%s: locator %s was not found",
173 __func__
, locator_name
);
175 loc
= srv6_locator_alloc(locator_name
);
177 zlog_info("%s: locator %s can't allocated",
178 __func__
, locator_name
);
182 loc
->status_up
= false;
183 chunk
= srv6_locator_chunk_alloc();
184 chunk
->proto
= NO_PROTO
;
185 listnode_add(loc
->chunks
, chunk
);
186 zebra_srv6_locator_add(loc
);
189 for (ALL_LIST_ELEMENTS_RO((struct list
*)loc
->chunks
, node
, chunk
)) {
190 if (chunk
->proto
!= NO_PROTO
&& chunk
->proto
!= proto
)
197 zlog_info("%s: locator is already owned", __func__
);
201 chunk
->proto
= proto
;
202 chunk
->instance
= instance
;
203 chunk
->session_id
= session_id
;
207 static int zebra_srv6_manager_get_locator_chunk(struct srv6_locator
**loc
,
208 struct zserv
*client
,
209 const char *locator_name
,
214 *loc
= assign_srv6_locator_chunk(client
->proto
, client
->instance
,
215 client
->session_id
, locator_name
);
218 zlog_err("Unable to assign locator chunk to %s instance %u",
219 zebra_route_string(client
->proto
), client
->instance
);
220 else if (IS_ZEBRA_DEBUG_PACKET
)
221 zlog_info("Assigned locator chunk %s to %s instance %u",
222 (*loc
)->name
, zebra_route_string(client
->proto
),
225 if (*loc
&& (*loc
)->status_up
)
226 ret
= zsend_srv6_manager_get_locator_chunk_response(client
,
233 * Core function, release no longer used srv6-locator chunks
235 * @param proto Daemon protocol of client, to identify the owner
236 * @param instance Instance, to identify the owner
237 * @param session_id Zclient session ID, to identify the zclient session
238 * @param locator_name SRv6-locator name, to identify the actual locator
239 * @return 0 on success, -1 otherwise
241 static int release_srv6_locator_chunk(uint8_t proto
, uint16_t instance
,
243 const char *locator_name
)
246 struct listnode
*node
;
247 struct srv6_locator_chunk
*chunk
;
248 struct srv6_locator
*loc
= NULL
;
250 loc
= zebra_srv6_locator_lookup(locator_name
);
254 if (IS_ZEBRA_DEBUG_PACKET
)
255 zlog_debug("%s: Releasing srv6-locator on %s", __func__
,
258 for (ALL_LIST_ELEMENTS_RO((struct list
*)loc
->chunks
, node
, chunk
)) {
259 if (chunk
->proto
!= proto
||
260 chunk
->instance
!= instance
||
261 chunk
->session_id
!= session_id
)
263 chunk
->proto
= NO_PROTO
;
265 chunk
->session_id
= 0;
272 flog_err(EC_ZEBRA_SRV6M_UNRELEASED_LOCATOR_CHUNK
,
273 "%s: SRv6 locator chunk not released", __func__
);
278 static int zebra_srv6_manager_release_locator_chunk(struct zserv
*client
,
279 const char *locator_name
,
282 if (vrf_id
!= VRF_DEFAULT
) {
283 zlog_err("SRv6 locator doesn't support vrf");
287 return release_srv6_locator_chunk(client
->proto
, client
->instance
,
288 client
->session_id
, locator_name
);
292 * Release srv6-locator chunks from a client.
294 * Called on client disconnection or reconnection. It only releases chunks
295 * with empty keep value.
297 * @param proto Daemon protocol of client, to identify the owner
298 * @param instance Instance, to identify the owner
299 * @return Number of chunks released
301 int release_daemon_srv6_locator_chunks(struct zserv
*client
)
305 struct zebra_srv6
*srv6
= zebra_srv6_get_default();
306 struct listnode
*loc_node
;
307 struct listnode
*chunk_node
;
308 struct srv6_locator
*loc
;
309 struct srv6_locator_chunk
*chunk
;
311 if (IS_ZEBRA_DEBUG_PACKET
)
312 zlog_debug("%s: Releasing chunks for client proto %s, instance %d, session %u",
313 __func__
, zebra_route_string(client
->proto
),
314 client
->instance
, client
->session_id
);
316 for (ALL_LIST_ELEMENTS_RO(srv6
->locators
, loc_node
, loc
)) {
317 for (ALL_LIST_ELEMENTS_RO(loc
->chunks
, chunk_node
, chunk
)) {
318 if (chunk
->proto
== client
->proto
&&
319 chunk
->instance
== client
->instance
&&
320 chunk
->session_id
== client
->session_id
&&
322 ret
= release_srv6_locator_chunk(
323 chunk
->proto
, chunk
->instance
,
324 chunk
->session_id
, loc
->name
);
331 if (IS_ZEBRA_DEBUG_PACKET
)
332 zlog_debug("%s: Released %d srv6-locator chunks",
338 void zebra_srv6_init(void)
340 hook_register(zserv_client_close
, zebra_srv6_cleanup
);
341 hook_register(srv6_manager_get_chunk
,
342 zebra_srv6_manager_get_locator_chunk
);
343 hook_register(srv6_manager_release_chunk
,
344 zebra_srv6_manager_release_locator_chunk
);
347 bool zebra_srv6_is_enable(void)
349 struct zebra_srv6
*srv6
= zebra_srv6_get_default();
351 return listcount(srv6
->locators
);