mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-08-29 03:36:29 +00:00
IP packet passing through 6lowpan compression and 802.15.4 fragmentation has an issue. (RFC 6282 and 4944) RFC4944, 5.3 says "fragment header's datagram_size and datagram_offset values as the size and offset of the IPv6 datagram before compression". At the moment datagram size and offset values are after compression. Due to multiple bearer (15.4 and bluetooth) support and multiple incoming buffers support functionality is divided to compression and fragmentation parts. And datagram size and offset values for BT are after compression. Small packet (which doesn't need fragmentation) doesn't go through this. So cacheing compressed and uncompressed header lengths and with hdr difference preparing fragments as per original buffer (total buf size and offset). Change-Id: I9d3b0433e64964c68519d7c007cc06ec6035b573 Jira: ZEP-208 Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@linux.intel.com>
403 lines
12 KiB
C
403 lines
12 KiB
C
/** @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;
|
|
#if defined(CONFIG_NETWORKING_WITH_TCP)
|
|
int8_t sent_status; /* tells if the TCP packet was sent ok or not */
|
|
uint8_t tcp_retry_count;
|
|
#endif
|
|
|
|
/* 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;
|
|
|
|
/* 6lowpan specific vars */
|
|
uint8_t compressed_hdr_len;
|
|
uint8_t uncompressed_hdr_len;
|
|
uint8_t first_frag_len;
|
|
uint8_t uncompressed;
|
|
/* @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)
|
|
#define uip_compressed_hdr_len(buf) \
|
|
(((struct ip_buf *)net_buf_user_data((buf)))->compressed_hdr_len)
|
|
#define uip_uncompressed_hdr_len(buf) \
|
|
(((struct ip_buf *)net_buf_user_data((buf)))->uncompressed_hdr_len)
|
|
#define uip_first_frag_len(buf) \
|
|
(((struct ip_buf *)net_buf_user_data((buf)))->first_frag_len)
|
|
#define uip_uncompressed(buf) \
|
|
(((struct ip_buf *)net_buf_user_data((buf)))->uncompressed)
|
|
|
|
/* 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)
|
|
#define ip_buf_sent_status(ptr) (((struct ip_buf *)net_buf_user_data((ptr)))->sent_status)
|
|
#define ip_buf_tcp_retry_count(ptr) (((struct ip_buf *)net_buf_user_data((ptr)))->tcp_retry_count)
|
|
/* @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
|
|
|
|
/**
|
|
* @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 DEBUG_IP_BUFS
|
|
#define ip_buf_ref(buf) ip_buf_ref_debug(buf, __func__, __LINE__)
|
|
struct net_buf *ip_buf_ref_debug(struct net_buf *buf, const char *caller, int line);
|
|
#else
|
|
struct net_buf *ip_buf_ref(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 */
|