Boot Linux faster!

Check our new training course

Boot Linux faster!

Check our new training course
and Creative Commons CC-BY-SA
lecture and lab materials

Bootlin logo

Elixir Cross Referencer

/** @file
 * @brief L2 buffer API
 *
 * L2 (layer 2 or MAC layer) data is passed between application and
 * IP stack via a l2_buf struct. Currently L2 buffers are only used
 * in IEEE 802.15.4 code.
 */

/*
 * 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 __L2_BUF_H
#define __L2_BUF_H

#include <stdint.h>

#include <net/ip_buf.h>

#include "contiki/ip/uipopt.h"
#include "contiki/ip/uip.h"
#include "contiki/packetbuf.h"
#include "contiki/os/lib/list.h"

#ifdef __cplusplus
extern "C" {
#endif

#if defined(CONFIG_L2_BUFFERS)

#ifdef CONFIG_NETWORKING_WITH_LOGGING
#undef DEBUG_L2_BUFS
#define DEBUG_L2_BUFS
#endif

/** @cond ignore */
void l2_buf_init(void);
/* @endcond */

/** For the MAC/L2 layer (after the IPv6 packet is fragmented to smaller
 * chunks), we can use much smaller buffers (depending on used radio
 * technology). For 802.15.4 we use the 128 bytes long buffers.
 */
#ifndef NET_L2_BUF_MAX_SIZE
#define NET_L2_BUF_MAX_SIZE (PACKETBUF_SIZE + PACKETBUF_HDR_SIZE)
#endif

struct l2_buf {
	/** @cond ignore */
	/* 6LoWPAN pointers */
	uint8_t *packetbuf_ptr;
	uint8_t packetbuf_hdr_len;
	uint8_t packetbuf_payload_len;
	uint8_t uncomp_hdr_len;
	int last_tx_status;
#if defined(CONFIG_NETWORKING_WITH_15_4)
	LIST_STRUCT(neighbor_list);
#endif

	struct packetbuf_attr pkt_packetbuf_attrs[PACKETBUF_NUM_ATTRS];
	struct packetbuf_addr pkt_packetbuf_addrs[PACKETBUF_NUM_ADDRS];
	uint16_t pkt_buflen, pkt_bufptr;
	uint8_t pkt_hdrptr;
	uint8_t *pkt_packetbufptr;
	/* @endcond */
};

/** @cond ignore */
#define uip_packetbuf_ptr(buf) \
	(((struct l2_buf *)net_buf_user_data((buf)))->packetbuf_ptr)
#define uip_packetbuf_hdr_len(buf) \
	(((struct l2_buf *)net_buf_user_data((buf)))->packetbuf_hdr_len)
#define uip_packetbuf_payload_len(buf) \
	(((struct l2_buf *)net_buf_user_data((buf)))->packetbuf_payload_len)
#define uip_uncomp_hdr_len(buf) \
	(((struct l2_buf *)net_buf_user_data((buf)))->uncomp_hdr_len)
#define uip_last_tx_status(buf) \
	(((struct l2_buf *)net_buf_user_data((buf)))->last_tx_status)
#if defined(CONFIG_NETWORKING_WITH_15_4)
#define uip_neighbor_list(buf) \
	(((struct l2_buf *)net_buf_user_data((buf)))->neighbor_list)
#endif
#define uip_pkt_buflen(buf) \
	(((struct l2_buf *)net_buf_user_data((buf)))->pkt_buflen)
#define uip_pkt_bufptr(buf) \
	(((struct l2_buf *)net_buf_user_data((buf)))->pkt_bufptr)
#define uip_pkt_hdrptr(buf) \
	(((struct l2_buf *)net_buf_user_data((buf)))->pkt_hdrptr)
#define uip_pkt_packetbufptr(buf) \
	(((struct l2_buf *)net_buf_user_data((buf)))->pkt_packetbufptr)
#define uip_pkt_packetbuf_attrs(buf) \
	(((struct l2_buf *)net_buf_user_data((buf)))->pkt_packetbuf_attrs)
#define uip_pkt_packetbuf_addrs(buf) \
	(((struct l2_buf *)net_buf_user_data((buf)))->pkt_packetbuf_addrs)

/* Note that we do not reserve extra space for the header when the packetbuf
 * is converted to use net_buf, so the packet starts directly from the
 * data pointer. This is done in order to simplify the 802.15.4 packet
 * handling. So the L2 buffer should only be allocated by calling
 * reserve function like this: l2_buf_get_reserve(0);
 */
#define uip_pkt_packetbuf(ptr) ((ptr)->data)
/* @endcond */

/**
 * @brief Get buffer from the available buffers pool
 * and 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 How many bytes to reserve for headroom.
 *
 * @return Network buffer if successful, NULL otherwise.
 */
#ifdef DEBUG_L2_BUFS
#define l2_buf_get_reserve(res) l2_buf_get_reserve_debug(res, \
							 __func__, __LINE__)
struct net_buf *l2_buf_get_reserve_debug(uint16_t reserve_head,
					 const char *caller, int line);
#else
struct net_buf *l2_buf_get_reserve(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_L2_BUFS
#define l2_buf_unref(buf) l2_buf_unref_debug(buf, __func__, __LINE__)
void l2_buf_unref_debug(struct net_buf *buf, const char *caller, int line);
#else
void l2_buf_unref(struct net_buf *buf);
#endif

#else /* defined(CONFIG_L2_BUFFERS) */

#define l2_buf_init(...)

#endif /* defined(CONFIG_L2_BUFFERS) */

#ifdef __cplusplus
}
#endif

#endif /* __L2_BUF_H */