273 lines
8.6 KiB
C
273 lines
8.6 KiB
C
/** @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 */
|