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