1 /*
2 * Copyright (c) 2016 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief Public API for offloading IP stack
10 */
11
12 #ifndef ZEPHYR_INCLUDE_NET_NET_OFFLOAD_H_
13 #define ZEPHYR_INCLUDE_NET_NET_OFFLOAD_H_
14
15 /**
16 * @brief Network offloading interface
17 * @defgroup net_offload Network Offloading Interface
18 * @since 1.7
19 * @version 0.8.0
20 * @ingroup networking
21 * @{
22 */
23
24 #include <zephyr/net/buf.h>
25 #include <zephyr/net/net_ip.h>
26 #include <zephyr/net/net_context.h>
27
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31
32 #if defined(CONFIG_NET_OFFLOAD)
33
34 /** @cond INTERNAL_HIDDEN */
35
timeout_to_int32(k_timeout_t timeout)36 static inline int32_t timeout_to_int32(k_timeout_t timeout)
37 {
38 if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
39 return 0;
40 } else if (K_TIMEOUT_EQ(timeout, K_FOREVER)) {
41 return -1;
42 } else {
43 return k_ticks_to_ms_floor32(timeout.ticks);
44 }
45 }
46
47 /** @endcond */
48
49 /** For return parameters and return values of the elements in this
50 * struct, see similarly named functions in net_context.h
51 */
52 struct net_offload {
53 /**
54 * This function is called when the socket is to be opened.
55 */
56 int (*get)(sa_family_t family,
57 enum net_sock_type type,
58 enum net_ip_protocol ip_proto,
59 struct net_context **context);
60
61 /**
62 * This function is called when user wants to bind to local IP address.
63 */
64 int (*bind)(struct net_context *context,
65 const struct sockaddr *addr,
66 socklen_t addrlen);
67
68 /**
69 * This function is called when user wants to mark the socket
70 * to be a listening one.
71 */
72 int (*listen)(struct net_context *context, int backlog);
73
74 /**
75 * This function is called when user wants to create a connection
76 * to a peer host.
77 */
78 int (*connect)(struct net_context *context,
79 const struct sockaddr *addr,
80 socklen_t addrlen,
81 net_context_connect_cb_t cb,
82 int32_t timeout,
83 void *user_data);
84
85 /**
86 * This function is called when user wants to accept a connection
87 * being established.
88 */
89 int (*accept)(struct net_context *context,
90 net_tcp_accept_cb_t cb,
91 int32_t timeout,
92 void *user_data);
93
94 /**
95 * This function is called when user wants to send data to peer host.
96 */
97 int (*send)(struct net_pkt *pkt,
98 net_context_send_cb_t cb,
99 int32_t timeout,
100 void *user_data);
101
102 /**
103 * This function is called when user wants to send data to peer host.
104 */
105 int (*sendto)(struct net_pkt *pkt,
106 const struct sockaddr *dst_addr,
107 socklen_t addrlen,
108 net_context_send_cb_t cb,
109 int32_t timeout,
110 void *user_data);
111
112 /**
113 * This function is called when user wants to receive data from peer
114 * host.
115 */
116 int (*recv)(struct net_context *context,
117 net_context_recv_cb_t cb,
118 int32_t timeout,
119 void *user_data);
120
121 /**
122 * This function is called when user wants to close the socket.
123 */
124 int (*put)(struct net_context *context);
125 };
126
127 /**
128 * @brief Get a network socket/context from the offloaded IP stack.
129 *
130 * @details Network socket is used to define the connection
131 * 5-tuple (protocol, remote address, remote port, source
132 * address and source port). This is similar as BSD socket()
133 * function.
134 *
135 * @param iface Network interface where the offloaded IP stack can be
136 * reached.
137 * @param family IP address family (AF_INET or AF_INET6)
138 * @param type Type of the socket, SOCK_STREAM or SOCK_DGRAM
139 * @param ip_proto IP protocol, IPPROTO_UDP or IPPROTO_TCP
140 * @param context The allocated context is returned to the caller.
141 *
142 * @return 0 if ok, < 0 if error
143 */
net_offload_get(struct net_if * iface,sa_family_t family,enum net_sock_type type,enum net_ip_protocol ip_proto,struct net_context ** context)144 static inline int net_offload_get(struct net_if *iface,
145 sa_family_t family,
146 enum net_sock_type type,
147 enum net_ip_protocol ip_proto,
148 struct net_context **context)
149 {
150 NET_ASSERT(iface);
151 NET_ASSERT(net_if_offload(iface));
152 NET_ASSERT(net_if_offload(iface)->get);
153
154 return net_if_offload(iface)->get(family, type, ip_proto, context);
155 }
156
157 /**
158 * @brief Assign a socket a local address.
159 *
160 * @details This is similar as BSD bind() function.
161 *
162 * @param iface Network interface where the offloaded IP stack can be
163 * reached.
164 * @param context The context to be assigned.
165 * @param addr Address to assigned.
166 * @param addrlen Length of the address.
167 *
168 * @return 0 if ok, < 0 if error
169 */
net_offload_bind(struct net_if * iface,struct net_context * context,const struct sockaddr * addr,socklen_t addrlen)170 static inline int net_offload_bind(struct net_if *iface,
171 struct net_context *context,
172 const struct sockaddr *addr,
173 socklen_t addrlen)
174 {
175 NET_ASSERT(iface);
176 NET_ASSERT(net_if_offload(iface));
177 NET_ASSERT(net_if_offload(iface)->bind);
178
179 return net_if_offload(iface)->bind(context, addr, addrlen);
180 }
181
182 /**
183 * @brief Mark the context as a listening one.
184 *
185 * @details This is similar as BSD listen() function.
186 *
187 * @param iface Network interface where the offloaded IP stack can be
188 * reached.
189 * @param context The context to use.
190 * @param backlog The size of the pending connections backlog.
191 *
192 * @return 0 if ok, < 0 if error
193 */
net_offload_listen(struct net_if * iface,struct net_context * context,int backlog)194 static inline int net_offload_listen(struct net_if *iface,
195 struct net_context *context,
196 int backlog)
197 {
198 NET_ASSERT(iface);
199 NET_ASSERT(net_if_offload(iface));
200 NET_ASSERT(net_if_offload(iface)->listen);
201
202 return net_if_offload(iface)->listen(context, backlog);
203 }
204
205 /**
206 * @brief Create a network connection.
207 *
208 * @details The net_context_connect function creates a network
209 * connection to the host specified by addr. After the
210 * connection is established, the user-supplied callback (cb)
211 * is executed. cb is called even if the timeout was set to
212 * K_FOREVER. cb is not called if the timeout expires.
213 * For datagram sockets (SOCK_DGRAM), this function only sets
214 * the peer address.
215 * This function is similar to the BSD connect() function.
216 *
217 * @param iface Network interface where the offloaded IP stack can be
218 * reached.
219 * @param context The network context.
220 * @param addr The peer address to connect to.
221 * @param addrlen Peer address length.
222 * @param cb Callback function. Set to NULL if not required.
223 * @param timeout The timeout value for the connection. Possible values:
224 * * K_NO_WAIT: this function will return immediately,
225 * * K_FOREVER: this function will block until the
226 * connection is established,
227 * * >0: this function will wait the specified ms.
228 * @param user_data Data passed to the callback function.
229 *
230 * @return 0 on success.
231 * @return -EINVAL if an invalid parameter is passed as an argument.
232 * @return -ENOTSUP if the operation is not supported or implemented.
233 */
net_offload_connect(struct net_if * iface,struct net_context * context,const struct sockaddr * addr,socklen_t addrlen,net_context_connect_cb_t cb,k_timeout_t timeout,void * user_data)234 static inline int net_offload_connect(struct net_if *iface,
235 struct net_context *context,
236 const struct sockaddr *addr,
237 socklen_t addrlen,
238 net_context_connect_cb_t cb,
239 k_timeout_t timeout,
240 void *user_data)
241 {
242 NET_ASSERT(iface);
243 NET_ASSERT(net_if_offload(iface));
244 NET_ASSERT(net_if_offload(iface)->connect);
245
246 return net_if_offload(iface)->connect(
247 context, addr, addrlen, cb,
248 timeout_to_int32(timeout),
249 user_data);
250 }
251
252 /**
253 * @brief Accept a network connection attempt.
254 *
255 * @details Accept a connection being established. This function
256 * will return immediately if the timeout is set to K_NO_WAIT.
257 * In this case the context will call the supplied callback when ever
258 * there is a connection established to this context. This is "a register
259 * handler and forget" type of call (async).
260 * If the timeout is set to K_FOREVER, the function will wait
261 * until the connection is established. Timeout value > 0, will wait as
262 * many ms.
263 * After the connection is established a caller-supplied callback is called.
264 * The callback is called even if timeout was set to K_FOREVER, the
265 * callback is called before this function will return in this case.
266 * The callback is not called if the timeout expires.
267 * This is similar as BSD accept() function.
268 *
269 * @param iface Network interface where the offloaded IP stack can be
270 * reached.
271 * @param context The context to use.
272 * @param cb Caller-supplied callback function.
273 * @param timeout Timeout for the connection. Possible values
274 * are K_FOREVER, K_NO_WAIT, >0.
275 * @param user_data Caller-supplied user data.
276 *
277 * @return 0 if ok, < 0 if error
278 */
net_offload_accept(struct net_if * iface,struct net_context * context,net_tcp_accept_cb_t cb,k_timeout_t timeout,void * user_data)279 static inline int net_offload_accept(struct net_if *iface,
280 struct net_context *context,
281 net_tcp_accept_cb_t cb,
282 k_timeout_t timeout,
283 void *user_data)
284 {
285 NET_ASSERT(iface);
286 NET_ASSERT(net_if_offload(iface));
287 NET_ASSERT(net_if_offload(iface)->accept);
288
289 return net_if_offload(iface)->accept(
290 context, cb,
291 timeout_to_int32(timeout),
292 user_data);
293 }
294
295 /**
296 * @brief Send a network packet to a peer.
297 *
298 * @details This function can be used to send network data to a peer
299 * connection. This function will return immediately if the timeout
300 * is set to K_NO_WAIT. If the timeout is set to K_FOREVER, the function
301 * will wait until the network packet is sent. Timeout value > 0 will
302 * wait as many ms. After the network packet is sent,
303 * a caller-supplied callback is called. The callback is called even
304 * if timeout was set to K_FOREVER, the callback is called
305 * before this function will return in this case. The callback is not
306 * called if the timeout expires. For context of type SOCK_DGRAM,
307 * the destination address must have been set by the call to
308 * net_context_connect().
309 * This is similar as BSD send() function.
310 *
311 * @param iface Network interface where the offloaded IP stack can be
312 * reached.
313 * @param pkt The network packet to send.
314 * @param cb Caller-supplied callback function.
315 * @param timeout Timeout for the connection. Possible values
316 * are K_FOREVER, K_NO_WAIT, >0.
317 * @param user_data Caller-supplied user data.
318 *
319 * @return 0 if ok, < 0 if error
320 */
net_offload_send(struct net_if * iface,struct net_pkt * pkt,net_context_send_cb_t cb,k_timeout_t timeout,void * user_data)321 static inline int net_offload_send(struct net_if *iface,
322 struct net_pkt *pkt,
323 net_context_send_cb_t cb,
324 k_timeout_t timeout,
325 void *user_data)
326 {
327 NET_ASSERT(iface);
328 NET_ASSERT(net_if_offload(iface));
329 NET_ASSERT(net_if_offload(iface)->send);
330
331 return net_if_offload(iface)->send(
332 pkt, cb,
333 timeout_to_int32(timeout),
334 user_data);
335 }
336
337 /**
338 * @brief Send a network packet to a peer specified by address.
339 *
340 * @details This function can be used to send network data to a peer
341 * specified by address. This variant can only be used for datagram
342 * connections of type SOCK_DGRAM. This function will return immediately
343 * if the timeout is set to K_NO_WAIT. If the timeout is set to K_FOREVER,
344 * the function will wait until the network packet is sent. Timeout
345 * value > 0 will wait as many ms. After the network packet
346 * is sent, a caller-supplied callback is called. The callback is called
347 * even if timeout was set to K_FOREVER, the callback is called
348 * before this function will return. The callback is not called if the
349 * timeout expires.
350 * This is similar as BSD sendto() function.
351 *
352 * @param iface Network interface where the offloaded IP stack can be
353 * reached.
354 * @param pkt The network packet to send.
355 * @param dst_addr Destination address. This will override the address
356 * already set in network packet.
357 * @param addrlen Length of the address.
358 * @param cb Caller-supplied callback function.
359 * @param timeout Timeout for the connection. Possible values
360 * are K_FOREVER, K_NO_WAIT, >0.
361 * @param user_data Caller-supplied user data.
362 *
363 * @return 0 if ok, < 0 if error
364 */
net_offload_sendto(struct net_if * iface,struct net_pkt * pkt,const struct sockaddr * dst_addr,socklen_t addrlen,net_context_send_cb_t cb,k_timeout_t timeout,void * user_data)365 static inline int net_offload_sendto(struct net_if *iface,
366 struct net_pkt *pkt,
367 const struct sockaddr *dst_addr,
368 socklen_t addrlen,
369 net_context_send_cb_t cb,
370 k_timeout_t timeout,
371 void *user_data)
372 {
373 NET_ASSERT(iface);
374 NET_ASSERT(net_if_offload(iface));
375 NET_ASSERT(net_if_offload(iface)->sendto);
376
377 return net_if_offload(iface)->sendto(
378 pkt, dst_addr, addrlen, cb,
379 timeout_to_int32(timeout),
380 user_data);
381 }
382
383 /**
384 * @brief Receive network data from a peer specified by context.
385 *
386 * @details This function can be used to register a callback function
387 * that is called by the network stack when network data has been received
388 * for this context. As this function registers a callback, then there
389 * is no need to call this function multiple times if timeout is set to
390 * K_NO_WAIT.
391 * If callback function or user data changes, then the function can be called
392 * multiple times to register new values.
393 * This function will return immediately if the timeout is set to K_NO_WAIT.
394 * If the timeout is set to K_FOREVER, the function will wait until the
395 * network packet is received. Timeout value > 0 will wait as many ms.
396 * After the network packet is received, a caller-supplied callback is
397 * called. The callback is called even if timeout was set to K_FOREVER,
398 * the callback is called before this function will return in this case.
399 * The callback is not called if the timeout expires. The timeout functionality
400 * can be compiled out if synchronous behavior is not needed. The sync call
401 * logic requires some memory that can be saved if only async way of call is
402 * used. If CONFIG_NET_CONTEXT_SYNC_RECV is not set, then the timeout parameter
403 * value is ignored.
404 * This is similar as BSD recv() function.
405 *
406 * @param iface Network interface where the offloaded IP stack can be
407 * reached.
408 * @param context The network context to use.
409 * @param cb Caller-supplied callback function.
410 * @param timeout Caller-supplied timeout. Possible values
411 * are K_FOREVER, K_NO_WAIT, >0.
412 * @param user_data Caller-supplied user data.
413 *
414 * @return 0 if ok, < 0 if error
415 */
net_offload_recv(struct net_if * iface,struct net_context * context,net_context_recv_cb_t cb,k_timeout_t timeout,void * user_data)416 static inline int net_offload_recv(struct net_if *iface,
417 struct net_context *context,
418 net_context_recv_cb_t cb,
419 k_timeout_t timeout,
420 void *user_data)
421 {
422 NET_ASSERT(iface);
423 NET_ASSERT(net_if_offload(iface));
424 NET_ASSERT(net_if_offload(iface)->recv);
425
426 return net_if_offload(iface)->recv(
427 context, cb,
428 timeout_to_int32(timeout),
429 user_data);
430 }
431
432 /**
433 * @brief Free/close a network context.
434 *
435 * @details This releases the context. It is not possible to
436 * send or receive data via this context after this call.
437 * This is similar as BSD shutdown() function.
438 *
439 * @param iface Network interface where the offloaded IP stack can be
440 * reached.
441 * @param context The context to be closed.
442 *
443 * @return 0 if ok, < 0 if error
444 */
net_offload_put(struct net_if * iface,struct net_context * context)445 static inline int net_offload_put(struct net_if *iface,
446 struct net_context *context)
447 {
448 NET_ASSERT(iface);
449 NET_ASSERT(net_if_offload(iface));
450 NET_ASSERT(net_if_offload(iface)->put);
451
452 return net_if_offload(iface)->put(context);
453 }
454
455 #else
456
457 /** @cond INTERNAL_HIDDEN */
458
459 static inline int net_offload_get(struct net_if *iface,
460 sa_family_t family,
461 enum net_sock_type type,
462 enum net_ip_protocol ip_proto,
463 struct net_context **context)
464 {
465 return 0;
466 }
467
468 static inline int net_offload_bind(struct net_if *iface,
469 struct net_context *context,
470 const struct sockaddr *addr,
471 socklen_t addrlen)
472 {
473 return 0;
474 }
475
476 static inline int net_offload_listen(struct net_if *iface,
477 struct net_context *context,
478 int backlog)
479 {
480 return 0;
481 }
482
483 static inline int net_offload_connect(struct net_if *iface,
484 struct net_context *context,
485 const struct sockaddr *addr,
486 socklen_t addrlen,
487 net_context_connect_cb_t cb,
488 k_timeout_t timeout,
489 void *user_data)
490 {
491 return 0;
492 }
493
494 static inline int net_offload_accept(struct net_if *iface,
495 struct net_context *context,
496 net_tcp_accept_cb_t cb,
497 k_timeout_t timeout,
498 void *user_data)
499 {
500 return 0;
501 }
502
503 static inline int net_offload_send(struct net_if *iface,
504 struct net_pkt *pkt,
505 net_context_send_cb_t cb,
506 k_timeout_t timeout,
507 void *user_data)
508 {
509 return 0;
510 }
511
512 static inline int net_offload_sendto(struct net_if *iface,
513 struct net_pkt *pkt,
514 const struct sockaddr *dst_addr,
515 socklen_t addrlen,
516 net_context_send_cb_t cb,
517 k_timeout_t timeout,
518 void *user_data)
519 {
520 return 0;
521 }
522
523 static inline int net_offload_recv(struct net_if *iface,
524 struct net_context *context,
525 net_context_recv_cb_t cb,
526 k_timeout_t timeout,
527 void *user_data)
528 {
529 return 0;
530 }
531
532 static inline int net_offload_put(struct net_if *iface,
533 struct net_context *context)
534 {
535 return 0;
536 }
537
538 /** @endcond */
539
540 #endif /* CONFIG_NET_OFFLOAD */
541
542 #ifdef __cplusplus
543 }
544 #endif
545
546 /**
547 * @}
548 */
549
550 #endif /* ZEPHYR_INCLUDE_NET_NET_OFFLOAD_H_ */
551