blob: da0cc3ca3f2a8736643a7b62f7c1f53f9a01bbbf [file] [log] [blame]
/** @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 */