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