diff --git a/Makefile.dep b/Makefile.dep index 85076fee24bf..eae1387beb19 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -47,6 +47,14 @@ ifneq (,$(filter sixlowpan,$(USEMODULE))) USEMODULE += vtimer endif +ifneq (,$(filter slip,$(USEMODULE))) + USEMODULE += pktbuf + ifeq (,$(filter $(BOARD),arduino-due iot-lab_M3 pca10000 pca10005 stm32f0discovery stm32f3discovery stm32f4discovery)) + USEMODULE += posix + USEMODULE += uart0 + endif +endif + ifneq (,$(filter aodvv2,$(USEMODULE))) USEMODULE += vtimer USEMODULE += sixlowpan @@ -108,10 +116,22 @@ ifneq (,$(filter ccn_lite,$(USEMODULE))) USEMODULE += crypto endif +ifneq (,$(filter nomac,$(USEMODULE))) + USEMODULE += pktbuf +endif + +ifneq (,$(filter netapi,$(USEMODULE))) + USEMODULE += pkt +endif + ifneq (,$(filter netdev_802154,$(USEMODULE))) USEMODULE += netdev_base endif +ifneq (,$(filter pktbuf,$(USEMODULE))) + USEMODULE += pkt +endif + ifneq (,$(filter rgbled,$(USEMODULE))) USEMODULE += color endif diff --git a/drivers/include/netdev/base.h b/drivers/include/netdev/base.h index a6a4bcff73a0..4ebfb7c262d7 100644 --- a/drivers/include/netdev/base.h +++ b/drivers/include/netdev/base.h @@ -82,6 +82,7 @@ typedef enum { * @detail Sends frames as defined by cc110x_packet_t. */ NETDEV_PROTO_CC110X = 0x0008, + NETDEV_PROTO_SLIP = 0x0009, /**< Serial line IP. */ } netdev_proto_t; /** @@ -192,7 +193,7 @@ typedef int (*netdev_rcv_data_cb_t)(netdev_t *dev, void *src, size_t src_len, /** * @brief Network device API definition. * - * @details This is a set of functions that must be implemented by any driver + * @details This is a set of functions that must be implemented by any driver * for a network device. */ typedef struct { @@ -328,7 +329,7 @@ typedef struct { * * @param[in] dev the network device that fired the event. * @param[in] event_type Event type. Values are free to choose for the - * driver. Must be given in the @ref msg_t::value + * driver. Must be given in the @ref msg_t::content::value * of the received message */ void (*event)(netdev_t *dev, uint32_t event_type); diff --git a/sys/Makefile b/sys/Makefile index 27c2ef30a6f3..c92ed6ffd600 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -22,6 +22,9 @@ endif ifneq (,$(filter nomac,$(USEMODULE))) DIRS += net/link_layer/nomac endif +ifneq (,$(filter slip,$(USEMODULE))) + DIRS += net/link_layer/slip +endif ifneq (,$(filter transport_layer,$(USEMODULE))) USEMODULE += udp USEMODULE += tcp diff --git a/sys/Makefile.include b/sys/Makefile.include index d56b9809e7b2..a27fa272bac6 100644 --- a/sys/Makefile.include +++ b/sys/Makefile.include @@ -16,6 +16,9 @@ endif ifneq (,$(filter netapi,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include endif +ifneq (,$(filter slip,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include +endif ifneq (,$(filter net_help,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include USEMODULE_INCLUDES += $(RIOTBASE)/drivers/cc110x diff --git a/sys/net/crosslayer/netapi/netapi.c b/sys/net/crosslayer/netapi/netapi.c index 2d5cd7e6889a..5875d4a4a1ef 100644 --- a/sys/net/crosslayer/netapi/netapi.c +++ b/sys/net/crosslayer/netapi/netapi.c @@ -58,20 +58,18 @@ int netapi_send_command(kernel_pid_t pid, netapi_cmd_t *cmd) return ack_result; } -int netapi_send_packet(kernel_pid_t pid, netdev_hlist_t *upper_layer_hdrs, - void *addr, size_t addr_len, void *data, size_t data_len) +int netapi_send_packet(kernel_pid_t pid, void *dest, size_t dest_len, + pkt_t *pkt) { - netapi_snd_pkt_t pkt; + netapi_pkt_t cmd; - pkt.type = NETAPI_CMD_SND; + cmd.type = NETAPI_CMD_SND; - pkt.ulh = upper_layer_hdrs; - pkt.dest = addr; - pkt.dest_len = addr_len; - pkt.data = data; - pkt.data_len = data_len; + cmd.dest = dest; + cmd.dest_len = dest_len; + cmd.pkt = pkt; - return netapi_send_command(pid, (netapi_cmd_t *)(&pkt)); + return netapi_send_command(pid, (netapi_cmd_t *)(&cmd)); } static unsigned int _get_set_option(kernel_pid_t pid, netapi_cmd_type_t type, @@ -125,21 +123,19 @@ int netapi_unregister(kernel_pid_t pid, kernel_pid_t reg_pid) #ifdef MODULE_NETDEV_DUMMY int netapi_fire_receive_event(kernel_pid_t pid, void *src, size_t src_len, - void *dest, size_t dest_len, void *data, - size_t data_len) + void *dest, size_t dest_len, pkt_t *pkt) { - netapi_rcv_pkt_t pkt; + netapi_pkt_t cmd; - pkt.type = NETAPI_CMD_FIRE_RCV; + cmd.type = NETAPI_CMD_FIRE_RCV; - pkt.src = src; - pkt.src_len = src_len; - pkt.dest = dest; - pkt.dest_len = dest_len; - pkt.data = data; - pkt.data_len = data_len; + cmd.src = src; + cmd.src_len = src_len; + cmd.dest = dest; + cmd.dest_len = dest_len; + cmd.pkt = pkt; - return netapi_send_command(pid, (netapi_cmd_t *)(&pkt)); + return netapi_send_command(pid, (netapi_cmd_t *)(&cmd)); } #endif /** diff --git a/sys/net/crosslayer/pktbuf/pktbuf.c b/sys/net/crosslayer/pktbuf/pktbuf.c index 3b417cb55e4e..7727a55059cb 100644 --- a/sys/net/crosslayer/pktbuf/pktbuf.c +++ b/sys/net/crosslayer/pktbuf/pktbuf.c @@ -20,21 +20,20 @@ #include #include "mutex.h" +#include "pkt.h" #include "pktbuf.h" -#if PKTBUF_SIZE < 128 -typedef uint8_t _pktsize_t; -#elif PKTBUF_SIZE < 65536 -typedef uint16_t _pktsize_t; -#else -typedef size_t _pktsize_t; -#endif - -typedef struct __attribute__((packed)) _packet_t { - volatile struct _packet_t *next; +/** + * @brief Data type to represent describe chunks in packet buffer. + */ +typedef struct __attribute__((packed)) _pkt_internal_t { + struct _pkt_internal_t *next; uint8_t processing; - _pktsize_t size; -} _packet_t; + pkt_hlist_t *header_ptr; + void *data; + pktsize_t size; + pkt_proto_t proto; +} _pkt_internal_t; static uint8_t _pktbuf[PKTBUF_SIZE]; static mutex_t _pktbuf_mutex = MUTEX_INIT; @@ -42,34 +41,46 @@ static mutex_t _pktbuf_mutex = MUTEX_INIT; /** * @brief Get first element in packet buffer. */ -static inline _packet_t *_pktbuf_head(void) +static inline _pkt_internal_t *_pktbuf_head(void) { - return (_packet_t *)(&(_pktbuf[0])); + return (_pkt_internal_t *)(&(_pktbuf[0])); } /** - * @brief Get data part (memory behind `_packet_t` descriptive header) of a packet + * @brief Get _pkt_internal from pkt_t * - * @param[in] pkt A packet + * @param[in] pkt An external representation packet + * + * @return Internal representation of a packet. + */ +static inline _pkt_internal_t *_pkt_internal_cast(pkt_t *pkt) +{ + return (_pkt_internal_t *)(((uint8_t *)pkt) - sizeof(_pkt_internal_t) + sizeof(pkt_t)); +} + +/** + * @brief Get pkt_t from _pkt_internal_t + * + * @param[in] pkt An internal representation packet * - * @return Data part of the packet. + * @return External representation of a packet. */ -static inline void *_pkt_data(_packet_t *pkt) +static inline pkt_t *_pkt_cast(_pkt_internal_t *pkt) { - return (void *)(((_packet_t *)pkt) + 1); + return (pkt_t *)(&(pkt->header_ptr)); } /** - * @brief Calculates total size (*size* + size of `_packet_t` descriptive header) of a - * packet in memory + * @brief Calculates total size (@p size + size of _pkt_internal_t descriptive + * header) of a chunk in packet buffer. * * @param[in] size A given packet size * * @return Total size of a packet in memory. */ -static inline size_t _pkt_total_sz(size_t size) +static inline pktsize_t _pkt_total_sz(pktsize_t size) { - return sizeof(_packet_t) + size; + return (pktsize_t)(sizeof(_pkt_internal_t) + size); } /** @@ -77,9 +88,9 @@ static inline size_t _pkt_total_sz(size_t size) * * @param[in] pkt A packet * - * @return Pointer to the last byte of a packet + * @return Pointer to the byte after the last byte of a packet */ -static inline void *_pkt_end(_packet_t *pkt) +static inline void *_pkt_end(_pkt_internal_t *pkt) { return (void *)((uint8_t *)pkt + _pkt_total_sz(pkt->size)); } @@ -91,9 +102,9 @@ static inline void *_pkt_end(_packet_t *pkt) * * @return Index in packet buffer of the first byte of *pkt*'s data part. */ -static inline size_t _pktbuf_start_idx(_packet_t *pkt) +static inline pktsize_t _pktbuf_start_idx(_pkt_internal_t *pkt) { - return (size_t)(((uint8_t *)pkt) - (&(_pktbuf[0]))); + return (pktsize_t)(((uint8_t *)pkt) - (&(_pktbuf[0]))); } /** @@ -103,26 +114,26 @@ static inline size_t _pktbuf_start_idx(_packet_t *pkt) * * @return Index in packet buffer of the last byte of *pkt*'s data part. */ -static inline size_t _pktbuf_end_idx(_packet_t *pkt) +static inline pktsize_t _pktbuf_end_idx(_pkt_internal_t *pkt) { return _pktbuf_start_idx(pkt) + _pkt_total_sz(pkt->size) - 1; } -static _packet_t *_pktbuf_find_with_prev(_packet_t **prev_ptr, - _packet_t **packet_ptr, const void *pkt) +static _pkt_internal_t *_pktbuf_find_with_prev(_pkt_internal_t **prev_ptr, + _pkt_internal_t **packet_ptr, const void *pkt) { - _packet_t *packet = _pktbuf_head(), *prev = NULL; + _pkt_internal_t *packet = _pktbuf_head(), *prev = NULL; while (packet != NULL) { - if (_pkt_data(packet) == pkt) { + if (packet->data == pkt) { *prev_ptr = prev; *packet_ptr = packet; return packet; } prev = packet; - packet = (_packet_t *)packet->next; + packet = packet->next; } *prev_ptr = NULL; @@ -131,9 +142,9 @@ static _packet_t *_pktbuf_find_with_prev(_packet_t **prev_ptr, return NULL; } -static _packet_t *_pktbuf_find(const void *pkt) +static _pkt_internal_t *_pktbuf_find(const void *pkt) { - _packet_t *packet = _pktbuf_head(); + _pkt_internal_t *packet = _pktbuf_head(); #ifdef DEVELHELP @@ -144,20 +155,20 @@ static _packet_t *_pktbuf_find(const void *pkt) #endif /* DEVELHELP */ while (packet != NULL) { - if ((_pkt_data(packet) <= pkt) && (pkt < _pkt_end(packet))) { + if ((((void *)packet) <= pkt) && (pkt < _pkt_end(packet))) { mutex_unlock(&_pktbuf_mutex); return packet; } - packet = (_packet_t *)packet->next; + packet = (_pkt_internal_t *)packet->next; } return NULL; } -static _packet_t *_pktbuf_alloc(size_t size) +static _pkt_internal_t *_pktbuf_alloc(pktsize_t size) { - _packet_t *packet = _pktbuf_head(), *old_next; + _pkt_internal_t *packet = _pktbuf_head(), *old_next; if ((size == 0) || (size > PKTBUF_SIZE)) { return NULL; @@ -168,13 +179,13 @@ static _packet_t *_pktbuf_alloc(size_t size) * and next in its slot */ && (packet->processing == 0) && (packet->next != NULL) - && ((_pktbuf_start_idx((_packet_t *)(packet->next)) - _pkt_total_sz(packet->size)) < size)) { - packet = (_packet_t *)packet->next; + && ((_pktbuf_start_idx(packet->next) - _pkt_total_sz(packet->size)) < size)) { + packet = packet->next; } /* while packet is not initialized */ while ((packet->processing > 0) || (packet->size > size)) { - old_next = (_packet_t *)packet->next; + old_next = packet->next; /* if current packet is the last in buffer, but buffer space is exceeded */ if ((old_next == NULL) @@ -185,10 +196,9 @@ static _packet_t *_pktbuf_alloc(size_t size) /* if current packet is the last in the buffer or if space between * current packet and next packet is big enough */ if ((old_next == NULL) - || ((_pktbuf_start_idx((_packet_t *)(packet->next)) - _pktbuf_end_idx(packet)) >= _pkt_total_sz( - size))) { + || ((_pktbuf_start_idx(packet->next) - _pktbuf_end_idx(packet)) >= _pkt_total_sz(size))) { - _packet_t *new_next = (_packet_t *)(((uint8_t *)packet) + _pkt_total_sz(packet->size)); + _pkt_internal_t *new_next = (_pkt_internal_t *)(((uint8_t *)packet) + _pkt_total_sz(packet->size)); /* jump ahead size of current packet. */ packet->next = new_next; packet->next->next = old_next; @@ -201,17 +211,19 @@ static _packet_t *_pktbuf_alloc(size_t size) packet = old_next; } - packet->size = size; packet->processing = 1; + packet->size = size; + packet->data = (void *)(packet + 1); /* first pointer after packet */ + packet->header_ptr = NULL; return packet; } -static void _pktbuf_free(_packet_t *prev, _packet_t *packet) +static void _pktbuf_free(_pkt_internal_t *prev, _pkt_internal_t *packet) { - if ((packet->processing)-- > 1) { /* `> 1` because packet->processing may already - * be 0 in which case --(packet->processing) - * would wrap to 255. */ + if ((packet->processing)-- > 1) { + /* `> 1` because packet->processing may already be 0 in which case + * --(packet->processing) would wrap to 255. */ return; } @@ -228,13 +240,13 @@ int pktbuf_contains(const void *pkt) return ((&(_pktbuf[0]) < ((uint8_t *)pkt)) && (((uint8_t *)pkt) <= &(_pktbuf[PKTBUF_SIZE - 1]))); } -void *pktbuf_alloc(size_t size) +pkt_t *pktbuf_alloc(pktsize_t payload_len) { - _packet_t *packet; + _pkt_internal_t *packet; mutex_lock(&_pktbuf_mutex); - packet = _pktbuf_alloc(size); + packet = _pktbuf_alloc(payload_len); if (packet == NULL) { mutex_unlock(&_pktbuf_mutex); @@ -243,142 +255,171 @@ void *pktbuf_alloc(size_t size) mutex_unlock(&_pktbuf_mutex); - return _pkt_data(packet); + return _pkt_cast(packet); } -void *pktbuf_realloc(const void *pkt, size_t size) +pkt_t *pktbuf_realloc_payload(const pkt_t *pkt, pktsize_t payload_len) { - _packet_t *new, *prev, *orig; + _pkt_internal_t *new, *prev, *orig; mutex_lock(&_pktbuf_mutex); - if ((size == 0) || (size > PKTBUF_SIZE)) { + if ((payload_len == 0) || (payload_len > PKTBUF_SIZE)) { mutex_unlock(&_pktbuf_mutex); return NULL; } - _pktbuf_find_with_prev(&prev, &orig, pkt); + _pktbuf_find_with_prev(&prev, &orig, pkt->payload_data); if ((orig != NULL) && - ((orig->size >= size) /* and *orig* is last packet, and space in - * _pktbuf is sufficient */ + ((orig->size >= payload_len) /* and *orig* is last packet, and space in + * _pktbuf is sufficient */ || ((orig->next == NULL) - && ((_pktbuf_start_idx(orig) + _pkt_total_sz(size)) < PKTBUF_SIZE)) + && ((_pktbuf_start_idx(orig) + _pkt_total_sz(payload_len)) < PKTBUF_SIZE)) || ((orig->next != NULL) /* or space between pointer and the next is big enough: */ - && ((_pktbuf_start_idx((_packet_t *)(orig->next)) - _pktbuf_start_idx(orig)) - >= _pkt_total_sz(size))))) { - orig->size = size; + && ((_pktbuf_start_idx(orig->next) - _pktbuf_start_idx(orig)) + >= _pkt_total_sz(payload_len))))) { + orig->size = payload_len; mutex_unlock(&_pktbuf_mutex); return (void *)pkt; } - new = _pktbuf_alloc(size); + new = _pktbuf_alloc(payload_len); if (new == NULL) { mutex_unlock(&_pktbuf_mutex); return NULL; } + /* cppcheck-suppress nullPointer cppcheck says this check is redundant but + * it's * vital: orig is NULL if pkt was not previously allocated in the + * packet buffer and thus it's data needs to be copied. */ if (orig != NULL) { - memcpy(_pkt_data(new), _pkt_data(orig), orig->size); - + memcpy(new->data, orig->data, orig->size); + new->header_ptr = orig->header_ptr; _pktbuf_free(prev, orig); } else { - memcpy(_pkt_data(new), pkt, size); + memcpy(new->data, pkt->payload_data, pkt->payload_len); } mutex_unlock(&_pktbuf_mutex); - return _pkt_data(new); + return _pkt_cast(new); } -void *pktbuf_insert(const void *data, size_t size) +pkt_t *pktbuf_insert(const void *payload_data, pktsize_t payload_len) { - _packet_t *packet; + _pkt_internal_t *packet; - if ((data == NULL) || (size == 0)) { + if ((payload_data == NULL) || (payload_len == 0)) { return NULL; } mutex_lock(&_pktbuf_mutex); - packet = _pktbuf_alloc(size); + + packet = _pktbuf_alloc(payload_len); if (packet == NULL) { mutex_unlock(&_pktbuf_mutex); return NULL; } - memcpy(_pkt_data(packet), data, size); + memcpy(packet->data, payload_data, payload_len); mutex_unlock(&_pktbuf_mutex); - return _pkt_data(packet); + return _pkt_cast(packet); } -int pktbuf_copy(void *pkt, const void *data, size_t data_len) +int pktbuf_copy(void *data, const void *data_new, pktsize_t data_new_len) { - _packet_t *packet; - - mutex_lock(&_pktbuf_mutex); + _pkt_internal_t *packet; #ifdef DEVELHELP - if (data == NULL) { - mutex_unlock(&_pktbuf_mutex); + if (data_new == NULL) { return -EFAULT; } - if (pkt == NULL) { - mutex_unlock(&_pktbuf_mutex); + if (data == NULL) { return -EINVAL; } #endif /* DEVELHELP */ - packet = _pktbuf_find(pkt); + mutex_lock(&_pktbuf_mutex); + packet = _pktbuf_find(data); if ((packet != NULL) && (packet->size > 0) && (packet->processing > 0)) { + /* if packet does not point to data's meta-data */ + if ((packet->data > data) || (_pkt_end(packet) <= data)) { + return -EINVAL; + } + /* packet space not engough? */ - if (data_len > (size_t)(((uint8_t *)_pkt_end(packet)) - ((uint8_t *)pkt))) { + if (data_new_len > (pktsize_t)(((uint8_t *)_pkt_end(packet)) - ((uint8_t *)data))) { mutex_unlock(&_pktbuf_mutex); return -ENOMEM; } } - - memcpy(pkt, data, data_len); + memcpy(data, data_new, data_new_len); mutex_unlock(&_pktbuf_mutex); - return data_len; + return data_new_len; } -void pktbuf_hold(const void *pkt) +int pktbuf_add_header(pkt_t *pkt, void *header_data, pktsize_t header_len) { - _packet_t *packet; + _pkt_internal_t *packet, *header; + +#ifdef DEVELHELP + + if (header_data == NULL) { + return -EFAULT; + } + + if (pkt == NULL) { + return -EINVAL; + } + +#endif /* DEVELHELP */ mutex_lock(&_pktbuf_mutex); packet = _pktbuf_find(pkt); - if (packet != NULL) { - packet->processing++; + if ((packet == NULL) || (_pkt_cast(packet) != pkt)) { + mutex_unlock(&_pktbuf_mutex); + return -EINVAL; } + header = _pktbuf_alloc(header_len); + + if (header == NULL) { + mutex_unlock(&_pktbuf_mutex); + return -ENOMEM; + } + + memcpy(header->data, header_data, header_len); + + pkt_add_header(_pkt_cast(packet), (pkt_hlist_t *)_pkt_cast(header)); + mutex_unlock(&_pktbuf_mutex); + + return 0; } -void pktbuf_release(const void *pkt) +static void _pkt_release(const pkt_t *pkt) { - _packet_t *packet = _pktbuf_head(), *prev = NULL; - - mutex_lock(&_pktbuf_mutex); + _pkt_internal_t *packet = _pktbuf_head(), *prev = NULL; while (packet != NULL) { - if ((_pkt_data(packet) <= pkt) && (pkt < _pkt_end(packet))) { + if ((_pkt_cast(packet) <= pkt) && (((void *)pkt) < _pkt_end(packet))) { _pktbuf_free(prev, packet); mutex_unlock(&_pktbuf_mutex); @@ -386,7 +427,65 @@ void pktbuf_release(const void *pkt) } prev = packet; - packet = (_packet_t *)packet->next; + packet = packet->next; + } +} + +void pktbuf_remove_header(pkt_t *pkt, pkt_hlist_t *header) +{ + mutex_lock(&_pktbuf_mutex); + + pkt_remove_header(pkt, header); + _pkt_release((pkt_t *)header); + + mutex_unlock(&_pktbuf_mutex); +} + +void pktbuf_hold(const pkt_t *pkt) +{ + _pkt_internal_t *packet; + + mutex_lock(&_pktbuf_mutex); + + packet = _pktbuf_find(pkt); + + if (packet != NULL) { + _pkt_internal_t *ptr = packet; + + while (ptr) { + ptr->processing++; + + if (ptr->header_ptr == NULL) { + break; + } + + ptr = _pkt_internal_cast((pkt_t *)(ptr->header_ptr)); + } + } + + mutex_unlock(&_pktbuf_mutex); +} + +void pktbuf_release(const pkt_t *pkt) +{ + _pkt_internal_t *ptr = _pkt_internal_cast((pkt_t *)pkt); /* cast to remove const */ + + if (pkt == NULL || !pktbuf_contains_pkt(pkt)) { + return; + } + + mutex_lock(&_pktbuf_mutex); + + while (ptr != NULL) { + _pkt_internal_t *next = NULL; + + if (ptr->header_ptr != NULL) { + next = _pkt_internal_cast((pkt_t *)(ptr->header_ptr)); + } + + _pkt_release(_pkt_cast(ptr)); + + ptr = next; } mutex_unlock(&_pktbuf_mutex); @@ -397,7 +496,7 @@ void pktbuf_release(const void *pkt) void pktbuf_print(void) { - _packet_t *packet = _pktbuf_head(); + _pkt_internal_t *packet = _pktbuf_head(); int i = 0; mutex_lock(&_pktbuf_mutex); @@ -414,34 +513,35 @@ void pktbuf_print(void) return; } else if (packet->next != NULL && packet->size == 0) { - packet = (_packet_t *)packet->next; + packet = (_pkt_internal_t *)packet->next; } while (packet != NULL) { - uint8_t *data = (uint8_t *)_pkt_data(packet); + uint8_t *data = packet->data; - printf("packet %d (%p):\n", i, (void *)packet); + printf("chunk %d (%p):\n", i, (void *)packet); printf(" next: %p\n", (void *)(packet->next)); - printf(" size: %" PRIu32 "\n", (uint32_t)packet->size); printf(" processing: %" PRIu8 "\n", packet->processing); + printf(" size: %" PRIpktsize "\n", packet->size); + printf(" data: (start address: %p)\n ", packet->data); + printf(" protocol: 0x%04x\n", packet->proto); + printf(" header_ptr: %p", (void *)(packet->header_ptr)); if (packet->next != NULL) { printf(" free data after: %" PRIu32 "\n", - (uint32_t)(_pktbuf_start_idx((_packet_t *)(packet->next)) - _pktbuf_end_idx(packet) - 1)); + (uint32_t)(_pktbuf_start_idx(packet->next) - _pktbuf_end_idx(packet) - 1)); } else { printf(" free data after: %" PRIu32 "\n", (uint32_t)(PKTBUF_SIZE - _pktbuf_end_idx(packet) - 1)); } - printf(" data: (start address: %p)\n ", data); - if (packet->size > PKTBUF_SIZE) { printf(" We have a problem: packet->size (%" PRIu32 ") > PKTBUF_SIZE (%" PRIu32 ")\n", (uint32_t)(packet->size), (uint32_t)PKTBUF_SIZE); } else { - for (size_t j = 0; j < packet->size; j++) { + for (pktsize_t j = 0; j < packet->size; j++) { printf(" %02x", data[j]); if (((j + 1) % 16) == 0) { @@ -452,7 +552,7 @@ void pktbuf_print(void) printf("\n\n"); } - packet = (_packet_t *)packet->next; + packet = (_pkt_internal_t *)packet->next; i++; } @@ -465,16 +565,16 @@ void pktbuf_print(void) #endif #ifdef TEST_SUITES -size_t pktbuf_bytes_allocated(void) +pktsize_t pktbuf_bytes_allocated(void) { - _packet_t *packet = _pktbuf_head(); - size_t bytes = 0; + _pkt_internal_t *packet = _pktbuf_head(); + pktsize_t bytes = 0; mutex_lock(&_pktbuf_mutex); while (packet != NULL) { bytes += packet->size; - packet = (_packet_t *)(packet->next); + packet = packet->next; } mutex_unlock(&_pktbuf_mutex); @@ -484,7 +584,7 @@ size_t pktbuf_bytes_allocated(void) unsigned int pktbuf_packets_allocated(void) { - _packet_t *packet = _pktbuf_head(); + _pkt_internal_t *packet = _pktbuf_head(); unsigned int packets = 0; mutex_lock(&_pktbuf_mutex); @@ -494,7 +594,7 @@ unsigned int pktbuf_packets_allocated(void) packets++; } - packet = (_packet_t *)(packet->next); + packet = packet->next; } mutex_unlock(&_pktbuf_mutex); diff --git a/sys/net/include/netapi.h b/sys/net/include/netapi.h index 220635c51d4b..4ec9d195196a 100644 --- a/sys/net/include/netapi.h +++ b/sys/net/include/netapi.h @@ -55,6 +55,7 @@ #include #include "kernel.h" +#include "pkt.h" #include "netdev/base.h" #include "thread.h" @@ -216,56 +217,34 @@ typedef struct { } netapi_cmd_t; /** - * @brief Command definition for receiving packets. + * @brief Command definition for receiving and sending packets. * @extends netapi_cmd_t */ typedef struct { /* cppcheck-suppress unusedStructMember because interface is not used yet */ - netapi_cmd_type_t type; /**< Type of the command. Must be NETAPI_CMD_RCV. */ + netapi_cmd_type_t type; /**< Type of the command. Must be NETAPI_CMD_RCV or NETAPI_CMD_SND. */ netapi_ack_t *ack; /**< Pointer to where the acknowledgement to this message is stored. Must not be NULL. */ - void *src; /**< Source address for this message. */ - /* cppcheck-suppress unusedStructMember because interface is not used yet */ - size_t src_len; /**< Length of netapi_rcv_pkt_t::src. */ - void *dest; /**< Destination address for this message. */ - /* cppcheck-suppress unusedStructMember because interface is not used yet */ - size_t dest_len; /**< Length of netapi_rcv_pkt_t::dest. */ - void *data; /**< Data of the packet. */ - /* cppcheck-suppress unusedStructMember because interface is not used yet */ - size_t data_len; /**< Buffer length of netapi_rcv_pkt_t::data - * (set to maximum available space when sending - * to control thread, the control thread - * **must** check this). */ -} netapi_rcv_pkt_t; -/** - * @brief Command definition for sending packets. - * @extends netapi_cmd_t - * - * @details The netapi_snd_pkt_t::ulh will be prepended - * to the data stream on the lowest level (usually - * by the driver, but adaption layers as 6LoWPAN might - * also prepend headers). - */ -typedef struct { - /* cppcheck-suppress unusedStructMember because interface is not used yet */ - netapi_cmd_type_t type; /**< Type of the command. Must be NETAPI_CMD_SND. */ - netapi_ack_t *ack; /**< Pointer to where the acknowledgement to this - * message is stored. Must not be NULL. */ - netdev_hlist_t *ulh; /**< Headers of upper layers; lowest first, highest last. - * May be NULL if none exist. */ - void *dest; /**< Destination address for this message. */ - /* cppcheck-suppress unusedStructMember because interface is not used yet */ - size_t dest_len; /**< Length of netapi_snd_pkt_t::dest. */ /** - * @brief Data of the packet (without upper layer headers). + * @brief Source address for this message. * - * @see netapi_snd_pkt_t::upper_layer_hdrs + * @details Can be NULL for sending + */ + void *src; + + /** + * @brief Length of netapi_rcv_pkt_t::src. + * + * @details Can be 0 for sending */ - void *data; /* cppcheck-suppress unusedStructMember because interface is not used yet */ - size_t data_len; /**< Length of netapi_snd_pkt_t::data. */ -} netapi_snd_pkt_t; + size_t src_len; + void *dest; /**< Destination address for this message. */ + /* cppcheck-suppress unusedStructMember because interface is not used yet */ + size_t dest_len; /**< Length of netapi_rcv_pkt_t::dest. */ + pkt_t *pkt; /**< Data of the packet. */ +} netapi_pkt_t; /** * @brief Command definition for getting and setting packets. @@ -356,59 +335,26 @@ int netapi_send_command(kernel_pid_t pid, netapi_cmd_t *cmd); * * @note Wraps IPC call of NETAPI_CMD_SND. * - * @details The upper layer information will be prepended - * on the lowest possible level. + * @details The upper layer information of *pkt* must be prepended on the + * lowest possible level. * * @param[in] pid The PID of the protocol's control thread. - * @param[in] upper_layer_hdrs Headers of upper layer protocols, lowest layer - * first, highest layer last. - * @param[in] addr The address you want the data send to. If the control + * @param[in] dest The address you want the data send to. If the control * thread knows for some reason where to send the data - * (e.g. a connected TCP socket), *addr* may be NULL. - * @param[in] addr_len Length of *addr*. If the control thread knows for some + * (e.g. a connected TCP socket), *dest* may be NULL. + * @param[in] dest_len Length of *dest*. If the control thread knows for some * reason where to send the data (e.g. a connected TCP - * socket), *addr_len* may be 0. - * @param[in] data The data you want to send over the protocol layer - * controled by *pid* (without upper layer protocol - * information). - * @param[in] data_len Length of *data_len*. - * - * @see netapi_snd_pkt_t - * - * @return result of the acknowledgement. - * @return -ENOMSG if wrong acknowledgement was received or was no - * acknowledgement at all. - */ -int netapi_send_packet(kernel_pid_t pid, netdev_hlist_t *upper_layer_hdrs, - void *addr, size_t addr_len, void *data, - size_t data_len); - -/** - * @brief Sends data over a protocol layer identified by *pid*. - * - * @note Wraps IPC call of NETAPI_CMD_SND with `netapi_snd_pkt_t::ulh == NULL`. - * - * @param[in] pid The PID of the protocol's control thread. - * @param[in] addr The address you want the data send to. If the control - * thread knows for some reason where to send the data - * (e.g. a connected TCP socket), *addr* may be NULL. - * @param[in] addr_len Length of *addr*. If the control thread knows for some - * reason where to send the data (e.g. a connected TCP - * socket), *addr_len* may be 0. - * @param[in] data The data you want to send over the protocol layer + * socket), *dest_len* may be 0. + * @param[in] pkt The packet you want to send over the protocol layer * controled by *pid*. - * @param[in] data_len Length of *data_len*. + * + * @see netapi_pkt_t * * @return result of the acknowledgement. * @return -ENOMSG if wrong acknowledgement was received or was no * acknowledgement at all. */ -static inline int netapi_send_payload(kernel_pid_t pid, void *addr, - size_t addr_len, void *data, - size_t data_len) -{ - return netapi_send_packet(pid, NULL, addr, addr_len, data, data_len); -} +int netapi_send_packet(kernel_pid_t pid, void *dest, size_t dest_len, pkt_t *pkt); /** * @brief Get an option of a protocol layer identified by *pid*. @@ -524,16 +470,14 @@ static inline int netapi_unregister_current_thread(kernel_pid_t pid) * @param[in] src_len Length of *src*. * @param[in] dest Destination address of the received packet. * @param[in] dest_len Length of *dest*. - * @param[in] data Content of the received packet. - * @param[in] data_len Length of *data*. + * @param[in] pkt The received packet. * * @return result of the acknowledgement. * @return -ENOMSG if wrong acknowledgement was received or was no * acknowledgement at all. */ int netapi_fire_receive_event(kernel_pid_t pid, void *src, size_t src_len, - void *dest, size_t dest_len, void *data, - size_t data_len); + void *dest, size_t dest_len, pkt_t *pkt); #endif /* MODULE_NETDEV_DUMMY */ #endif /* MODULE_NETAPI */ diff --git a/sys/net/include/pktbuf.h b/sys/net/include/pktbuf.h index 118daa0bca46..7f24da6e8da6 100644 --- a/sys/net/include/pktbuf.h +++ b/sys/net/include/pktbuf.h @@ -30,6 +30,7 @@ #include #include "cpu-conf.h" +#include "pkt.h" #ifdef __cplusplus extern "C" { @@ -52,68 +53,98 @@ extern "C" { * * @see @ref pktbuf_hold() * - * @param[in] size The length of the packet you want to allocate + * @param[in] payload_len The length of the packet you want to allocate. * - * @return Pointer to the start of the data in the packet buffer, on success. + * @return Pointer to the packet in the packet buffer, on success. * @return NULL, if no space is left in the packet buffer or size was 0. */ -void *pktbuf_alloc(size_t size); +pkt_t *pktbuf_alloc(pktsize_t payload_len); /** - * @brief Reallocates new space in the packet buffer, without changing the - * content. + * @brief Reallocates payload of packet in the packet buffer, without changing + * the content. * - * @details If enough memory is available behind it or *size* is smaller than - * the original size the packet will not be moved. Otherwise, it will - * be moved. If no space is available nothing happens. + * @details If enough memory is available behind it or @p size is smaller than + * the original size the packet and payload will not be moved. + * Otherwise, it will be moved. If no space is available nothing + * happens. If @p pkt is not in the packet buffer it will be copied + * into it with pkt_t::payload_len == size. * - * @param[in] pkt Old position of the packet in the packet buffer - * @param[in] size New amount of data you want to allocate + * @param[in] pkt A packet. + * @param[in] payload_len The new payload length for @p pkt. * - * @return Pointer to the (maybe new) position of the packet in the packet buffer, - * on success. + * @return New position of @p pkt, on success. * @return NULL, if no space is left in the packet buffer or size was 0. - * The packet will remain at *ptr*. + * The payload will remain where it was. */ -void *pktbuf_realloc(const void *pkt, size_t size); +pkt_t *pktbuf_realloc_payload(const pkt_t *pkt, pktsize_t payload_len); /** - * @brief Allocates and copies new packet data into the packet buffer. + * @brief Allocates new packet in the packet buffer and copies data into it. * This also marks the allocated data as processed for the current * thread. * * @see @ref pktbuf_hold() * - * @param[in] data Data you want to copy into the new packet. - * @param[in] size The length of the packet you want to allocate + * @param[in] payload_data Payload data you want to copy into the new packet. + * @param[in] payload_len The length of the packet you want to allocate. * - * @return Pointer to the start of the data in the packet buffer, on success. + * @return Pointer to the packet in the packet buffer, on success. * @return NULL, if no space is left in the packet buffer. */ -void *pktbuf_insert(const void *data, size_t size); +pkt_t *pktbuf_insert(const void *payload_data, pktsize_t payload_len); /** - * @brief Copies packet data into the packet buffer, safely. + * @brief Copies packet payload or header data into the packet buffer, safely. * * @details Use this instead of memcpy, since it is thread-safe and checks if - * *pkt* is + * @p data is * * -# in the buffer at all - * -# its *size* is smaller or equal to the data allocated at *pkt* + * -# its @p new_data is smaller or equal to the data allocated at + * @p new_data * - * If the *pkt* is not in the buffer the data is just copied as + * It also uses the thread-safe abilities of the packet buffer. + * + * If the @p data is not in the buffer the data is just copied as * memcpy would do. * - * @param[in,out] pkt The packet you want to set the data for. - * @param[in] data The data you want to copy into the packet. - * @param[in] data_len The length of the data you want to copy. + * @param[in,out] data Some payload or header data pointer in the packet + * buffer. + * @param[in] new_data The data you want to copy into the packet. + * @param[in] new_data_len The length of the data you want to copy. + * + * @return @p new_data_len, on success. + * @return -EFAULT, if @p data is NULL and DEVELHELP is defined. + * @return -EINVAL, if @p data is NULL and DEVELHELP is defined. + * @return -EINVAL, if @p data is not a pointer to payload data in packet buffer. + * @return -ENOMEM, if @p data_len was greater than the packet size of @p data. + */ +int pktbuf_copy(void *data, const void *new_data, pktsize_t new_data_len); + +/** + * @brief Adds a header to the packet and allocates it in packet buffer. + * + * @param[in] pkt The packet to add the new header to + * @param[in] header_data The data of the header + * @param[in] header_len The length of the header + * + * @return 0, on success + * @return -EFAULT, if @p header_data is NULL and DEVELHELP is defined. + * @return -EINVAL, if @p pkt is NULL and DEVELHELP is defined. + * @return -EINVAL, if @p pkt not a packet in packet buffer. + * @return -ENOMEM, if no space is left in the packet buffer or @p header_len was 0. + */ +int pktbuf_add_header(pkt_t *pkt, void *header_data, pktsize_t header_len); + +/** + * @brief Removes a header from the packet and releases it in the packet + * buffer. * - * @return *data_len*, on success. - * @return -EFAULT, if *data* is NULL and DEVELHELP is defined. - * @return -EINVAL, if *pkt* is NULL and DEVELHELP is defined. - * @return -ENOBUFS, if *data_len* was greater than the packet size of *pkt*. + * @param[in] pkt The packet to add the new header to + * @param[in] header The header to remove. */ -int pktbuf_copy(void *pkt, const void *data, size_t data_len); +void pktbuf_remove_header(pkt_t *pkt, pkt_hlist_t *header); /** * @brief Marks the data as being processed. @@ -124,7 +155,7 @@ int pktbuf_copy(void *pkt, const void *data, size_t data_len); * * @param[in] pkt The packet you want mark as being processed. */ -void pktbuf_hold(const void *pkt); +void pktbuf_hold(const pkt_t *pkt); /** * @brief Marks the data as not being processed. @@ -136,7 +167,30 @@ void pktbuf_hold(const void *pkt); * operation initializes it. If the counter is <=0 the reserved data * block in the buffer will be made available again. */ -void pktbuf_release(const void *pkt); +void pktbuf_release(const pkt_t *pkt); + +/** + * @brief Checks if a given pointer is stored in the packet buffer + * + * @param[in] ptr Pointer to be checked + * + * @return 1, if @p ptr is in packet buffer + * @return 0, otherwise + */ +int pktbuf_contains(const void *ptr); + +/** + * @brief Checks if a given packet is stored in the packet buffer + * + * @param[in] pkt Packet to be checked + * + * @return 1, if @p pkt is in packet buffer + * @return 0, otherwise + */ +static inline int pktbuf_contains_pkt(const pkt_t *pkt) +{ + return pktbuf_contains(pkt); +} /** * @brief Prints current packet buffer to stdout if DEVELHELP is defined. @@ -154,14 +208,14 @@ void pktbuf_print(void); * * @return Number of allocated bytes */ -size_t pktbuf_bytes_allocated(void); +pktsize_t pktbuf_bytes_allocated(void); /** * @brief Counts the number of allocated packets * * @return Number of allocated packets */ -size_t pktbuf_packets_allocated(void); +unsigned int pktbuf_packets_allocated(void); /** * @brief Checks if packet buffer is empty @@ -171,16 +225,6 @@ size_t pktbuf_packets_allocated(void); */ int pktbuf_is_empty(void); -/** - * @brief Checks if a given pointer is stored in the packet buffer - * - * @param[in] pkt Pointer to be checked - * - * @return 1, if *pkt* is in packet buffer - * @return 0, otherwise - */ -int pktbuf_contains(const void *pkt); - /** * @brief Sets the whole packet buffer to 0 */ diff --git a/sys/net/include/slip.h b/sys/net/include/slip.h new file mode 100644 index 000000000000..5c9569fdbfec --- /dev/null +++ b/sys/net/include/slip.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2014 Martin Lenders + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup slip SLIP transceiver + * @ingroup net + * @{ + * + * @file + * @brief Provides a SLIP interface over UART. + * @see RFC 1055 + * + * @author Martine Lenders + * + * @} + */ + +#ifndef __SLIP_H_ +#define __SLIP_H_ + +#include + +#include "netapi.h" +#include "pkt.h" +#include "periph/uart.h" +#include "ringbuffer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !UART_NUMOF +/** + * @brief Guard type in the case that the board does not implement the new + * driver model + */ +typedef uint8_t uart_t; +#endif + +/** + * Initializes a new @ref slip control thread for UART device @p uart. If + * the board does not support the uart_t type it falls back to using + * board_uart0.h + * + * @param[in] uart The (uninitialized) UART device, ignored if UART_NUMOF == 0 or not defined + * @param[in] baudrate Symbole rate for the UART device + * @param[in] in_buf Ringbuffer to store the incoming data from the UART in. + * Must hold at least L3 packet. + * + * @return The PID of the @ref slip control thread + */ +kernel_pid_t slip_init(uart_t uart, uint32_t baudrate, ringbuffer_t *in_buf); + +/** + * @func slip_send_l3_packet + * @brief Send a layer 3 packet over the UART device + * + * @param[in] pid The PID for the @ref slip control thread. + * @param[in] pkt Packet to send over the UART device. + * + * @return Number of bytes transmitted. + */ + +#ifdef MODULE_NETAPI +static inline int slip_send_l3_packet(kernel_pid_t pid, pkt_t *pkt) +{ + return netapi_send_packet(pid, NULL, 0, pkt); +} +#else +int slip_send_l3_packet(kernel_pid_t pid, pkt_t *pkt); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __SLIP_H_ */ diff --git a/sys/net/link_layer/nomac/nomac.c b/sys/net/link_layer/nomac/nomac.c index aaa16492ff58..06a3049da6ca 100644 --- a/sys/net/link_layer/nomac/nomac.c +++ b/sys/net/link_layer/nomac/nomac.c @@ -11,6 +11,7 @@ #include "netapi.h" #include "msg.h" #include "netdev/base.h" +#include "pktbuf.h" #include "thread.h" #include "nomac.h" @@ -35,7 +36,7 @@ static int _nomac_recv_cb(netdev_t *dev, void *src, size_t src_len, void *dest, (void)dev; kernel_pid_t current_pid = thread_getpid(); size_t offset; - netapi_rcv_pkt_t packet; + netapi_pkt_t packet; netapi_ack_t ack_mem; msg_t msg_pkt, msg_ack; @@ -54,11 +55,17 @@ static int _nomac_recv_cb(netdev_t *dev, void *src, size_t src_len, void *dest, while (offset < payload_len) { netapi_ack_t *ack; - packet.data = (void *)(((char *)payload) + offset); - packet.data_len = payload_len - offset; + pkt_t *pkt = pktbuf_insert(((char *)payload) + offset, + payload_len - offset); + /* TODO: replace line with pktbuf_hold(pkt) after merge of #2297 */ + + packet.pkt = pkt; msg_send_receive(&msg_pkt, &msg_ack, _nomac_registry[i].recipient_pid); + + pktbuf_release(pkt); + ack = (netapi_ack_t *)(msg_ack.content.ptr); if ((msg_ack.type == NETAPI_MSG_TYPE) && @@ -95,10 +102,95 @@ static int _nomac_recv_cb(netdev_t *dev, void *src, size_t src_len, void *dest, return payload_len; } -static inline int _nomac_send(netdev_t *dev, netapi_snd_pkt_t *pkt) +/* remove after merge of #2297 */ +static int _hlist_size(pkt_t *pkt) { - return dev->driver->send_data(dev, pkt->dest, pkt->dest_len, pkt->ulh, - pkt->data, pkt->data_len); + pkt_hlist_t *ptr = pkt->headers; + int i = 0; + + while (ptr) { + i++; + pkt_hlist_advance(&ptr); + } + + return i; +} + +static int _nomac_send(netdev_t *dev, netapi_pkt_t *snd) +{ + int result; + pktbuf_hold(snd->pkt); + + /* TODO: remove transformation after merge of #2297 */ + + netdev_hlist_t *headers = NULL; + int hlist_size = _hlist_size(snd->pkt); + netdev_hlist_t hbuf[hlist_size]; + + if (hlist_size > 0) { + int i = 0; + pkt_hlist_t *ptr = snd->pkt->headers; + + while (ptr != NULL) { + hbuf[i].next = NULL; + hbuf[i].prev = NULL; + + switch (ptr->header_proto) { + case PKT_PROTO_RADIO: + hbuf[i].protocol = NETDEV_PROTO_RADIO; + break; + + case PKT_PROTO_802154_DATA: + hbuf[i].protocol = NETDEV_PROTO_802154; + break; + + case PKT_PROTO_6LOWPAN: + hbuf[i].protocol = NETDEV_PROTO_6LOWPAN; + break; + + case PKT_PROTO_IPV6: + hbuf[i].protocol = NETDEV_PROTO_IPV6; + break; + + case PKT_PROTO_UDP: + hbuf[i].protocol = NETDEV_PROTO_UDP; + break; + + case PKT_PROTO_TCP: + hbuf[i].protocol = NETDEV_PROTO_IPV6; + break; + + case PKT_PROTO_CCNL: + hbuf[i].protocol = NETDEV_PROTO_CCNL; + break; + + case PKT_PROTO_CC110X: + hbuf[i].protocol = NETDEV_PROTO_CC110X; + break; + + default: + hbuf[i].protocol = NETDEV_PROTO_UNKNOWN; + break; + + } + + hbuf[i].header = ptr->header_data; + hbuf[i].header_len = ptr->header_len; + + netdev_hlist_add(&headers, &(hbuf[i++])); + + pkt_hlist_advance(&ptr); + } + } + + /* XXX: end of transformation */ + + result = dev->driver->send_data(dev, snd->dest, snd->dest_len, headers, + snd->pkt->payload_data, snd->pkt->payload_len); + + pktbuf_release(snd->pkt); + + return result; } static int _nomac_get_registry(netapi_conf_t *conf) @@ -199,7 +291,7 @@ static void *_nomac_runner(void *args) switch (cmd->type) { case NETAPI_CMD_SND: - ack->result = _nomac_send(dev, (netapi_snd_pkt_t *)cmd); + ack->result = _nomac_send(dev, (netapi_pkt_t *)cmd); break; case NETAPI_CMD_GET: @@ -248,12 +340,12 @@ static void *_nomac_runner(void *args) case NETAPI_CMD_FIRE_RCV: ack->result = unittest_netdev_dummy_fire_rcv_event(dev, - ((netapi_rcv_pkt_t *)cmd)->src, - ((netapi_rcv_pkt_t *)cmd)->src_len, - ((netapi_rcv_pkt_t *)cmd)->dest, - ((netapi_rcv_pkt_t *)cmd)->dest_len, - ((netapi_rcv_pkt_t *)cmd)->data, - ((netapi_rcv_pkt_t *)cmd)->data_len); + ((netapi_pkt_t *)cmd)->src, + ((netapi_pkt_t *)cmd)->src_len, + ((netapi_pkt_t *)cmd)->dest, + ((netapi_pkt_t *)cmd)->dest_len, + ((netapi_pkt_t *)cmd)->pkt->payload_data, + ((netapi_pkt_t *)cmd)->pkt->payload_len); break; #endif diff --git a/sys/net/link_layer/slip/Makefile b/sys/net/link_layer/slip/Makefile new file mode 100644 index 000000000000..8886e9848d9f --- /dev/null +++ b/sys/net/link_layer/slip/Makefile @@ -0,0 +1,2 @@ +INCLUDES += -I$(RIOTBASE)/sys/net/include +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/link_layer/slip/README.md b/sys/net/link_layer/slip/README.md new file mode 100644 index 000000000000..af2c6d7b40f7 --- /dev/null +++ b/sys/net/link_layer/slip/README.md @@ -0,0 +1,17 @@ +SLIP network interface +====================== + +This module provides access to the [http://tools.ietf.org/html/rfc1055](Serial Line Internet Protocol (SLIP)). +It allows you to send IP and IPv6 packages over the U(S)ART. For this you +have to initialize your serial device as a network device. In Linux (and Mac OS X) [http://playground.arduino.cc/Code/SerialIP#Connecting_Linux](this is easy): + +```bash +sudo modprobe slip # you do not need this line in Mac OS X +sudo slattach -s -p slip +sudo ifconfig sl0 mtu 1280 # or smaller, for e.g. MSP-430 boards +sudo ifconfig sl0 add fe80::/64 +sudo ifconfig sl0 add abcd::/64 # replace with an IPv6 prefix of your choice +sudo ifconfig sl0 up +``` + +If your RIOT board is configured as an IPv6 router, the rest should happen automatically. diff --git a/sys/net/link_layer/slip/slip.c b/sys/net/link_layer/slip/slip.c new file mode 100644 index 000000000000..46632a60a245 --- /dev/null +++ b/sys/net/link_layer/slip/slip.c @@ -0,0 +1,434 @@ +/* + * Copyright (C) 2014 Martin Lenders + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#include +#include +#include + +#include "kernel.h" +#include "netapi.h" +#include "netdev/base.h" +#include "periph/uart.h" +#include "pktbuf.h" +#include "ringbuffer.h" +#include "thread.h" + +#include "slip.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +#define _SLIP_END ((uint8_t)0xC0) +#define _SLIP_ESC ((uint8_t)0xDB) +#define _SLIP_END_ESC ((uint8_t)0xDC) +#define _SLIP_ESC_ESC ((uint8_t)0xDD) + +#define _SLIP_MSG_TYPE (NETAPI_MSG_TYPE + 1) +#define _SLIP_STACK_SIZE (KERNEL_CONF_STACKSIZE_DEFAULT) +#define _SLIP_MSG_QUEUE_SIZE (16) +#define _SLIP_MAX_NAME_LEN (24) + +#ifndef _SLIP_REGISTRY_SIZE +#define _SLIP_REGISTRY_SIZE (1) +#endif +#define _SLIP_BUFFER_SIZE (sizeof(border_l3_header_t) + IPV6_MTU) + +typedef struct { + kernel_pid_t control_pid; + kernel_pid_t registry[_SLIP_REGISTRY_SIZE]; + uint8_t esc; + size_t bytes; + ringbuffer_t *in_buf; +} _uart_ctx_t; + +#if UART_NUMOF +_uart_ctx_t _uart_ctx[UART_NUMOF]; +#else +#include "posix_io.h" +#include "board_uart0.h" + +_uart_ctx_t _uart_ctx[1]; +#endif + +#define CTX(arg) ((_uart_ctx_t *)arg) + +static char _slip_control_stack[_SLIP_STACK_SIZE]; + +void _slip_rx_cb(void *arg, char data) +{ + if (((uint8_t)data) == _SLIP_END) { + msg_t msg; + + msg.type = _SLIP_MSG_TYPE; + msg.content.ptr = arg; + + msg_send_receive(&msg, &msg, CTX(arg)->control_pid); + + CTX(arg)->bytes = 0; + } + + if (CTX(arg)->esc) { + CTX(arg)->esc = 0; + + switch ((uint8_t)data) { + case (_SLIP_END_ESC): + ringbuffer_add_one(CTX(arg)->in_buf, _SLIP_ESC); + CTX(arg)->bytes++; + break; + + case (_SLIP_ESC_ESC): + ringbuffer_add_one(CTX(arg)->in_buf, _SLIP_ESC); + CTX(arg)->bytes++; + break; + + default: + break; + } + } + else if ((uint8_t)data == _SLIP_ESC) { + CTX(arg)->esc = 1; + } + else { + ringbuffer_add_one(CTX(arg)->in_buf, data); + CTX(arg)->bytes++; + } +} + +#if UART_NUMOF +static inline int _slip_putc(uart_t uart, uint8_t c) +{ + return uart_write_blocking(uart, (char)c); +} +#else +static char _slip_reader_stack[_SLIP_STACK_SIZE]; + +static void *_slip_reader(void *arg) +{ + msg_t msg_queue[_SLIP_MSG_QUEUE_SIZE]; + + (void)arg; + + msg_init_queue(msg_queue, _SLIP_REGISTRY_SIZE); + + posix_open(uart0_handler_pid, 0); + + while (1) { + _slip_rx_cb(&(_uart_ctx[0]), uart0_readc()); + } + + return NULL; +} + +static int _slip_putc(uart_t uart, char c) +{ + (void)uart; + + uart0_putc(c); + return 1; +} +#endif + +static void _slip_receive(msg_t *uart_msg, _uart_ctx_t *ctx) +{ + netapi_pkt_t rcv; + netapi_ack_t ack_mem; + msg_t l3_pkt, l3_ack, uart_reply; + size_t bytes = ctx->bytes; + + msg_reply(uart_msg, &uart_reply); + + rcv.type = NETAPI_CMD_RCV; + rcv.ack = &ack_mem; + rcv.src = NULL; + rcv.src_len = 0; + rcv.dest = NULL; + rcv.dest_len = 0; + l3_pkt.type = NETAPI_MSG_TYPE; + l3_pkt.content.ptr = (char *)(&rcv); + + for (int i = 0; i < _SLIP_REGISTRY_SIZE; i++) { + if (ctx->registry[i] != KERNEL_PID_UNDEF) { + size_t offset = 0; + + while (offset < ctx->bytes) { + pkt_t *pkt = pktbuf_alloc(bytes); + + ringbuffer_get(ctx->in_buf, pkt->payload_data, bytes - offset); + rcv.pkt = pkt; + netapi_ack_t *ack; + + msg_send_receive(&l3_pkt, &l3_ack, ctx->registry[i]); + pktbuf_release(pkt); + ack = (netapi_ack_t *)(l3_ack.content.ptr); + + if (l3_ack.type == NETAPI_MSG_TYPE && + ack->type == NETAPI_CMD_ACK && + ack->orig == NETAPI_CMD_RCV) { + if (ack->result > 0) { + offset += (ack->result); + } + else { + DEBUG("Error code received from %d: %d", + ctx->registry[i], -ack->result); + + return; + } + } + else { + DEBUG("Unexpected msg instead of ACK. Abort for %d: " + "msg.type = %d, ack->type = %d, ack->orig = %d", + ctx->registry[i], l3_ack->type, ack->type, ack - orig); + return; + } + } + } + } +} + +static int _slip_write(uart_t uart, uint8_t *bytes, size_t len) +{ + int res; + + for (unsigned int i = 0; i < len; i++) { + switch (bytes[i]) { + case _SLIP_END: + if (_slip_putc(uart, _SLIP_ESC) < 0) { + return -EIO; + } + + res = _slip_putc(uart, _SLIP_END_ESC); + break; + + case _SLIP_ESC: + if (_slip_putc(uart, _SLIP_ESC) < 0) { + return -EIO; + } + + res = _slip_putc(uart, _SLIP_ESC_ESC); + break; + + default: + res = _slip_putc(uart, bytes[i]); + break; + } + + if (res < 0) { + return -EIO; + } + } + + return len; +} + +static int _slip_send(uart_t uart, netapi_pkt_t *snd) +{ + int snd_byte = 0, res; + pkt_hlist_t *ptr = snd->pkt->headers; + + pktbuf_hold(snd->pkt); + + while (ptr) { + if ((res = _slip_write(uart, ptr->header_data, ptr->header_len)) < 0) { + return res; + } + + snd_byte += res; + pkt_hlist_advance(&ptr); + } + + if (snd->pkt->payload_data != NULL) { + if ((res = _slip_write(uart, snd->pkt->payload_data, + snd->pkt->payload_len))) { + return res; + } + + snd_byte += res; + } + + _slip_putc(uart, _SLIP_END); + + pktbuf_release(snd->pkt); + + return snd_byte; +} + +static void _slip_handle_cmd(uart_t uart, msg_t *msg_cmd) +{ + msg_t msg_ack; + netapi_cmd_t *cmd = (netapi_cmd_t *)(msg_cmd->content.ptr); + netapi_ack_t *ack = cmd->ack; + + msg_ack.type = NETAPI_MSG_TYPE; + msg_ack.content.ptr = (char *)ack; + + ack->type = NETAPI_CMD_ACK; + ack->orig = cmd->type; + + switch (cmd->type) { + case NETAPI_CMD_SND: + ack->result = _slip_send(uart, (netapi_pkt_t *)cmd); + break; + + case NETAPI_CMD_GET: + switch (((netapi_conf_t *)cmd)->param) { + case NETAPI_CONF_PROTO: + if (((netapi_conf_t *)cmd)->data_len < sizeof(netdev_proto_t)) { + ack->result = -EOVERFLOW; + } + else { + netapi_conf_t *conf = (netapi_conf_t *)cmd; + *((netdev_proto_t *)conf->data) = NETDEV_PROTO_SLIP; + conf->data_len = sizeof(netdev_proto_t); + ack->result = sizeof(netdev_proto_t); + } + + default: + ack->result = -ENOTSUP; + break; + } + + case NETAPI_CMD_REG: + ack->result = -ENOBUFS; + + for (int i = 0; i < _SLIP_REGISTRY_SIZE; i++) { + netapi_reg_t *reg = (netapi_reg_t *)cmd; + + if (_uart_ctx[uart].registry[i] == KERNEL_PID_UNDEF) { + _uart_ctx[uart].registry[i] = reg->reg_pid; + ack->result = NETAPI_STATUS_OK; + break; + } + } + + break; + + case NETAPI_CMD_UNREG: + ack->result = NETAPI_STATUS_OK; + + for (int i = 0; i < _SLIP_REGISTRY_SIZE; i++) { + netapi_reg_t *reg = (netapi_reg_t *)cmd; + + if (_uart_ctx[uart].registry[i] == reg->reg_pid) { + _uart_ctx[uart].registry[i] = KERNEL_PID_UNDEF; + break; + } + } + + break; + + default: + ack->result = -ENOTSUP; + break; + } + + msg_reply(msg_cmd, &msg_ack); +} + +static void *_slip_control(void *arg) +{ + uart_t uart = *((uart_t *)arg); + msg_t msg, msg_queue[_SLIP_MSG_QUEUE_SIZE]; + + (void)arg; + + msg_init_queue(msg_queue, _SLIP_MSG_QUEUE_SIZE); + + while (1) { + msg_receive(&msg); + + switch (msg.type) { + case _SLIP_MSG_TYPE: + _slip_receive(&msg, (_uart_ctx_t *)msg.content.ptr); + break; + + case NETAPI_MSG_TYPE: + _slip_handle_cmd(uart, &msg); + break; + + default: + break; + } + } + + return NULL; +} + +kernel_pid_t slip_init(uart_t uart, uint32_t baudrate, ringbuffer_t *in_buf) +{ + char control_name[_SLIP_MAX_NAME_LEN]; + + sprintf(control_name, "slip_contol_uart%02u", uart); + +#if UART_NUMOF + _uart_ctx[uart].bytes = 0; + _uart_ctx[uart].esc = 0; + _uart_ctx[uart].in_buf = in_buf; + + for (int i = 0; i < _SLIP_REGISTRY_SIZE; i++) { + _uart_ctx[uart].registry[i] = KERNEL_PID_UNDEF; + } + + uart_init(uart, baudrate, _slip_rx_cb, NULL, &(_uart_ctx[uart])); +#else + (void)baudrate; + + _uart_ctx[0].bytes = 0; + _uart_ctx[0].esc = 0; + _uart_ctx[0].in_buf = in_buf; + + + for (int i = 0; i < _SLIP_REGISTRY_SIZE; i++) { + _uart_ctx[0].registry[i] = KERNEL_PID_UNDEF; + } + + thread_create(_slip_reader_stack, _SLIP_STACK_SIZE, PRIORITY_MAIN - 1, 0, + _slip_reader, NULL, "slip_uart_null_reader"); + +#endif + + _uart_ctx[uart].control_pid = thread_create(_slip_control_stack, _SLIP_STACK_SIZE, + PRIORITY_MAIN - 1, 0, _slip_control, &uart, control_name); + + return _uart_ctx[uart].control_pid; +} + +#ifndef MODULE_NETAPI +int slip_send_l3_packet(kernel_pid_t pid, pkt_t *pkt) +{ + msg_t msg_pkt, msg_ack; + netapi_pkt_t snd; + netapi_ack_t ack; + int ack_result; + + msg_pkt.type = NETAPI_MSG_TYPE; + msg_pkt.content.ptr = (char *)(&snd); + + pktbuf_hold(pkt); + + snd.type = NETAPI_CMD_SND; + snd.ack = &ack; + snd.dest = NULL; + snd.dest_len = 0; + snd.pkt = pkt; + + msg_send_receive(&msg_pkt, &msg_ack, pid); + + pktbuf_release(pkt); + + if (msg_ack.content.ptr != (char *)(&ack) || + msg_ack.type != NETAPI_MSG_TYPE || + ack.type != NETAPI_CMD_ACK || + ack.orig != snd.type) { + return -ENOMSG; + } + + ack_result = ack.result; + + return ack_result; +} +#endif diff --git a/tests/slip/Makefile b/tests/slip/Makefile new file mode 100644 index 000000000000..0cd7b5a931c1 --- /dev/null +++ b/tests/slip/Makefile @@ -0,0 +1,9 @@ +APPLICATION = slip +include ../Makefile.tests_common + +USEMODULE += slip +USEMODULE += netapi + +BOARD_WHITELIST += avsextrem iot-lab_M3 msba2 native pttu spark-core + +include $(RIOTBASE)/Makefile.include diff --git a/tests/slip/main.c b/tests/slip/main.c new file mode 100644 index 000000000000..974c0b5f4877 --- /dev/null +++ b/tests/slip/main.c @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2014 Martin Lenders + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup tests + * @{ + * + * @file + * @brief Tests for general network device interface + * + * + * @author Martine Lenders + * + * @} + */ + +#include + +#include "board.h" +#include "kernel.h" +#include "netapi.h" +#include "netdev/base.h" +#include "periph/uart.h" +#include "pktbuf.h" +#include "ringbuffer.h" +#include "slip.h" +#include "thread.h" + +#define MSG_QUEUE_SIZE (4) +#define INBUF_SIZE (64) +#define READER_STACK_SIZE (KERNEL_CONF_STACKSIZE_DEFAULT) + +#ifndef LED_ON +# ifdef LED_GREEN_ON +# define LED_ON LED_GREEN_ON; +# elif defined(LED_ORANGE_ON) +# define LED_ON LED_ORANGE_ON; +# elif defined(LED_RED_ON) +# define LED_ON LED_RED_ON; +# endif +#endif + +#ifndef LED_OFF +# ifdef LED_GREEN_OFF +# define LED_OFF LED_GREEN_OFF; +# elif defined(LED_ORANGE_OFF) +# define LED_OFF LED_ORANGE_OFF; +# elif defined(LED_RED_OFF) +# define LED_OFF LED_RED_OFF; +# endif +#endif + +static char inbuf_mem[INBUF_SIZE], reader_stack[READER_STACK_SIZE]; +static ringbuffer_t inbuf = RINGBUFFER_INIT(inbuf_mem); +static kernel_pid_t slip_pid; + +static void blink_led(pkt_t *pkt) +{ + uint8_t *data = pkt->payload_data; + + for (size_t i = 0; i < pkt->payload_len; i++) { + if (data[i] % 2) { + LED_ON; + } + else { + LED_OFF; + } + } +} + +static inline void echo(pkt_t *pkt) +{ + slip_send_l3_packet(slip_pid, pkt); +} + +static void *reader(void *args) +{ + msg_t msg_rcv, msg_ack, msg_queue[MSG_QUEUE_SIZE]; + + netapi_pkt_t *rcv; + netapi_ack_t *ack; + + (void)args; + + msg_init_queue(msg_queue, MSG_QUEUE_SIZE); + + msg_ack.type = NETAPI_MSG_TYPE; + + while (1) { + msg_receive(&msg_rcv); + + if (msg_rcv.type != NETAPI_MSG_TYPE) { + msg_ack.type = 0; /* Send random reply, API handles this case */ + msg_reply(&msg_rcv, &msg_ack); + continue; + } + + rcv = (netapi_pkt_t *)(msg_rcv.content.ptr); + msg_ack.content.ptr = (char *)rcv->ack; + ack = rcv->ack; + + if (rcv->type != NETAPI_CMD_RCV) { + ack->result = -ENOMSG; + msg_reply(&msg_rcv, &msg_ack); + continue; + } + + pktbuf_hold(rcv->pkt); + msg_reply(&msg_rcv, &msg_ack); + + blink_led(rcv->pkt); + echo(rcv->pkt); + pktbuf_release(rcv->pkt); + } + + return NULL; +} + +int main(void) +{ + kernel_pid_t reader_pid = thread_create(reader_stack, READER_STACK_SIZE, + PRIORITY_MAIN - 1, 0, reader, NULL, + "slip_reader"); + +#if UART_NUMOF + slip_pid = slip_init(UART_0, 115200, &inbuf); +#else + slip_pid = slip_init(0, 115200, &inbuf); +#endif + + netapi_register(slip_pid, reader_pid, 0); + + return 0; +} diff --git a/tests/unittests/tests-nomac/tests-nomac.c b/tests/unittests/tests-nomac/tests-nomac.c index 9c8b0e9772d5..ab294075a68a 100644 --- a/tests/unittests/tests-nomac/tests-nomac.c +++ b/tests/unittests/tests-nomac/tests-nomac.c @@ -12,6 +12,7 @@ #include "clist.h" #include "nomac.h" #include "netdev_dummy.h" +#include "pktbuf.h" #include "thread.h" #include "vtimer.h" @@ -53,7 +54,7 @@ static void _reset_received(void) received_dst_len = 0; } -static void _fill_received(netapi_rcv_pkt_t *rcv) +static void _fill_received(netapi_pkt_t *rcv) { netapi_ack_t *ack = rcv->ack; ack->type = NETAPI_CMD_ACK; @@ -68,8 +69,8 @@ static void _fill_received(netapi_rcv_pkt_t *rcv) received_src_len = rcv->src_len; memcpy(received_dst, rcv->dest, rcv->dest_len); received_dst_len = rcv->dest_len; - memcpy(received_data, rcv->data, rcv->data_len); - received_data_len = rcv->data_len; + memcpy(received_data, rcv->pkt->payload_data, rcv->pkt->payload_len); + received_data_len = rcv->pkt->payload_len; ack->result = received_data_len; return; @@ -79,7 +80,7 @@ static void *test_nomac_receive_thread(void *args) { msg_t msg_rcv, msg_ack, done; - netapi_rcv_pkt_t *rcv; + netapi_pkt_t *rcv; (void)args; @@ -97,7 +98,7 @@ static void *test_nomac_receive_thread(void *args) return NULL; } - rcv = (netapi_rcv_pkt_t *)(msg_rcv.content.ptr); + rcv = (netapi_pkt_t *)(msg_rcv.content.ptr); msg_ack.content.ptr = (char *)rcv->ack; _fill_received(rcv); @@ -129,6 +130,7 @@ static void set_up_with_thread(void) static void tear_down(void) { _reset_received(); + pktbuf_reset(); nomac_receiver = KERNEL_PID_UNDEF; } @@ -147,18 +149,22 @@ static void test_nomac_send_data_dest_too_long(void) { char dest[] = TEST_STRING8; char data[] = TEST_STRING64; - TEST_ASSERT_EQUAL_INT(-EAFNOSUPPORT, netapi_send_payload(nomac_pid, dest, + pkt_t *pkt = pktbuf_insert(data, 1); + + + TEST_ASSERT_EQUAL_INT(-EAFNOSUPPORT, netapi_send_packet(nomac_pid, dest, UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN + TEST_UINT8, - data, 1)); + pkt)); } static void test_nomac_send_data_data_too_long(void) { char dest[] = TEST_STRING8; char data[] = TEST_STRING64; - TEST_ASSERT_EQUAL_INT(-EMSGSIZE, netapi_send_payload(nomac_pid, dest, - UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN, data, - UNITTESTS_NETDEV_DUMMY_MAX_PACKET + TEST_UINT8)); + pkt_t *pkt = pktbuf_insert(data, UNITTESTS_NETDEV_DUMMY_MAX_PACKET + TEST_UINT8); + + TEST_ASSERT_EQUAL_INT(-EMSGSIZE, netapi_send_packet(nomac_pid, dest, + UNITTESTS_NETDEV_DUMMY_MAX_LONG_ADDR_LEN, pkt)); } static void test_nomac_send_data_send(void) @@ -167,12 +173,15 @@ static void test_nomac_send_data_send(void) size_t dest_len = UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN; char data[] = TEST_STRING8; #if UNITTESTS_NETDEV_DUMMY_MAX_PACKET < 8 - size_t data_len = UNITTESTS_NETDEV_DUMMY_MAX_PACKET; + pktsize_t data_len = UNITTESTS_NETDEV_DUMMY_MAX_PACKET; #else - size_t data_len = 8; + pktsize_t data_len = 8; #endif - TEST_ASSERT_EQUAL_INT((int)data_len, netapi_send_payload(nomac_pid, - dest, dest_len, data, data_len)); + pkt_t *pkt = pktbuf_insert(data, data_len); + + + TEST_ASSERT_EQUAL_INT((int)data_len, netapi_send_packet(nomac_pid, + dest, dest_len, pkt)); TEST_ASSERT_EQUAL_INT(0, unittest_netdev_dummy_check_transmitted(dev, dest, dest_len, data, data_len)); } @@ -180,25 +189,25 @@ static void test_nomac_send_data_send(void) #if UNITTESTS_NETDEV_DUMMY_MAX_PACKET > 4 static void test_nomac_send_data_send2(void) { - netdev_hlist_t hlist_node = {NULL, NULL, NETDEV_PROTO_UNKNOWN, TEST_STRING8, 4}; - netdev_hlist_t *hlist = NULL; char dest[] = TEST_STRING64; size_t dest_len = UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN; char data[] = TEST_STRING16; #if UNITTESTS_NETDEV_DUMMY_MAX_PACKET < 12 - size_t data_len = UNITTESTS_NETDEV_DUMMY_MAX_PACKET - 4; + pktsize_t data_len = UNITTESTS_NETDEV_DUMMY_MAX_PACKET - 4; char expected[UNITTESTS_NETDEV_DUMMY_MAX_PACKET]; #else - size_t data_len = 8; + pktsize_t data_len = 8; char expected[12]; #endif + pkt_t *pkt = pktbuf_insert(data, data_len); memcpy(expected, TEST_STRING8, 4); memcpy(&(expected[4]), TEST_STRING16, data_len); - clist_add((clist_node_t **)&hlist, (clist_node_t *)&hlist_node); + pktbuf_add_header(pkt, TEST_STRING8, 4); + TEST_ASSERT_EQUAL_INT((int)sizeof(expected), netapi_send_packet(nomac_pid, - hlist, dest, dest_len, data, data_len)); + dest, dest_len, pkt)); TEST_ASSERT_EQUAL_INT(0, unittest_netdev_dummy_check_transmitted(dev, dest, dest_len, expected, data_len + 4)); } @@ -226,15 +235,16 @@ static void test_nomac_register(void) size_t dest_len = UNITTESTS_NETDEV_DUMMY_MAX_ADDR_LEN; char data[] = TEST_STRING8; #if UNITTESTS_NETDEV_DUMMY_MAX_PACKET < 8 - size_t data_len = UNITTESTS_NETDEV_DUMMY_MAX_PACKET; + pktsize_t data_len = UNITTESTS_NETDEV_DUMMY_MAX_PACKET; #else - size_t data_len = 8; + pktsize_t data_len = 8; #endif int res; + pkt_t *pkt = pktbuf_insert(data, data_len); TEST_ASSERT(nomac_receiver != KERNEL_PID_UNDEF); TEST_ASSERT_EQUAL_INT(0, netapi_register(nomac_pid, nomac_receiver, 0)); - res = netapi_fire_receive_event(nomac_pid, src, src_len, dest, dest_len, data, data_len); + res = netapi_fire_receive_event(nomac_pid, src, src_len, dest, dest_len, pkt); TEST_ASSERT_EQUAL_INT(0, res); msg_receive(&done); diff --git a/tests/unittests/tests-pktbuf/tests-pktbuf.c b/tests/unittests/tests-pktbuf/tests-pktbuf.c index 58e9176611d5..99365377e0e0 100644 --- a/tests/unittests/tests-pktbuf/tests-pktbuf.c +++ b/tests/unittests/tests-pktbuf/tests-pktbuf.c @@ -53,120 +53,130 @@ static void test_pktbuf_alloc_memfull(void) static void test_pktbuf_alloc_success(void) { - void *data, *data_prev = NULL; + pkt_t *pkt, *pkt_prev = NULL; for (int i = 0; i < 9; i++) { - data = pktbuf_alloc((PKTBUF_SIZE / 10) + 4); + pkt = pktbuf_alloc((PKTBUF_SIZE / 10) + 4); - TEST_ASSERT(data_prev < data); + TEST_ASSERT_NOT_NULL(pkt); - data_prev = data; + if (pkt_prev != NULL) { + TEST_ASSERT(pkt_prev < pkt); + TEST_ASSERT(pkt_prev->payload_data < pkt->payload_data); + } + + pkt_prev = pkt; } } -static void test_pktbuf_realloc_0(void) +static void test_pktbuf_realloc_payload_0(void) { - void *data = pktbuf_alloc(512); + pkt_t *pkt = pktbuf_alloc(512); - TEST_ASSERT_NULL(pktbuf_realloc(data, 0)); + TEST_ASSERT_NULL(pktbuf_realloc_payload(pkt, 0)); } -static void test_pktbuf_realloc_memfull(void) +static void test_pktbuf_realloc_payload_memfull(void) { - void *data = pktbuf_alloc(512); + pkt_t *pkt = pktbuf_alloc(512); - TEST_ASSERT_NULL(pktbuf_realloc(data, PKTBUF_SIZE + 1)); + TEST_ASSERT_NULL(pktbuf_realloc_payload(pkt, PKTBUF_SIZE + 1)); } -static void test_pktbuf_realloc_memfull2(void) +static void test_pktbuf_realloc_payload_memfull2(void) { - void *data = pktbuf_alloc(512); + pkt_t *pkt = pktbuf_alloc(512); - TEST_ASSERT_NOT_NULL(data); + TEST_ASSERT_NOT_NULL(pkt); TEST_ASSERT_NOT_NULL(pktbuf_alloc(512)); - TEST_ASSERT_NULL(pktbuf_realloc(data, PKTBUF_SIZE - 512)); + TEST_ASSERT_NULL(pktbuf_realloc_payload(pkt, PKTBUF_SIZE - 512)); } -static void test_pktbuf_realloc_memfull3(void) +static void test_pktbuf_realloc_payload_memfull3(void) { - void *data; + pkt_t *pkt; TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - data = pktbuf_alloc(512); + pkt = pktbuf_alloc(512); - TEST_ASSERT_NOT_NULL(data); + TEST_ASSERT_NOT_NULL(pkt); TEST_ASSERT_NOT_NULL(pktbuf_alloc(73)); - TEST_ASSERT_NULL(pktbuf_realloc(data, PKTBUF_SIZE - 512)); + TEST_ASSERT_NULL(pktbuf_realloc_payload(pkt, PKTBUF_SIZE - 512)); } -static void test_pktbuf_realloc_smaller(void) +static void test_pktbuf_realloc_payload_smaller(void) { - void *data; + pkt_t *pkt; - data = pktbuf_alloc(512); + pkt = pktbuf_alloc(512); - TEST_ASSERT_NOT_NULL(data); + TEST_ASSERT_NOT_NULL(pkt); TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - TEST_ASSERT(data == pktbuf_realloc(data, 128)); + TEST_ASSERT(pkt == pktbuf_realloc_payload(pkt, 128)); } -static void test_pktbuf_realloc_memenough(void) +static void test_pktbuf_realloc_payload_memenough(void) { - void *data; + pkt_t *pkt; - data = pktbuf_alloc(128); + pkt = pktbuf_alloc(128); - TEST_ASSERT_NOT_NULL(data); + TEST_ASSERT_NOT_NULL(pkt); - TEST_ASSERT(data == pktbuf_realloc(data, 200)); + TEST_ASSERT(pkt == pktbuf_realloc_payload(pkt, 200)); } -static void test_pktbuf_realloc_memenough2(void) +static void test_pktbuf_realloc_payload_memenough2(void) { - void *data, *data2; + pkt_t *pkt, *pkt2; - data = pktbuf_alloc(128); + pkt = pktbuf_alloc(128); - TEST_ASSERT_NOT_NULL(data); + TEST_ASSERT_NOT_NULL(pkt); - data2 = pktbuf_alloc(128); + pkt2 = pktbuf_alloc(128); - TEST_ASSERT_NOT_NULL(data); + TEST_ASSERT_NOT_NULL(pkt); TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - pktbuf_release(data2); + pktbuf_release(pkt2); - TEST_ASSERT(data == pktbuf_realloc(data, 200)); + TEST_ASSERT(pkt == pktbuf_realloc_payload(pkt, 200)); } -static void test_pktbuf_realloc_nomemenough(void) +static void test_pktbuf_realloc_payload_nomemenough(void) { - void *data, *data2; + pkt_t *pkt, *pkt2; - data = pktbuf_alloc(128); + pkt = pktbuf_alloc(128); - TEST_ASSERT_NOT_NULL(data); + TEST_ASSERT_NOT_NULL(pkt); - data2 = pktbuf_alloc(128); + pkt2 = pktbuf_alloc(128); - TEST_ASSERT_NOT_NULL(data); + TEST_ASSERT_NOT_NULL(pkt); TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - pktbuf_release(data2); + pktbuf_release(pkt2); - TEST_ASSERT(data != pktbuf_realloc(data, 512)); + TEST_ASSERT(pkt != pktbuf_realloc_payload(pkt, 512)); } -static void test_pktbuf_realloc_unknown_ptr(void) +static void test_pktbuf_realloc_payload_unknown_ptr(void) { - char *data = "abcd", *new_data = pktbuf_realloc(data, 5); + pkt_t pkt = { NULL, "abcd", 4, PKT_PROTO_UNKNOWN }; + pkt_t *new_pkt = pktbuf_realloc_payload(&pkt, 5); - TEST_ASSERT_NOT_NULL(new_data); - TEST_ASSERT(data != new_data); - TEST_ASSERT_EQUAL_STRING(data, new_data); + TEST_ASSERT_NOT_NULL(new_pkt); + TEST_ASSERT_NOT_NULL(new_pkt->payload_data); + TEST_ASSERT(&pkt != new_pkt); + TEST_ASSERT(pkt.payload_data != new_pkt->payload_data); + TEST_ASSERT_EQUAL_STRING(pkt.payload_data, new_pkt->payload_data); + TEST_ASSERT_EQUAL_INT(4, pkt.payload_len); + TEST_ASSERT_EQUAL_INT(5, new_pkt->payload_len); } static void test_pktbuf_insert_size_0(void) @@ -188,256 +198,401 @@ static void test_pktbuf_insert_memfull(void) static void test_pktbuf_insert_success(void) { - char *data, *data_prev = NULL; + pkt_t *pkt, *pkt_prev = NULL; for (int i = 0; i < 10; i++) { - data = (char *)pktbuf_insert("abc", 4); + pkt = pktbuf_insert("abc", 4); + + TEST_ASSERT_NOT_NULL(pkt); - TEST_ASSERT(data_prev < data); - TEST_ASSERT_EQUAL_STRING("abc", data); + if (pkt_prev != NULL) { + TEST_ASSERT(pkt_prev < pkt); + TEST_ASSERT(pkt_prev->payload_data < pkt->payload_data); + } - data_prev = data; + TEST_ASSERT_EQUAL_STRING("abc", pkt->payload_data); + TEST_ASSERT_EQUAL_INT(4, pkt->payload_len); + + pkt_prev = pkt; } } #ifdef DEVELHELP +static void test_pktbuf_copy_einval(void) +{ + TEST_ASSERT_EQUAL_INT(-EINVAL, pktbuf_copy(NULL, "ab", 3)); +} + static void test_pktbuf_copy_efault(void) { - char *data = (char *)pktbuf_insert("abcd", 5); + pkt_t *pkt = pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_EQUAL_INT(-EFAULT, pktbuf_copy(data, NULL, 3)); - TEST_ASSERT_EQUAL_STRING("abcd", data); + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_EQUAL_INT(-EFAULT, pktbuf_copy(pkt->payload_data, NULL, 3)); + TEST_ASSERT_EQUAL_STRING("abcd", pkt->payload_data); + TEST_ASSERT_EQUAL_INT(5, pkt->payload_len); +} + +static void test_pktbuf_copy_einval2(void) +{ + pkt_t *pkt = pktbuf_insert("abcd", 5); + + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_EQUAL_INT(-EINVAL, pktbuf_copy(pkt->headers, "ab", 3)); + TEST_ASSERT_EQUAL_STRING("abcd", pkt->payload_data); + TEST_ASSERT_EQUAL_INT(5, pkt->payload_len); } #endif static void test_pktbuf_copy_data_len_too_long(void) { - char *data = (char *)pktbuf_insert("ab", 3); + pkt_t *pkt = pktbuf_insert("ab", 3); - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_EQUAL_INT(-ENOMEM, pktbuf_copy(data, "cdef", 5)); - TEST_ASSERT_EQUAL_STRING("ab", data); + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_EQUAL_INT(-ENOMEM, pktbuf_copy(pkt->payload_data, "cdef", 5)); + TEST_ASSERT_EQUAL_STRING("ab", pkt->payload_data); + TEST_ASSERT_EQUAL_INT(3, pkt->payload_len); } static void test_pktbuf_copy_data_len_too_long2(void) { - char *data = (char *)pktbuf_insert("abcd", 5); + pkt_t *pkt = pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_EQUAL_INT(-ENOMEM, pktbuf_copy(data + 2, "efgh", 5)); - TEST_ASSERT_EQUAL_STRING("abcd", data); + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_EQUAL_INT(-ENOMEM, pktbuf_copy(((uint8_t *)(pkt->payload_data)) + 2, "efgh", 5)); + TEST_ASSERT_EQUAL_STRING("abcd", pkt->payload_data); + TEST_ASSERT_EQUAL_INT(5, pkt->payload_len); } static void test_pktbuf_copy_data_len_0(void) { - char *data = (char *)pktbuf_insert("abcd", 5); + pkt_t *pkt = pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_EQUAL_INT(0, pktbuf_copy(data, "ef", 0)); - TEST_ASSERT_EQUAL_STRING("abcd", data); + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_EQUAL_INT(0, pktbuf_copy(pkt->payload_data, "ef", 0)); + TEST_ASSERT_EQUAL_STRING("abcd", pkt->payload_data); + TEST_ASSERT_EQUAL_INT(5, pkt->payload_len); } static void test_pktbuf_copy_success(void) { - char *data = (char *)pktbuf_insert("abcd", 5); + pkt_t *pkt = pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_EQUAL_INT(3, pktbuf_copy(data, "ef", 3)); - TEST_ASSERT_EQUAL_STRING("ef", data); + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_EQUAL_INT(3, pktbuf_copy(pkt->payload_data, "ef", 3)); + TEST_ASSERT_EQUAL_STRING("ef", pkt->payload_data); + TEST_ASSERT_EQUAL_INT(5, pkt->payload_len); } static void test_pktbuf_copy_success2(void) { - char *data = (char *)pktbuf_insert("abcdef", 7); + pkt_t *pkt = pktbuf_insert("abcdef", 7); + + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_EQUAL_INT(2, pktbuf_copy(((uint8_t *)(pkt->payload_data)) + 3, "gh", 2)); + TEST_ASSERT_EQUAL_STRING("abcghf", pkt->payload_data); + TEST_ASSERT_EQUAL_INT(7, pkt->payload_len); +} + +#ifdef DEVELHELP +static void test_pktbuf_add_header_efault(void) +{ + pkt_t *pkt = pktbuf_insert("abcd", 5); + + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_EQUAL_INT(-EFAULT, pktbuf_add_header(pkt, NULL, 3)); + TEST_ASSERT_EQUAL_STRING("abcd", pkt->payload_data); + TEST_ASSERT_EQUAL_INT(5, pkt->payload_len); + TEST_ASSERT_NULL(pkt->headers); +} + +static void test_pktbuf_add_header_einval(void) +{ + TEST_ASSERT_EQUAL_INT(-EINVAL, pktbuf_add_header(NULL, "abcd", 3)); +} +#endif + +static void test_pktbuf_add_header_einval2(void) +{ + pkt_t pkt = { NULL, "abcd", 5, PKT_PROTO_UNKNOWN }; + + TEST_ASSERT_EQUAL_INT(-EINVAL, pktbuf_add_header(&pkt, "ef", 3)); + TEST_ASSERT_EQUAL_STRING("abcd", pkt.payload_data); + TEST_ASSERT_EQUAL_INT(5, pkt.payload_len); + TEST_ASSERT_NULL(pkt.headers); +} + +static void test_pktbuf_add_header_header_len_too_long(void) +{ + pkt_t *pkt = pktbuf_insert("ab", 3); - TEST_ASSERT_NOT_NULL(data); - TEST_ASSERT_EQUAL_INT(2, pktbuf_copy(data + 3, "gh", 2)); - TEST_ASSERT_EQUAL_STRING("abcghf", data); + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_EQUAL_INT(-ENOMEM, pktbuf_add_header(pkt, "cdef", PKTBUF_SIZE + 1)); + TEST_ASSERT_EQUAL_STRING("ab", pkt->payload_data); + TEST_ASSERT_EQUAL_INT(3, pkt->payload_len); +} + +static void test_pktbuf_add_header_header_len_0(void) +{ + pkt_t *pkt = pktbuf_insert("abcd", 5); + + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_EQUAL_INT(-ENOMEM, pktbuf_add_header(pkt, "ef", 0)); + TEST_ASSERT_EQUAL_STRING("abcd", pkt->payload_data); + TEST_ASSERT_EQUAL_INT(5, pkt->payload_len); + TEST_ASSERT_NULL(pkt->headers); +} + +static void test_pktbuf_add_header_success(void) +{ + pkt_t *pkt = pktbuf_insert("abcd", 5); + + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_EQUAL_INT(0, pktbuf_add_header(pkt, "ef", 2)); + TEST_ASSERT_EQUAL_STRING("abcd", pkt->payload_data); + TEST_ASSERT_EQUAL_INT(5, pkt->payload_len); + TEST_ASSERT_NOT_NULL(pkt->headers); + TEST_ASSERT_EQUAL_STRING("ef", pkt->headers->header_data); + TEST_ASSERT_EQUAL_INT(2, pkt->headers->header_len); + TEST_ASSERT_NULL(pkt->headers->next); +} + +static void test_pktbuf_add_header_success2(void) +{ + pkt_t *pkt = pktbuf_insert("abcd", 5); + + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_EQUAL_INT(0, pktbuf_add_header(pkt, "ef", 2)); + TEST_ASSERT_NOT_NULL(pkt->headers); + TEST_ASSERT_NULL(pkt->headers->next); + TEST_ASSERT_EQUAL_INT(0, pktbuf_add_header(pkt, "ghi", 3)); + TEST_ASSERT_EQUAL_STRING("abcd", pkt->payload_data); + TEST_ASSERT_EQUAL_INT(5, pkt->payload_len); + TEST_ASSERT_NOT_NULL(pkt->headers); + TEST_ASSERT_EQUAL_STRING("ghi", pkt->headers->header_data); + TEST_ASSERT_EQUAL_INT(3, pkt->headers->header_len); + TEST_ASSERT_NOT_NULL(pkt->headers->next); + TEST_ASSERT_EQUAL_STRING("ef", pkt->headers->next->header_data); + TEST_ASSERT_EQUAL_INT(2, pkt->headers->next->header_len); + TEST_ASSERT_NULL(pkt->headers->next->next); +} + +static void test_pktbuf_remove_header_success(void) +{ + pkt_t *pkt = pktbuf_insert("abcd", 5); + + TEST_ASSERT_NOT_NULL(pkt); + TEST_ASSERT_EQUAL_INT(0, pktbuf_add_header(pkt, "ef", 3)); + TEST_ASSERT_EQUAL_INT(0, pktbuf_add_header(pkt, "ghi", 4)); + TEST_ASSERT_EQUAL_INT(0, pktbuf_add_header(pkt, "j", 2)); + pktbuf_remove_header(pkt, pkt->headers->next); + + TEST_ASSERT_EQUAL_STRING("abcd", pkt->payload_data); + TEST_ASSERT_EQUAL_INT(5, pkt->payload_len); + TEST_ASSERT_NOT_NULL(pkt->headers); + TEST_ASSERT_EQUAL_STRING("j", pkt->headers->header_data); + TEST_ASSERT_EQUAL_INT(2, pkt->headers->header_len); + TEST_ASSERT_NOT_NULL(pkt->headers->next); + TEST_ASSERT_EQUAL_STRING("ef", pkt->headers->next->header_data); + TEST_ASSERT_EQUAL_INT(3, pkt->headers->next->header_len); + TEST_ASSERT_NULL(pkt->headers->next->next); + + pktbuf_remove_header(pkt, pkt->headers); + + TEST_ASSERT_EQUAL_STRING("abcd", pkt->payload_data); + TEST_ASSERT_EQUAL_INT(5, pkt->payload_len); + TEST_ASSERT_NOT_NULL(pkt->headers); + TEST_ASSERT_EQUAL_STRING("ef", pkt->headers->header_data); + TEST_ASSERT_EQUAL_INT(3, pkt->headers->header_len); + TEST_ASSERT_NULL(pkt->headers->next); + + pktbuf_remove_header(pkt, pkt->headers); + + TEST_ASSERT_NULL(pkt->headers); } static void test_pktbuf_hold_ptr_null(void) { - char *data; + pkt_t *pkt; TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - data = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); + pkt = pktbuf_insert("abcd", 5); + TEST_ASSERT_NOT_NULL(pkt); TEST_ASSERT_NOT_NULL(pktbuf_alloc(16)); TEST_ASSERT_EQUAL_INT(3, pktbuf_packets_allocated()); pktbuf_hold(NULL); - pktbuf_release(data); + pktbuf_release(pkt); TEST_ASSERT_EQUAL_INT(2, pktbuf_packets_allocated()); - TEST_ASSERT_EQUAL_STRING("abcd", data); + TEST_ASSERT_EQUAL_STRING("abcd", pkt->payload_data); } static void test_pktbuf_hold_wrong_ptr(void) { - char *data, wrong; + pkt_t *pkt, wrong; TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - data = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); + pkt = pktbuf_insert("abcd", 5); + TEST_ASSERT_NOT_NULL(pkt); TEST_ASSERT_NOT_NULL(pktbuf_alloc(16)); TEST_ASSERT_EQUAL_INT(3, pktbuf_packets_allocated()); pktbuf_hold(&wrong); - pktbuf_release(data); + pktbuf_release(pkt); TEST_ASSERT_EQUAL_INT(2, pktbuf_packets_allocated()); - TEST_ASSERT_EQUAL_STRING("abcd", data); + TEST_ASSERT_EQUAL_STRING("abcd", pkt->payload_data); } static void test_pktbuf_hold_success(void) { - char *data; + pkt_t *pkt; TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - data = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); + pkt = pktbuf_insert("abcd", 5); + TEST_ASSERT_NOT_NULL(pkt); TEST_ASSERT_NOT_NULL(pktbuf_alloc(16)); - pktbuf_hold(data); - pktbuf_release(data); + pktbuf_hold(pkt); + pktbuf_release(pkt); - TEST_ASSERT_EQUAL_INT(3, pktbuf_copy(data, "ef", 3)); - TEST_ASSERT_EQUAL_STRING("ef", data); + TEST_ASSERT_EQUAL_INT(3, pktbuf_copy(pkt->payload_data, "ef", 3)); + TEST_ASSERT_EQUAL_STRING("ef", pkt->payload_data); } static void test_pktbuf_hold_success2(void) { - char *data; + pkt_t *pkt; TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - data = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); + pkt = pktbuf_insert("abcd", 5); + TEST_ASSERT_NOT_NULL(pkt); TEST_ASSERT_NOT_NULL(pktbuf_alloc(16)); - pktbuf_hold(data + 4); - pktbuf_release(data + 4); + pktbuf_hold(pkt + 4); + pktbuf_release(pkt + 4); - TEST_ASSERT_EQUAL_INT(3, pktbuf_copy(data, "ef", 3)); - TEST_ASSERT_EQUAL_STRING("ef", data); + TEST_ASSERT_EQUAL_INT(3, pktbuf_copy(pkt->payload_data, "ef", 3)); + TEST_ASSERT_EQUAL_STRING("ef", pkt->payload_data); } static void test_pktbuf_release_ptr_null(void) { - char *data; + pkt_t *pkt; TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - data = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); + pkt = pktbuf_insert("abcd", 5); + TEST_ASSERT_NOT_NULL(pkt); TEST_ASSERT_NOT_NULL(pktbuf_alloc(16)); pktbuf_release(NULL); - TEST_ASSERT_EQUAL_INT(3, pktbuf_copy(data, "ef", 3)); - TEST_ASSERT_EQUAL_STRING("ef", data); + TEST_ASSERT_EQUAL_INT(3, pktbuf_copy(pkt->payload_data, "ef", 3)); + TEST_ASSERT_EQUAL_STRING("ef", pkt->payload_data); } static void test_pktbuf_release_wrong_ptr(void) { - char *data, wrong; + pkt_t *pkt, wrong; TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - data = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); + pkt = pktbuf_insert("abcd", 5); + TEST_ASSERT_NOT_NULL(pkt); TEST_ASSERT_NOT_NULL(pktbuf_alloc(16)); pktbuf_release(&wrong); - TEST_ASSERT_EQUAL_INT(3, pktbuf_copy(data, "ef", 3)); - TEST_ASSERT_EQUAL_STRING("ef", data); + TEST_ASSERT_EQUAL_INT(3, pktbuf_copy(pkt->payload_data, "ef", 3)); + TEST_ASSERT_EQUAL_STRING("ef", pkt->payload_data); } static void test_pktbuf_release_success(void) { - char *data; + pkt_t *pkt; TEST_ASSERT_NOT_NULL(pktbuf_alloc(25)); - data = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data); + pkt = pktbuf_insert("abcd", 5); + TEST_ASSERT_NOT_NULL(pkt); TEST_ASSERT_NOT_NULL(pktbuf_alloc(16)); TEST_ASSERT_EQUAL_INT(3, pktbuf_packets_allocated()); - pktbuf_hold(data); - pktbuf_hold(data); - pktbuf_release(data + 3); - pktbuf_release(data + 4); - pktbuf_release(data + 2); + pktbuf_hold(pkt); + pktbuf_hold(pkt); + pktbuf_release(pkt); + pktbuf_release(pkt); + pktbuf_release(pkt); TEST_ASSERT_EQUAL_INT(2, pktbuf_packets_allocated()); } static void test_pktbuf_release_success2(void) { - char *data1, *data2, *data3; + pkt_t *pkt1, *pkt2, *pkt3; - data1 = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data1); - data2 = (char *)pktbuf_insert("ef", 3); - TEST_ASSERT_NOT_NULL(data2); - data3 = (char *)pktbuf_insert("ghijkl", 7); - TEST_ASSERT_NOT_NULL(data3); + pkt1 = pktbuf_insert("abcd", 5); + TEST_ASSERT_NOT_NULL(pkt1); + pkt2 = pktbuf_insert("ef", 3); + TEST_ASSERT_NOT_NULL(pkt2); + pkt3 = pktbuf_insert("ghijkl", 7); + TEST_ASSERT_NOT_NULL(pkt3); TEST_ASSERT_EQUAL_INT(3, pktbuf_packets_allocated()); - pktbuf_release(data2); + pktbuf_release(pkt2); TEST_ASSERT_EQUAL_INT(2, pktbuf_packets_allocated()); - TEST_ASSERT_EQUAL_INT(2, pktbuf_copy(data1, "m", 2)); - TEST_ASSERT_EQUAL_STRING("m", data1); - TEST_ASSERT_EQUAL_INT(4, pktbuf_copy(data3, "nop", 4)); - TEST_ASSERT_EQUAL_STRING("nop", data3); + TEST_ASSERT_EQUAL_INT(2, pktbuf_copy(pkt1->payload_data, "m", 2)); + TEST_ASSERT_EQUAL_STRING("m", pkt1->payload_data); + TEST_ASSERT_EQUAL_INT(4, pktbuf_copy(pkt3->payload_data, "nop", 4)); + TEST_ASSERT_EQUAL_STRING("nop", pkt3->payload_data); } static void test_pktbuf_release_success3(void) { - char *data1, *data2, *data3; + pkt_t *pkt1, *pkt2, *pkt3; - data1 = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data1); - data2 = (char *)pktbuf_insert("ef", 3); - TEST_ASSERT_NOT_NULL(data2); - data3 = (char *)pktbuf_insert("ghijkl", 7); - TEST_ASSERT_NOT_NULL(data3); + pkt1 = pktbuf_insert("abcd", 5); + TEST_ASSERT_NOT_NULL(pkt1); + pkt2 = pktbuf_insert("ef", 3); + TEST_ASSERT_NOT_NULL(pkt2); + pkt3 = pktbuf_insert("ghijkl", 7); + TEST_ASSERT_NOT_NULL(pkt3); TEST_ASSERT_EQUAL_INT(3, pktbuf_packets_allocated()); - pktbuf_release(data1); + pktbuf_release(pkt1); TEST_ASSERT_EQUAL_INT(2, pktbuf_packets_allocated()); - TEST_ASSERT_EQUAL_INT(2, pktbuf_copy(data2, "m", 2)); - TEST_ASSERT_EQUAL_STRING("m", data2); - TEST_ASSERT_EQUAL_INT(4, pktbuf_copy(data3, "nop", 4)); - TEST_ASSERT_EQUAL_STRING("nop", data3); + TEST_ASSERT_EQUAL_INT(2, pktbuf_copy(pkt2->payload_data, "m", 2)); + TEST_ASSERT_EQUAL_STRING("m", pkt2->payload_data); + TEST_ASSERT_EQUAL_INT(4, pktbuf_copy(pkt3->payload_data, "nop", 4)); + TEST_ASSERT_EQUAL_STRING("nop", pkt3->payload_data); } static void test_pktbuf_release_success4(void) { - char *data1, *data2, *data3; + pkt_t *pkt1, *pkt2, *pkt3; - data1 = (char *)pktbuf_insert("abcd", 5); - TEST_ASSERT_NOT_NULL(data1); - data2 = (char *)pktbuf_insert("ef", 3); - TEST_ASSERT_NOT_NULL(data2); - data3 = (char *)pktbuf_insert("ghijkl", 7); - TEST_ASSERT_NOT_NULL(data3); + pkt1 = pktbuf_insert("abcd", 5); + TEST_ASSERT_NOT_NULL(pkt1); + pkt2 = pktbuf_insert("ef", 3); + TEST_ASSERT_NOT_NULL(pkt2); + pkt3 = pktbuf_insert("ghijkl", 7); + TEST_ASSERT_NOT_NULL(pkt3); TEST_ASSERT_EQUAL_INT(3, pktbuf_packets_allocated()); - pktbuf_release(data3); + pktbuf_release(pkt3); TEST_ASSERT_EQUAL_INT(2, pktbuf_packets_allocated()); - TEST_ASSERT_EQUAL_INT(2, pktbuf_copy(data1, "m", 2)); - TEST_ASSERT_EQUAL_STRING("m", data1); - TEST_ASSERT_EQUAL_INT(1, pktbuf_copy(data2, "", 1)); - TEST_ASSERT_EQUAL_STRING("", data2); + TEST_ASSERT_EQUAL_INT(2, pktbuf_copy(pkt1->payload_data, "m", 2)); + TEST_ASSERT_EQUAL_STRING("m", pkt1->payload_data); + TEST_ASSERT_EQUAL_INT(1, pktbuf_copy(pkt2->payload_data, "", 1)); + TEST_ASSERT_EQUAL_STRING("", pkt2->payload_data); } static void test_pktbuf_insert_packed_struct(void) @@ -446,8 +601,10 @@ static void test_pktbuf_insert_packed_struct(void) 34, -4469, 149699748, -46590430597 }; test_pktbuf_struct_t *data_cpy; + pkt_t *pkt; - data_cpy = (test_pktbuf_struct_t *)pktbuf_insert(&data, sizeof(test_pktbuf_struct_t)); + pkt = pktbuf_insert(&data, sizeof(test_pktbuf_struct_t)); + data_cpy = (test_pktbuf_struct_t *)pkt->payload_data; TEST_ASSERT_EQUAL_INT(data.u8, data_cpy->u8); TEST_ASSERT_EQUAL_INT(data.u16, data_cpy->u16); @@ -461,25 +618,25 @@ static void test_pktbuf_insert_packed_struct(void) static void test_pktbuf_alloc_off_by_one1(void) { - char *data1, *data2, *data3, *data4; + pkt_t *pkt1, *pkt2, *pkt3, *pkt4; - data1 = (char *)pktbuf_insert("1234567890a", 12); - TEST_ASSERT_NOT_NULL(data1); - data2 = (char *)pktbuf_alloc(44); - TEST_ASSERT_NOT_NULL(data2); - data4 = (char *)pktbuf_alloc(4); - TEST_ASSERT_NOT_NULL(data4); + pkt1 = pktbuf_insert("1234567890a", 12); + TEST_ASSERT_NOT_NULL(pkt1); + pkt2 = pktbuf_alloc(44); + TEST_ASSERT_NOT_NULL(pkt2); + pkt4 = pktbuf_alloc(4); + TEST_ASSERT_NOT_NULL(pkt4); TEST_ASSERT_EQUAL_INT(3, pktbuf_packets_allocated()); TEST_ASSERT_EQUAL_INT(12 + 44 + 4, pktbuf_bytes_allocated()); - pktbuf_release(data1); + pktbuf_release(pkt1); TEST_ASSERT_EQUAL_INT(2, pktbuf_packets_allocated()); TEST_ASSERT_EQUAL_INT(44 + 4, pktbuf_bytes_allocated()); - data3 = (char *)pktbuf_insert("bcdefghijklm", 13); - TEST_ASSERT_NOT_NULL(data3); - TEST_ASSERT(data1 != data3); + pkt3 = pktbuf_insert("bcdefghijklm", 13); + TEST_ASSERT_NOT_NULL(pkt3); + TEST_ASSERT(pkt1 != pkt3); TEST_ASSERT_EQUAL_INT(3, pktbuf_packets_allocated()); TEST_ASSERT_EQUAL_INT(44 + 4 + 13, pktbuf_bytes_allocated()); @@ -491,27 +648,39 @@ Test *tests_pktbuf_tests(void) new_TestFixture(test_pktbuf_alloc_0), new_TestFixture(test_pktbuf_alloc_memfull), new_TestFixture(test_pktbuf_alloc_success), - new_TestFixture(test_pktbuf_realloc_0), - new_TestFixture(test_pktbuf_realloc_memfull), - new_TestFixture(test_pktbuf_realloc_memfull2), - new_TestFixture(test_pktbuf_realloc_memfull3), - new_TestFixture(test_pktbuf_realloc_smaller), - new_TestFixture(test_pktbuf_realloc_memenough), - new_TestFixture(test_pktbuf_realloc_memenough2), - new_TestFixture(test_pktbuf_realloc_nomemenough), - new_TestFixture(test_pktbuf_realloc_unknown_ptr), + new_TestFixture(test_pktbuf_realloc_payload_0), + new_TestFixture(test_pktbuf_realloc_payload_memfull), + new_TestFixture(test_pktbuf_realloc_payload_memfull2), + new_TestFixture(test_pktbuf_realloc_payload_memfull3), + new_TestFixture(test_pktbuf_realloc_payload_smaller), + new_TestFixture(test_pktbuf_realloc_payload_memenough), + new_TestFixture(test_pktbuf_realloc_payload_memenough2), + new_TestFixture(test_pktbuf_realloc_payload_nomemenough), + new_TestFixture(test_pktbuf_realloc_payload_unknown_ptr), new_TestFixture(test_pktbuf_insert_size_0), new_TestFixture(test_pktbuf_insert_data_NULL), new_TestFixture(test_pktbuf_insert_memfull), new_TestFixture(test_pktbuf_insert_success), #ifdef DEVELHELP new_TestFixture(test_pktbuf_copy_efault), + new_TestFixture(test_pktbuf_copy_einval), + new_TestFixture(test_pktbuf_copy_einval2), #endif new_TestFixture(test_pktbuf_copy_data_len_too_long), new_TestFixture(test_pktbuf_copy_data_len_too_long2), new_TestFixture(test_pktbuf_copy_data_len_0), new_TestFixture(test_pktbuf_copy_success), new_TestFixture(test_pktbuf_copy_success2), +#ifdef DEVELHELP + new_TestFixture(test_pktbuf_add_header_efault), + new_TestFixture(test_pktbuf_add_header_einval), +#endif + new_TestFixture(test_pktbuf_add_header_einval2), + new_TestFixture(test_pktbuf_add_header_header_len_too_long), + new_TestFixture(test_pktbuf_add_header_header_len_0), + new_TestFixture(test_pktbuf_add_header_success), + new_TestFixture(test_pktbuf_add_header_success2), + new_TestFixture(test_pktbuf_remove_header_success), new_TestFixture(test_pktbuf_hold_ptr_null), new_TestFixture(test_pktbuf_hold_wrong_ptr), new_TestFixture(test_pktbuf_hold_success),