updated picoTCP to 1.4.0, lowered build optimization levels to -O2, improved selftest

This commit is contained in:
Joseph Henry
2017-06-05 14:26:06 -07:00
parent 47a80e8954
commit 19839eeac9
367 changed files with 107850 additions and 3813 deletions

View File

@@ -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, Markian Yskout
*********************************************************************/
@@ -22,20 +22,25 @@
#include "pico_aodv.h"
#include "pico_socket_multicast.h"
#include "pico_fragments.h"
#include "pico_ethernet.h"
#include "pico_mcast.h"
#include "../../../include/Debug.hpp"
#ifdef PICO_SUPPORT_IPV4
#ifdef PICO_SUPPORT_MCAST
# define ip_mcast_dbg(...) do {} while(0) /* so_mcast_dbg in pico_socket.c */
/* #define ip_mcast_dbg dbg */
#ifdef DEBUG_MCAST
#define ip_mcast_dbg dbg
#else
#define ip_mcast_dbg(...) do {} while(0)
#endif
# define PICO_MCAST_ALL_HOSTS long_be(0xE0000001) /* 224.0.0.1 */
/* Default network interface for multicast transmission */
static struct pico_ipv4_link *mcast_default_link = NULL;
#endif
#ifdef PICO_SUPPORT_IPV4FRAG
/* # define reassembly_dbg dbg */
# define reassembly_dbg(...) do {} while(0)
#endif
/* Queues */
static struct pico_queue in = {
@@ -47,7 +52,7 @@ static struct pico_queue out = {
/* Functions */
static int ipv4_route_compare(void *ka, void *kb);
static struct pico_frame *pico_ipv4_alloc(struct pico_protocol *self, uint16_t size);
static struct pico_frame *pico_ipv4_alloc(struct pico_protocol *self, struct pico_device *dev, uint16_t size);
int pico_ipv4_compare(struct pico_ip4 *a, struct pico_ip4 *b)
@@ -284,7 +289,7 @@ static int ipv4_link_compare(void *ka, void *kb)
return 0;
}
PICO_TREE_DECLARE(Tree_dev_link, ipv4_link_compare);
static PICO_TREE_DECLARE(Tree_dev_link, ipv4_link_compare);
static int pico_ipv4_process_bcast_in(struct pico_frame *f)
{
@@ -364,7 +369,7 @@ static int pico_ipv4_process_local_unicast_in(struct pico_frame *f)
static void pico_ipv4_process_finally_try_forward(struct pico_frame *f)
{
struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
if ((pico_ipv4_is_broadcast(hdr->dst.addr)) || ((f->flags & PICO_FRAME_FLAG_BCAST)!= 0)) {
if ((pico_ipv4_is_broadcast(hdr->dst.addr)) || ((f->flags & PICO_FRAME_FLAG_BCAST) != 0)) {
/* don't forward broadcast frame, discard! */
pico_frame_discard(f);
} else if (pico_ipv4_forward(f) != 0) {
@@ -381,12 +386,12 @@ static int pico_ipv4_process_in(struct pico_protocol *self, struct pico_frame *f
int ret = 0;
struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
uint16_t max_allowed = (uint16_t) ((int)f->buffer_len - (f->net_hdr - f->buffer) - (int)PICO_SIZE_IP4HDR);
uint16_t flag = short_be(hdr->frag);
(void)self;
if (!hdr)
return -1;
(void)self;
/* NAT needs transport header information */
if (((hdr->vhl) & 0x0F) > 5) {
option_len = (uint8_t)(4 * (((hdr->vhl) & 0x0F) - 5));
@@ -395,6 +400,9 @@ static int pico_ipv4_process_in(struct pico_protocol *self, struct pico_frame *f
f->transport_hdr = ((uint8_t *)f->net_hdr) + PICO_SIZE_IP4HDR + option_len;
f->transport_len = (uint16_t)(short_be(hdr->len) - PICO_SIZE_IP4HDR - option_len);
f->net_len = (uint16_t)(PICO_SIZE_IP4HDR + option_len);
#if defined(PICO_SUPPORT_IPV4FRAG) || defined(PICO_SUPPORT_IPV6FRAG)
f->frag = short_be(hdr->frag);
#endif
if (f->transport_len > max_allowed) {
pico_frame_discard(f);
@@ -421,11 +429,13 @@ static int pico_ipv4_process_in(struct pico_protocol *self, struct pico_frame *f
return 0;
}
if (hdr->frag & short_be(PICO_IPV4_EVIL)) {
#if defined(PICO_SUPPORT_IPV4FRAG) || defined(PICO_SUPPORT_IPV6FRAG)
if (f->frag & PICO_IPV4_EVIL) {
(void)pico_icmp4_param_problem(f, 0);
pico_frame_discard(f); /* RFC 3514 */
return 0;
}
#endif
if ((hdr->vhl & 0x0f) < 5) {
/* RFC 791: IHL minimum value is 5 */
@@ -434,16 +444,18 @@ static int pico_ipv4_process_in(struct pico_protocol *self, struct pico_frame *f
return 0;
}
if (flag & (PICO_IPV4_MOREFRAG | PICO_IPV4_FRAG_MASK))
#if defined(PICO_SUPPORT_IPV4FRAG) || defined(PICO_SUPPORT_IPV6FRAG)
if (f->frag & (PICO_IPV4_MOREFRAG | PICO_IPV4_FRAG_MASK))
{
#ifdef PICO_SUPPORT_IPV4FRAG
pico_ipv4_process_frag(hdr, f, hdr ? hdr->proto : 0 );
pico_ipv4_process_frag(hdr, f, hdr->proto);
/* Frame can be discarded, frag will handle its own copy */
#endif
/* We do not support fragmentation, discard quietly */
pico_frame_discard(f);
return 0;
}
#endif
if (pico_ipv4_process_bcast_in(f) > 0)
return 0;
@@ -473,24 +485,28 @@ static int pico_ipv4_process_out(struct pico_protocol *self, struct pico_frame *
}
#endif
return pico_sendto_dev(f);
return pico_datalink_send(f);
}
static struct pico_frame *pico_ipv4_alloc(struct pico_protocol *self, uint16_t size)
static struct pico_frame *pico_ipv4_alloc(struct pico_protocol *self, struct pico_device *dev, uint16_t size)
{
struct pico_frame *f = pico_frame_alloc(size + PICO_SIZE_IP4HDR + PICO_SIZE_ETHHDR);
struct pico_frame *f = NULL;
IGNORE_PARAMETER(self);
f = pico_proto_ethernet.alloc(&pico_proto_ethernet, dev, (uint16_t)(size + PICO_SIZE_IP4HDR));
/* TODO: In 6LoWPAN topic branch update to make use of dev->ll_mode */
if (!f)
return NULL;
f->datalink_hdr = f->buffer;
f->net_hdr = f->buffer + PICO_SIZE_ETHHDR;
f->net_len = PICO_SIZE_IP4HDR;
f->transport_hdr = f->net_hdr + PICO_SIZE_IP4HDR;
f->transport_len = size;
f->len = size + PICO_SIZE_IP4HDR;
f->transport_len = (uint16_t)size;
/* Datalink size is accounted for in pico_datalink_send (link layer) */
f->len = (uint32_t)(size + PICO_SIZE_IP4HDR);
return f;
}
@@ -559,6 +575,10 @@ static struct pico_ipv4_route *route_find(const struct pico_ip4 *addr)
struct pico_ipv4_route *r;
struct pico_tree_node *index;
if (addr->addr == PICO_IP4_ANY) {
return NULL;
}
if (addr->addr != PICO_IP4_BCAST) {
pico_tree_foreach_reverse(index, &Routes) {
r = index->keyValue;
@@ -598,10 +618,6 @@ struct pico_ip4 *pico_ipv4_source_find(const struct pico_ip4 *dst)
struct pico_ipv4_route *rt;
#ifdef PICO_SUPPORT_AODV
union pico_address node_address;
node_address.ip4.addr = dst->addr;
if (dst->addr && pico_ipv4_is_unicast(dst->addr))
pico_aodv_lookup(&node_address);
#endif
if (!dst) {
@@ -609,6 +625,13 @@ struct pico_ip4 *pico_ipv4_source_find(const struct pico_ip4 *dst)
return NULL;
}
#ifdef PICO_SUPPORT_AODV
node_address.ip4.addr = dst->addr;
if (dst->addr && pico_ipv4_is_unicast(dst->addr))
pico_aodv_lookup(&node_address);
#endif
rt = route_find(dst);
if (rt && rt->link) {
myself = &rt->link->address;
@@ -657,7 +680,7 @@ struct pico_device *pico_ipv4_source_dev_find(const struct pico_ip4 *dst)
static int ipv4_mcast_groups_cmp(void *ka, void *kb)
{
struct pico_mcast_group *a = ka, *b = kb;
return pico_ipv4_compare(&a->mcast_addr, &b->mcast_addr);
return pico_ipv4_compare(&a->mcast_addr.ip4, &b->mcast_addr.ip4);
}
static int ipv4_mcast_sources_cmp(void *ka, void *kb)
@@ -682,7 +705,7 @@ static void pico_ipv4_mcast_print_groups(struct pico_ipv4_link *mcast_link)
pico_tree_foreach(index, mcast_link->MCASTGroups) {
g = index->keyValue;
ip_mcast_dbg("+ %04d | %16s | %08X | %05u | %u | %8s +\n", i, mcast_link->dev->name, g->mcast_addr.addr, g->reference_count, g->filter_mode, "");
ip_mcast_dbg("+ %04d | %16s | %08X | %05u | %u | %8s +\n", i, mcast_link->dev->name, g->mcast_addr.ip4.addr, g->reference_count, g->filter_mode, "");
pico_tree_foreach(index2, &g->MCASTSources) {
source = index2->keyValue;
ip_mcast_dbg("+ %4s | %16s | %8s | %5s | %s | %08X +\n", "", "", "", "", "", source->addr);
@@ -711,9 +734,12 @@ static int mcast_group_update(struct pico_mcast_group *g, struct pico_tree *MCAS
pico_err = PICO_ERR_ENOMEM;
return -1;
}
source->addr = ((struct pico_ip4 *)index->keyValue)->addr;
pico_tree_insert(&g->MCASTSources, source);
if (pico_tree_insert(&g->MCASTSources, source)) {
dbg("IPv4: Failed to insert source in tree\n");
PICO_FREE(source);
return -1;
}
}
}
}
@@ -735,13 +761,15 @@ int pico_ipv4_mcast_join(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_gro
if (!link)
link = mcast_default_link;
test.mcast_addr = *mcast_group;
test.mcast_addr.ip4 = *mcast_group;
g = pico_tree_findKey(link->MCASTGroups, &test);
if (g) {
if (reference_count)
g->reference_count++;
#ifdef PICO_SUPPORT_IGMP
pico_igmp_state_change(mcast_link, mcast_group, filter_mode, MCASTFilter, PICO_IGMP_STATE_UPDATE);
#endif
} else {
g = PICO_ZALLOC(sizeof(struct pico_mcast_group));
if (!g) {
@@ -752,11 +780,18 @@ int pico_ipv4_mcast_join(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_gro
/* "non-existent" state of filter mode INCLUDE and empty source list */
g->filter_mode = PICO_IP_MULTICAST_INCLUDE;
g->reference_count = 1;
g->mcast_addr = *mcast_group;
g->mcast_addr.ip4 = *mcast_group;
g->MCASTSources.root = &LEAF;
g->MCASTSources.compare = ipv4_mcast_sources_cmp;
pico_tree_insert(link->MCASTGroups, g);
if (pico_tree_insert(link->MCASTGroups, g)) {
dbg("IPv4: Failed to insert group in tree\n");
PICO_FREE(g);
return -1;
}
#ifdef PICO_SUPPORT_IGMP
pico_igmp_state_change(mcast_link, mcast_group, filter_mode, MCASTFilter, PICO_IGMP_STATE_CREATE);
#endif
}
if (mcast_group_update(g, MCASTFilter, filter_mode) < 0) {
@@ -787,14 +822,16 @@ int pico_ipv4_mcast_leave(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_gr
if (!link)
return -1;
test.mcast_addr = *mcast_group;
test.mcast_addr.ip4 = *mcast_group;
g = pico_tree_findKey(link->MCASTGroups, &test);
if (!g) {
pico_err = PICO_ERR_EINVAL;
return -1;
} else {
if (reference_count && (--(g->reference_count) < 1)) {
#ifdef PICO_SUPPORT_IGMP
pico_igmp_state_change(mcast_link, mcast_group, filter_mode, MCASTFilter, PICO_IGMP_STATE_DELETE);
#endif
/* cleanup filter */
pico_tree_foreach_safe(index, &g->MCASTSources, _tmp) {
source = index->keyValue;
@@ -804,7 +841,9 @@ int pico_ipv4_mcast_leave(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_gr
pico_tree_delete(link->MCASTGroups, g);
PICO_FREE(g);
} else {
#ifdef PICO_SUPPORT_IGMP
pico_igmp_state_change(mcast_link, mcast_group, filter_mode, MCASTFilter, PICO_IGMP_STATE_UPDATE);
#endif
if (mcast_group_update(g, MCASTFilter, filter_mode) < 0)
return -1;
}
@@ -828,7 +867,7 @@ static int pico_ipv4_mcast_filter(struct pico_frame *f)
};
struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
test.mcast_addr = hdr->dst;
test.mcast_addr.ip4 = hdr->dst;
pico_tree_foreach(index, &Tree_dev_link) {
link = index->keyValue;
@@ -875,12 +914,22 @@ static int pico_ipv4_mcast_filter(struct pico_frame *f)
int pico_ipv4_mcast_join(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group, uint8_t reference_count, uint8_t filter_mode, struct pico_tree *MCASTFilter)
{
IGNORE_PARAMETER(mcast_link);
IGNORE_PARAMETER(mcast_group);
IGNORE_PARAMETER(reference_count);
IGNORE_PARAMETER(filter_mode);
IGNORE_PARAMETER(MCASTFilter);
pico_err = PICO_ERR_EPROTONOSUPPORT;
return -1;
}
int pico_ipv4_mcast_leave(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group, uint8_t reference_count, uint8_t filter_mode, struct pico_tree *MCASTFilter)
{
IGNORE_PARAMETER(mcast_link);
IGNORE_PARAMETER(mcast_group);
IGNORE_PARAMETER(reference_count);
IGNORE_PARAMETER(filter_mode);
IGNORE_PARAMETER(MCASTFilter);
pico_err = PICO_ERR_EPROTONOSUPPORT;
return -1;
}
@@ -920,6 +969,7 @@ int pico_ipv4_frame_push(struct pico_frame *f, struct pico_ip4 *dst, uint8_t pro
struct pico_ipv4_hdr *hdr;
uint8_t ttl = PICO_IPV4_DEFAULT_TTL;
uint8_t vhl = 0x45; /* version 4, header length 20 */
int32_t retval = 0;
static uint16_t ipv4_progressive_id = 0x91c0;
#ifdef PICO_SUPPORT_MCAST
struct pico_tree_node *index;
@@ -927,7 +977,7 @@ int pico_ipv4_frame_push(struct pico_frame *f, struct pico_ip4 *dst, uint8_t pro
if (!f || !dst) {
pico_err = PICO_ERR_EINVAL;
return -1;
goto drop;
}
@@ -994,7 +1044,7 @@ int pico_ipv4_frame_push(struct pico_frame *f, struct pico_ip4 *dst, uint8_t pro
if (
#ifdef PICO_SUPPORT_IPV4FRAG
(0 == (f->frag & PICO_IPV4_MOREFRAG)) &&
(0 == (f->frag & PICO_IPV4_MOREFRAG)) &&
#endif
1 )
ipv4_progressive_id++;
@@ -1046,7 +1096,15 @@ int pico_ipv4_frame_push(struct pico_frame *f, struct pico_ip4 *dst, uint8_t pro
if ((proto != PICO_PROTO_IGMP) && (pico_ipv4_mcast_filter(f) == 0)) {
ip_mcast_dbg("MCAST: sender is member of group, loopback copy\n");
cpy = pico_frame_copy(f);
pico_enqueue(&in, cpy);
if (!cpy) {
pico_err = PICO_ERR_ENOMEM;
ip_mcast_dbg("MCAST: Failed to copy frame\n");
goto drop;
}
retval = pico_enqueue(&in, cpy);
if (retval <= 0)
pico_frame_discard(cpy);
}
}
@@ -1064,10 +1122,14 @@ int pico_ipv4_frame_push(struct pico_frame *f, struct pico_ip4 *dst, uint8_t pro
if (pico_ipv4_link_get(&hdr->dst)) {
/* it's our own IP */
return pico_enqueue(&in, f);
retval = pico_enqueue(&in, f);
if (retval > 0)
return retval;
} else{
/* TODO: Check if there are members subscribed here */
return pico_enqueue(&out, f);
retval = pico_enqueue(&out, f);
if (retval > 0)
return retval;
}
drop:
@@ -1145,7 +1207,12 @@ int MOCKABLE pico_ipv4_route_add(struct pico_ip4 address, struct pico_ip4 netmas
return -1;
}
pico_tree_insert(&Routes, new);
if (pico_tree_insert(&Routes, new)) {
dbg("IPv4: Failed to insert route in tree\n");
PICO_FREE(new);
return -1;
}
dbg_route();
return 0;
}
@@ -1222,7 +1289,15 @@ extern int pico_ipv4_link_add(struct pico_device *dev, struct pico_ip4 address,
#endif
#endif
pico_tree_insert(&Tree_dev_link, new);
if (pico_tree_insert(&Tree_dev_link, new)) {
dbg("IPv4: Failed to insert link in tree\n");
#ifdef PICO_SUPPORT_MCAST
PICO_FREE(new->MCASTGroups);
#endif
PICO_FREE(new);
return -1;
}
#ifdef PICO_SUPPORT_MCAST
do {
struct pico_ip4 mcast_all_hosts, mcast_addr, mcast_nm, mcast_gw;
@@ -1243,7 +1318,7 @@ extern int pico_ipv4_link_add(struct pico_device *dev, struct pico_ip4 address,
gateway.addr = 0U;
pico_ipv4_route_add(network, netmask, gateway, 1, new);
pico_ipv4_to_string(ipstr, new->address.addr);
dbg("Assigned ipv4 %s to device %s\n", ipstr, new->dev->name);
DEBUG_EXTRA("Assigned ipv4 %s to device %s", ipstr, new->dev->name);
if (default_bcast_route.link == NULL)
default_bcast_route.link = new;
@@ -1404,7 +1479,7 @@ static int pico_ipv4_rebound_large(struct pico_frame *f)
if (space > PICO_IPV4_MAXPAYLOAD)
space = PICO_IPV4_MAXPAYLOAD;
fr = pico_ipv4_alloc(&pico_proto_ipv4, (uint16_t)space);
fr = pico_ipv4_alloc(&pico_proto_ipv4, NULL, (uint16_t)space);
if (!fr) {
pico_err = PICO_ERR_ENOMEM;
return -1;
@@ -1425,7 +1500,7 @@ static int pico_ipv4_rebound_large(struct pico_frame *f)
if (pico_ipv4_frame_push(fr, &dst, hdr->proto) > 0) {
total_payload_written = (uint16_t)((uint16_t)fr->transport_len + total_payload_written);
} else {
pico_frame_discard(fr);
/* No need to discard frame here, pico_ipv4_frame_push() already did that */
break;
}
} /* while() */
@@ -1539,7 +1614,7 @@ static int pico_ipv4_forward(struct pico_frame *f)
if (pico_ipv4_forward_check_dev(f) < 0)
return -1;
pico_sendto_dev(f);
pico_datalink_send(f);
return 0;
}