Line data Source code
1 1 : /*
2 : * Copyright (c) 2023 Nordic Semiconductor ASA
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : */
6 :
7 : /**
8 : * @file
9 : * @brief API for defining conn_mgr connectivity implementations (allowing ifaces to be used with
10 : * conn_mgr_connectivity).
11 : */
12 :
13 : #ifndef ZEPHYR_INCLUDE_CONN_MGR_CONNECTIVITY_IMPL_H_
14 : #define ZEPHYR_INCLUDE_CONN_MGR_CONNECTIVITY_IMPL_H_
15 :
16 : #include <zephyr/device.h>
17 : #include <zephyr/net/net_if.h>
18 : #include <zephyr/sys/iterable_sections.h>
19 : #include <zephyr/net/net_mgmt.h>
20 : #include <zephyr/net/conn_mgr_connectivity.h>
21 :
22 : #ifdef __cplusplus
23 : extern "C" {
24 : #endif
25 :
26 : /**
27 : * @brief Connection Manager Connectivity Implementation API
28 : * @defgroup conn_mgr_connectivity_impl Connection Manager Connectivity Implementation API
29 : * @since 3.4
30 : * @version 0.8.0
31 : * @ingroup conn_mgr_connectivity
32 : * @{
33 : */
34 :
35 : /* Forward declaration */
36 : struct conn_mgr_conn_binding;
37 :
38 : /**
39 : * @brief Connectivity Manager Connectivity API structure
40 : *
41 : * Used to provide generic access to network association parameters and procedures
42 : */
43 1 : struct conn_mgr_conn_api {
44 : /**
45 : * @brief When called, the connectivity implementation should start attempting to
46 : * establish connectivity (association with a network) for the bound iface pointed
47 : * to by if_conn->iface.
48 : *
49 : * Must be non-blocking.
50 : *
51 : * Called by @ref conn_mgr_if_connect.
52 : */
53 1 : int (*connect)(struct conn_mgr_conn_binding *const binding);
54 :
55 : /**
56 : * @brief When called, the connectivity implementation should disconnect (disassociate), or
57 : * stop any in-progress attempts to associate to a network, the bound iface pointed to by
58 : * if_conn->iface.
59 : *
60 : * Called by @ref conn_mgr_if_disconnect.
61 : */
62 1 : int (*disconnect)(struct conn_mgr_conn_binding *const binding);
63 :
64 : /**
65 : * @brief Called once for each iface that has been bound to a connectivity implementation
66 : * using this API.
67 : *
68 : * Connectivity implementations should use this callback to perform any required
69 : * per-bound-iface initialization.
70 : *
71 : * Implementations may choose to gracefully handle invalid buffer lengths with partial
72 : * writes, rather than raise errors, if deemed appropriate.
73 : */
74 1 : void (*init)(struct conn_mgr_conn_binding *const binding);
75 :
76 : /**
77 : * @brief Implementation callback for conn_mgr_if_set_opt.
78 : *
79 : * Used to set implementation-specific connectivity settings.
80 : *
81 : * Calls to conn_mgr_if_set_opt on an iface will result in calls to this callback with
82 : * the conn_mgr_conn_binding struct bound to that iface.
83 : *
84 : * It is up to the connectivity implementation to interpret optname. Options can be
85 : * specific to the bound iface (pointed to by if_conn->iface), or can apply to the whole
86 : * connectivity implementation.
87 : *
88 : * See the description of conn_mgr_if_set_opt for more details.
89 : * set_opt implementations should conform to that description.
90 : *
91 : * Implementations may choose to gracefully handle invalid buffer lengths with partial
92 : * reads, rather than raise errors, if deemed appropriate.
93 : */
94 1 : int (*set_opt)(struct conn_mgr_conn_binding *const binding,
95 : int optname, const void *optval, size_t optlen);
96 :
97 : /**
98 : * @brief Implementation callback for conn_mgr_if_get_opt.
99 : *
100 : * Used to retrieve implementation-specific connectivity settings.
101 : *
102 : * Calls to conn_mgr_if_get_opt on an iface will result in calls to this callback with
103 : * the conn_mgr_conn_binding struct bound to that iface.
104 : *
105 : * It is up to the connectivity implementation to interpret optname. Options can be
106 : * specific to the bound iface (pointed to by if_conn->iface), or can apply to the whole
107 : * connectivity implementation.
108 : *
109 : * See the description of conn_mgr_if_get_opt for more details.
110 : * get_opt implementations should conform to that description.
111 : */
112 1 : int (*get_opt)(struct conn_mgr_conn_binding *const binding,
113 : int optname, void *optval, size_t *optlen);
114 : };
115 :
116 : /** @cond INTERNAL_HIDDEN */
117 : #define CONN_MGR_CONN_IMPL_GET_NAME(conn_id) __conn_mgr_conn_##conn_id
118 : #define CONN_MGR_CONN_IMPL_GET_CTX_TYPE(conn_id) conn_id##_CTX_TYPE
119 : /** @endcond */
120 :
121 : /**
122 : * @brief Connectivity Implementation struct
123 : *
124 : * Declares a conn_mgr connectivity layer implementation with the provided API
125 : */
126 1 : struct conn_mgr_conn_impl {
127 : /** The connectivity API used by the implementation */
128 1 : struct conn_mgr_conn_api *api;
129 : };
130 :
131 : /**
132 : * @brief Define a conn_mgr connectivity implementation that can be bound to network devices.
133 : *
134 : * @param conn_id The name of the new connectivity implementation
135 : * @param conn_api A pointer to a conn_mgr_conn_api struct
136 : */
137 1 : #define CONN_MGR_CONN_DEFINE(conn_id, conn_api) \
138 : const struct conn_mgr_conn_impl CONN_MGR_CONN_IMPL_GET_NAME(conn_id) = { \
139 : .api = conn_api, \
140 : };
141 :
142 : /**
143 : * @brief Helper macro to make a conn_mgr connectivity implementation publicly available.
144 : */
145 1 : #define CONN_MGR_CONN_DECLARE_PUBLIC(conn_id) \
146 : extern const struct conn_mgr_conn_impl CONN_MGR_CONN_IMPL_GET_NAME(conn_id)
147 :
148 : /** @cond INTERNAL_HIDDEN */
149 : #define CONN_MGR_CONN_BINDING_GET_NAME(dev_id, sfx) __conn_mgr_bndg_##dev_id##_##sfx
150 : #define CONN_MGR_CONN_BINDING_GET_DATA(dev_id, sfx) __conn_mgr_bndg_data_##dev_id##_##sfx
151 : #define CONN_MGR_CONN_BINDING_GET_MUTEX(dev_id, sfx) __conn_mgr_bndg_mutex_##dev_id##_##sfx
152 : /** @endcond */
153 :
154 : /**
155 : * @brief Connectivity Manager network interface binding structure
156 : *
157 : * Binds a conn_mgr connectivity implementation to an iface / network device.
158 : * Stores per-iface state for the connectivity implementation.
159 : */
160 1 : struct conn_mgr_conn_binding {
161 : /** The network interface the connectivity implementation is bound to */
162 1 : struct net_if *iface;
163 :
164 : /** The connectivity implementation the network device is bound to */
165 1 : const struct conn_mgr_conn_impl *impl;
166 :
167 : /** Pointer to private, per-iface connectivity context */
168 1 : void *ctx;
169 :
170 : /**
171 : * @name Generic connectivity state
172 : * @{
173 : */
174 :
175 : /**
176 : * Connectivity flags
177 : *
178 : * Public boolean state and configuration values supported by all bindings.
179 : * See conn_mgr_if_flag for options.
180 : */
181 1 : uint32_t flags;
182 :
183 : /**
184 : * Timeout (seconds)
185 : *
186 : * Indicates to the connectivity implementation how long it should attempt to
187 : * establish connectivity for during a connection attempt before giving up.
188 : *
189 : * The connectivity implementation should give up on establishing connectivity after this
190 : * timeout, even if persistence is enabled.
191 : *
192 : * Set to @ref CONN_MGR_IF_NO_TIMEOUT to indicate that no timeout should be used.
193 : */
194 1 : int timeout;
195 :
196 : /**
197 : * Usage timeout (seconds)
198 : *
199 : * Indicates to the connectivity implementation how long the interface can be idle
200 : * for before automatically taking the interface down.
201 : *
202 : * Set to @ref CONN_MGR_IF_NO_TIMEOUT to indicate that no idle timeout should be used.
203 : */
204 1 : int idle_timeout;
205 :
206 : /** @} */
207 :
208 : /** @cond INTERNAL_HIDDEN */
209 : /* Internal-use work item for tracking interface idle timeouts */
210 : struct k_work_delayable idle_worker;
211 :
212 : /* Internal-use mutex for protecting access to the binding and API functions. */
213 : struct k_mutex *mutex;
214 : /** @endcond */
215 : };
216 :
217 : /**
218 : * @brief Associate a connectivity implementation with an existing network device instance
219 : *
220 : * @param dev_id Network device id.
221 : * @param inst Network device instance.
222 : * @param conn_id Name of the connectivity implementation to associate.
223 : */
224 1 : #define CONN_MGR_BIND_CONN_INST(dev_id, inst, conn_id) \
225 : K_MUTEX_DEFINE(CONN_MGR_CONN_BINDING_GET_MUTEX(dev_id, inst)); \
226 : static CONN_MGR_CONN_IMPL_GET_CTX_TYPE(conn_id) \
227 : CONN_MGR_CONN_BINDING_GET_DATA(dev_id, inst); \
228 : static STRUCT_SECTION_ITERABLE(conn_mgr_conn_binding, \
229 : CONN_MGR_CONN_BINDING_GET_NAME(dev_id, inst)) = { \
230 : .iface = NET_IF_GET(dev_id, inst), \
231 : .impl = &(CONN_MGR_CONN_IMPL_GET_NAME(conn_id)), \
232 : .ctx = &(CONN_MGR_CONN_BINDING_GET_DATA(dev_id, inst)), \
233 : .mutex = &(CONN_MGR_CONN_BINDING_GET_MUTEX(dev_id, inst)) \
234 : };
235 :
236 : /**
237 : * @brief Associate a connectivity implementation with an existing network device
238 : *
239 : * @param dev_id Network device id.
240 : * @param conn_id Name of the connectivity implementation to associate.
241 : */
242 1 : #define CONN_MGR_BIND_CONN(dev_id, conn_id) \
243 : CONN_MGR_BIND_CONN_INST(dev_id, 0, conn_id)
244 :
245 : /**
246 : * @brief Retrieves the conn_mgr binding struct for a provided iface if it exists.
247 : *
248 : * Bindings for connectivity implementations with missing API structs are ignored.
249 : *
250 : * For use only by connectivity implementations.
251 : *
252 : * @param iface - bound network interface to obtain the binding struct for.
253 : * @return struct conn_mgr_conn_binding* Pointer to the retrieved binding struct if it exists,
254 : * NULL otherwise.
255 : */
256 1 : static inline struct conn_mgr_conn_binding *conn_mgr_if_get_binding(struct net_if *iface)
257 : {
258 : STRUCT_SECTION_FOREACH(conn_mgr_conn_binding, binding) {
259 : if (iface == binding->iface) {
260 : if (binding->impl->api) {
261 : return binding;
262 : }
263 : return NULL;
264 : }
265 : }
266 : return NULL;
267 : }
268 :
269 : /**
270 : * @brief Lock the passed-in binding, making it safe to access.
271 : *
272 : * Call this whenever accessing binding data, unless inside a conn_mgr_conn_api callback, where it
273 : * is called automatically by conn_mgr.
274 : *
275 : * Reentrant.
276 : *
277 : * For use only by connectivity implementations.
278 : *
279 : * @param binding - Binding to lock
280 : */
281 1 : static inline void conn_mgr_binding_lock(struct conn_mgr_conn_binding *binding)
282 : {
283 : (void)k_mutex_lock(binding->mutex, K_FOREVER);
284 : }
285 :
286 : /**
287 : * @brief Unlocks the passed-in binding.
288 : *
289 : * Call this after any call to @ref conn_mgr_binding_lock once done accessing binding data.
290 : *
291 : * Reentrant.
292 : *
293 : * For use only by connectivity implementations.
294 : *
295 : * @param binding - Binding to unlock
296 : */
297 1 : static inline void conn_mgr_binding_unlock(struct conn_mgr_conn_binding *binding)
298 : {
299 : (void)k_mutex_unlock(binding->mutex);
300 : }
301 :
302 : /**
303 : * @brief Set the value of the specified connectivity flag for the provided binding
304 : *
305 : * Can be used from any thread or callback without calling @ref conn_mgr_binding_lock.
306 : *
307 : * For use only by connectivity implementations
308 : *
309 : * @param binding The binding to check
310 : * @param flag The flag to check
311 : * @param value New value for the specified flag
312 : */
313 1 : static inline void conn_mgr_binding_set_flag(struct conn_mgr_conn_binding *binding,
314 : enum conn_mgr_if_flag flag, bool value)
315 : {
316 : conn_mgr_binding_lock(binding);
317 :
318 : binding->flags &= ~BIT(flag);
319 : if (value) {
320 : binding->flags |= BIT(flag);
321 : }
322 :
323 : conn_mgr_binding_unlock(binding);
324 : }
325 :
326 : /**
327 : * @brief Check the value of the specified connectivity flag for the provided binding
328 : *
329 : * Can be used from any thread or callback without calling @ref conn_mgr_binding_lock.
330 : *
331 : * For use only by connectivity implementations
332 : *
333 : * @param binding The binding to check
334 : * @param flag The flag to check
335 : * @return bool The value of the specified flag
336 : */
337 1 : static inline bool conn_mgr_binding_get_flag(struct conn_mgr_conn_binding *binding,
338 : enum conn_mgr_if_flag flag)
339 : {
340 : bool value = false;
341 :
342 : conn_mgr_binding_lock(binding);
343 :
344 : value = !!(binding->flags & BIT(flag));
345 :
346 : conn_mgr_binding_unlock(binding);
347 :
348 : return value;
349 : }
350 :
351 : /**
352 : * @}
353 : */
354 :
355 : #ifdef __cplusplus
356 : }
357 : #endif
358 :
359 : #endif /* ZEPHYR_INCLUDE_CONN_MGR_CONNECTIVITY_IMPL_H_ */
|