| /** @file |
| * @brief IP buffer API |
| * |
| * IP data is passed between application and IP stack via a ip_buf struct. |
| */ |
| |
| /* |
| * Copyright (c) 2015 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 __IP_BUF_H |
| #define __IP_BUF_H |
| |
| #include <stdint.h> |
| #include <stdbool.h> |
| |
| #include <net/net_core.h> |
| |
| #include "contiki/ip/uipopt.h" |
| #include "contiki/ip/uip.h" |
| #include "contiki/packetbuf.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #ifdef CONFIG_NETWORKING_WITH_LOGGING |
| #undef DEBUG_IP_BUFS |
| #define DEBUG_IP_BUFS |
| #endif |
| |
| #ifdef DEBUG_IP_BUFS |
| #define NET_BUF_CHECK_IF_IN_USE(buf) \ |
| do { \ |
| if (buf->ref) { \ |
| NET_ERR("**ERROR** buf %p in use (%s:%s():%d)\n", \ |
| buf, __FILE__, __func__, __LINE__); \ |
| } \ |
| } while (0) |
| |
| #define NET_BUF_CHECK_IF_NOT_IN_USE(buf) \ |
| do { \ |
| if (!buf->ref) { \ |
| NET_ERR("**ERROR** buf %p not in use (%s:%s():%d)\n",\ |
| buf, __FILE__, __func__, __LINE__); \ |
| } \ |
| } while (0) |
| #else |
| #define NET_BUF_CHECK_IF_IN_USE(buf) |
| #define NET_BUF_CHECK_IF_NOT_IN_USE(buf) |
| #endif |
| |
| struct net_context; |
| |
| /** @cond ignore */ |
| enum ip_buf_type { |
| IP_BUF_RX = 0, |
| IP_BUF_TX = 1, |
| }; |
| /** @endcond */ |
| |
| /** 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! |
| */ |
| #define IP_BUF_MAX_DATA UIP_BUFSIZE |
| |
| struct ip_buf { |
| /** @cond ignore */ |
| enum ip_buf_type type; |
| uint16_t reserve; /* length of the protocol headers */ |
| /* @endcond */ |
| |
| /** Network connection context */ |
| struct net_context *context; |
| |
| /** @cond ignore */ |
| /* uIP stack specific data */ |
| uint16_t len; /* Contiki will set this to 0 if packet is discarded */ |
| uint8_t uip_ext_len; |
| uint8_t uip_ext_bitmap; |
| uint8_t uip_ext_opt_offset; |
| uint8_t uip_flags; |
| uint16_t uip_slen; |
| uint16_t uip_appdatalen; |
| uint8_t *uip_next_hdr; |
| void *uip_appdata; /* application data */ |
| void *uip_sappdata; /* app data to be sent */ |
| void *uip_conn; |
| void *uip_udp_conn; |
| linkaddr_t dest; |
| linkaddr_t src; |
| |
| /* Neighbor discovery vars. Note that we are using void pointers here |
| * so that we do not need to include Contiki headers in this file. |
| */ |
| void *nd6_opt_prefix_info; |
| void *nd6_prefix; |
| void *nd6_nbr; |
| void *nd6_defrt; |
| void *nd6_ifaddr; |
| uint8_t *nd6_opt_llao; |
| uip_ipaddr_t ipaddr; |
| uint8_t nd6_opt_offset; |
| /* @endcond */ |
| }; |
| |
| /** @cond ignore */ |
| /* Value returned by ip_buf_len() contains length of all the protocol headers, |
| * like IP and UDP, and the length of the user payload. |
| */ |
| #define ip_buf_len(buf) ((buf)->len) |
| |
| /* Macros to access net_buf when inside Contiki stack */ |
| #define uip_buf(buf) ((buf)->data) |
| #define uip_len(buf) (((struct ip_buf *)net_buf_user_data((buf)))->len) |
| #define uip_slen(buf) (((struct ip_buf *)net_buf_user_data((buf)))->uip_slen) |
| #define uip_ext_len(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->uip_ext_len) |
| #define uip_ext_bitmap(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->uip_ext_bitmap) |
| #define uip_ext_opt_offset(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->uip_ext_opt_offset) |
| #define uip_nd6_opt_offset(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->nd6_opt_offset) |
| #define uip_next_hdr(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->uip_next_hdr) |
| #define uip_appdata(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->uip_appdata) |
| #define uip_appdatalen(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->uip_appdatalen) |
| #define uip_sappdata(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->uip_sappdata) |
| #define uip_flags(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->uip_flags) |
| #define uip_conn(buf) \ |
| ((struct uip_conn *) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->uip_conn)) |
| #define uip_set_conn(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->uip_conn) |
| #define uip_udp_conn(buf) \ |
| ((struct uip_udp_conn *) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->uip_udp_conn)) |
| #define uip_set_udp_conn(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->uip_udp_conn) |
| #define uip_nd6_opt_prefix_info(buf) \ |
| ((uip_nd6_opt_prefix_info *) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->nd6_opt_prefix_info)) |
| #define uip_set_nd6_opt_prefix_info(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->nd6_opt_prefix_info) |
| #define uip_prefix(buf) \ |
| ((uip_ds6_prefix_t *) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->nd6_prefix)) |
| #define uip_set_prefix(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->nd6_prefix) |
| #define uip_nbr(buf) \ |
| ((uip_ds6_nbr_t *) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->nd6_nbr)) |
| #define uip_set_nbr(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->nd6_nbr) |
| #define uip_defrt(buf) \ |
| ((uip_ds6_defrt_t *) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->nd6_defrt)) |
| #define uip_set_defrt(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->nd6_defrt) |
| #define uip_addr(buf) \ |
| ((uip_ds6_addr_t *) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->nd6_ifaddr)) |
| #define uip_set_addr(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->nd6_ifaddr) |
| #define uip_nd6_opt_llao(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->nd6_opt_llao) |
| #define uip_set_nd6_opt_llao(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->nd6_opt_llao) |
| #define uip_nd6_ipaddr(buf) \ |
| (((struct ip_buf *)net_buf_user_data((buf)))->ipaddr) |
| |
| /* These two return only the application data and length without |
| * IP and UDP header length. |
| */ |
| #define ip_buf_appdata(buf) uip_appdata(buf) |
| #define ip_buf_appdatalen(buf) uip_appdatalen(buf) |
| #define ip_buf_reserve(buf) (((struct ip_buf *) \ |
| net_buf_user_data((buf)))->reserve) |
| |
| #define ip_buf_ll_src(buf) (((struct ip_buf *)net_buf_user_data((buf)))->src) |
| #define ip_buf_ll_dest(buf) (((struct ip_buf *)net_buf_user_data((buf)))->dest) |
| #define ip_buf_context(buf) (((struct ip_buf *)net_buf_user_data((buf)))->context) |
| #define ip_buf_type(ptr) (((struct ip_buf *)net_buf_user_data((ptr)))->type) |
| /* @endcond */ |
| |
| /** NET_BUF_IP |
| * |
| * @brief This macro returns IP header information struct stored in net_buf. |
| * |
| * @details The macro returns pointer to uip_ip_hdr struct which |
| * contains IP header information. |
| * |
| * @param buf Network buffer. |
| * |
| * @return Pointer to uip_ip_hdr. |
| */ |
| #define NET_BUF_IP(buf) ((struct uip_ip_hdr *)&uip_buf(buf)[UIP_LLH_LEN]) |
| |
| /** NET_BUF_UDP |
| * |
| * @brief This macro returns UDP header information struct stored in net_buf. |
| * |
| * @details The macro returns pointer to uip_udp_hdr struct which |
| * contains UDP header information. |
| * |
| * @param buf Network buffer. |
| * |
| * @return Pointer to uip_ip_hdr. |
| */ |
| #define NET_BUF_UDP(buf) ((struct uip_udp_hdr *)&uip_buf(buf)[UIP_LLIPH_LEN]) |
| |
| /** |
| * @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 */ |
| #ifdef DEBUG_IP_BUFS |
| #define ip_buf_get_rx(context) ip_buf_get_rx_debug(context, __func__, __LINE__) |
| #define ip_buf_get_tx(context) ip_buf_get_tx_debug(context, __func__, __LINE__) |
| struct net_buf *ip_buf_get_rx_debug(struct net_context *context, |
| const char *caller, int line); |
| struct net_buf *ip_buf_get_tx_debug(struct net_context *context, |
| const char *caller, int line); |
| #else |
| struct net_buf *ip_buf_get_rx(struct net_context *context); |
| struct net_buf *ip_buf_get_tx(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 */ |
| #ifdef DEBUG_IP_BUFS |
| #define ip_buf_get_reserve_rx(res) ip_buf_get_reserve_rx_debug(res, \ |
| __func__, \ |
| __LINE__) |
| #define ip_buf_get_reserve_tx(res) ip_buf_get_reserve_tx_debug(res, \ |
| __func__, \ |
| __LINE__) |
| struct net_buf *ip_buf_get_reserve_rx_debug(uint16_t reserve_head, |
| const char *caller, int line); |
| struct net_buf *ip_buf_get_reserve_tx_debug(uint16_t reserve_head, |
| const char *caller, int line); |
| #else |
| struct net_buf *ip_buf_get_reserve_rx(uint16_t reserve_head); |
| struct net_buf *ip_buf_get_reserve_tx(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 DEBUG_IP_BUFS |
| #define ip_buf_unref(buf) ip_buf_unref_debug(buf, __func__, __LINE__) |
| void ip_buf_unref_debug(struct net_buf *buf, const char *caller, int line); |
| #else |
| void ip_buf_unref(struct net_buf *buf); |
| #endif |
| |
| /** @cond ignore */ |
| void ip_buf_init(void); |
| /* @endcond */ |
| |
| /** @cond ignore */ |
| #if defined(CONFIG_INIT_STACKS) && defined(CONFIG_PRINTK) |
| #include <offsets.h> |
| #include <misc/printk.h> |
| |
| static inline void net_analyze_stack(const char *name, |
| unsigned char *stack, |
| size_t size) |
| { |
| unsigned i, stack_offset, pcnt, unused = 0; |
| |
| /* The TCS is always placed on a 4-byte aligned boundary - if |
| * the stack beginning doesn't match that there will be some |
| * unused bytes in the beginning. |
| */ |
| stack_offset = __tTCS_SIZEOF + ((4 - ((unsigned)stack % 4)) % 4); |
| |
| /* TODO |
| * Currently all supported platforms have stack growth down and there is no |
| * Kconfig option to configure it so this always build "else" branch. |
| * When support for platform with stack direction up (or configurable direction) |
| * is added this check should be confirmed that correct Kconfig option is used. |
| */ |
| #if defined(CONFIG_STACK_GROWS_UP) |
| for (i = size - 1; i >= stack_offset; i--) { |
| if ((unsigned char)stack[i] == 0xaa) { |
| unused++; |
| } else { |
| break; |
| } |
| } |
| #else |
| for (i = stack_offset; i < size; i++) { |
| if ((unsigned char)stack[i] == 0xaa) { |
| unused++; |
| } else { |
| break; |
| } |
| } |
| #endif |
| |
| /* Calculate the real size reserved for the stack */ |
| size -= stack_offset; |
| pcnt = ((size - unused) * 100) / size; |
| |
| printk("net (%p): %s stack real size %u " |
| "unused %u usage %u/%u (%u %%)\n", |
| sys_thread_self_get(), name, |
| size + stack_offset, unused, size - unused, size, pcnt); |
| } |
| #else |
| #define net_analyze_stack(...) |
| #endif |
| /* @endcond */ |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* __IP_BUF_H */ |