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