| /** @file |
| * @brief Network buffer API |
| * |
| * Network data is passed between different parts of the stack via |
| * net_buf struct. |
| */ |
| |
| /* |
| * Copyright (c) 2016 Intel Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* Data buffer API - used for all data to/from net */ |
| |
| #ifndef __NBUF_H |
| #define __NBUF_H |
| |
| #include <stdint.h> |
| #include <stdbool.h> |
| |
| #include <net/buf.h> |
| |
| #if defined(CONFIG_NETWORK_IP_STACK_DEBUG_NET_BUF) |
| #undef NET_DEBUG_NBUFS |
| #define NET_DEBUG_NBUFS 1 |
| #if !defined(NET_DEBUG) |
| #define NET_DEBUG 1 |
| #endif |
| #endif |
| |
| #include <net/net_core.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #if defined(NET_DEBUG_NBUFS) |
| #define NET_BUF_CHECK_IF_IN_USE(buf, ref) \ |
| do { \ |
| if (ref) { \ |
| NET_ERR("**ERROR** buf %p in use (%s:%s():%d)", \ |
| buf, __FILE__, __func__, __LINE__); \ |
| } \ |
| } while (0) |
| |
| #define NET_BUF_CHECK_IF_NOT_IN_USE(buf, ref) \ |
| do { \ |
| if (!(ref)) { \ |
| NET_ERR("**ERROR** buf %p not in use (%s:%s():%d)", \ |
| buf, __FILE__, __func__, __LINE__); \ |
| } \ |
| } while (0) |
| #else |
| #define NET_BUF_CHECK_IF_IN_USE(buf, ref) |
| #define NET_BUF_CHECK_IF_NOT_IN_USE(buf, ref) |
| #endif |
| |
| struct net_context; |
| |
| /** @cond ignore */ |
| enum net_nbuf_type { |
| NET_NBUF_RX = 0, |
| NET_NBUF_TX = 1, |
| NET_NBUF_DATA = 2, |
| }; |
| /** @endcond */ |
| |
| /** Note that the buf len is usually smaller that the minimum IPv6 MTU 1280 |
| * bytes. The default MTU is 1280 (minimum IPv6 packet size) + LL header |
| * In Contiki terms this is UIP_LINK_MTU + UIP_LLH_LEN = UIP_BUFSIZE |
| * |
| * Contiki assumes that this value is UIP_BUFSIZE so do not change it |
| * without changing the value of UIP_BUFSIZE! |
| */ |
| #if defined(CONFIG_NET_BUF_MAX_DATA) |
| #define NBUF_MAX_DATA CONFIG_NET_BUF_MAX_DATA |
| #else |
| #define NBUF_MAX_DATA 128 |
| #endif |
| |
| struct net_nbuf { |
| /** @cond ignore */ |
| enum net_nbuf_type type; |
| uint16_t reserve; /* length of the protocol headers */ |
| uint8_t ll_reserve; /* link layer header length */ |
| uint8_t family; /* IPv4 vs IPv6 */ |
| uint8_t ip_hdr_len; /* pre-filled in order to avoid func call */ |
| uint8_t ext_len; /* length of extension headers */ |
| uint8_t ext_bitmap; |
| uint8_t *next_hdr; |
| /* @endcond */ |
| |
| /** Network connection context */ |
| struct net_context *context; |
| |
| /** Network interface */ |
| struct net_if *iface; |
| |
| /** @cond ignore */ |
| uint8_t *appdata; /* application data */ |
| uint16_t appdatalen; |
| /* @endcond */ |
| }; |
| |
| /** @cond ignore */ |
| |
| /* Value returned by nbuf_len() contains length of all the protocol headers, |
| * like IP and UDP, and the length of the user payload. |
| */ |
| #define net_nbuf_len(buf) ((buf)->len) |
| |
| /* This returns pointer to start of the protocol IP header */ |
| #define net_nbuf_ip_data(buf) ((buf)->frags->data) |
| #define net_nbuf_udp_data(buf) (&(buf)->frags->data[net_nbuf_ip_hdr_len(buf)]) |
| #define net_nbuf_tcp_data(buf) (&(buf)->frags->data[net_nbuf_ip_hdr_len(buf)]) |
| #define net_nbuf_icmp_data(buf) (&(buf)->frags->data[net_nbuf_ip_hdr_len(buf) +\ |
| net_nbuf_ext_len(buf)]) |
| |
| /* These two return only the application data length without |
| * IP and other protocol header length. |
| */ |
| #define net_nbuf_appdata(buf) (((struct net_nbuf *) \ |
| net_buf_user_data((buf)))->appdata) |
| #define net_nbuf_appdatalen(buf) (((struct net_nbuf *) \ |
| net_buf_user_data((buf)))->appdatalen) |
| #define net_nbuf_reserve(buf) (((struct net_nbuf *) \ |
| net_buf_user_data((buf)))->reserve) |
| #define net_nbuf_ll_reserve(buf) (((struct net_nbuf *) \ |
| net_buf_user_data((buf)))->ll_reserve) |
| #define net_nbuf_ll(buf) (net_nbuf_ip_data(buf) - net_nbuf_ll_reserve(buf)) |
| |
| #define net_nbuf_ll_src(buf) \ |
| (((struct net_nbuf *)net_buf_user_data((buf)))->src) |
| #define net_nbuf_ll_dest(buf) \ |
| (((struct net_nbuf *)net_buf_user_data((buf)))->dest) |
| #define net_nbuf_context(buf) \ |
| (((struct net_nbuf *)net_buf_user_data((buf)))->context) |
| #define net_nbuf_iface(buf) \ |
| (((struct net_nbuf *)net_buf_user_data((buf)))->iface) |
| #define net_nbuf_type(ptr) (((struct net_nbuf *)net_buf_user_data((ptr)))->type) |
| #define net_nbuf_family(ptr) (((struct net_nbuf *) \ |
| net_buf_user_data((ptr)))->family) |
| #define net_nbuf_ip_hdr_len(buf) (((struct net_nbuf *) \ |
| net_buf_user_data((buf)))->ip_hdr_len) |
| #define net_nbuf_ext_len(buf) \ |
| (((struct net_nbuf *)net_buf_user_data((buf)))->ext_len) |
| #define net_nbuf_ext_bitmap(buf) \ |
| (((struct net_nbuf *)net_buf_user_data((buf)))->ext_bitmap) |
| #define net_nbuf_next_hdr(buf) \ |
| (((struct net_nbuf *)net_buf_user_data((buf)))->next_hdr) |
| |
| #define NET_IPV6_BUF(buf) ((struct net_ipv6_hdr *)net_nbuf_ip_data(buf)) |
| #define NET_IPV4_BUF(buf) ((struct net_ipv4_hdr *)net_nbuf_ip_data(buf)) |
| #define NET_ICMP_BUF(buf) ((struct net_icmp_hdr *)net_nbuf_icmp_data(buf)) |
| |
| #define net_nbuf_set_src_ipv6_addr(buf) \ |
| net_if_select_src(net_context_get_if(nbuf_context(buf)), \ |
| &NET_IPV6_BUF(buf)->src, \ |
| &NET_IPV6_BUF(buf)->dst) |
| /* @endcond */ |
| |
| /** |
| * @brief Get buffer from the available buffers pool. |
| * |
| * @details Get network buffer from buffer pool. You must have |
| * network context before able to use this function. |
| * |
| * @param context Network context that will be related to |
| * this buffer. |
| * |
| * @return Network buffer if successful, NULL otherwise. |
| */ |
| /* Get buffer from the available buffers pool */ |
| #if defined(NET_DEBUG_NBUFS) |
| #define net_nbuf_get_rx(context) net_nbuf_get_rx_debug(context, __func__, __LINE__) |
| #define net_nbuf_get_tx(context) net_nbuf_get_tx_debug(context, __func__, __LINE__) |
| #define net_nbuf_get_data(context) net_nbuf_get_data_debug(context, __func__, __LINE__) |
| struct net_buf *net_nbuf_get_rx_debug(struct net_context *context, |
| const char *caller, int line); |
| struct net_buf *net_nbuf_get_tx_debug(struct net_context *context, |
| const char *caller, int line); |
| struct net_buf *net_nbuf_get_data_debug(struct net_context *context, |
| const char *caller, int line); |
| #else |
| struct net_buf *net_nbuf_get_rx(struct net_context *context); |
| struct net_buf *net_nbuf_get_tx(struct net_context *context); |
| struct net_buf *net_nbuf_get_data(struct net_context *context); |
| #endif |
| |
| /** |
| * @brief Get buffer from pool but also reserve headroom for |
| * potential headers. |
| * |
| * @details Normally this version is not useful for applications |
| * but is mainly used by network fragmentation code. |
| * |
| * @param reserve_head How many bytes to reserve for headroom. |
| * |
| * @return Network buffer if successful, NULL otherwise. |
| */ |
| /* Same as net_buf_get, but also reserve headroom for potential headers */ |
| #if defined(NET_DEBUG_NBUFS) |
| #define net_nbuf_get_reserve_rx(res) net_nbuf_get_reserve_rx_debug(res, \ |
| __func__, \ |
| __LINE__) |
| #define net_nbuf_get_reserve_tx(res) net_nbuf_get_reserve_tx_debug(res, \ |
| __func__, \ |
| __LINE__) |
| #define net_nbuf_get_reserve_data(res) net_nbuf_get_reserve_data_debug(res, \ |
| __func__, \ |
| __LINE__) |
| struct net_buf *net_nbuf_get_reserve_rx_debug(uint16_t reserve_head, |
| const char *caller, int line); |
| struct net_buf *net_nbuf_get_reserve_tx_debug(uint16_t reserve_head, |
| const char *caller, int line); |
| struct net_buf *net_nbuf_get_reserve_data_debug(uint16_t reserve_head, |
| const char *caller, int line); |
| #else |
| struct net_buf *net_nbuf_get_reserve_rx(uint16_t reserve_head); |
| struct net_buf *net_nbuf_get_reserve_tx(uint16_t reserve_head); |
| struct net_buf *net_nbuf_get_reserve_data(uint16_t reserve_head); |
| #endif |
| |
| /** |
| * @brief Place buffer back into the available buffers pool. |
| * |
| * @details Releases the buffer to other use. This needs to be |
| * called by application after it has finished with |
| * the buffer. |
| * |
| * @param buf Network buffer to release. |
| * |
| */ |
| #ifdef NET_DEBUG_NBUFS |
| #define net_nbuf_unref(buf) net_nbuf_unref_debug(buf, __func__, __LINE__) |
| void net_nbuf_unref_debug(struct net_buf *buf, const char *caller, int line); |
| #else |
| void net_nbuf_unref(struct net_buf *buf); |
| #endif |
| |
| /** |
| * @brief Increase the ref count |
| * |
| * @details Mark the buffer to be used still. |
| * |
| * @param buf Network buffer to ref. |
| * |
| * @return Network buffer if successful, NULL otherwise. |
| */ |
| #ifdef NET_DEBUG_NBUFS |
| #define net_nbuf_ref(buf) net_nbuf_ref_debug(buf, __func__, __LINE__) |
| struct net_buf *net_nbuf_ref_debug(struct net_buf *buf, const char *caller, int line); |
| #else |
| struct net_buf *net_nbuf_ref(struct net_buf *buf); |
| #endif |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* __NBUF_H */ |