updated picoTCP to 1.4.0, lowered build optimization levels to -O2, improved selftest
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/*********************************************************************
|
||||
PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved.
|
||||
See LICENSE and COPYING for usage.
|
||||
PicoTCP. Copyright (c) 2012-2017 Altran Intelligent Systems. Some rights reserved.
|
||||
See COPYING, LICENSE.GPLv2 and LICENSE.GPLv3 for usage.
|
||||
|
||||
.
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
#include "pico_ipv4.h"
|
||||
#include "pico_icmp6.h"
|
||||
#include "pico_eth.h"
|
||||
#include "pico_802154.h"
|
||||
#include "pico_6lowpan.h"
|
||||
#include "pico_6lowpan_ll.h"
|
||||
#include "pico_addressing.h"
|
||||
#define PICO_DEVICE_DEFAULT_MTU (1500)
|
||||
|
||||
struct pico_devices_rr_info {
|
||||
@@ -32,6 +36,7 @@ static int pico_dev_cmp(void *ka, void *kb)
|
||||
if (a->hash < b->hash)
|
||||
return -1;
|
||||
|
||||
|
||||
if (a->hash > b->hash)
|
||||
return 1;
|
||||
|
||||
@@ -40,6 +45,43 @@ static int pico_dev_cmp(void *ka, void *kb)
|
||||
|
||||
PICO_TREE_DECLARE(Device_tree, pico_dev_cmp);
|
||||
|
||||
#ifdef PICO_SUPPORT_6LOWPAN
|
||||
static struct pico_ipv6_link * pico_6lowpan_link_add(struct pico_device *dev, const struct pico_ip6 *prefix)
|
||||
{
|
||||
struct pico_ip6 netmask64 = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
struct pico_6lowpan_info *info = (struct pico_6lowpan_info *)dev->eth;
|
||||
struct pico_ipv6_link *link = NULL; /* Make sure to return NULL */
|
||||
struct pico_ip6 newaddr;
|
||||
|
||||
memcpy(newaddr.addr, prefix->addr, PICO_SIZE_IP6);
|
||||
memcpy(newaddr.addr + 8, info->addr_ext.addr, SIZE_6LOWPAN_EXT);
|
||||
newaddr.addr[8] = newaddr.addr[8] ^ 0x02; /* Toggle U/L bit */
|
||||
|
||||
/* RFC6775: No Duplicate Address Detection (DAD) is performed if
|
||||
* EUI-64-based IPv6 addresses are used (as these addresses are assumed
|
||||
* to be globally unique). */
|
||||
if ((link = pico_ipv6_link_add_no_dad(dev, newaddr, netmask64))) {
|
||||
if (pico_ipv6_is_linklocal(newaddr.addr))
|
||||
pico_6lp_nd_start_soliciting(link, NULL);
|
||||
else
|
||||
pico_6lp_nd_register(link);
|
||||
}
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
static int pico_6lowpan_store_info(struct pico_device *dev, const uint8_t *mac)
|
||||
{
|
||||
if ((dev->eth = PICO_ZALLOC(sizeof(struct pico_6lowpan_info)))) {
|
||||
memcpy(dev->eth, mac, sizeof(struct pico_6lowpan_info));
|
||||
return 0;
|
||||
} else {
|
||||
pico_err = PICO_ERR_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
static void device_init_ipv6_final(struct pico_device *dev, struct pico_ip6 *linklocal)
|
||||
{
|
||||
@@ -47,62 +89,78 @@ static void device_init_ipv6_final(struct pico_device *dev, struct pico_ip6 *lin
|
||||
/* RFC 4861 $6.3.2 value between 0.5 and 1.5 times basetime */
|
||||
dev->hostvars.reachabletime = ((5 + (pico_rand() % 10)) * PICO_ND_REACHABLE_TIME) / 10;
|
||||
dev->hostvars.retranstime = PICO_ND_RETRANS_TIMER;
|
||||
pico_icmp6_router_solicitation(dev, linklocal);
|
||||
pico_icmp6_router_solicitation(dev, linklocal, NULL);
|
||||
dev->hostvars.hoplimit = PICO_IPV6_DEFAULT_HOP;
|
||||
}
|
||||
|
||||
struct pico_ipv6_link *pico_ipv6_link_add_local(struct pico_device *dev, const struct pico_ip6 *prefix)
|
||||
{
|
||||
struct pico_ip6 newaddr;
|
||||
struct pico_ip6 netmask64 = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
struct pico_ipv6_link *link;
|
||||
memcpy(newaddr.addr, prefix->addr, PICO_SIZE_IP6);
|
||||
/* modified EUI-64 + invert universal/local bit */
|
||||
newaddr.addr[8] = (dev->eth->mac.addr[0] ^ 0x02);
|
||||
newaddr.addr[9] = dev->eth->mac.addr[1];
|
||||
newaddr.addr[10] = dev->eth->mac.addr[2];
|
||||
newaddr.addr[11] = 0xff;
|
||||
newaddr.addr[12] = 0xfe;
|
||||
newaddr.addr[13] = dev->eth->mac.addr[3];
|
||||
newaddr.addr[14] = dev->eth->mac.addr[4];
|
||||
newaddr.addr[15] = dev->eth->mac.addr[5];
|
||||
link = pico_ipv6_link_add(dev, newaddr, netmask64);
|
||||
if (link) {
|
||||
device_init_ipv6_final(dev, &newaddr);
|
||||
struct pico_ipv6_link *link = NULL; /* Make sure to return NULL */
|
||||
struct pico_ip6 newaddr;
|
||||
|
||||
if (0) {}
|
||||
#ifdef PICO_SUPPORT_6LOWPAN
|
||||
else if (PICO_DEV_IS_6LOWPAN(dev)) {
|
||||
link = pico_6lowpan_link_add(dev, prefix);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
memcpy(newaddr.addr, prefix->addr, PICO_SIZE_IP6);
|
||||
/* modified EUI-64 + invert universal/local bit */
|
||||
newaddr.addr[8] = (dev->eth->mac.addr[0] ^ 0x02);
|
||||
newaddr.addr[9] = dev->eth->mac.addr[1];
|
||||
newaddr.addr[10] = dev->eth->mac.addr[2];
|
||||
newaddr.addr[11] = 0xff;
|
||||
newaddr.addr[12] = 0xfe;
|
||||
newaddr.addr[13] = dev->eth->mac.addr[3];
|
||||
newaddr.addr[14] = dev->eth->mac.addr[4];
|
||||
newaddr.addr[15] = dev->eth->mac.addr[5];
|
||||
if ((link = pico_ipv6_link_add(dev, newaddr, netmask64))) {
|
||||
device_init_ipv6_final(dev, &newaddr);
|
||||
}
|
||||
}
|
||||
|
||||
return link;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int device_init_mac(struct pico_device *dev, uint8_t *mac)
|
||||
static int device_init_mac(struct pico_device *dev, const uint8_t *mac)
|
||||
{
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
struct pico_ip6 linklocal = {{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xff, 0xfe, 0xaa, 0xaa, 0xaa}};
|
||||
#endif
|
||||
dev->eth = PICO_ZALLOC(sizeof(struct pico_ethdev));
|
||||
if (dev->eth) {
|
||||
memcpy(dev->eth->mac.addr, mac, PICO_SIZE_ETH);
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
if (pico_ipv6_link_add_local(dev, &linklocal) == NULL) {
|
||||
PICO_FREE(dev->q_in);
|
||||
PICO_FREE(dev->q_out);
|
||||
PICO_FREE(dev->eth);
|
||||
#endif
|
||||
|
||||
if (0) {}
|
||||
#ifdef PICO_SUPPORT_6LOWPAN
|
||||
else if (PICO_DEV_IS_6LOWPAN(dev)) {
|
||||
if (pico_6lowpan_store_info(dev, mac))
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
if ((dev->eth = PICO_ZALLOC(sizeof(struct pico_ethdev)))) {
|
||||
memcpy(dev->eth->mac.addr, mac, PICO_SIZE_ETH);
|
||||
} else {
|
||||
pico_err = PICO_ERR_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
} else {
|
||||
pico_err = PICO_ERR_ENOMEM;
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
if (pico_ipv6_link_add_local(dev, &linklocal) == NULL) {
|
||||
PICO_FREE(dev->q_in);
|
||||
PICO_FREE(dev->q_out);
|
||||
PICO_FREE(dev->eth);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pico_device_ipv6_random_ll(struct pico_device *dev)
|
||||
{
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
struct pico_ip6 linklocal = {{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xff, 0xfe, 0xaa, 0xaa, 0xaa}};
|
||||
struct pico_ip6 netmask6 = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
|
||||
uint32_t len = (uint32_t)strlen(dev->name);
|
||||
@@ -127,7 +185,7 @@ int pico_device_ipv6_random_ll(struct pico_device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -143,10 +201,17 @@ static int device_init_nomac(struct pico_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int pico_device_init(struct pico_device *dev, const char *name, uint8_t *mac)
|
||||
#define DEBUG_IPV6(ip) { \
|
||||
char ipstr[40] = { 0 }; \
|
||||
pico_ipv6_to_string(ipstr, (ip).addr); \
|
||||
dbg("IPv6 (%s)\n", ipstr); \
|
||||
}
|
||||
|
||||
int pico_device_init(struct pico_device *dev, const char *name, const uint8_t *mac)
|
||||
{
|
||||
uint32_t len = (uint32_t)strlen(name);
|
||||
int ret = 0;
|
||||
|
||||
if(len > MAX_DEVICE_NAME)
|
||||
len = MAX_DEVICE_NAME;
|
||||
|
||||
@@ -165,16 +230,33 @@ extern int pico_device_init(struct pico_device *dev, const char *name, uint8_t *
|
||||
return -1;
|
||||
}
|
||||
|
||||
pico_tree_insert(&Device_tree, dev);
|
||||
if (pico_tree_insert(&Device_tree, dev)) {
|
||||
PICO_FREE(dev->q_in);
|
||||
PICO_FREE(dev->q_out);
|
||||
return -1;
|
||||
}
|
||||
if (!dev->mtu)
|
||||
dev->mtu = PICO_DEVICE_DEFAULT_MTU;
|
||||
|
||||
#ifdef PICO_SUPPORT_6LOWPAN
|
||||
if (PICO_DEV_IS_6LOWPAN(dev) && LL_MODE_ETHERNET == dev->mode)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
if (mac) {
|
||||
ret = device_init_mac(dev, mac);
|
||||
} else {
|
||||
ret = device_init_nomac(dev);
|
||||
if (!dev->mode) {
|
||||
ret = device_init_nomac(dev);
|
||||
}
|
||||
#ifdef PICO_SUPPORT_6LOWPAN
|
||||
else {
|
||||
/* RFC6775: Link Local to be formed based on EUI-64 as per RFC6775 */
|
||||
dbg("Link local address to be formed based on EUI-64\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -192,7 +274,7 @@ void pico_device_destroy(struct pico_device *dev)
|
||||
pico_queue_destroy(dev->q_in);
|
||||
pico_queue_destroy(dev->q_out);
|
||||
|
||||
if (dev->eth)
|
||||
if (!dev->mode && dev->eth)
|
||||
PICO_FREE(dev->eth);
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV4
|
||||
@@ -202,7 +284,7 @@ void pico_device_destroy(struct pico_device *dev)
|
||||
pico_ipv6_cleanup_links(dev);
|
||||
#endif
|
||||
pico_tree_delete(&Device_tree, dev);
|
||||
|
||||
|
||||
if (dev->destroy)
|
||||
dev->destroy(dev);
|
||||
|
||||
@@ -240,14 +322,7 @@ static int devloop_in(struct pico_device *dev, int loop_score)
|
||||
/* Receive */
|
||||
f = pico_dequeue(dev->q_in);
|
||||
if (f) {
|
||||
if (dev->eth) {
|
||||
f->datalink_hdr = f->buffer;
|
||||
(void)pico_ethernet_receive(f);
|
||||
} else {
|
||||
f->net_hdr = f->buffer;
|
||||
pico_network_receive(f);
|
||||
}
|
||||
|
||||
pico_datalink_receive(f);
|
||||
loop_score--;
|
||||
}
|
||||
}
|
||||
@@ -256,14 +331,12 @@ static int devloop_in(struct pico_device *dev, int loop_score)
|
||||
|
||||
static int devloop_sendto_dev(struct pico_device *dev, struct pico_frame *f)
|
||||
{
|
||||
|
||||
if (dev->eth) {
|
||||
/* Ethernet: pass management of the frame to the pico_ethernet_send() rdv function */
|
||||
return pico_ethernet_send(f);
|
||||
} else {
|
||||
/* non-ethernet: no post-processing needed */
|
||||
return (dev->send(dev, f->start, (int)f->len) <= 0); /* Return 0 upon success, which is dev->send() > 0 */
|
||||
#ifdef PICO_SUPPORT_6LOWPAN
|
||||
if (PICO_DEV_IS_6LOWPAN(dev)) {
|
||||
return (pico_6lowpan_ll_sendto_dev(dev, f) <= 0);
|
||||
}
|
||||
#endif
|
||||
return (dev->send(dev, f->start, (int)f->len) <= 0);
|
||||
}
|
||||
|
||||
static int devloop_out(struct pico_device *dev, int loop_score)
|
||||
@@ -286,6 +359,7 @@ static int devloop_out(struct pico_device *dev, int loop_score)
|
||||
break; /* Don't discard */
|
||||
|
||||
}
|
||||
|
||||
return loop_score;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/*********************************************************************
|
||||
PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved.
|
||||
See LICENSE and COPYING for usage.
|
||||
PicoTCP. Copyright (c) 2012-2017 Altran Intelligent Systems. Some rights reserved.
|
||||
See COPYING, LICENSE.GPLv2 and LICENSE.GPLv3 for usage.
|
||||
|
||||
.
|
||||
|
||||
Authors: Daniele Lacamera
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
#include "pico_config.h"
|
||||
#include "pico_frame.h"
|
||||
#include "pico_protocol.h"
|
||||
#include "pico_stack.h"
|
||||
#include "pico_socket.h"
|
||||
|
||||
#ifdef PICO_SUPPORT_DEBUG_MEMORY
|
||||
static int n_frames_allocated;
|
||||
@@ -64,7 +64,6 @@ struct pico_frame *pico_frame_copy(struct pico_frame *f)
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
static struct pico_frame *pico_frame_do_alloc(uint32_t size, int zerocopy, int ext_buffer)
|
||||
{
|
||||
struct pico_frame *p = PICO_ZALLOC(sizeof(struct pico_frame));
|
||||
@@ -85,13 +84,13 @@ static struct pico_frame *pico_frame_do_alloc(uint32_t size, int zerocopy, int e
|
||||
frame_buffer_size += (uint32_t)sizeof(uint32_t) - align;
|
||||
}
|
||||
|
||||
p->buffer = PICO_ZALLOC(frame_buffer_size + sizeof(uint32_t));
|
||||
p->buffer = PICO_ZALLOC((size_t)frame_buffer_size + sizeof(uint32_t));
|
||||
if (!p->buffer) {
|
||||
PICO_FREE(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p->usage_count = (uint32_t *)((void *)(((uint8_t*)p->buffer) + frame_buffer_size));
|
||||
p->usage_count = (uint32_t *)(((uint8_t*)p->buffer) + frame_buffer_size);
|
||||
} else {
|
||||
p->buffer = NULL;
|
||||
p->flags |= PICO_FRAME_FLAG_EXT_USAGE_COUNTER;
|
||||
@@ -102,13 +101,17 @@ static struct pico_frame *pico_frame_do_alloc(uint32_t size, int zerocopy, int e
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
p->buffer_len = size;
|
||||
|
||||
/* By default, frame content is the full buffer. */
|
||||
p->start = p->buffer;
|
||||
p->len = p->buffer_len;
|
||||
*p->usage_count = 1;
|
||||
p->net_hdr = p->buffer;
|
||||
p->datalink_hdr = p->buffer;
|
||||
p->transport_hdr = p->buffer;
|
||||
p->app_hdr = p->buffer;
|
||||
p->payload = p->buffer;
|
||||
|
||||
if (ext_buffer)
|
||||
p->flags |= PICO_FRAME_FLAG_EXT_BUFFER;
|
||||
@@ -125,17 +128,16 @@ struct pico_frame *pico_frame_alloc(uint32_t size)
|
||||
return pico_frame_do_alloc(size, 0, 0);
|
||||
}
|
||||
|
||||
int pico_frame_grow(struct pico_frame *f, uint32_t size)
|
||||
static uint8_t *
|
||||
pico_frame_new_buffer(struct pico_frame *f, uint32_t size, uint32_t *oldsize)
|
||||
{
|
||||
uint8_t *oldbuf;
|
||||
uint32_t usage_count, *p_old_usage;
|
||||
uint32_t frame_buffer_size;
|
||||
uint32_t oldsize;
|
||||
unsigned int align;
|
||||
int addr_diff = 0;
|
||||
|
||||
if (!f || (size < f->buffer_len)) {
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
align = size % sizeof(uint32_t);
|
||||
@@ -145,22 +147,28 @@ int pico_frame_grow(struct pico_frame *f, uint32_t size)
|
||||
}
|
||||
|
||||
oldbuf = f->buffer;
|
||||
oldsize = f->buffer_len;
|
||||
*oldsize = f->buffer_len;
|
||||
usage_count = *(f->usage_count);
|
||||
p_old_usage = f->usage_count;
|
||||
f->buffer = PICO_ZALLOC(frame_buffer_size + sizeof(uint32_t));
|
||||
f->buffer = PICO_ZALLOC((size_t)frame_buffer_size + sizeof(uint32_t));
|
||||
if (!f->buffer) {
|
||||
f->buffer = oldbuf;
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f->usage_count = (uint32_t *)((void *)(((uint8_t*)f->buffer) + frame_buffer_size));
|
||||
f->usage_count = (uint32_t *)(((uint8_t*)f->buffer) + frame_buffer_size);
|
||||
*f->usage_count = usage_count;
|
||||
f->buffer_len = size;
|
||||
memcpy(f->buffer, oldbuf, oldsize);
|
||||
|
||||
/* Update hdr fields to new buffer*/
|
||||
addr_diff = (int)(f->buffer - oldbuf);
|
||||
if (f->flags & PICO_FRAME_FLAG_EXT_USAGE_COUNTER)
|
||||
PICO_FREE(p_old_usage);
|
||||
/* Now, the frame is not zerocopy anymore, and the usage counter has been moved within it */
|
||||
return oldbuf;
|
||||
}
|
||||
|
||||
static int
|
||||
pico_frame_update_pointers(struct pico_frame *f, ptrdiff_t addr_diff, uint8_t *oldbuf)
|
||||
{
|
||||
f->net_hdr += addr_diff;
|
||||
f->datalink_hdr += addr_diff;
|
||||
f->transport_hdr += addr_diff;
|
||||
@@ -168,19 +176,45 @@ int pico_frame_grow(struct pico_frame *f, uint32_t size)
|
||||
f->start += addr_diff;
|
||||
f->payload += addr_diff;
|
||||
|
||||
if (f->flags & PICO_FRAME_FLAG_EXT_USAGE_COUNTER)
|
||||
PICO_FREE(p_old_usage);
|
||||
|
||||
if (!(f->flags & PICO_FRAME_FLAG_EXT_BUFFER))
|
||||
PICO_FREE(oldbuf);
|
||||
else if (f->notify_free)
|
||||
f->notify_free(oldbuf);
|
||||
|
||||
f->flags = 0;
|
||||
/* Now, the frame is not zerocopy anymore, and the usage counter has been moved within it */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pico_frame_grow_head(struct pico_frame *f, uint32_t size)
|
||||
{
|
||||
ptrdiff_t addr_diff = 0;
|
||||
uint32_t oldsize = 0;
|
||||
uint8_t *oldbuf = pico_frame_new_buffer(f, size, &oldsize);
|
||||
if (!oldbuf)
|
||||
return -1;
|
||||
|
||||
/* Put old buffer at the end of new buffer */
|
||||
memcpy(f->buffer + f->buffer_len - oldsize, oldbuf, (size_t)oldsize);
|
||||
addr_diff = (ptrdiff_t)(f->buffer + f->buffer_len - oldsize - oldbuf);
|
||||
|
||||
return pico_frame_update_pointers(f, addr_diff, oldbuf);
|
||||
}
|
||||
|
||||
int pico_frame_grow(struct pico_frame *f, uint32_t size)
|
||||
{
|
||||
ptrdiff_t addr_diff = 0;
|
||||
uint32_t oldsize = 0;
|
||||
uint8_t *oldbuf = pico_frame_new_buffer(f, size, &oldsize);
|
||||
if (!oldbuf)
|
||||
return -1;
|
||||
|
||||
/* Just put old buffer at the beginning of new buffer */
|
||||
memcpy(f->buffer, oldbuf, (size_t)oldsize);
|
||||
addr_diff = (ptrdiff_t)(f->buffer - oldbuf);
|
||||
|
||||
return pico_frame_update_pointers(f, addr_diff, oldbuf);
|
||||
}
|
||||
|
||||
struct pico_frame *pico_frame_alloc_skeleton(uint32_t size, int ext_buffer)
|
||||
{
|
||||
return pico_frame_do_alloc(size, 1, ext_buffer);
|
||||
@@ -199,7 +233,7 @@ int pico_frame_skeleton_set_buffer(struct pico_frame *f, void *buf)
|
||||
struct pico_frame *pico_frame_deepcopy(struct pico_frame *f)
|
||||
{
|
||||
struct pico_frame *new = pico_frame_alloc(f->buffer_len);
|
||||
int addr_diff;
|
||||
ptrdiff_t addr_diff;
|
||||
unsigned char *buf;
|
||||
uint32_t *uc;
|
||||
if (!new)
|
||||
@@ -217,7 +251,7 @@ struct pico_frame *pico_frame_deepcopy(struct pico_frame *f)
|
||||
new->usage_count = uc;
|
||||
|
||||
/* Update in-buffer pointers with offset */
|
||||
addr_diff = (int)(new->buffer - f->buffer);
|
||||
addr_diff = (ptrdiff_t)(new->buffer - f->buffer);
|
||||
new->datalink_hdr += addr_diff;
|
||||
new->net_hdr += addr_diff;
|
||||
new->transport_hdr += addr_diff;
|
||||
@@ -225,6 +259,15 @@ struct pico_frame *pico_frame_deepcopy(struct pico_frame *f)
|
||||
new->start += addr_diff;
|
||||
new->payload += addr_diff;
|
||||
|
||||
if (f->info) {
|
||||
new->info = PICO_ZALLOC(sizeof(struct pico_remote_endpoint));
|
||||
if (!new->info) {
|
||||
pico_frame_discard(new);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(new->info, f->info, sizeof(struct pico_remote_endpoint));
|
||||
}
|
||||
|
||||
#ifdef PICO_SUPPORT_DEBUG_MEMORY
|
||||
dbg("Deep-Copied frame @%p, into %p, usage count now: %d\n", f, new, *new->usage_count);
|
||||
#endif
|
||||
@@ -247,7 +290,7 @@ static inline uint32_t pico_checksum_adder(uint32_t sum, void *data, uint32_t le
|
||||
#endif
|
||||
}
|
||||
|
||||
stop = (uint16_t *)((void *)(((uint8_t *)data) + len));
|
||||
stop = (uint16_t *)(((uint8_t *)data) + len);
|
||||
|
||||
while (buf < stop) {
|
||||
sum += *buf++;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*********************************************************************
|
||||
* PicoTCP. Copyright (c) 2015 Altran Intelligent Systems. Some rights reserved.
|
||||
* See LICENSE and COPYING for usage.
|
||||
* PicoTCP. Copyright (c) 2015-2017 Altran Intelligent Systems. Some rights reserved.
|
||||
* See COPYING, LICENSE.GPLv2 and LICENSE.GPLv3 for usage.
|
||||
*
|
||||
* Authors: Daniele Lacamera
|
||||
* *********************************************************************/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*********************************************************************
|
||||
PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved.
|
||||
See LICENSE and COPYING for usage.
|
||||
PicoTCP. Copyright (c) 2012-2017 Altran Intelligent Systems. Some rights reserved.
|
||||
See COPYING, LICENSE.GPLv2 and LICENSE.GPLv3 for usage.
|
||||
|
||||
.
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "pico_protocol.h"
|
||||
#include "pico_tree.h"
|
||||
#include "../../../include/Debug.hpp"
|
||||
|
||||
struct pico_proto_rr
|
||||
{
|
||||
@@ -30,10 +31,10 @@ static int pico_proto_cmp(void *ka, void *kb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
PICO_TREE_DECLARE(Datalink_proto_tree, pico_proto_cmp);
|
||||
PICO_TREE_DECLARE(Network_proto_tree, pico_proto_cmp);
|
||||
PICO_TREE_DECLARE(Transport_proto_tree, pico_proto_cmp);
|
||||
PICO_TREE_DECLARE(Socket_proto_tree, pico_proto_cmp);
|
||||
static PICO_TREE_DECLARE(Datalink_proto_tree, pico_proto_cmp);
|
||||
static PICO_TREE_DECLARE(Network_proto_tree, pico_proto_cmp);
|
||||
static PICO_TREE_DECLARE(Transport_proto_tree, pico_proto_cmp);
|
||||
static PICO_TREE_DECLARE(Socket_proto_tree, pico_proto_cmp);
|
||||
|
||||
/* Static variables to keep track of the round robin loop */
|
||||
static struct pico_proto_rr proto_rr_datalink = {
|
||||
@@ -186,29 +187,41 @@ static void proto_layer_rr_reset(struct pico_proto_rr *rr)
|
||||
|
||||
void pico_protocol_init(struct pico_protocol *p)
|
||||
{
|
||||
struct pico_tree *tree = NULL;
|
||||
struct pico_proto_rr *proto = NULL;
|
||||
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
p->hash = pico_hash(p->name, (uint32_t)strlen(p->name));
|
||||
switch (p->layer) {
|
||||
case PICO_LAYER_DATALINK:
|
||||
pico_tree_insert(&Datalink_proto_tree, p);
|
||||
proto_layer_rr_reset(&proto_rr_datalink);
|
||||
break;
|
||||
case PICO_LAYER_NETWORK:
|
||||
pico_tree_insert(&Network_proto_tree, p);
|
||||
proto_layer_rr_reset(&proto_rr_network);
|
||||
break;
|
||||
case PICO_LAYER_TRANSPORT:
|
||||
pico_tree_insert(&Transport_proto_tree, p);
|
||||
proto_layer_rr_reset(&proto_rr_transport);
|
||||
break;
|
||||
case PICO_LAYER_SOCKET:
|
||||
pico_tree_insert(&Socket_proto_tree, p);
|
||||
proto_layer_rr_reset(&proto_rr_socket);
|
||||
break;
|
||||
case PICO_LAYER_DATALINK:
|
||||
tree = &Datalink_proto_tree;
|
||||
proto = &proto_rr_datalink;
|
||||
break;
|
||||
case PICO_LAYER_NETWORK:
|
||||
tree = &Network_proto_tree;
|
||||
proto = &proto_rr_network;
|
||||
break;
|
||||
case PICO_LAYER_TRANSPORT:
|
||||
tree = &Transport_proto_tree;
|
||||
proto = &proto_rr_transport;
|
||||
break;
|
||||
case PICO_LAYER_SOCKET:
|
||||
tree = &Socket_proto_tree;
|
||||
proto = &proto_rr_socket;
|
||||
break;
|
||||
default:
|
||||
DEBUG_EXTRA("Unknown protocol: %s (layer: %d)", p->name, p->layer);
|
||||
return;
|
||||
}
|
||||
//dbg("Protocol %s registered (layer: %d).\n", p->name, p->layer);
|
||||
|
||||
if (pico_tree_insert(tree, p)) {
|
||||
DEBUG_EXTRA("Failed to insert protocol %s", p->name);
|
||||
return;
|
||||
}
|
||||
|
||||
proto_layer_rr_reset(proto);
|
||||
DEBUG_EXTRA("Protocol %s registered (layer: %d).", p->name, p->layer);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*********************************************************************
|
||||
PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved.
|
||||
See LICENSE and COPYING for usage.
|
||||
PicoTCP. Copyright (c) 2012-2017 Altran Intelligent Systems. Some rights reserved.
|
||||
See COPYING, LICENSE.GPLv2 and LICENSE.GPLv3 for usage.
|
||||
|
||||
|
||||
Authors: Daniele Lacamera
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "pico_socket_tcp.h"
|
||||
#include "pico_socket_udp.h"
|
||||
|
||||
#include "../../../include/Debug.hpp"
|
||||
|
||||
#if defined (PICO_SUPPORT_IPV4) || defined (PICO_SUPPORT_IPV6)
|
||||
#if defined (PICO_SUPPORT_TCP) || defined (PICO_SUPPORT_UDP)
|
||||
|
||||
@@ -35,17 +37,30 @@
|
||||
static void *Mutex = NULL;
|
||||
#endif
|
||||
|
||||
/* Mockables */
|
||||
#if defined UNIT_TEST
|
||||
# define MOCKABLE __attribute__((weak))
|
||||
#else
|
||||
# define MOCKABLE
|
||||
#endif
|
||||
|
||||
#define PROTO(s) ((s)->proto->proto_number)
|
||||
|
||||
#define PICO_SOCKET_MTU 1480 /* Ethernet MTU(1500) - IP header size(20) */
|
||||
|
||||
# define frag_dbg(...) do {} while(0)
|
||||
#ifdef PICO_SUPPORT_IPV4FRAG
|
||||
|
||||
#ifdef DEBUG_FRAG
|
||||
#define frag_dbg dbg
|
||||
#else
|
||||
#define frag_dbg(...) do {} while(0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
static struct pico_sockport *sp_udp = NULL, *sp_tcp = NULL;
|
||||
|
||||
struct pico_frame *pico_socket_frame_alloc(struct pico_socket *s, uint16_t len);
|
||||
struct pico_frame *pico_socket_frame_alloc(struct pico_socket *s, struct pico_device *dev, uint16_t len);
|
||||
|
||||
static int socket_cmp_family(struct pico_socket *a, struct pico_socket *b)
|
||||
{
|
||||
@@ -123,7 +138,7 @@ static int socket_cmp_addresses(struct pico_socket *a, struct pico_socket *b)
|
||||
if (ret == 0)
|
||||
ret = socket_cmp_remotehost(a, b);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int socket_cmp(void *ka, void *kb)
|
||||
@@ -160,25 +175,21 @@ static int sockport_cmp(void *ka, void *kb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
PICO_TREE_DECLARE(UDPTable, sockport_cmp);
|
||||
PICO_TREE_DECLARE(TCPTable, sockport_cmp);
|
||||
static PICO_TREE_DECLARE(UDPTable, sockport_cmp);
|
||||
static PICO_TREE_DECLARE(TCPTable, sockport_cmp);
|
||||
|
||||
struct pico_sockport *pico_get_sockport(uint16_t proto, uint16_t port)
|
||||
{
|
||||
struct pico_sockport test = INIT_SOCKPORT;
|
||||
test.number = port;
|
||||
|
||||
if (proto == PICO_PROTO_UDP){
|
||||
if (proto == PICO_PROTO_UDP)
|
||||
return pico_tree_findKey(&UDPTable, &test);
|
||||
}
|
||||
|
||||
else if (proto == PICO_PROTO_TCP){
|
||||
else if (proto == PICO_PROTO_TCP)
|
||||
return pico_tree_findKey(&TCPTable, &test);
|
||||
}
|
||||
|
||||
else
|
||||
{ return NULL;
|
||||
}
|
||||
else return NULL;
|
||||
}
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV4
|
||||
@@ -344,6 +355,7 @@ static int pico_check_socket(struct pico_socket *s)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -365,13 +377,21 @@ struct pico_socket *pico_sockets_find(uint16_t local, uint16_t remote)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
|
||||
int8_t pico_socket_add(struct pico_socket *s)
|
||||
{
|
||||
struct pico_sockport *sp = pico_get_sockport(PROTO(s), s->local_port);
|
||||
struct pico_sockport *sp;
|
||||
if (PROTO(s) != PICO_PROTO_UDP && PROTO(s) != PICO_PROTO_TCP)
|
||||
{
|
||||
pico_err = PICO_ERR_EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sp = pico_get_sockport(PROTO(s), s->local_port);
|
||||
PICOTCP_MUTEX_LOCK(Mutex);
|
||||
if (!sp) {
|
||||
/* dbg("Creating sockport..%04x\n", s->local_port); / * In comment due to spam during test * / */
|
||||
@@ -390,21 +410,32 @@ int8_t pico_socket_add(struct pico_socket *s)
|
||||
|
||||
if (PROTO(s) == PICO_PROTO_UDP)
|
||||
{
|
||||
pico_tree_insert(&UDPTable, sp);
|
||||
if (pico_tree_insert(&UDPTable, sp)) {
|
||||
PICO_FREE(sp);
|
||||
PICOTCP_MUTEX_UNLOCK(Mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
else if (PROTO(s) == PICO_PROTO_TCP)
|
||||
{
|
||||
pico_tree_insert(&TCPTable, sp);
|
||||
if (pico_tree_insert(&TCPTable, sp)) {
|
||||
PICO_FREE(sp);
|
||||
PICOTCP_MUTEX_UNLOCK(Mutex);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pico_tree_insert(&sp->socks, s);
|
||||
if (pico_tree_insert(&sp->socks, s)) {
|
||||
PICOTCP_MUTEX_UNLOCK(Mutex);
|
||||
return -1;
|
||||
}
|
||||
s->state |= PICO_SOCKET_STATE_BOUND;
|
||||
PICOTCP_MUTEX_UNLOCK(Mutex);
|
||||
#ifdef DEBUG_SOCKET_TREE
|
||||
{
|
||||
struct pico_tree_node *index;
|
||||
/* RB_FOREACH(s, socket_tree, &sp->socks) { */
|
||||
pico_tree_foreach(index, &sp->socks){
|
||||
s = index->keyValue;
|
||||
dbg(">>>> List Socket lc=%hu rm=%hu\n", short_be(s->local_port), short_be(s->remote_port));
|
||||
@@ -482,10 +513,17 @@ int8_t pico_socket_del(struct pico_socket *s)
|
||||
PICOTCP_MUTEX_LOCK(Mutex);
|
||||
pico_tree_delete(&sp->socks, s);
|
||||
pico_socket_check_empty_sockport(s, sp);
|
||||
#ifdef PICO_SUPPORT_MCAST
|
||||
pico_multicast_delete(s);
|
||||
#endif
|
||||
pico_socket_tcp_delete(s);
|
||||
s->state = PICO_SOCKET_STATE_CLOSED;
|
||||
pico_timer_add((pico_time)10, socket_garbage_collect, s);
|
||||
if (!pico_timer_add((pico_time)10, socket_garbage_collect, s)) {
|
||||
dbg("SOCKET: Failed to start garbage collect timer, doing garbage collection now\n");
|
||||
PICOTCP_MUTEX_UNLOCK(Mutex);
|
||||
socket_garbage_collect((pico_time)0, s);
|
||||
return -1;
|
||||
}
|
||||
PICOTCP_MUTEX_UNLOCK(Mutex);
|
||||
return 0;
|
||||
}
|
||||
@@ -548,7 +586,7 @@ static int pico_socket_deliver(struct pico_protocol *p, struct pico_frame *f, ui
|
||||
|
||||
sp = pico_get_sockport(p->proto_number, localport);
|
||||
if (!sp) {
|
||||
//dbg("No such port %d\n", short_be(localport));
|
||||
DEBUG_EXTRA("No such port %d", short_be(localport));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -597,7 +635,7 @@ static struct pico_socket *pico_socket_transport_open(uint16_t proto, uint16_t f
|
||||
|
||||
}
|
||||
|
||||
extern struct pico_socket *pico_socket_open(uint16_t net, uint16_t proto, void (*wakeup)(uint16_t ev, struct pico_socket *))
|
||||
extern struct pico_socket *MOCKABLE pico_socket_open(uint16_t net, uint16_t proto, void (*wakeup)(uint16_t ev, struct pico_socket *))
|
||||
{
|
||||
|
||||
struct pico_socket *s = NULL;
|
||||
@@ -688,7 +726,6 @@ static int pico_socket_transport_read(struct pico_socket *s, void *buf, int len)
|
||||
return pico_socket_tcp_read(s, buf, (uint32_t)len);
|
||||
else return 0;
|
||||
}
|
||||
#include <stdio.h>
|
||||
|
||||
int pico_socket_read(struct pico_socket *s, void *buf, int len)
|
||||
{
|
||||
@@ -1036,11 +1073,32 @@ static int pico_socket_xmit_one(struct pico_socket *s, const void *buf, const in
|
||||
struct pico_remote_endpoint *ep, struct pico_msginfo *msginfo)
|
||||
{
|
||||
struct pico_frame *f;
|
||||
struct pico_device *dev = NULL;
|
||||
uint16_t hdr_offset = (uint16_t)pico_socket_sendto_transport_offset(s);
|
||||
int ret = 0;
|
||||
(void)src;
|
||||
|
||||
f = pico_socket_frame_alloc(s, (uint16_t)(len + hdr_offset));
|
||||
|
||||
if (msginfo) {
|
||||
dev = msginfo->dev;
|
||||
}
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
else if (IS_SOCK_IPV6(s) && ep && pico_ipv6_is_multicast(&ep->remote_addr.ip6.addr[0])) {
|
||||
dev = pico_ipv6_link_find(src);
|
||||
}
|
||||
#endif
|
||||
else if (IS_SOCK_IPV6(s) && ep) {
|
||||
dev = pico_ipv6_source_dev_find(&ep->remote_addr.ip6);
|
||||
} else if (IS_SOCK_IPV4(s) && ep) {
|
||||
dev = pico_ipv4_source_dev_find(&ep->remote_addr.ip4);
|
||||
} else {
|
||||
dev = get_sock_dev(s);
|
||||
}
|
||||
|
||||
if (!dev) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
f = pico_socket_frame_alloc(s, dev, (uint16_t)(len + hdr_offset));
|
||||
if (!f) {
|
||||
pico_err = PICO_ERR_ENOMEM;
|
||||
return -1;
|
||||
@@ -1062,16 +1120,8 @@ static int pico_socket_xmit_one(struct pico_socket *s, const void *buf, const in
|
||||
if (msginfo) {
|
||||
f->send_ttl = (uint8_t)msginfo->ttl;
|
||||
f->send_tos = (uint8_t)msginfo->tos;
|
||||
f->dev = msginfo->dev;
|
||||
}
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
if(IS_SOCK_IPV6(s) && ep && pico_ipv6_is_multicast(&ep->remote_addr.ip6.addr[0])) {
|
||||
f->dev = pico_ipv6_link_find(src);
|
||||
if(!f->dev) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
memcpy(f->payload, (const uint8_t *)buf, f->payload_len);
|
||||
/* dbg("Pushing segment, hdr len: %d, payload_len: %d\n", header_offset, f->payload_len); */
|
||||
ret = pico_socket_final_xmit(s, f);
|
||||
@@ -1116,6 +1166,12 @@ static int pico_socket_xmit_fragments(struct pico_socket *s, const void *buf, co
|
||||
int retval = 0;
|
||||
struct pico_frame *f = NULL;
|
||||
|
||||
if (space < 0) {
|
||||
pico_err = PICO_ERR_EPROTONOSUPPORT;
|
||||
pico_endpoint_free(ep);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (space > len) {
|
||||
retval = pico_socket_xmit_one(s, buf, len, src, ep, msginfo);
|
||||
pico_endpoint_free(ep);
|
||||
@@ -1141,7 +1197,7 @@ static int pico_socket_xmit_fragments(struct pico_socket *s, const void *buf, co
|
||||
if (space > len - total_payload_written) /* update space for last fragment */
|
||||
space = len - total_payload_written;
|
||||
|
||||
f = pico_socket_frame_alloc(s, (uint16_t)(space + hdr_offset));
|
||||
f = pico_socket_frame_alloc(s, get_sock_dev(s), (uint16_t)(space + hdr_offset));
|
||||
if (!f) {
|
||||
pico_err = PICO_ERR_ENOMEM;
|
||||
pico_endpoint_free(ep);
|
||||
@@ -1196,7 +1252,7 @@ static int pico_socket_xmit_fragments(struct pico_socket *s, const void *buf, co
|
||||
#endif
|
||||
}
|
||||
|
||||
static void get_sock_dev(struct pico_socket *s)
|
||||
struct pico_device *get_sock_dev(struct pico_socket *s)
|
||||
{
|
||||
if (0) {}
|
||||
|
||||
@@ -1209,6 +1265,7 @@ static void get_sock_dev(struct pico_socket *s)
|
||||
s->dev = pico_ipv4_source_dev_find(&s->remote_addr.ip4);
|
||||
#endif
|
||||
|
||||
return s->dev;
|
||||
}
|
||||
|
||||
|
||||
@@ -1423,8 +1480,8 @@ int pico_socket_recvfrom_extended(struct pico_socket *s, void *buf, int len, voi
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int pico_socket_recvfrom(struct pico_socket *s, void *buf, int len, void *orig,
|
||||
uint16_t *remote_port)
|
||||
extern int MOCKABLE pico_socket_recvfrom(struct pico_socket *s, void *buf, int len, void *orig,
|
||||
uint16_t *remote_port)
|
||||
{
|
||||
return pico_socket_recvfrom_extended(s, buf, len, orig, remote_port, NULL);
|
||||
|
||||
@@ -1499,7 +1556,7 @@ int pico_socket_getpeername(struct pico_socket *s, void *remote_addr, uint16_t *
|
||||
|
||||
}
|
||||
|
||||
int pico_socket_bind(struct pico_socket *s, void *local_addr, uint16_t *port)
|
||||
int MOCKABLE pico_socket_bind(struct pico_socket *s, void *local_addr, uint16_t *port)
|
||||
{
|
||||
if (!s || !local_addr || !port) {
|
||||
pico_err = PICO_ERR_EINVAL;
|
||||
@@ -1684,7 +1741,7 @@ extern int pico_socket_listen(struct pico_socket *s, int backlog)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pico_socket *pico_socket_accept(struct pico_socket *s, void *orig, uint16_t *port)
|
||||
extern struct pico_socket *pico_socket_accept(struct pico_socket *s, void *orig, uint16_t *port)
|
||||
{
|
||||
if (!s || !orig || !port) {
|
||||
pico_err = PICO_ERR_EINVAL;
|
||||
@@ -1736,7 +1793,7 @@ struct pico_socket *pico_socket_accept(struct pico_socket *s, void *orig, uint16
|
||||
|
||||
#else
|
||||
|
||||
extern int pico_socket_listen(struct pico_socket *s, int backlog)
|
||||
int pico_socket_listen(struct pico_socket *s, int backlog)
|
||||
{
|
||||
IGNORE_PARAMETER(s);
|
||||
IGNORE_PARAMETER(backlog);
|
||||
@@ -1744,7 +1801,7 @@ extern int pico_socket_listen(struct pico_socket *s, int backlog)
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern struct pico_socket *pico_socket_accept(struct pico_socket *s, void *orig, uint16_t *local_port)
|
||||
struct pico_socket *pico_socket_accept(struct pico_socket *s, void *orig, uint16_t *local_port)
|
||||
{
|
||||
IGNORE_PARAMETER(s);
|
||||
IGNORE_PARAMETER(orig);
|
||||
@@ -1756,7 +1813,7 @@ extern struct pico_socket *pico_socket_accept(struct pico_socket *s, void *orig,
|
||||
#endif
|
||||
|
||||
|
||||
int pico_socket_setoption(struct pico_socket *s, int option, void *value)
|
||||
int MOCKABLE pico_socket_setoption(struct pico_socket *s, int option, void *value)
|
||||
{
|
||||
|
||||
if (s == NULL) {
|
||||
@@ -1960,6 +2017,7 @@ static int check_socket_sanity(struct pico_socket *s)
|
||||
if((PICO_TIME_MS() - s->timestamp) >= PICO_SOCKET_BOUND_TIMEOUT)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -2113,19 +2171,19 @@ int pico_count_sockets(uint8_t proto)
|
||||
}
|
||||
|
||||
|
||||
struct pico_frame *pico_socket_frame_alloc(struct pico_socket *s, uint16_t len)
|
||||
struct pico_frame *pico_socket_frame_alloc(struct pico_socket *s, struct pico_device *dev, uint16_t len)
|
||||
{
|
||||
struct pico_frame *f = NULL;
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
if (is_sock_ipv6(s))
|
||||
f = pico_proto_ipv6.alloc(&pico_proto_ipv6, len);
|
||||
f = pico_proto_ipv6.alloc(&pico_proto_ipv6, dev, len);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV4
|
||||
if (is_sock_ipv4(s))
|
||||
f = pico_proto_ipv4.alloc(&pico_proto_ipv4, len);
|
||||
f = pico_proto_ipv4.alloc(&pico_proto_ipv4, dev, len);
|
||||
|
||||
#endif
|
||||
if (!f) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/*********************************************************************
|
||||
PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved.
|
||||
See LICENSE and COPYING for usage.
|
||||
PicoTCP. Copyright (c) 2012-2017 Altran Intelligent Systems. Some rights reserved.
|
||||
See COPYING, LICENSE.GPLv2 and LICENSE.GPLv3 for usage.
|
||||
|
||||
.
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
#include "pico_addressing.h"
|
||||
#include "pico_dns_client.h"
|
||||
|
||||
#include "pico_6lowpan_ll.h"
|
||||
#include "pico_ethernet.h"
|
||||
#include "pico_6lowpan.h"
|
||||
#include "pico_olsr.h"
|
||||
#include "pico_aodv.h"
|
||||
#include "pico_eth.h"
|
||||
@@ -30,22 +33,11 @@
|
||||
#include "pico_socket.h"
|
||||
#include "heap.h"
|
||||
|
||||
#define IS_LIMITED_BCAST(f) (((struct pico_ipv4_hdr *) f->net_hdr)->dst.addr == PICO_IP4_BCAST)
|
||||
|
||||
const uint8_t PICO_ETHADDR_ALL[6] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
# define PICO_SIZE_MCAST 3
|
||||
const uint8_t PICO_ETHADDR_MCAST[6] = {
|
||||
0x01, 0x00, 0x5e, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
# define PICO_SIZE_MCAST6 2
|
||||
const uint8_t PICO_ETHADDR_MCAST6[6] = {
|
||||
0x33, 0x33, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
/* Mockables */
|
||||
#if defined UNIT_TEST
|
||||
# define MOCKABLE __attribute__((weak))
|
||||
#else
|
||||
# define MOCKABLE
|
||||
#endif
|
||||
|
||||
|
||||
@@ -190,8 +182,10 @@ int pico_notify_pkt_too_big(struct pico_frame *f)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* TRANSPORT LAYER
|
||||
******************************************************************************/
|
||||
|
||||
/* Transport layer */
|
||||
MOCKABLE int32_t pico_transport_receive(struct pico_frame *f, uint8_t proto)
|
||||
{
|
||||
int32_t ret = -1;
|
||||
@@ -238,7 +232,11 @@ MOCKABLE int32_t pico_transport_receive(struct pico_frame *f, uint8_t proto)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t pico_network_receive(struct pico_frame *f)
|
||||
/*******************************************************************************
|
||||
* NETWORK LAYER
|
||||
******************************************************************************/
|
||||
|
||||
MOCKABLE int32_t pico_network_receive(struct pico_frame *f)
|
||||
{
|
||||
if (0) {}
|
||||
|
||||
@@ -260,7 +258,7 @@ int32_t pico_network_receive(struct pico_frame *f)
|
||||
return (int32_t)f->buffer_len;
|
||||
}
|
||||
|
||||
/* Network layer: interface towards socket for frame sending */
|
||||
/// Interface towards socket for frame sending
|
||||
int32_t pico_network_send(struct pico_frame *f)
|
||||
{
|
||||
if (!f || !f->sock || !f->sock->net) {
|
||||
@@ -295,350 +293,6 @@ int pico_source_is_local(struct pico_frame *f)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef PICO_SUPPORT_ETH
|
||||
/* DATALINK LEVEL: interface from network to the device
|
||||
* and vice versa.
|
||||
*/
|
||||
|
||||
/* The pico_ethernet_receive() function is used by
|
||||
* those devices supporting ETH in order to push packets up
|
||||
* into the stack.
|
||||
*/
|
||||
|
||||
static int destination_is_bcast(struct pico_frame *f)
|
||||
{
|
||||
if (!f)
|
||||
return 0;
|
||||
|
||||
if (IS_IPV6(f))
|
||||
return 0;
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV4
|
||||
else {
|
||||
struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
|
||||
return pico_ipv4_is_broadcast(hdr->dst.addr);
|
||||
}
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int destination_is_mcast(struct pico_frame *f)
|
||||
{
|
||||
int ret = 0;
|
||||
if (!f)
|
||||
return 0;
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
if (IS_IPV6(f)) {
|
||||
struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *) f->net_hdr;
|
||||
ret = pico_ipv6_is_multicast(hdr->dst.addr);
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef PICO_SUPPORT_IPV4
|
||||
else {
|
||||
struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
|
||||
ret = pico_ipv4_is_multicast(hdr->dst.addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV4
|
||||
static int32_t pico_ipv4_ethernet_receive(struct pico_frame *f)
|
||||
{
|
||||
if (IS_IPV4(f)) {
|
||||
pico_enqueue(pico_proto_ipv4.q_in, f);
|
||||
} else {
|
||||
(void)pico_icmp4_param_problem(f, 0);
|
||||
pico_frame_discard(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int32_t)f->buffer_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
static int32_t pico_ipv6_ethernet_receive(struct pico_frame *f)
|
||||
{
|
||||
if (IS_IPV6(f)) {
|
||||
pico_enqueue(pico_proto_ipv6.q_in, f);
|
||||
} else {
|
||||
/* Wrong version for link layer type */
|
||||
pico_frame_discard(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int32_t)f->buffer_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int32_t pico_ll_receive(struct pico_frame *f)
|
||||
{
|
||||
struct pico_eth_hdr *hdr = (struct pico_eth_hdr *) f->datalink_hdr;
|
||||
f->net_hdr = f->datalink_hdr + sizeof(struct pico_eth_hdr);
|
||||
|
||||
#if (defined PICO_SUPPORT_IPV4) && (defined PICO_SUPPORT_ETH)
|
||||
if (hdr->proto == PICO_IDETH_ARP)
|
||||
return pico_arp_receive(f);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (PICO_SUPPORT_IPV4)
|
||||
if (hdr->proto == PICO_IDETH_IPV4)
|
||||
return pico_ipv4_ethernet_receive(f);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (PICO_SUPPORT_IPV6)
|
||||
if (hdr->proto == PICO_IDETH_IPV6)
|
||||
return pico_ipv6_ethernet_receive(f);
|
||||
|
||||
#endif
|
||||
|
||||
pico_frame_discard(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void pico_ll_check_bcast(struct pico_frame *f)
|
||||
{
|
||||
struct pico_eth_hdr *hdr = (struct pico_eth_hdr *) f->datalink_hdr;
|
||||
/* Indicate a link layer broadcast packet */
|
||||
if (memcmp(hdr->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH) == 0)
|
||||
f->flags |= PICO_FRAME_FLAG_BCAST;
|
||||
}
|
||||
|
||||
int32_t pico_ethernet_receive(struct pico_frame *f)
|
||||
{
|
||||
struct pico_eth_hdr *hdr;
|
||||
if (!f || !f->dev || !f->datalink_hdr)
|
||||
{
|
||||
pico_frame_discard(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hdr = (struct pico_eth_hdr *) f->datalink_hdr;
|
||||
if ((memcmp(hdr->daddr, f->dev->eth->mac.addr, PICO_SIZE_ETH) != 0) &&
|
||||
(memcmp(hdr->daddr, PICO_ETHADDR_MCAST, PICO_SIZE_MCAST) != 0) &&
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
(memcmp(hdr->daddr, PICO_ETHADDR_MCAST6, PICO_SIZE_MCAST6) != 0) &&
|
||||
#endif
|
||||
(memcmp(hdr->daddr, PICO_ETHADDR_ALL, PICO_SIZE_ETH) != 0))
|
||||
{
|
||||
pico_frame_discard(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pico_ll_check_bcast(f);
|
||||
return pico_ll_receive(f);
|
||||
}
|
||||
|
||||
static struct pico_eth *pico_ethernet_mcast_translate(struct pico_frame *f, uint8_t *pico_mcast_mac)
|
||||
{
|
||||
struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
|
||||
|
||||
/* place 23 lower bits of IP in lower 23 bits of MAC */
|
||||
pico_mcast_mac[5] = (long_be(hdr->dst.addr) & 0x000000FFu);
|
||||
pico_mcast_mac[4] = (uint8_t)((long_be(hdr->dst.addr) & 0x0000FF00u) >> 8u);
|
||||
pico_mcast_mac[3] = (uint8_t)((long_be(hdr->dst.addr) & 0x007F0000u) >> 16u);
|
||||
|
||||
return (struct pico_eth *)pico_mcast_mac;
|
||||
}
|
||||
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
static struct pico_eth *pico_ethernet_mcast6_translate(struct pico_frame *f, uint8_t *pico_mcast6_mac)
|
||||
{
|
||||
struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->net_hdr;
|
||||
|
||||
/* first 2 octets are 0x33, last four are the last four of dst */
|
||||
pico_mcast6_mac[5] = hdr->dst.addr[PICO_SIZE_IP6 - 1];
|
||||
pico_mcast6_mac[4] = hdr->dst.addr[PICO_SIZE_IP6 - 2];
|
||||
pico_mcast6_mac[3] = hdr->dst.addr[PICO_SIZE_IP6 - 3];
|
||||
pico_mcast6_mac[2] = hdr->dst.addr[PICO_SIZE_IP6 - 4];
|
||||
|
||||
return (struct pico_eth *)pico_mcast6_mac;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int pico_ethernet_ipv6_dst(struct pico_frame *f, struct pico_eth *const dstmac)
|
||||
{
|
||||
int retval = -1;
|
||||
if (!dstmac)
|
||||
return -1;
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
if (destination_is_mcast(f)) {
|
||||
uint8_t pico_mcast6_mac[6] = {
|
||||
0x33, 0x33, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
pico_ethernet_mcast6_translate(f, pico_mcast6_mac);
|
||||
memcpy(dstmac, pico_mcast6_mac, PICO_SIZE_ETH);
|
||||
retval = 0;
|
||||
} else {
|
||||
struct pico_eth *neighbor = pico_ipv6_get_neighbor(f);
|
||||
if (neighbor)
|
||||
{
|
||||
memcpy(dstmac, neighbor, PICO_SIZE_ETH);
|
||||
retval = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
(void)f;
|
||||
pico_err = PICO_ERR_EPROTONOSUPPORT;
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/* Ethernet send, first attempt: try our own address.
|
||||
* Returns 0 if the packet is not for us.
|
||||
* Returns 1 if the packet is cloned to our own receive queue, so the caller can discard the original frame.
|
||||
* */
|
||||
static int32_t pico_ethsend_local(struct pico_frame *f, struct pico_eth_hdr *hdr)
|
||||
{
|
||||
if (!hdr)
|
||||
return 0;
|
||||
|
||||
/* Check own mac */
|
||||
if(!memcmp(hdr->daddr, hdr->saddr, PICO_SIZE_ETH)) {
|
||||
struct pico_frame *clone = pico_frame_copy(f);
|
||||
dbg("sending out packet destined for our own mac\n");
|
||||
(void)pico_ethernet_receive(clone);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ethernet send, second attempt: try bcast.
|
||||
* Returns 0 if the packet is not bcast, so it will be handled somewhere else.
|
||||
* Returns 1 if the packet is handled by the pico_device_broadcast() function, so it can be discarded.
|
||||
* */
|
||||
static int32_t pico_ethsend_bcast(struct pico_frame *f)
|
||||
{
|
||||
if (IS_LIMITED_BCAST(f)) {
|
||||
(void)pico_device_broadcast(f); /* We can discard broadcast even if it's not sent. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ethernet send, third attempt: try unicast.
|
||||
* If the device driver is busy, we return 0, so the stack won't discard the frame.
|
||||
* In case of success, we can safely return 1.
|
||||
*/
|
||||
static int32_t pico_ethsend_dispatch(struct pico_frame *f)
|
||||
{
|
||||
int ret = f->dev->send(f->dev, f->start, (int) f->len);
|
||||
if (ret <= 0)
|
||||
return 0; /* Failure to deliver! */
|
||||
else {
|
||||
return 1; /* Frame is in flight by now. */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* This function looks for the destination mac address
|
||||
* in order to send the frame being processed.
|
||||
*/
|
||||
|
||||
int32_t MOCKABLE pico_ethernet_send(struct pico_frame *f)
|
||||
{
|
||||
struct pico_eth dstmac;
|
||||
uint8_t dstmac_valid = 0;
|
||||
uint16_t proto = PICO_IDETH_IPV4;
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
/* Step 1: If the frame has an IPv6 packet,
|
||||
* destination address is taken from the ND tables
|
||||
*/
|
||||
if (IS_IPV6(f)) {
|
||||
if (pico_ethernet_ipv6_dst(f, &dstmac) < 0)
|
||||
{
|
||||
pico_ipv6_nd_postpone(f);
|
||||
return 0; /* I don't care if frame was actually postponed. If there is no room in the ND table, discard safely. */
|
||||
}
|
||||
|
||||
dstmac_valid = 1;
|
||||
proto = PICO_IDETH_IPV6;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
/* In case of broadcast (IPV4 only), dst mac is FF:FF:... */
|
||||
if (IS_BCAST(f) || destination_is_bcast(f))
|
||||
{
|
||||
memcpy(&dstmac, PICO_ETHADDR_ALL, PICO_SIZE_ETH);
|
||||
dstmac_valid = 1;
|
||||
}
|
||||
|
||||
/* In case of multicast, dst mac is translated from the group address */
|
||||
else if (destination_is_mcast(f)) {
|
||||
uint8_t pico_mcast_mac[6] = {
|
||||
0x01, 0x00, 0x5e, 0x00, 0x00, 0x00
|
||||
};
|
||||
pico_ethernet_mcast_translate(f, pico_mcast_mac);
|
||||
memcpy(&dstmac, pico_mcast_mac, PICO_SIZE_ETH);
|
||||
dstmac_valid = 1;
|
||||
}
|
||||
|
||||
#if (defined PICO_SUPPORT_IPV4)
|
||||
else {
|
||||
struct pico_eth *arp_get;
|
||||
arp_get = pico_arp_get(f);
|
||||
if (arp_get) {
|
||||
memcpy(&dstmac, arp_get, PICO_SIZE_ETH);
|
||||
dstmac_valid = 1;
|
||||
} else {
|
||||
/* At this point, ARP will discard the frame in any case.
|
||||
* It is safe to return without discarding.
|
||||
*/
|
||||
pico_arp_postpone(f);
|
||||
return 0;
|
||||
/* Same case as for IPv6 ... */
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This sets destination and source address, then pushes the packet to the device. */
|
||||
if (dstmac_valid) {
|
||||
struct pico_eth_hdr *hdr;
|
||||
hdr = (struct pico_eth_hdr *) f->datalink_hdr;
|
||||
if ((f->start > f->buffer) && ((f->start - f->buffer) >= PICO_SIZE_ETHHDR))
|
||||
{
|
||||
f->start -= PICO_SIZE_ETHHDR;
|
||||
f->len += PICO_SIZE_ETHHDR;
|
||||
f->datalink_hdr = f->start;
|
||||
hdr = (struct pico_eth_hdr *) f->datalink_hdr;
|
||||
memcpy(hdr->saddr, f->dev->eth->mac.addr, PICO_SIZE_ETH);
|
||||
memcpy(hdr->daddr, &dstmac, PICO_SIZE_ETH);
|
||||
hdr->proto = proto;
|
||||
}
|
||||
|
||||
if (pico_ethsend_local(f, hdr) || pico_ethsend_bcast(f) || pico_ethsend_dispatch(f)) {
|
||||
/* one of the above functions has delivered the frame accordingly. (returned != 0)
|
||||
* It is safe to directly return success.
|
||||
* */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Failure: do not dequeue the frame, keep it for later. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* PICO_SUPPORT_ETH */
|
||||
|
||||
|
||||
void pico_store_network_origin(void *src, struct pico_frame *f)
|
||||
{
|
||||
#ifdef PICO_SUPPORT_IPV4
|
||||
@@ -717,23 +371,73 @@ int pico_frame_dst_is_unicast(struct pico_frame *f)
|
||||
else return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* DATALINK LAYER
|
||||
******************************************************************************/
|
||||
|
||||
/* LOWEST LEVEL: interface towards devices. */
|
||||
/* Device driver will call this function which returns immediately.
|
||||
* Incoming packet will be processed later on in the dev loop.
|
||||
*/
|
||||
extern int32_t pico_stack_recv(struct pico_device *dev, uint8_t *buffer, uint32_t len)
|
||||
int pico_datalink_receive(struct pico_frame *f)
|
||||
{
|
||||
if (f->dev->eth) {
|
||||
/* If device has stack with datalink-layer pass frame through it */
|
||||
switch (f->dev->mode) {
|
||||
#ifdef PICO_SUPPORT_802154
|
||||
case LL_MODE_IEEE802154:
|
||||
f->datalink_hdr = f->buffer;
|
||||
return pico_enqueue(pico_proto_6lowpan_ll.q_in, f);
|
||||
#endif
|
||||
default:
|
||||
#ifdef PICO_SUPPORT_ETH
|
||||
f->datalink_hdr = f->buffer;
|
||||
return pico_enqueue(pico_proto_ethernet.q_in,f);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
/* If device handles raw IP-frames send it straight to network-layer */
|
||||
f->net_hdr = f->buffer;
|
||||
pico_network_receive(f);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MOCKABLE int pico_datalink_send(struct pico_frame *f)
|
||||
{
|
||||
if (f->dev->eth) {
|
||||
switch (f->dev->mode) {
|
||||
#ifdef PICO_SUPPORT_802154
|
||||
case LL_MODE_IEEE802154:
|
||||
return pico_enqueue(pico_proto_6lowpan.q_out, f);
|
||||
#endif
|
||||
default:
|
||||
#ifdef PICO_SUPPORT_ETH
|
||||
return pico_enqueue(pico_proto_ethernet.q_out, f);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
/* non-ethernet: no post-processing needed */
|
||||
return pico_sendto_dev(f);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* PHYSICAL LAYER
|
||||
******************************************************************************/
|
||||
|
||||
struct pico_frame *pico_stack_recv_new_frame(struct pico_device *dev, uint8_t *buffer, uint32_t len)
|
||||
{
|
||||
struct pico_frame *f;
|
||||
int32_t ret;
|
||||
if (len == 0)
|
||||
return -1;
|
||||
return NULL;
|
||||
|
||||
f = pico_frame_alloc(len);
|
||||
if (!f)
|
||||
{
|
||||
dbg("Cannot alloc incoming frame!\n");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Association to the device that just received the frame. */
|
||||
@@ -750,11 +454,25 @@ extern int32_t pico_stack_recv(struct pico_device *dev, uint8_t *buffer, uint32_
|
||||
}
|
||||
|
||||
memcpy(f->buffer, buffer, len);
|
||||
return f;
|
||||
}
|
||||
|
||||
/* LOWEST LEVEL: interface towards devices. */
|
||||
/* Device driver will call this function which returns immediately.
|
||||
* Incoming packet will be processed later on in the dev loop.
|
||||
*/
|
||||
int32_t pico_stack_recv(struct pico_device *dev, uint8_t *buffer, uint32_t len)
|
||||
{
|
||||
struct pico_frame *f = pico_stack_recv_new_frame (dev, buffer, len);
|
||||
int32_t ret;
|
||||
|
||||
if (!f)
|
||||
return -1;
|
||||
|
||||
ret = pico_enqueue(dev->q_in, f);
|
||||
if (ret <= 0) {
|
||||
pico_frame_discard(f);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -837,6 +555,7 @@ struct pico_timer_ref
|
||||
{
|
||||
pico_time expire;
|
||||
uint32_t id;
|
||||
uint32_t hash;
|
||||
struct pico_timer *tmr;
|
||||
};
|
||||
|
||||
@@ -891,7 +610,6 @@ static void pico_check_timers(void)
|
||||
PICO_FREE(t);
|
||||
}
|
||||
|
||||
t = NULL;
|
||||
heap_peek(Timers, &tref_unused);
|
||||
tref = heap_first(Timers);
|
||||
}
|
||||
@@ -900,18 +618,44 @@ static void pico_check_timers(void)
|
||||
void MOCKABLE pico_timer_cancel(uint32_t id)
|
||||
{
|
||||
uint32_t i;
|
||||
struct pico_timer_ref *tref = Timers->top;
|
||||
struct pico_timer_ref *tref;
|
||||
if (id == 0u)
|
||||
return;
|
||||
|
||||
for (i = 1; i <= Timers->n; i++) {
|
||||
if (tref[i].id == id) {
|
||||
PICO_FREE(Timers->top[i].tmr);
|
||||
Timers->top[i].tmr = NULL;
|
||||
tref = heap_get_element(Timers, i);
|
||||
if (tref->id == id) {
|
||||
if (tref->tmr)
|
||||
{
|
||||
PICO_FREE(tref->tmr);
|
||||
tref->tmr = NULL;
|
||||
tref->id = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pico_timer_cancel_hashed(uint32_t hash)
|
||||
{
|
||||
uint32_t i;
|
||||
struct pico_timer_ref *tref;
|
||||
if (hash == 0u)
|
||||
return;
|
||||
|
||||
for (i = 1; i <= Timers->n; i++) {
|
||||
tref = heap_get_element(Timers, i);
|
||||
if (tref->hash == hash) {
|
||||
if (tref->tmr)
|
||||
{
|
||||
PICO_FREE(tref->tmr);
|
||||
tref->tmr = NULL;
|
||||
tref[i].id = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define PROTO_DEF_NR 11
|
||||
#define PROTO_DEF_AVG_NR 4
|
||||
#define PROTO_DEF_SCORE 32
|
||||
@@ -1076,26 +820,22 @@ void pico_stack_loop(void)
|
||||
}
|
||||
}
|
||||
|
||||
MOCKABLE uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
|
||||
static uint32_t
|
||||
pico_timer_ref_add(pico_time expire, struct pico_timer *t, uint32_t id, uint32_t hash)
|
||||
{
|
||||
struct pico_timer *t = PICO_ZALLOC(sizeof(struct pico_timer));
|
||||
struct pico_timer_ref tref;
|
||||
|
||||
/* zero is guard for timers */
|
||||
if (tmr_id == 0u)
|
||||
tmr_id++;
|
||||
tref.expire = PICO_TIME_MS() + expire;
|
||||
tref.tmr = t;
|
||||
tref.id = id;
|
||||
tref.hash = hash;
|
||||
|
||||
if (!t) {
|
||||
if (heap_insert(Timers, &tref) < 0) {
|
||||
dbg("Error: failed to insert timer(ID %u) into heap\n", id);
|
||||
PICO_FREE(t);
|
||||
pico_err = PICO_ERR_ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
tref.expire = PICO_TIME_MS() + expire;
|
||||
t->arg = arg;
|
||||
t->timer = timer;
|
||||
tref.tmr = t;
|
||||
tref.id = tmr_id++;
|
||||
heap_insert(Timers, &tref);
|
||||
if (Timers->n > PICO_MAX_TIMERS) {
|
||||
dbg("Warning: I have %d timers\n", (int)Timers->n);
|
||||
}
|
||||
@@ -1103,8 +843,62 @@ MOCKABLE uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void
|
||||
return tref.id;
|
||||
}
|
||||
|
||||
extern int pico_stack_init(void)
|
||||
static struct pico_timer *
|
||||
pico_timer_create(void (*timer)(pico_time, void *), void *arg)
|
||||
{
|
||||
struct pico_timer *t = PICO_ZALLOC(sizeof(struct pico_timer));
|
||||
|
||||
if (!t) {
|
||||
pico_err = PICO_ERR_ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
t->arg = arg;
|
||||
t->timer = timer;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
MOCKABLE uint32_t pico_timer_add(pico_time expire, void (*timer)(pico_time, void *), void *arg)
|
||||
{
|
||||
struct pico_timer *t = pico_timer_create(timer, arg);
|
||||
|
||||
/* zero is guard for timers */
|
||||
if (tmr_id == 0u) {
|
||||
tmr_id++;
|
||||
}
|
||||
|
||||
if (!t)
|
||||
return 0;
|
||||
|
||||
return pico_timer_ref_add(expire, t, tmr_id++, 0);
|
||||
}
|
||||
|
||||
uint32_t pico_timer_add_hashed(pico_time expire, void (*timer)(pico_time, void *), void *arg, uint32_t hash)
|
||||
{
|
||||
struct pico_timer *t = pico_timer_create(timer, arg);
|
||||
|
||||
/* zero is guard for timers */
|
||||
if (tmr_id == 0u) {
|
||||
tmr_id++;
|
||||
}
|
||||
|
||||
if (!t)
|
||||
return 0;
|
||||
|
||||
return pico_timer_ref_add(expire, t, tmr_id++, hash);
|
||||
} /* Static path count: 4 */
|
||||
|
||||
extern int MOCKABLE pico_stack_init(void)
|
||||
{
|
||||
#ifdef PICO_SUPPORT_ETH
|
||||
pico_protocol_init(&pico_proto_ethernet);
|
||||
#endif
|
||||
|
||||
#ifdef PICO_SUPPORT_6LOWPAN
|
||||
pico_protocol_init(&pico_proto_6lowpan);
|
||||
pico_protocol_init(&pico_proto_6lowpan_ll);
|
||||
#endif
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV4
|
||||
pico_protocol_init(&pico_proto_ipv4);
|
||||
@@ -1161,7 +955,10 @@ extern int pico_stack_init(void)
|
||||
#ifdef PICO_SUPPORT_AODV
|
||||
pico_aodv_init();
|
||||
#endif
|
||||
|
||||
#ifdef PICO_SUPPORT_6LOWPAN
|
||||
if (pico_6lowpan_init())
|
||||
return -1;
|
||||
#endif
|
||||
pico_stack_tick();
|
||||
pico_stack_tick();
|
||||
pico_stack_tick();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*********************************************************************
|
||||
PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved.
|
||||
See LICENSE and COPYING for usage.
|
||||
PicoTCP. Copyright (c) 2012-2017 Altran Intelligent Systems. Some rights reserved.
|
||||
See COPYING, LICENSE.GPLv2 and LICENSE.GPLv3 for usage.
|
||||
|
||||
Author: Andrei Carp <andrei.carp@tass.be>
|
||||
*********************************************************************/
|
||||
@@ -77,6 +77,7 @@ struct pico_tree_node *pico_tree_next(struct pico_tree_node *node)
|
||||
{
|
||||
if (!node)
|
||||
return NULL;
|
||||
|
||||
if(IS_NOT_LEAF(node->rightChild))
|
||||
{
|
||||
node = node->rightChild;
|
||||
@@ -127,35 +128,12 @@ void *pico_tree_insert(struct pico_tree *tree, void *key)
|
||||
return pico_tree_insert_implementation(tree, key, USE_PICO_ZALLOC);
|
||||
}
|
||||
|
||||
void *pico_tree_insert_implementation(struct pico_tree *tree, void *key, uint8_t allocator)
|
||||
static void pico_tree_insert_node(struct pico_tree *tree, struct pico_tree_node *insert)
|
||||
{
|
||||
struct pico_tree_node *last_node = INIT_LEAF;
|
||||
struct pico_tree_node *temp = tree->root;
|
||||
struct pico_tree_node *insert;
|
||||
void *LocalKey;
|
||||
struct pico_tree_node *last_node = INIT_LEAF;
|
||||
int result = 0;
|
||||
|
||||
LocalKey = (IS_NOT_LEAF(tree->root) ? pico_tree_findKey(tree, key) : NULL);
|
||||
|
||||
/* if node already in, bail out */
|
||||
if(LocalKey) {
|
||||
return LocalKey;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(allocator == USE_PICO_PAGE0_ZALLOC)
|
||||
insert = create_node(tree, key, USE_PICO_PAGE0_ZALLOC);
|
||||
else
|
||||
insert = create_node(tree, key, USE_PICO_ZALLOC);
|
||||
|
||||
if(!insert)
|
||||
{
|
||||
pico_err = PICO_ERR_ENOMEM;
|
||||
/* to let the user know that it couldn't insert */
|
||||
return (void *)&LEAF;
|
||||
}
|
||||
}
|
||||
|
||||
/* search for the place to insert the new node */
|
||||
while(IS_NOT_LEAF(temp))
|
||||
{
|
||||
@@ -176,6 +154,31 @@ void *pico_tree_insert_implementation(struct pico_tree *tree, void *key, uint8_t
|
||||
else
|
||||
last_node->rightChild = insert;
|
||||
}
|
||||
}
|
||||
|
||||
void *pico_tree_insert_implementation(struct pico_tree *tree, void *key, uint8_t allocator)
|
||||
{
|
||||
struct pico_tree_node *insert;
|
||||
void *LocalKey;
|
||||
|
||||
LocalKey = (IS_NOT_LEAF(tree->root) ? pico_tree_findKey(tree, key) : NULL);
|
||||
|
||||
/* if node already in, bail out */
|
||||
if(LocalKey) {
|
||||
pico_err = PICO_ERR_EEXIST;
|
||||
return LocalKey;
|
||||
}
|
||||
|
||||
insert = create_node(tree, key, allocator);
|
||||
|
||||
if(!insert)
|
||||
{
|
||||
pico_err = PICO_ERR_ENOMEM;
|
||||
/* to let the user know that it couldn't insert */
|
||||
return (void *)&LEAF;
|
||||
}
|
||||
|
||||
pico_tree_insert_node(tree, insert);
|
||||
|
||||
/* fix colour issues */
|
||||
fix_insert_collisions(tree, insert);
|
||||
@@ -194,9 +197,7 @@ struct pico_tree_node *pico_tree_findNode(struct pico_tree *tree, void *key)
|
||||
int result;
|
||||
result = tree->compare(found->keyValue, key);
|
||||
if(result == 0)
|
||||
{
|
||||
return found;
|
||||
}
|
||||
else if(result < 0)
|
||||
found = found->rightChild;
|
||||
else
|
||||
@@ -209,22 +210,10 @@ void *pico_tree_findKey(struct pico_tree *tree, void *key)
|
||||
{
|
||||
struct pico_tree_node *found;
|
||||
|
||||
|
||||
found = tree->root;
|
||||
while(IS_NOT_LEAF(found))
|
||||
{
|
||||
int result;
|
||||
|
||||
result = tree->compare(found->keyValue, key);
|
||||
if(result == 0)
|
||||
return found->keyValue;
|
||||
else if(result < 0)
|
||||
found = found->rightChild;
|
||||
else
|
||||
found = found->leftChild;
|
||||
|
||||
}
|
||||
return NULL;
|
||||
found = pico_tree_findNode(tree, key);
|
||||
if (found == NULL)
|
||||
return NULL;
|
||||
return found->keyValue;
|
||||
}
|
||||
|
||||
void *pico_tree_first(struct pico_tree *tree)
|
||||
@@ -302,7 +291,7 @@ void *pico_tree_delete(struct pico_tree *tree, void *key)
|
||||
static inline void if_nodecolor_black_fix_collisions(struct pico_tree *tree, struct pico_tree_node *temp, uint8_t nodeColor)
|
||||
{
|
||||
/* deleted node is black, this will mess up the black path property */
|
||||
if(nodeColor == BLACK)
|
||||
if(nodeColor == BLACK)
|
||||
fix_delete_collisions(tree, temp);
|
||||
}
|
||||
|
||||
@@ -314,12 +303,13 @@ void *pico_tree_delete_implementation(struct pico_tree *tree, void *key, uint8_t
|
||||
struct pico_tree_node *delete; /* keeps a copy of the node to be extracted */
|
||||
if (!key)
|
||||
return NULL;
|
||||
|
||||
delete = pico_tree_findNode(tree, key);
|
||||
|
||||
/* this key isn't in the tree, bail out */
|
||||
if(!delete)
|
||||
if(!delete)
|
||||
return NULL;
|
||||
|
||||
|
||||
lkey = delete->keyValue;
|
||||
nodeColor = pico_tree_delete_check_switch(tree, delete, &temp);
|
||||
|
||||
@@ -442,7 +432,7 @@ static void fix_insert_collisions(struct pico_tree*tree, struct pico_tree_node*n
|
||||
node = GRANPA(node);
|
||||
}
|
||||
else if(temp->color == BLACK) {
|
||||
if(node == node->parent->leftChild) {
|
||||
if(AM_I_LEFT_CHILD(node)) {
|
||||
node = node->parent;
|
||||
rotateToRight(tree, node);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user