You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ad...@apache.org on 2017/04/19 18:18:12 UTC
[16/30] incubator-mynewt-core git commit: net/ip/lwip_base;
update to LwIP to tag STABLE-2_0_2_RELEASE
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/netif.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/core/netif.c b/net/ip/lwip_base/src/core/netif.c
index 7ea4482..428b148 100644
--- a/net/ip/lwip_base/src/core/netif.c
+++ b/net/ip/lwip_base/src/core/netif.c
@@ -58,6 +58,7 @@
#include "lwip/netif.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/udp.h"
+#include "lwip/raw.h"
#include "lwip/snmp.h"
#include "lwip/igmp.h"
#include "lwip/etharp.h"
@@ -179,7 +180,7 @@ netif_init(void)
#endif /* NO_SYS */
#if LWIP_IPV6
- IP_ADDR6(loop_netif.ip6_addr, 0, 0, 0, PP_HTONL(0x00000001UL));
+ IP_ADDR6_HOST(loop_netif.ip6_addr, 0, 0, 0, 0x00000001UL);
loop_netif.ip6_addr_state[0] = IP6_ADDR_VALID;
#endif /* LWIP_IPV6 */
@@ -227,8 +228,13 @@ netif_input(struct pbuf *p, struct netif *inp)
* These functions use netif flags NETIF_FLAG_ETHARP and NETIF_FLAG_ETHERNET
* to decide whether to forward to ethernet_input() or ip_input().
* In other words, the functions only work when the netif
- * driver is implemented correctly!
- *
+ * driver is implemented correctly!\n
+ * Most members of struct netif should be be initialized by the
+ * netif init function = netif driver (init parameter of this function).\n
+ * IPv6: Don't forget to call netif_create_ip6_linklocal_address() after
+ * setting the MAC address in struct netif.hwaddr
+ * (IPv6 requires a link-local address).
+ *
* @return netif, or NULL if failed.
*/
struct netif *
@@ -253,7 +259,7 @@ netif_add(struct netif *netif,
#if LWIP_IPV6
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
ip_addr_set_zero_ip6(&netif->ip6_addr[i]);
- netif->ip6_addr_state[0] = IP6_ADDR_INVALID;
+ netif->ip6_addr_state[i] = IP6_ADDR_INVALID;
}
netif->output_ip6 = netif_null_output_ip6;
#endif /* LWIP_IPV6 */
@@ -386,6 +392,9 @@ netif_remove(struct netif *netif)
#if LWIP_UDP
udp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL);
#endif /* LWIP_UDP */
+#if LWIP_RAW
+ raw_netif_ip_addr_changed(netif_ip_addr4(netif), NULL);
+#endif /* LWIP_RAW */
}
#if LWIP_IGMP
@@ -405,6 +414,9 @@ netif_remove(struct netif *netif)
#if LWIP_UDP
udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
#endif /* LWIP_UDP */
+#if LWIP_RAW
+ raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL);
+#endif /* LWIP_RAW */
}
}
#if LWIP_IPV6_MLD
@@ -466,7 +478,7 @@ netif_find(const char *name)
return NULL;
}
- num = name[2] - '0';
+ num = (u8_t)(name[2] - '0');
for (netif = netif_list; netif != NULL; netif = netif->next) {
if (num == netif->num &&
@@ -495,7 +507,7 @@ void
netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr)
{
ip_addr_t new_addr;
- *ip_2_ip4(&new_addr) = (ipaddr ? *ipaddr : *IP4_ADDR_ANY);
+ *ip_2_ip4(&new_addr) = (ipaddr ? *ipaddr : *IP4_ADDR_ANY4);
IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_V4);
/* address is actually being changed? */
@@ -507,6 +519,9 @@ netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr)
#if LWIP_UDP
udp_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr);
#endif /* LWIP_UDP */
+#if LWIP_RAW
+ raw_netif_ip_addr_changed(netif_ip_addr4(netif), &new_addr);
+#endif /* LWIP_RAW */
mib2_remove_ip4(netif);
mib2_remove_route_ip4(0, netif);
@@ -786,7 +801,7 @@ netif_loop_output(struct netif *netif, struct pbuf *p)
err_t err;
struct pbuf *last;
#if LWIP_LOOPBACK_MAX_PBUFS
- u8_t clen = 0;
+ u16_t clen = 0;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
/* If we have a loopif, SNMP counters are adjusted for it,
* if not they are adjusted for 'netif'. */
@@ -889,7 +904,6 @@ netif_loop_output_ipv6(struct netif *netif, struct pbuf *p, const ip6_addr_t* ad
void
netif_poll(struct netif *netif)
{
- struct pbuf *in;
/* If we have a loopif, SNMP counters are adjusted for it,
* if not they are adjusted for 'netif'. */
#if MIB2_STATS
@@ -901,56 +915,52 @@ netif_poll(struct netif *netif)
#endif /* MIB2_STATS */
SYS_ARCH_DECL_PROTECT(lev);
- do {
- /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
- SYS_ARCH_PROTECT(lev);
- in = netif->loop_first;
- if (in != NULL) {
- struct pbuf *in_end = in;
+ /* Get a packet from the list. With SYS_LIGHTWEIGHT_PROT=1, this is protected */
+ SYS_ARCH_PROTECT(lev);
+ while (netif->loop_first != NULL) {
+ struct pbuf *in, *in_end;
#if LWIP_LOOPBACK_MAX_PBUFS
- u8_t clen = 1;
+ u8_t clen = 1;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
- while (in_end->len != in_end->tot_len) {
- LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
- in_end = in_end->next;
+
+ in = in_end = netif->loop_first;
+ while (in_end->len != in_end->tot_len) {
+ LWIP_ASSERT("bogus pbuf: len != tot_len but next == NULL!", in_end->next != NULL);
+ in_end = in_end->next;
#if LWIP_LOOPBACK_MAX_PBUFS
- clen++;
+ clen++;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
- }
+ }
#if LWIP_LOOPBACK_MAX_PBUFS
- /* adjust the number of pbufs on queue */
- LWIP_ASSERT("netif->loop_cnt_current underflow",
- ((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
- netif->loop_cnt_current -= clen;
+ /* adjust the number of pbufs on queue */
+ LWIP_ASSERT("netif->loop_cnt_current underflow",
+ ((netif->loop_cnt_current - clen) < netif->loop_cnt_current));
+ netif->loop_cnt_current -= clen;
#endif /* LWIP_LOOPBACK_MAX_PBUFS */
- /* 'in_end' now points to the last pbuf from 'in' */
- if (in_end == netif->loop_last) {
- /* this was the last pbuf in the list */
- netif->loop_first = netif->loop_last = NULL;
- } else {
- /* pop the pbuf off the list */
- netif->loop_first = in_end->next;
- LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
- }
- /* De-queue the pbuf from its successors on the 'loop_' list. */
- in_end->next = NULL;
+ /* 'in_end' now points to the last pbuf from 'in' */
+ if (in_end == netif->loop_last) {
+ /* this was the last pbuf in the list */
+ netif->loop_first = netif->loop_last = NULL;
+ } else {
+ /* pop the pbuf off the list */
+ netif->loop_first = in_end->next;
+ LWIP_ASSERT("should not be null since first != last!", netif->loop_first != NULL);
}
+ /* De-queue the pbuf from its successors on the 'loop_' list. */
+ in_end->next = NULL;
SYS_ARCH_UNPROTECT(lev);
- if (in != NULL) {
- LINK_STATS_INC(link.recv);
- MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len);
- MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts);
- /* loopback packets are always IP packets! */
- if (ip_input(in, netif) != ERR_OK) {
- pbuf_free(in);
- }
- /* Don't reference the packet any more! */
- in = NULL;
+ LINK_STATS_INC(link.recv);
+ MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len);
+ MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts);
+ /* loopback packets are always IP packets! */
+ if (ip_input(in, netif) != ERR_OK) {
+ pbuf_free(in);
}
- /* go on while there is a packet on the list */
- } while (netif->loop_first != NULL);
+ SYS_ARCH_PROTECT(lev);
+ }
+ SYS_ARCH_UNPROTECT(lev);
}
#if !LWIP_NETIF_LOOPBACK_MULTITHREADING
@@ -1042,6 +1052,9 @@ netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1,
#if LWIP_UDP
udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
#endif /* LWIP_UDP */
+#if LWIP_RAW
+ raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr);
+#endif /* LWIP_RAW */
}
/* @todo: remove/readd mib2 ip6 entries? */
@@ -1083,6 +1096,13 @@ netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state)
u8_t new_valid = state & IP6_ADDR_VALID;
LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n"));
+#if LWIP_IPV6_MLD
+ /* Reevaluate solicited-node multicast group membership. */
+ if (netif->flags & NETIF_FLAG_MLD6) {
+ nd6_adjust_mld_membership(netif, addr_idx, state);
+ }
+#endif /* LWIP_IPV6_MLD */
+
if (old_valid && !new_valid) {
/* address about to be removed by setting invalid */
#if LWIP_TCP
@@ -1091,6 +1111,9 @@ netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state)
#if LWIP_UDP
udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
#endif /* LWIP_UDP */
+#if LWIP_RAW
+ raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL);
+#endif /* LWIP_RAW */
/* @todo: remove mib2 ip6 entries? */
}
netif->ip6_addr_state[addr_idx] = state;
@@ -1154,11 +1177,11 @@ netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit)
/* Generate interface ID. */
if (from_mac_48bit) {
/* Assume hwaddr is a 48-bit IEEE 802 MAC. Convert to EUI-64 address. Complement Group bit. */
- ip_2_ip6(&netif->ip6_addr[0])->addr[2] = htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) |
+ ip_2_ip6(&netif->ip6_addr[0])->addr[2] = lwip_htonl((((u32_t)(netif->hwaddr[0] ^ 0x02)) << 24) |
((u32_t)(netif->hwaddr[1]) << 16) |
((u32_t)(netif->hwaddr[2]) << 8) |
(0xff));
- ip_2_ip6(&netif->ip6_addr[0])->addr[3] = htonl((0xfeul << 24) |
+ ip_2_ip6(&netif->ip6_addr[0])->addr[3] = lwip_htonl((0xfeul << 24) |
((u32_t)(netif->hwaddr[3]) << 16) |
((u32_t)(netif->hwaddr[4]) << 8) |
(netif->hwaddr[5]));
@@ -1179,10 +1202,10 @@ netif_create_ip6_linklocal_address(struct netif *netif, u8_t from_mac_48bit)
/* Set address state. */
#if LWIP_IPV6_DUP_DETECT_ATTEMPTS
/* Will perform duplicate address detection (DAD). */
- netif->ip6_addr_state[0] = IP6_ADDR_TENTATIVE;
+ netif_ip6_addr_set_state(netif, 0, IP6_ADDR_TENTATIVE);
#else
/* Consider address valid. */
- netif->ip6_addr_state[0] = IP6_ADDR_PREFERRED;
+ netif_ip6_addr_set_state(netif, 0, IP6_ADDR_PREFERRED);
#endif /* LWIP_IPV6_AUTOCONFIG */
}
@@ -1212,7 +1235,7 @@ netif_add_ip6_address(struct netif *netif, const ip6_addr_t *ip6addr, s8_t *chos
/* Find a free slot -- musn't be the first one (reserved for link local) */
for (i = 1; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
- if (!ip6_addr_isvalid(netif->ip6_addr_state[i])) {
+ if (ip6_addr_isinvalid(netif_ip6_addr_state(netif, i))) {
ip_addr_copy_from_ip6(netif->ip6_addr[i], *ip6addr);
netif_ip6_addr_set_state(netif, i, IP6_ADDR_TENTATIVE);
if (chosen_idx != NULL) {
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/pbuf.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/core/pbuf.c b/net/ip/lwip_base/src/core/pbuf.c
index a145dff..059f83a 100644
--- a/net/ip/lwip_base/src/core/pbuf.c
+++ b/net/ip/lwip_base/src/core/pbuf.c
@@ -41,21 +41,28 @@ typedef struct my_custom_pbuf
void* dma_descriptor;
} my_custom_pbuf_t;
+LWIP_MEMPOOL_DECLARE(RX_POOL, 10, sizeof(my_custom_pbuf_t), "Zero-copy RX PBUF pool");
+
void my_pbuf_free_custom(void* p)
{
my_custom_pbuf_t* my_puf = (my_custom_pbuf_t*)p;
+
+ LOCK_INTERRUPTS();
free_rx_dma_descriptor(my_pbuf->dma_descriptor);
- my_pbuf_pool_put(my_pbuf);
+ LWIP_MEMPOOL_FREE(RX_POOL, my_pbuf);
+ UNLOCK_INTERRUPTS();
}
void eth_rx_irq()
{
dma_descriptor* dma_desc = get_RX_DMA_descriptor_from_ethernet();
- my_custom_pbuf_t* my_pbuf = my_pbuf_pool_get();
+ my_custom_pbuf_t* my_pbuf = (my_custom_pbuf_t*)LWIP_MEMPOOL_ALLOC(RX_POOL);
my_pbuf->p.custom_free_function = my_pbuf_free_custom;
my_pbuf->dma_descriptor = dma_desc;
+ invalidate_cpu_cache(dma_desc->rx_data, dma_desc->rx_length);
+
struct pbuf* p = pbuf_alloced_custom(PBUF_RAW,
dma_desc->rx_length,
PBUF_REF,
@@ -343,8 +350,18 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
break;
case PBUF_RAM:
- /* If pbuf is to be allocated in RAM, allocate memory for it. */
- p = (struct pbuf*)mem_malloc(LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length));
+ {
+ mem_size_t alloc_len = LWIP_MEM_ALIGN_SIZE(SIZEOF_STRUCT_PBUF + offset) + LWIP_MEM_ALIGN_SIZE(length);
+
+ /* bug #50040: Check for integer overflow when calculating alloc_len */
+ if (alloc_len < LWIP_MEM_ALIGN_SIZE(length)) {
+ return NULL;
+ }
+
+ /* If pbuf is to be allocated in RAM, allocate memory for it. */
+ p = (struct pbuf*)mem_malloc(alloc_len);
+ }
+
if (p == NULL) {
return NULL;
}
@@ -561,11 +578,11 @@ pbuf_header_impl(struct pbuf *p, s16_t header_size_increment, u8_t force)
}
if (header_size_increment < 0) {
- increment_magnitude = -header_size_increment;
+ increment_magnitude = (u16_t)-header_size_increment;
/* Check that we aren't going to move off the end of the pbuf */
LWIP_ERROR("increment_magnitude <= p->len", (increment_magnitude <= p->len), return 1;);
} else {
- increment_magnitude = header_size_increment;
+ increment_magnitude = (u16_t)header_size_increment;
#if 0
/* Can't assert these as some callers speculatively call
pbuf_header() to see if it's OK. Will return 1 below instead. */
@@ -779,10 +796,10 @@ pbuf_free(struct pbuf *p)
* @param p first pbuf of chain
* @return the number of pbufs in a chain
*/
-u8_t
-pbuf_clen(struct pbuf *p)
+u16_t
+pbuf_clen(const struct pbuf *p)
{
- u8_t len;
+ u16_t len;
len = 0;
while (p != NULL) {
@@ -805,6 +822,7 @@ pbuf_ref(struct pbuf *p)
/* pbuf given? */
if (p != NULL) {
SYS_ARCH_INC(p->ref, 1);
+ LWIP_ASSERT("pbuf ref overflow", p->ref > 0);
}
}
@@ -927,12 +945,12 @@ pbuf_dechain(struct pbuf *p)
* enough to hold p_from
*/
err_t
-pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
+pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
{
u16_t offset_to=0, offset_from=0, len;
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n",
- (void*)p_to, (void*)p_from));
+ (const void*)p_to, (const void*)p_from));
/* is the target big enough to hold the source? */
LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) &&
@@ -994,9 +1012,9 @@ pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
* @return the number of bytes copied, or 0 on failure
*/
u16_t
-pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
+pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
{
- struct pbuf *p;
+ const struct pbuf *p;
u16_t left;
u16_t buf_copy_len;
u16_t copied_total = 0;
@@ -1082,20 +1100,12 @@ void pbuf_split_64k(struct pbuf *p, struct pbuf **rest)
}
#endif /* LWIP_TCP && TCP_QUEUE_OOSEQ && LWIP_WND_SCALE */
-/**
- * @ingroup pbuf
- * Skip a number of bytes at the start of a pbuf
- *
- * @param in input pbuf
- * @param in_offset offset to skip
- * @param out_offset resulting offset in the returned pbuf
- * @return the pbuf in the queue where the offset is
- */
-struct pbuf*
-pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset)
+/* Actual implementation of pbuf_skip() but returning const pointer... */
+static const struct pbuf*
+pbuf_skip_const(const struct pbuf* in, u16_t in_offset, u16_t* out_offset)
{
u16_t offset_left = in_offset;
- struct pbuf* q = in;
+ const struct pbuf* q = in;
/* get the correct pbuf */
while ((q != NULL) && (q->len <= offset_left)) {
@@ -1110,6 +1120,22 @@ pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset)
/**
* @ingroup pbuf
+ * Skip a number of bytes at the start of a pbuf
+ *
+ * @param in input pbuf
+ * @param in_offset offset to skip
+ * @param out_offset resulting offset in the returned pbuf
+ * @return the pbuf in the queue where the offset is
+ */
+struct pbuf*
+pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset)
+{
+ const struct pbuf* out = pbuf_skip_const(in, in_offset, out_offset);
+ return LWIP_CONST_CAST(struct pbuf*, out);
+}
+
+/**
+ * @ingroup pbuf
* Copy application supplied data into a pbuf.
* This function can only be used to copy the equivalent of buf->tot_len data.
*
@@ -1213,6 +1239,7 @@ pbuf_coalesce(struct pbuf *p, pbuf_layer layer)
return p;
}
err = pbuf_copy(q, p);
+ LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */
LWIP_ASSERT("pbuf_copy failed", err == ERR_OK);
pbuf_free(p);
return q;
@@ -1269,7 +1296,7 @@ pbuf_fill_chksum(struct pbuf *p, u16_t start_offset, const void *dataptr,
* @return byte at an offset into p OR ZERO IF 'offset' >= p->tot_len
*/
u8_t
-pbuf_get_at(struct pbuf* p, u16_t offset)
+pbuf_get_at(const struct pbuf* p, u16_t offset)
{
int ret = pbuf_try_get_at(p, offset);
if (ret >= 0) {
@@ -1287,10 +1314,10 @@ pbuf_get_at(struct pbuf* p, u16_t offset)
* @return byte at an offset into p [0..0xFF] OR negative if 'offset' >= p->tot_len
*/
int
-pbuf_try_get_at(struct pbuf* p, u16_t offset)
+pbuf_try_get_at(const struct pbuf* p, u16_t offset)
{
u16_t q_idx;
- struct pbuf* q = pbuf_skip(p, offset, &q_idx);
+ const struct pbuf* q = pbuf_skip_const(p, offset, &q_idx);
/* return requested data if pbuf is OK */
if ((q != NULL) && (q->len > q_idx)) {
@@ -1332,10 +1359,10 @@ pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data)
* (0xffff if p is too short, diffoffset+1 otherwise)
*/
u16_t
-pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n)
+pbuf_memcmp(const struct pbuf* p, u16_t offset, const void* s2, u16_t n)
{
u16_t start = offset;
- struct pbuf* q = p;
+ const struct pbuf* q = p;
u16_t i;
/* pbuf long enough to perform check? */
@@ -1374,7 +1401,7 @@ pbuf_memcmp(struct pbuf* p, u16_t offset, const void* s2, u16_t n)
* @return 0xFFFF if substr was not found in p or the index where it was found
*/
u16_t
-pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset)
+pbuf_memfind(const struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset)
{
u16_t i;
u16_t max = p->tot_len - mem_len;
@@ -1401,7 +1428,7 @@ pbuf_memfind(struct pbuf* p, const void* mem, u16_t mem_len, u16_t start_offset)
* @return 0xFFFF if substr was not found in p or the index where it was found
*/
u16_t
-pbuf_strstr(struct pbuf* p, const char* substr)
+pbuf_strstr(const struct pbuf* p, const char* substr)
{
size_t substr_len;
if ((substr == NULL) || (substr[0] == 0) || (p->tot_len == 0xFFFF)) {
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/raw.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/core/raw.c b/net/ip/lwip_base/src/core/raw.c
index a3a9077..80cf9ec 100644
--- a/net/ip/lwip_base/src/core/raw.c
+++ b/net/ip/lwip_base/src/core/raw.c
@@ -196,7 +196,7 @@ raw_input(struct pbuf *p, struct netif *inp)
* Bind a RAW PCB.
*
* @param pcb RAW PCB to be bound with a local address ipaddr.
- * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
+ * @param ipaddr local IP address to bind with. Use IP4_ADDR_ANY to
* bind to all local interfaces.
*
* @return lwIP error code.
@@ -209,7 +209,7 @@ raw_input(struct pbuf *p, struct netif *inp)
err_t
raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
{
- if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
+ if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL;
}
ip_addr_set_ipaddr(&pcb->local_ip, ipaddr);
@@ -233,7 +233,7 @@ raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
err_t
raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
{
- if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
+ if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL;
}
ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr);
@@ -250,9 +250,6 @@ raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
* packet will not be passed to other raw PCBs or other protocol layers.
* - not free the packet, and return zero. The packet will be matched
* against further PCBs and/or forwarded to another protocol layers.
- *
- * @return non-zero if the packet was free()d, zero if the packet remains
- * available for others.
*/
void
raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg)
@@ -283,7 +280,6 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr)
const ip_addr_t *src_ip;
struct pbuf *q; /* q will be sent down the stack */
s16_t header_size;
- const ip_addr_t *dst_ip = ipaddr;
if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
return ERR_VAL;
@@ -324,10 +320,16 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr)
}
}
- netif = ip_route(&pcb->local_ip, dst_ip);
+ if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
+ /* Don't call ip_route() with IP_ANY_TYPE */
+ netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(ipaddr)), ipaddr);
+ } else {
+ netif = ip_route(&pcb->local_ip, ipaddr);
+ }
+
if (netif == NULL) {
LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to "));
- ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, dst_ip);
+ ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ipaddr);
/* free any temporary header pbuf allocated by pbuf_header() */
if (q != p) {
pbuf_free(q);
@@ -352,7 +354,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr)
if (ip_addr_isany(&pcb->local_ip)) {
/* use outgoing network interface IP address as source address */
- src_ip = ip_netif_get_local_ip(netif, dst_ip);
+ src_ip = ip_netif_get_local_ip(netif, ipaddr);
#if LWIP_IPV6
if (src_ip == NULL) {
if (q != p) {
@@ -369,15 +371,15 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr)
#if LWIP_IPV6
/* If requested, based on the IPV6_CHECKSUM socket option per RFC3542,
compute the checksum and update the checksum in the payload. */
- if (IP_IS_V6(dst_ip) && pcb->chksum_reqd) {
- u16_t chksum = ip6_chksum_pseudo(p, pcb->protocol, p->tot_len, ip_2_ip6(src_ip), ip_2_ip6(dst_ip));
+ if (IP_IS_V6(ipaddr) && pcb->chksum_reqd) {
+ u16_t chksum = ip6_chksum_pseudo(p, pcb->protocol, p->tot_len, ip_2_ip6(src_ip), ip_2_ip6(ipaddr));
LWIP_ASSERT("Checksum must fit into first pbuf", p->len >= (pcb->chksum_offset + 2));
SMEMCPY(((u8_t *)p->payload) + pcb->chksum_offset, &chksum, sizeof(u16_t));
}
#endif
NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint);
- err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, pcb->protocol, netif);
+ err = ip_output_if(q, src_ip, ipaddr, pcb->ttl, pcb->tos, pcb->protocol, netif);
NETIF_SET_HWADDRHINT(netif, NULL);
/* did we chain a header earlier? */
@@ -471,7 +473,7 @@ raw_new(u8_t proto)
* @return The RAW PCB which was created. NULL if the PCB data structure
* could not be allocated.
*
- * @param type IP address type, see IPADDR_TYPE_XX definitions.
+ * @param type IP address type, see @ref lwip_ip_addr_type definitions.
* If you want to listen to IPv4 and IPv6 (dual-stack) packets,
* supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE.
* @param proto the protocol number (next header) of the IPv6 packet payload
@@ -495,4 +497,25 @@ raw_new_ip_type(u8_t type, u8_t proto)
return pcb;
}
+/** This function is called from netif.c when address is changed
+ *
+ * @param old_addr IP address of the netif before change
+ * @param new_addr IP address of the netif after change
+ */
+void raw_netif_ip_addr_changed(const ip_addr_t* old_addr, const ip_addr_t* new_addr)
+{
+ struct raw_pcb* rpcb;
+
+ if (!ip_addr_isany(old_addr) && !ip_addr_isany(new_addr)) {
+ for (rpcb = raw_pcbs; rpcb != NULL; rpcb = rpcb->next) {
+ /* PCB bound to current local interface address? */
+ if (ip_addr_cmp(&rpcb->local_ip, old_addr)) {
+ /* The PCB is bound to the old ipaddr and
+ * is set to bound to the new one instead */
+ ip_addr_copy(rpcb->local_ip, *new_addr);
+ }
+ }
+ }
+}
+
#endif /* LWIP_RAW */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/stats.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/core/stats.c b/net/ip/lwip_base/src/core/stats.c
index c75fff2..893d199 100644
--- a/net/ip/lwip_base/src/core/stats.c
+++ b/net/ip/lwip_base/src/core/stats.c
@@ -50,7 +50,7 @@
struct stats_ lwip_stats;
void
-lwip_stats_init(void)
+stats_init(void)
{
#ifdef LWIP_DEBUG
#if MEM_STATS
@@ -96,7 +96,7 @@ stats_display_igmp(struct stats_igmp *igmp, const char *name)
LWIP_PLATFORM_DIAG(("rx_report: %"STAT_COUNTER_F"\n\t", igmp->rx_report));
LWIP_PLATFORM_DIAG(("tx_join: %"STAT_COUNTER_F"\n\t", igmp->tx_join));
LWIP_PLATFORM_DIAG(("tx_leave: %"STAT_COUNTER_F"\n\t", igmp->tx_leave));
- LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n\t", igmp->tx_report));
+ LWIP_PLATFORM_DIAG(("tx_report: %"STAT_COUNTER_F"\n", igmp->tx_report));
}
#endif /* IGMP_STATS || MLD6_STATS */
@@ -135,7 +135,7 @@ stats_display_sys(struct stats_sys *sys)
LWIP_PLATFORM_DIAG(("mutex.err: %"U32_F"\n\t", (u32_t)sys->mutex.err));
LWIP_PLATFORM_DIAG(("mbox.used: %"U32_F"\n\t", (u32_t)sys->mbox.used));
LWIP_PLATFORM_DIAG(("mbox.max: %"U32_F"\n\t", (u32_t)sys->mbox.max));
- LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n\t", (u32_t)sys->mbox.err));
+ LWIP_PLATFORM_DIAG(("mbox.err: %"U32_F"\n", (u32_t)sys->mbox.err));
}
#endif /* SYS_STATS */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/sys.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/core/sys.c b/net/ip/lwip_base/src/core/sys.c
index f177737..7059b4d 100644
--- a/net/ip/lwip_base/src/core/sys.c
+++ b/net/ip/lwip_base/src/core/sys.c
@@ -36,6 +36,44 @@
*
*/
+/**
+ * @defgroup sys_layer Porting (system abstraction layer)
+ * @ingroup lwip
+ * @verbinclude "sys_arch.txt"
+ *
+ * @defgroup sys_os OS abstraction layer
+ * @ingroup sys_layer
+ * No need to implement functions in this section in NO_SYS mode.
+ *
+ * @defgroup sys_sem Semaphores
+ * @ingroup sys_os
+ *
+ * @defgroup sys_mutex Mutexes
+ * @ingroup sys_os
+ * Mutexes are recommended to correctly handle priority inversion,
+ * especially if you use LWIP_CORE_LOCKING .
+ *
+ * @defgroup sys_mbox Mailboxes
+ * @ingroup sys_os
+ *
+ * @defgroup sys_time Time
+ * @ingroup sys_layer
+ *
+ * @defgroup sys_prot Critical sections
+ * @ingroup sys_layer
+ * Used to protect short regions of code against concurrent access.
+ * - Your system is a bare-metal system (probably with an RTOS)
+ * and interrupts are under your control:
+ * Implement this as LockInterrupts() / UnlockInterrupts()
+ * - Your system uses an RTOS with deferred interrupt handling from a
+ * worker thread: Implement as a global mutex or lock/unlock scheduler
+ * - Your system uses a high-level OS with e.g. POSIX signals:
+ * Implement as a global mutex
+ *
+ * @defgroup sys_misc Misc
+ * @ingroup sys_os
+ */
+
#include "lwip/opt.h"
#include "lwip/sys.h"
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/tcp.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/core/tcp.c b/net/ip/lwip_base/src/core/tcp.c
index 50aa31f..ec2e1f9 100644
--- a/net/ip/lwip_base/src/core/tcp.c
+++ b/net/ip/lwip_base/src/core/tcp.c
@@ -62,6 +62,10 @@
#include <string.h>
+#ifdef LWIP_HOOK_FILENAME
+#include LWIP_HOOK_FILENAME
+#endif
+
#ifndef TCP_LOCAL_PORT_RANGE_START
/* From http://www.iana.org/assignments/port-numbers:
"The Dynamic and/or Private Ports are those from 49152 through 65535" */
@@ -132,6 +136,8 @@ static u8_t tcp_timer;
static u8_t tcp_timer_ctr;
static u16_t tcp_new_port(void);
+static err_t tcp_close_shutdown_fin(struct tcp_pcb *pcb);
+
/**
* Initialize this module.
*/
@@ -258,8 +264,6 @@ tcp_backlog_accepted(struct tcp_pcb* pcb)
static err_t
tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
{
- err_t err;
-
if (rst_on_unacked_data && ((pcb->state == ESTABLISHED) || (pcb->state == CLOSE_WAIT))) {
if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND_MAX(pcb))) {
/* Not all data received by application, send RST to tell the remote
@@ -290,6 +294,8 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
}
}
+ /* - states which free the pcb are handled here,
+ - states which send FIN and change state are handled in tcp_close_shutdown_fin() */
switch (pcb->state) {
case CLOSED:
/* Closing a pcb in the CLOSED state might seem erroneous,
@@ -299,27 +305,34 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
* or for a pcb that has been used and then entered the CLOSED state
* is erroneous, but this should never happen as the pcb has in those cases
* been freed, and so any remaining handles are bogus. */
- err = ERR_OK;
if (pcb->local_port != 0) {
TCP_RMV(&tcp_bound_pcbs, pcb);
}
memp_free(MEMP_TCP_PCB, pcb);
- pcb = NULL;
break;
case LISTEN:
- err = ERR_OK;
tcp_listen_closed(pcb);
tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb);
memp_free(MEMP_TCP_PCB_LISTEN, pcb);
- pcb = NULL;
break;
case SYN_SENT:
- err = ERR_OK;
TCP_PCB_REMOVE_ACTIVE(pcb);
memp_free(MEMP_TCP_PCB, pcb);
- pcb = NULL;
MIB2_STATS_INC(mib2.tcpattemptfails);
break;
+ default:
+ return tcp_close_shutdown_fin(pcb);
+ }
+ return ERR_OK;
+}
+
+static err_t
+tcp_close_shutdown_fin(struct tcp_pcb *pcb)
+{
+ err_t err;
+ LWIP_ASSERT("pcb != NULL", pcb != NULL);
+
+ switch (pcb->state) {
case SYN_RCVD:
err = tcp_send_fin(pcb);
if (err == ERR_OK) {
@@ -344,18 +357,20 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data)
break;
default:
/* Has already been closed, do nothing. */
- err = ERR_OK;
- pcb = NULL;
+ return ERR_OK;
break;
}
- if (pcb != NULL && err == ERR_OK) {
+ if (err == ERR_OK) {
/* To ensure all data has been sent when tcp_close returns, we have
to make sure tcp_output doesn't fail.
Since we don't really have to ensure all data has been sent when tcp_close
returns (unsent data is sent from tcp timer functions, also), we don't care
for the return value of tcp_output for now. */
tcp_output(pcb);
+ } else if (err == ERR_MEM) {
+ /* Mark this pcb for closing. Closing is retried from tcp_tmr. */
+ pcb->flags |= TF_CLOSEPEND;
}
return err;
}
@@ -467,6 +482,7 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
} else {
int send_rst = 0;
u16_t local_port = 0;
+ enum tcp_state last_state;
seqno = pcb->snd_nxt;
ackno = pcb->rcv_nxt;
#if LWIP_CALLBACK_API
@@ -499,8 +515,9 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n"));
tcp_rst(seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port);
}
+ last_state = pcb->state;
memp_free(MEMP_TCP_PCB, pcb);
- TCP_EVENT_ERR(errf, errf_arg, ERR_ABRT);
+ TCP_EVENT_ERR(last_state, errf, errf_arg, ERR_ABRT);
}
}
@@ -529,7 +546,7 @@ tcp_abort(struct tcp_pcb *pcb)
*
* @param pcb the tcp_pcb to bind (no check is done whether this pcb is
* already bound!)
- * @param ipaddr the local ip address to bind to (use IP_ADDR_ANY to bind
+ * @param ipaddr the local ip address to bind to (use IP4_ADDR_ANY to bind
* to any local address
* @param port the local port to bind to
* @return ERR_USE if the port is already in use
@@ -546,12 +563,12 @@ tcp_bind(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
#if LWIP_IPV4
/* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */
if (ipaddr == NULL) {
- ipaddr = IP_ADDR_ANY;
+ ipaddr = IP4_ADDR_ANY;
}
#endif /* LWIP_IPV4 */
/* still need to check for ipaddr == NULL in IPv6 only case */
- if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
+ if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL;
}
@@ -636,19 +653,44 @@ tcp_accept_null(void *arg, struct tcp_pcb *pcb, err_t err)
*
* @note The original tcp_pcb is freed. This function therefore has to be
* called like this:
- * tpcb = tcp_listen(tpcb);
+ * tpcb = tcp_listen_with_backlog(tpcb, backlog);
*/
struct tcp_pcb *
tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
{
- struct tcp_pcb_listen *lpcb;
+ return tcp_listen_with_backlog_and_err(pcb, backlog, NULL);
+}
+
+/**
+ * @ingroup tcp_raw
+ * Set the state of the connection to be LISTEN, which means that it
+ * is able to accept incoming connections. The protocol control block
+ * is reallocated in order to consume less memory. Setting the
+ * connection to LISTEN is an irreversible process.
+ *
+ * @param pcb the original tcp_pcb
+ * @param backlog the incoming connections queue limit
+ * @param err when NULL is returned, this contains the error reason
+ * @return tcp_pcb used for listening, consumes less memory.
+ *
+ * @note The original tcp_pcb is freed. This function therefore has to be
+ * called like this:
+ * tpcb = tcp_listen_with_backlog_and_err(tpcb, backlog, &err);
+ */
+struct tcp_pcb *
+tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err)
+{
+ struct tcp_pcb_listen *lpcb = NULL;
+ err_t res;
LWIP_UNUSED_ARG(backlog);
- LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL);
+ LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, res = ERR_CLSD; goto done);
/* already listening? */
if (pcb->state == LISTEN) {
- return pcb;
+ lpcb = (struct tcp_pcb_listen*)pcb;
+ res = ERR_ALREADY;
+ goto done;
}
#if SO_REUSE
if (ip_get_option(pcb, SOF_REUSEADDR)) {
@@ -659,14 +701,17 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
if ((lpcb->local_port == pcb->local_port) &&
ip_addr_cmp(&lpcb->local_ip, &pcb->local_ip)) {
/* this address/port is already used */
- return NULL;
+ lpcb = NULL;
+ res = ERR_USE;
+ goto done;
}
}
}
#endif /* SO_REUSE */
lpcb = (struct tcp_pcb_listen *)memp_malloc(MEMP_TCP_PCB_LISTEN);
if (lpcb == NULL) {
- return NULL;
+ res = ERR_MEM;
+ goto done;
}
lpcb->callback_arg = pcb->callback_arg;
lpcb->local_port = pcb->local_port;
@@ -691,6 +736,11 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog)
tcp_backlog_set(lpcb, backlog);
#endif /* TCP_LISTEN_BACKLOG */
TCP_REG(&tcp_listen_pcbs.pcbs, (struct tcp_pcb *)lpcb);
+ res = ERR_OK;
+done:
+ if (err != NULL) {
+ *err = res;
+ }
return (struct tcp_pcb *)lpcb;
}
@@ -826,7 +876,7 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
u32_t iss;
u16_t old_local_port;
- if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
+ if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL;
}
@@ -880,10 +930,11 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
#endif /* SO_REUSE */
}
- iss = tcp_next_iss();
+ iss = tcp_next_iss(pcb);
pcb->rcv_nxt = 0;
pcb->snd_nxt = iss;
pcb->lastack = iss - 1;
+ pcb->snd_wl2 = iss - 1;
pcb->snd_lbb = iss - 1;
/* Start with a window that does not need scaling. When window scaling is
enabled and used, the window is enlarged when both sides agree on scaling. */
@@ -897,7 +948,6 @@ tcp_connect(struct tcp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port,
pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip);
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
pcb->cwnd = 1;
- pcb->ssthresh = TCP_WND;
#if LWIP_CALLBACK_API
pcb->connected = connected;
#else /* LWIP_CALLBACK_API */
@@ -963,11 +1013,11 @@ tcp_slowtmr_start:
pcb_remove = 0;
pcb_reset = 0;
- if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {
+ if (pcb->state == SYN_SENT && pcb->nrtx >= TCP_SYNMAXRTX) {
++pcb_remove;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n"));
}
- else if (pcb->nrtx == TCP_MAXRTX) {
+ else if (pcb->nrtx >= TCP_MAXRTX) {
++pcb_remove;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));
} else {
@@ -1001,7 +1051,8 @@ tcp_slowtmr_start:
/* Double retransmission time-out unless we are trying to
* connect to somebody (i.e., we are in SYN_SENT). */
if (pcb->state != SYN_SENT) {
- pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
+ u8_t backoff_idx = LWIP_MIN(pcb->nrtx, sizeof(tcp_backoff)-1);
+ pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[backoff_idx];
}
/* Reset the retransmission timer. */
@@ -1098,6 +1149,7 @@ tcp_slowtmr_start:
tcp_err_fn err_fn = pcb->errf;
#endif /* LWIP_CALLBACK_API */
void *err_arg;
+ enum tcp_state last_state;
tcp_pcb_purge(pcb);
/* Remove PCB from tcp_active_pcbs list. */
if (prev != NULL) {
@@ -1115,12 +1167,13 @@ tcp_slowtmr_start:
}
err_arg = pcb->callback_arg;
+ last_state = pcb->state;
pcb2 = pcb;
pcb = pcb->next;
memp_free(MEMP_TCP_PCB, pcb2);
tcp_active_pcbs_changed = 0;
- TCP_EVENT_ERR(err_fn, err_arg, ERR_ABRT);
+ TCP_EVENT_ERR(last_state, err_fn, err_arg, ERR_ABRT);
if (tcp_active_pcbs_changed) {
goto tcp_slowtmr_start;
}
@@ -1210,6 +1263,12 @@ tcp_fasttmr_start:
tcp_output(pcb);
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
}
+ /* send pending FIN */
+ if (pcb->flags & TF_CLOSEPEND) {
+ LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: pending FIN\n"));
+ pcb->flags &= ~(TF_CLOSEPEND);
+ tcp_close_shutdown_fin(pcb);
+ }
next = pcb->next;
@@ -1491,7 +1550,6 @@ struct tcp_pcb *
tcp_alloc(u8_t prio)
{
struct tcp_pcb *pcb;
- u32_t iss;
pcb = (struct tcp_pcb *)memp_malloc(MEMP_TCP_PCB);
if (pcb == NULL) {
@@ -1554,14 +1612,17 @@ tcp_alloc(u8_t prio)
pcb->sv = 3000 / TCP_SLOW_INTERVAL;
pcb->rtime = -1;
pcb->cwnd = 1;
- iss = tcp_next_iss();
- pcb->snd_wl2 = iss;
- pcb->snd_nxt = iss;
- pcb->lastack = iss;
- pcb->snd_lbb = iss;
pcb->tmr = tcp_ticks;
pcb->last_timer = tcp_timer_ctr;
+ /* RFC 5681 recommends setting ssthresh abritrarily high and gives an example
+ of using the largest advertised receive window. We've seen complications with
+ receiving TCPs that use window scaling and/or window auto-tuning where the
+ initial advertised window is very small and then grows rapidly once the
+ connection is established. To avoid these complications, we set ssthresh to the
+ largest effective cwnd (amount of in-flight data) that the sender can have. */
+ pcb->ssthresh = TCP_SND_BUF;
+
#if LWIP_CALLBACK_API
pcb->recv = tcp_recv_null;
#endif /* LWIP_CALLBACK_API */
@@ -1602,7 +1663,7 @@ tcp_new(void)
* place it on any of the TCP PCB lists.
* The pcb is not put on any list until binding using tcp_bind().
*
- * @param type IP address type, see IPADDR_TYPE_XX definitions.
+ * @param type IP address type, see @ref lwip_ip_addr_type definitions.
* If you want to listen to IPv4 and IPv6 (dual-stack) connections,
* supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE.
* @return a new tcp_pcb that initially is in state CLOSED
@@ -1826,12 +1887,18 @@ tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb)
* @return u32_t pseudo random sequence number
*/
u32_t
-tcp_next_iss(void)
+tcp_next_iss(struct tcp_pcb *pcb)
{
+#ifdef LWIP_HOOK_TCP_ISN
+ return LWIP_HOOK_TCP_ISN(&pcb->local_ip, pcb->local_port, &pcb->remote_ip, pcb->remote_port);
+#else /* LWIP_HOOK_TCP_ISN */
static u32_t iss = 6510;
+ LWIP_UNUSED_ARG(pcb);
+
iss += tcp_ticks; /* XXX */
return iss;
+#endif /* LWIP_HOOK_TCP_ISN */
}
#if TCP_CALCULATE_EFF_SEND_MSS
@@ -1972,13 +2039,13 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
LWIP_DEBUGF(TCP_DEBUG, ("TCP header:\n"));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
- ntohs(tcphdr->src), ntohs(tcphdr->dest)));
+ lwip_ntohs(tcphdr->src), lwip_ntohs(tcphdr->dest)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (seq no)\n",
- ntohl(tcphdr->seqno)));
+ lwip_ntohl(tcphdr->seqno)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %010"U32_F" | (ack no)\n",
- ntohl(tcphdr->ackno)));
+ lwip_ntohl(tcphdr->ackno)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| %2"U16_F" | |%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"%"U16_F"| %5"U16_F" | (hdrlen, flags (",
TCPH_HDRLEN(tcphdr),
@@ -1988,12 +2055,12 @@ tcp_debug_print(struct tcp_hdr *tcphdr)
(u16_t)(TCPH_FLAGS(tcphdr) >> 2 & 1),
(u16_t)(TCPH_FLAGS(tcphdr) >> 1 & 1),
(u16_t)(TCPH_FLAGS(tcphdr) & 1),
- ntohs(tcphdr->wnd)));
+ lwip_ntohs(tcphdr->wnd)));
tcp_debug_print_flags(TCPH_FLAGS(tcphdr));
LWIP_DEBUGF(TCP_DEBUG, ("), win)\n"));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(TCP_DEBUG, ("| 0x%04"X16_F" | %5"U16_F" | (chksum, urgp)\n",
- ntohs(tcphdr->chksum), ntohs(tcphdr->urgp)));
+ lwip_ntohs(tcphdr->chksum), lwip_ntohs(tcphdr->urgp)));
LWIP_DEBUGF(TCP_DEBUG, ("+-------------------------------+\n"));
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/tcp_in.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/core/tcp_in.c b/net/ip/lwip_base/src/core/tcp_in.c
index dd88e1e..ba87928 100644
--- a/net/ip/lwip_base/src/core/tcp_in.c
+++ b/net/ip/lwip_base/src/core/tcp_in.c
@@ -61,8 +61,6 @@
/** Initial CWND calculation as defined RFC 2581 */
#define LWIP_TCP_CALC_INITIAL_CWND(mss) LWIP_MIN((4U * (mss)), LWIP_MAX((2U * (mss)), 4380U));
-/** Initial slow start threshold value: we use the full window */
-#define LWIP_TCP_INITIAL_SSTHRESH(pcb) ((pcb)->snd_wnd)
/* These variables are global to all functions involved in the input
processing of TCP segments. They are set by the tcp_input()
@@ -209,11 +207,11 @@ tcp_input(struct pbuf *p, struct netif *inp)
}
/* Convert fields in TCP header to host byte order. */
- tcphdr->src = ntohs(tcphdr->src);
- tcphdr->dest = ntohs(tcphdr->dest);
- seqno = tcphdr->seqno = ntohl(tcphdr->seqno);
- ackno = tcphdr->ackno = ntohl(tcphdr->ackno);
- tcphdr->wnd = ntohs(tcphdr->wnd);
+ tcphdr->src = lwip_ntohs(tcphdr->src);
+ tcphdr->dest = lwip_ntohs(tcphdr->dest);
+ seqno = tcphdr->seqno = lwip_ntohl(tcphdr->seqno);
+ ackno = tcphdr->ackno = lwip_ntohl(tcphdr->ackno);
+ tcphdr->wnd = lwip_ntohs(tcphdr->wnd);
flags = TCPH_FLAGS(tcphdr);
tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0);
@@ -358,6 +356,11 @@ tcp_input(struct pbuf *p, struct netif *inp)
((pcb->refused_data != NULL) && (tcplen > 0))) {
/* pcb has been aborted or refused data is still refused and the new
segment contains data */
+ if (pcb->rcv_ann_wnd == 0) {
+ /* this is a zero-window probe, we respond to it with current RCV.NXT
+ and drop the data segment */
+ tcp_send_empty_ack(pcb);
+ }
TCP_STATS_INC(tcp.drop);
MIB2_STATS_INC(mib2.tcpinerrs);
goto aborted;
@@ -373,7 +376,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
end. We then call the error callback to inform the
application that the connection is dead before we
deallocate the PCB. */
- TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST);
+ TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_RST);
tcp_pcb_remove(&tcp_active_pcbs, pcb);
memp_free(MEMP_TCP_PCB, pcb);
} else {
@@ -408,7 +411,7 @@ tcp_input(struct pbuf *p, struct netif *inp)
/* Connection closed although the application has only shut down the
tx side: call the PCB's err callback and indicate the closure to
ensure the application doesn't continue using the PCB. */
- TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_CLSD);
+ TCP_EVENT_ERR(pcb->state, pcb->errf, pcb->callback_arg, ERR_CLSD);
}
tcp_pcb_remove(&tcp_active_pcbs, pcb);
memp_free(MEMP_TCP_PCB, pcb);
@@ -534,10 +537,7 @@ dropped:
* connection (from tcp_input()).
*
* @param pcb the tcp_pcb_listen for which a segment arrived
- * @return ERR_OK if the segment was processed
- * another err_t on error
*
- * @note the return value is not (yet?) used in tcp_input()
* @note the segment which arrived is saved in global variables, therefore only the pcb
* involved is passed as a parameter to this function
*/
@@ -545,6 +545,7 @@ static void
tcp_listen_input(struct tcp_pcb_listen *pcb)
{
struct tcp_pcb *npcb;
+ u32_t iss;
err_t rc;
if (flags & TCP_RST) {
@@ -592,6 +593,11 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
npcb->state = SYN_RCVD;
npcb->rcv_nxt = seqno + 1;
npcb->rcv_ann_right_edge = npcb->rcv_nxt;
+ iss = tcp_next_iss(npcb);
+ npcb->snd_wl2 = iss;
+ npcb->snd_nxt = iss;
+ npcb->lastack = iss;
+ npcb->snd_lbb = iss;
npcb->snd_wl1 = seqno - 1;/* initialise to seqno-1 to force window update */
npcb->callback_arg = pcb->callback_arg;
#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
@@ -605,9 +611,8 @@ tcp_listen_input(struct tcp_pcb_listen *pcb)
/* Parse any options in the SYN. */
tcp_parseopt(npcb);
- npcb->snd_wnd = SND_WND_SCALE(npcb, tcphdr->wnd);
+ npcb->snd_wnd = tcphdr->wnd;
npcb->snd_wnd_max = npcb->snd_wnd;
- npcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(npcb);
#if TCP_CALCULATE_EFF_SEND_MSS
npcb->mss = tcp_eff_send_mss(npcb->mss, &npcb->local_ip, &npcb->remote_ip);
@@ -747,14 +752,14 @@ tcp_process(struct tcp_pcb *pcb)
switch (pcb->state) {
case SYN_SENT:
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("SYN-SENT: ackno %"U32_F" pcb->snd_nxt %"U32_F" unacked %"U32_F"\n", ackno,
- pcb->snd_nxt, ntohl(pcb->unacked->tcphdr->seqno)));
+ pcb->snd_nxt, lwip_ntohl(pcb->unacked->tcphdr->seqno)));
/* received SYN ACK with expected sequence number? */
if ((flags & TCP_ACK) && (flags & TCP_SYN)
&& (ackno == pcb->lastack + 1)) {
pcb->rcv_nxt = seqno + 1;
pcb->rcv_ann_right_edge = pcb->rcv_nxt;
pcb->lastack = ackno;
- pcb->snd_wnd = SND_WND_SCALE(pcb, tcphdr->wnd);
+ pcb->snd_wnd = tcphdr->wnd;
pcb->snd_wnd_max = pcb->snd_wnd;
pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */
pcb->state = ESTABLISHED;
@@ -763,9 +768,6 @@ tcp_process(struct tcp_pcb *pcb)
pcb->mss = tcp_eff_send_mss(pcb->mss, &pcb->local_ip, &pcb->remote_ip);
#endif /* TCP_CALCULATE_EFF_SEND_MSS */
- /* Set ssthresh again after changing 'mss' and 'snd_wnd' */
- pcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(pcb);
-
pcb->cwnd = LWIP_TCP_CALC_INITIAL_CWND(pcb->mss);
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_process (SENT): cwnd %"TCPWNDSIZE_F
" ssthresh %"TCPWNDSIZE_F"\n",
@@ -808,9 +810,12 @@ tcp_process(struct tcp_pcb *pcb)
tcp_rst(ackno, seqno + tcplen, ip_current_dest_addr(),
ip_current_src_addr(), tcphdr->dest, tcphdr->src);
/* Resend SYN immediately (don't wait for rto timeout) to establish
- connection faster */
- pcb->rtime = 0;
- tcp_rexmit_rto(pcb);
+ connection faster, but do not send more SYNs than we otherwise would
+ have, or we might get caught in a loop on loopback interfaces. */
+ if (pcb->nrtx < TCP_SYNMAXRTX) {
+ pcb->rtime = 0;
+ tcp_rexmit_rto(pcb);
+ }
}
break;
case SYN_RCVD:
@@ -819,14 +824,16 @@ tcp_process(struct tcp_pcb *pcb)
if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) {
pcb->state = ESTABLISHED;
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
+#if LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG
#if LWIP_CALLBACK_API
LWIP_ASSERT("pcb->listener->accept != NULL",
(pcb->listener == NULL) || (pcb->listener->accept != NULL));
+#endif
if (pcb->listener == NULL) {
/* listen pcb might be closed by now */
err = ERR_VAL;
} else
-#endif
+#endif /* LWIP_CALLBACK_API || TCP_LISTEN_BACKLOG */
{
tcp_backlog_accepted(pcb);
/* Call the accept function. */
@@ -845,11 +852,6 @@ tcp_process(struct tcp_pcb *pcb)
* we'd better pass it on to the application as well. */
tcp_receive(pcb);
- /* passive open: update initial ssthresh now that the correct window is
- known: if the remote side supports window scaling, the window sent
- with the initial SYN can be smaller than the one used later */
- pcb->ssthresh = LWIP_TCP_INITIAL_SSTHRESH(pcb);
-
/* Prevent ACK for SYN to generate a sent event */
if (recv_acked != 0) {
recv_acked--;
@@ -886,7 +888,8 @@ tcp_process(struct tcp_pcb *pcb)
case FIN_WAIT_1:
tcp_receive(pcb);
if (recv_flags & TF_GOT_FIN) {
- if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
+ if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) &&
+ pcb->unsent == NULL) {
LWIP_DEBUGF(TCP_DEBUG,
("TCP connection closed: FIN_WAIT_1 %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
tcp_ack_now(pcb);
@@ -898,7 +901,8 @@ tcp_process(struct tcp_pcb *pcb)
tcp_ack_now(pcb);
pcb->state = CLOSING;
}
- } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt)) {
+ } else if ((flags & TCP_ACK) && (ackno == pcb->snd_nxt) &&
+ pcb->unsent == NULL) {
pcb->state = FIN_WAIT_2;
}
break;
@@ -915,7 +919,7 @@ tcp_process(struct tcp_pcb *pcb)
break;
case CLOSING:
tcp_receive(pcb);
- if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
+ if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: CLOSING %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
tcp_pcb_purge(pcb);
TCP_RMV_ACTIVE(pcb);
@@ -925,7 +929,7 @@ tcp_process(struct tcp_pcb *pcb)
break;
case LAST_ACK:
tcp_receive(pcb);
- if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
+ if ((flags & TCP_ACK) && ackno == pcb->snd_nxt && pcb->unsent == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed: LAST_ACK %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
/* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
recv_flags |= TF_CLOSED;
@@ -1138,18 +1142,18 @@ tcp_receive(struct tcp_pcb *pcb)
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: ACK for %"U32_F", unacked->seqno %"U32_F":%"U32_F"\n",
ackno,
pcb->unacked != NULL?
- ntohl(pcb->unacked->tcphdr->seqno): 0,
+ lwip_ntohl(pcb->unacked->tcphdr->seqno): 0,
pcb->unacked != NULL?
- ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
+ lwip_ntohl(pcb->unacked->tcphdr->seqno) + TCP_TCPLEN(pcb->unacked): 0));
/* Remove segment from the unacknowledged list if the incoming
ACK acknowledges them. */
while (pcb->unacked != NULL &&
- TCP_SEQ_LEQ(ntohl(pcb->unacked->tcphdr->seqno) +
+ TCP_SEQ_LEQ(lwip_ntohl(pcb->unacked->tcphdr->seqno) +
TCP_TCPLEN(pcb->unacked), ackno)) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unacked\n",
- ntohl(pcb->unacked->tcphdr->seqno),
- ntohl(pcb->unacked->tcphdr->seqno) +
+ lwip_ntohl(pcb->unacked->tcphdr->seqno),
+ lwip_ntohl(pcb->unacked->tcphdr->seqno) +
TCP_TCPLEN(pcb->unacked)));
next = pcb->unacked;
@@ -1197,10 +1201,10 @@ tcp_receive(struct tcp_pcb *pcb)
->unsent list after a retransmission, so these segments may
in fact have been sent once. */
while (pcb->unsent != NULL &&
- TCP_SEQ_BETWEEN(ackno, ntohl(pcb->unsent->tcphdr->seqno) +
+ TCP_SEQ_BETWEEN(ackno, lwip_ntohl(pcb->unsent->tcphdr->seqno) +
TCP_TCPLEN(pcb->unsent), pcb->snd_nxt)) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: removing %"U32_F":%"U32_F" from pcb->unsent\n",
- ntohl(pcb->unsent->tcphdr->seqno), ntohl(pcb->unsent->tcphdr->seqno) +
+ lwip_ntohl(pcb->unsent->tcphdr->seqno), lwip_ntohl(pcb->unsent->tcphdr->seqno) +
TCP_TCPLEN(pcb->unsent)));
next = pcb->unsent;
@@ -1407,7 +1411,7 @@ tcp_receive(struct tcp_pcb *pcb)
TCP_SEQ_GEQ(seqno + tcplen,
next->tcphdr->seqno + next->len)) {
/* inseg cannot have FIN here (already processed above) */
- if (TCPH_FLAGS(next->tcphdr) & TCP_FIN &&
+ if ((TCPH_FLAGS(next->tcphdr) & TCP_FIN) != 0 &&
(TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
TCPH_SET_FLAG(inseg.tcphdr, TCP_FIN);
tcplen = TCP_TCPLEN(&inseg);
@@ -1777,12 +1781,12 @@ tcp_parseopt(struct tcp_pcb *pcb)
tsval |= (tcp_getoptbyte() << 16);
tsval |= (tcp_getoptbyte() << 24);
if (flags & TCP_SYN) {
- pcb->ts_recent = ntohl(tsval);
+ pcb->ts_recent = lwip_ntohl(tsval);
/* Enable sending timestamps in every segment now that we know
the remote host supports it. */
pcb->flags |= TF_TIMESTAMP;
} else if (TCP_SEQ_BETWEEN(pcb->ts_lastacksent, seqno, seqno+tcplen)) {
- pcb->ts_recent = ntohl(tsval);
+ pcb->ts_recent = lwip_ntohl(tsval);
}
/* Advance to next option (6 bytes already read) */
tcp_optidx += LWIP_TCP_OPT_LEN_TS - 6;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/tcp_out.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/core/tcp_out.c b/net/ip/lwip_base/src/core/tcp_out.c
index 70bdfea..2435408 100644
--- a/net/ip/lwip_base/src/core/tcp_out.c
+++ b/net/ip/lwip_base/src/core/tcp_out.c
@@ -114,12 +114,12 @@ tcp_output_alloc_header(struct tcp_pcb *pcb, u16_t optlen, u16_t datalen,
LWIP_ASSERT("check that first pbuf can hold struct tcp_hdr",
(p->len >= TCP_HLEN + optlen));
tcphdr = (struct tcp_hdr *)p->payload;
- tcphdr->src = htons(pcb->local_port);
- tcphdr->dest = htons(pcb->remote_port);
+ tcphdr->src = lwip_htons(pcb->local_port);
+ tcphdr->dest = lwip_htons(pcb->remote_port);
tcphdr->seqno = seqno_be;
- tcphdr->ackno = htonl(pcb->rcv_nxt);
+ tcphdr->ackno = lwip_htonl(pcb->rcv_nxt);
TCPH_HDRLEN_FLAGS_SET(tcphdr, (5 + optlen / 4), TCP_ACK);
- tcphdr->wnd = htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
+ tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
tcphdr->chksum = 0;
tcphdr->urgp = 0;
@@ -204,9 +204,9 @@ tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno,
return NULL;
}
seg->tcphdr = (struct tcp_hdr *)seg->p->payload;
- seg->tcphdr->src = htons(pcb->local_port);
- seg->tcphdr->dest = htons(pcb->remote_port);
- seg->tcphdr->seqno = htonl(seqno);
+ seg->tcphdr->src = lwip_htons(pcb->local_port);
+ seg->tcphdr->dest = lwip_htons(pcb->remote_port);
+ seg->tcphdr->seqno = lwip_htonl(seqno);
/* ackno is set in tcp_output */
TCPH_HDRLEN_FLAGS_SET(seg->tcphdr, (5 + optlen / 4), flags);
/* wnd and chksum are set in tcp_output */
@@ -224,7 +224,7 @@ tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno,
* @param length size of the pbuf's payload.
* @param max_length maximum usable size of payload+oversize.
* @param oversize pointer to a u16_t that will receive the number of usable tail bytes.
- * @param pcb The TCP connection that willo enqueue the pbuf.
+ * @param pcb The TCP connection that will enqueue the pbuf.
* @param apiflags API flags given to tcp_write.
* @param first_seg true when this pbuf will be used in the first enqueued segment.
*/
@@ -242,7 +242,6 @@ tcp_pbuf_prealloc(pbuf_layer layer, u16_t length, u16_t max_length,
LWIP_UNUSED_ARG(pcb);
LWIP_UNUSED_ARG(apiflags);
LWIP_UNUSED_ARG(first_seg);
- /* always create MSS-sized pbufs */
alloc = max_length;
#else /* LWIP_NETIF_TX_SINGLE_PBUF */
if (length < max_length) {
@@ -377,7 +376,11 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
#if TCP_OVERSIZE
u16_t oversize = 0;
u16_t oversize_used = 0;
+#if TCP_OVERSIZE_DBGCHECK
+ u16_t oversize_add = 0;
+#endif /* TCP_OVERSIZE_DBGCHECK*/
#endif /* TCP_OVERSIZE */
+ u16_t extendlen = 0;
#if TCP_CHECKSUM_ON_COPY
u16_t concat_chksum = 0;
u8_t concat_chksum_swapped = 0;
@@ -461,13 +464,13 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
*/
#if TCP_OVERSIZE
#if TCP_OVERSIZE_DBGCHECK
- /* check that pcb->unsent_oversize matches last_unsent->unsent_oversize */
+ /* check that pcb->unsent_oversize matches last_unsent->oversize_left */
LWIP_ASSERT("unsent_oversize mismatch (pcb vs. last_unsent)",
pcb->unsent_oversize == last_unsent->oversize_left);
#endif /* TCP_OVERSIZE_DBGCHECK */
oversize = pcb->unsent_oversize;
if (oversize > 0) {
- LWIP_ASSERT("inconsistent oversize vs. space", oversize_used <= space);
+ LWIP_ASSERT("inconsistent oversize vs. space", oversize <= space);
seg = last_unsent;
oversize_used = LWIP_MIN(space, LWIP_MIN(oversize, len));
pos += oversize_used;
@@ -475,18 +478,22 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
space -= oversize_used;
}
/* now we are either finished or oversize is zero */
- LWIP_ASSERT("inconsistend oversize vs. len", (oversize == 0) || (pos == len));
+ LWIP_ASSERT("inconsistent oversize vs. len", (oversize == 0) || (pos == len));
#endif /* TCP_OVERSIZE */
/*
* Phase 2: Chain a new pbuf to the end of pcb->unsent.
*
+ * As an exception when NOT copying the data, if the given data buffer
+ * directly follows the last unsent data buffer in memory, extend the last
+ * ROM pbuf reference to the buffer, thus saving a ROM pbuf allocation.
+ *
* We don't extend segments containing SYN/FIN flags or options
* (len==0). The new pbuf is kept in concat_p and pbuf_cat'ed at
* the end.
*/
if ((pos < len) && (space > 0) && (last_unsent->len > 0)) {
- u16_t seglen = space < len - pos ? space : len - pos;
+ u16_t seglen = LWIP_MIN(space, len - pos);
seg = last_unsent;
/* Create a pbuf with a copy or reference to seglen bytes. We
@@ -501,18 +508,30 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
goto memerr;
}
#if TCP_OVERSIZE_DBGCHECK
- last_unsent->oversize_left += oversize;
+ oversize_add = oversize;
#endif /* TCP_OVERSIZE_DBGCHECK */
TCP_DATA_COPY2(concat_p->payload, (const u8_t*)arg + pos, seglen, &concat_chksum, &concat_chksum_swapped);
#if TCP_CHECKSUM_ON_COPY
concat_chksummed += seglen;
#endif /* TCP_CHECKSUM_ON_COPY */
+ queuelen += pbuf_clen(concat_p);
} else {
/* Data is not copied */
- if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
- LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
- ("tcp_write: could not allocate memory for zero-copy pbuf\n"));
- goto memerr;
+ /* If the last unsent pbuf is of type PBUF_ROM, try to extend it. */
+ struct pbuf *p;
+ for (p = last_unsent->p; p->next != NULL; p = p->next);
+ if (p->type == PBUF_ROM && (const u8_t *)p->payload + p->len == (const u8_t *)arg) {
+ LWIP_ASSERT("tcp_write: ROM pbufs cannot be oversized", pos == 0);
+ extendlen = seglen;
+ } else {
+ if ((concat_p = pbuf_alloc(PBUF_RAW, seglen, PBUF_ROM)) == NULL) {
+ LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
+ ("tcp_write: could not allocate memory for zero-copy pbuf\n"));
+ goto memerr;
+ }
+ /* reference the non-volatile payload data */
+ ((struct pbuf_rom*)concat_p)->payload = (const u8_t*)arg + pos;
+ queuelen += pbuf_clen(concat_p);
}
#if TCP_CHECKSUM_ON_COPY
/* calculate the checksum of nocopy-data */
@@ -520,12 +539,9 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
&concat_chksum, &concat_chksum_swapped);
concat_chksummed += seglen;
#endif /* TCP_CHECKSUM_ON_COPY */
- /* reference the non-volatile payload data */
- ((struct pbuf_rom*)concat_p)->payload = (const u8_t*)arg + pos;
}
pos += seglen;
- queuelen += pbuf_clen(concat_p);
}
} else {
#if TCP_OVERSIZE
@@ -544,7 +560,7 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
struct pbuf *p;
u16_t left = len - pos;
u16_t max_len = mss_local - optlen;
- u16_t seglen = left > max_len ? max_len : left;
+ u16_t seglen = LWIP_MIN(left, max_len);
#if TCP_CHECKSUM_ON_COPY
u16_t chksum = 0;
u8_t chksum_swapped = 0;
@@ -633,8 +649,8 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
prev_seg = seg;
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, ("tcp_write: queueing %"U32_F":%"U32_F"\n",
- ntohl(seg->tcphdr->seqno),
- ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg)));
+ lwip_ntohl(seg->tcphdr->seqno),
+ lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg)));
pos += seglen;
}
@@ -643,6 +659,11 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
* All three segmentation phases were successful. We can commit the
* transaction.
*/
+#if TCP_OVERSIZE_DBGCHECK
+ if ((last_unsent != NULL) && (oversize_add != 0)) {
+ last_unsent->oversize_left += oversize_add;
+ }
+#endif /* TCP_OVERSIZE_DBGCHECK */
/*
* Phase 1: If data has been added to the preallocated tail of
@@ -670,25 +691,39 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
#endif /* TCP_OVERSIZE */
/*
- * Phase 2: concat_p can be concatenated onto last_unsent->p
+ * Phase 2: concat_p can be concatenated onto last_unsent->p, unless we
+ * determined that the last ROM pbuf can be extended to include the new data.
*/
if (concat_p != NULL) {
LWIP_ASSERT("tcp_write: cannot concatenate when pcb->unsent is empty",
(last_unsent != NULL));
pbuf_cat(last_unsent->p, concat_p);
last_unsent->len += concat_p->tot_len;
+ } else if (extendlen > 0) {
+ struct pbuf *p;
+ LWIP_ASSERT("tcp_write: extension of reference requires reference",
+ last_unsent != NULL && last_unsent->p != NULL);
+ for (p = last_unsent->p; p->next != NULL; p = p->next) {
+ p->tot_len += extendlen;
+ }
+ p->tot_len += extendlen;
+ p->len += extendlen;
+ last_unsent->len += extendlen;
+ }
+
#if TCP_CHECKSUM_ON_COPY
- if (concat_chksummed) {
- /*if concat checksumm swapped - swap it back */
- if (concat_chksum_swapped) {
- concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum);
- }
- tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum,
- &last_unsent->chksum_swapped);
- last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED;
+ if (concat_chksummed) {
+ LWIP_ASSERT("tcp_write: concat checksum needs concatenated data",
+ concat_p != NULL || extendlen > 0);
+ /*if concat checksumm swapped - swap it back */
+ if (concat_chksum_swapped) {
+ concat_chksum = SWAP_BYTES_IN_WORD(concat_chksum);
}
-#endif /* TCP_CHECKSUM_ON_COPY */
+ tcp_seg_add_chksum(concat_chksum, concat_chksummed, &last_unsent->chksum,
+ &last_unsent->chksum_swapped);
+ last_unsent->flags |= TF_SEG_DATA_CHECKSUMMED;
}
+#endif /* TCP_CHECKSUM_ON_COPY */
/*
* Phase 3: Append queue to pcb->unsent. Queue may be NULL, but that
@@ -808,8 +843,8 @@ tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags)
LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE,
("tcp_enqueue_flags: queueing %"U32_F":%"U32_F" (0x%"X16_F")\n",
- ntohl(seg->tcphdr->seqno),
- ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
+ lwip_ntohl(seg->tcphdr->seqno),
+ lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg),
(u16_t)flags));
/* Now append seg to pcb->unsent queue */
@@ -856,8 +891,8 @@ tcp_build_timestamp_option(struct tcp_pcb *pcb, u32_t *opts)
{
/* Pad with two NOP options to make everything nicely aligned */
opts[0] = PP_HTONL(0x0101080A);
- opts[1] = htonl(sys_now());
- opts[2] = htonl(pcb->ts_recent);
+ opts[1] = lwip_htonl(sys_now());
+ opts[2] = lwip_htonl(pcb->ts_recent);
}
#endif
@@ -896,7 +931,7 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
}
#endif
- p = tcp_output_alloc_header(pcb, optlen, 0, htonl(pcb->snd_nxt));
+ p = tcp_output_alloc_header(pcb, optlen, 0, lwip_htonl(pcb->snd_nxt));
if (p == NULL) {
/* let tcp_fasttmr retry sending this ACK */
pcb->flags |= (TF_ACK_DELAY | TF_ACK_NOW);
@@ -989,7 +1024,7 @@ tcp_output(struct tcp_pcb *pcb)
*/
if (pcb->flags & TF_ACK_NOW &&
(seg == NULL ||
- ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
+ lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd)) {
return tcp_send_empty_ack(pcb);
}
@@ -1030,13 +1065,31 @@ tcp_output(struct tcp_pcb *pcb)
("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F
", effwnd %"U32_F", seq %"U32_F", ack %"U32_F"\n",
pcb->snd_wnd, pcb->cwnd, wnd,
- ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
- ntohl(seg->tcphdr->seqno), pcb->lastack));
+ lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len,
+ lwip_ntohl(seg->tcphdr->seqno), pcb->lastack));
}
#endif /* TCP_CWND_DEBUG */
+ /* Check if we need to start the persistent timer when the next unsent segment
+ * does not fit within the remaining send window and RTO timer is not running (we
+ * have no in-flight data). A traditional approach would fill the remaining window
+ * with part of the unsent segment (which will engage zero-window probing upon
+ * reception of the zero window update from the receiver). This ensures the
+ * subsequent window update is reliably received. With the goal of being lightweight,
+ * we avoid splitting the unsent segment and treat the window as already zero.
+ */
+ if (seg != NULL &&
+ lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len > wnd &&
+ wnd > 0 && wnd == pcb->snd_wnd && pcb->unacked == NULL) {
+ /* Start the persist timer */
+ if (pcb->persist_backoff == 0) {
+ pcb->persist_cnt = 0;
+ pcb->persist_backoff = 1;
+ }
+ goto output_done;
+ }
/* data available and window allows it to be sent? */
while (seg != NULL &&
- ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
+ lwip_ntohl(seg->tcphdr->seqno) - pcb->lastack + seg->len <= wnd) {
LWIP_ASSERT("RST not expected here!",
(TCPH_FLAGS(seg->tcphdr) & TCP_RST) == 0);
/* Stop sending if the nagle algorithm would prevent it
@@ -1053,9 +1106,9 @@ tcp_output(struct tcp_pcb *pcb)
#if TCP_CWND_DEBUG
LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_output: snd_wnd %"TCPWNDSIZE_F", cwnd %"TCPWNDSIZE_F", wnd %"U32_F", effwnd %"U32_F", seq %"U32_F", ack %"U32_F", i %"S16_F"\n",
pcb->snd_wnd, pcb->cwnd, wnd,
- ntohl(seg->tcphdr->seqno) + seg->len -
+ lwip_ntohl(seg->tcphdr->seqno) + seg->len -
pcb->lastack,
- ntohl(seg->tcphdr->seqno), pcb->lastack, i));
+ lwip_ntohl(seg->tcphdr->seqno), pcb->lastack, i));
++i;
#endif /* TCP_CWND_DEBUG */
@@ -1076,7 +1129,7 @@ tcp_output(struct tcp_pcb *pcb)
if (pcb->state != SYN_SENT) {
pcb->flags &= ~(TF_ACK_DELAY | TF_ACK_NOW);
}
- snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
+ snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
pcb->snd_nxt = snd_nxt;
}
@@ -1092,11 +1145,11 @@ tcp_output(struct tcp_pcb *pcb)
/* In the case of fast retransmit, the packet should not go to the tail
* of the unacked queue, but rather somewhere before it. We need to check for
* this case. -STJ Jul 27, 2004 */
- if (TCP_SEQ_LT(ntohl(seg->tcphdr->seqno), ntohl(useg->tcphdr->seqno))) {
+ if (TCP_SEQ_LT(lwip_ntohl(seg->tcphdr->seqno), lwip_ntohl(useg->tcphdr->seqno))) {
/* add segment to before tail of unacked list, keeping the list sorted */
struct tcp_seg **cur_seg = &(pcb->unacked);
while (*cur_seg &&
- TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
+ TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) {
cur_seg = &((*cur_seg)->next );
}
seg->next = (*cur_seg);
@@ -1113,6 +1166,7 @@ tcp_output(struct tcp_pcb *pcb)
}
seg = pcb->unsent;
}
+output_done:
#if TCP_OVERSIZE
if (pcb->unsent == NULL) {
/* last unsent has been removed, reset unsent_oversize */
@@ -1147,18 +1201,18 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif
/* The TCP header has already been constructed, but the ackno and
wnd fields remain. */
- seg->tcphdr->ackno = htonl(pcb->rcv_nxt);
+ seg->tcphdr->ackno = lwip_htonl(pcb->rcv_nxt);
/* advertise our receive window size in this TCP segment */
#if LWIP_WND_SCALE
if (seg->flags & TF_SEG_OPTS_WND_SCALE) {
/* The Window field in a SYN segment itself (the only type where we send
the window scale option) is never scaled. */
- seg->tcphdr->wnd = htons(TCPWND_MIN16(pcb->rcv_ann_wnd));
+ seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(pcb->rcv_ann_wnd));
} else
#endif /* LWIP_WND_SCALE */
{
- seg->tcphdr->wnd = htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
+ seg->tcphdr->wnd = lwip_htons(TCPWND_MIN16(RCV_WND_SCALE(pcb, pcb->rcv_ann_wnd)));
}
pcb->rcv_ann_right_edge = pcb->rcv_nxt + pcb->rcv_ann_wnd;
@@ -1200,12 +1254,12 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb, struct netif *netif
if (pcb->rttest == 0) {
pcb->rttest = tcp_ticks;
- pcb->rtseq = ntohl(seg->tcphdr->seqno);
+ pcb->rtseq = lwip_ntohl(seg->tcphdr->seqno);
LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_output_segment: rtseq %"U32_F"\n", pcb->rtseq));
}
LWIP_DEBUGF(TCP_OUTPUT_DEBUG, ("tcp_output_segment: %"U32_F":%"U32_F"\n",
- htonl(seg->tcphdr->seqno), htonl(seg->tcphdr->seqno) +
+ lwip_htonl(seg->tcphdr->seqno), lwip_htonl(seg->tcphdr->seqno) +
seg->len));
len = (u16_t)((u8_t *)seg->tcphdr - (u8_t *)seg->p->payload);
@@ -1303,10 +1357,10 @@ tcp_rst(u32_t seqno, u32_t ackno,
(p->len >= sizeof(struct tcp_hdr)));
tcphdr = (struct tcp_hdr *)p->payload;
- tcphdr->src = htons(local_port);
- tcphdr->dest = htons(remote_port);
- tcphdr->seqno = htonl(seqno);
- tcphdr->ackno = htonl(ackno);
+ tcphdr->src = lwip_htons(local_port);
+ tcphdr->dest = lwip_htons(remote_port);
+ tcphdr->seqno = lwip_htonl(seqno);
+ tcphdr->ackno = lwip_htonl(ackno);
TCPH_HDRLEN_FLAGS_SET(tcphdr, TCP_HLEN/4, TCP_RST | TCP_ACK);
#if LWIP_WND_SCALE
tcphdr->wnd = PP_HTONS(((TCP_WND >> TCP_RCV_SCALE) & 0xFFFF));
@@ -1366,7 +1420,9 @@ tcp_rexmit_rto(struct tcp_pcb *pcb)
pcb->unacked = NULL;
/* increment number of retransmissions */
- ++pcb->nrtx;
+ if (pcb->nrtx < 0xFF) {
+ ++pcb->nrtx;
+ }
/* Don't take any RTT measurements after retransmitting. */
pcb->rttest = 0;
@@ -1399,7 +1455,7 @@ tcp_rexmit(struct tcp_pcb *pcb)
cur_seg = &(pcb->unsent);
while (*cur_seg &&
- TCP_SEQ_LT(ntohl((*cur_seg)->tcphdr->seqno), ntohl(seg->tcphdr->seqno))) {
+ TCP_SEQ_LT(lwip_ntohl((*cur_seg)->tcphdr->seqno), lwip_ntohl(seg->tcphdr->seqno))) {
cur_seg = &((*cur_seg)->next );
}
seg->next = *cur_seg;
@@ -1411,7 +1467,9 @@ tcp_rexmit(struct tcp_pcb *pcb)
}
#endif /* TCP_OVERSIZE */
- ++pcb->nrtx;
+ if (pcb->nrtx < 0xFF) {
+ ++pcb->nrtx;
+ }
/* Don't take any rtt measurements after retransmitting. */
pcb->rttest = 0;
@@ -1437,16 +1495,12 @@ tcp_rexmit_fast(struct tcp_pcb *pcb)
("tcp_receive: dupacks %"U16_F" (%"U32_F
"), fast retransmit %"U32_F"\n",
(u16_t)pcb->dupacks, pcb->lastack,
- ntohl(pcb->unacked->tcphdr->seqno)));
+ lwip_ntohl(pcb->unacked->tcphdr->seqno)));
tcp_rexmit(pcb);
/* Set ssthresh to half of the minimum of the current
* cwnd and the advertised window */
- if (pcb->cwnd > pcb->snd_wnd) {
- pcb->ssthresh = pcb->snd_wnd / 2;
- } else {
- pcb->ssthresh = pcb->cwnd / 2;
- }
+ pcb->ssthresh = LWIP_MIN(pcb->cwnd, pcb->snd_wnd) / 2;
/* The minimum value for ssthresh should be 2 MSS */
if (pcb->ssthresh < (2U * pcb->mss)) {
@@ -1488,7 +1542,7 @@ tcp_keepalive(struct tcp_pcb *pcb)
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: tcp_ticks %"U32_F" pcb->tmr %"U32_F" pcb->keep_cnt_sent %"U16_F"\n",
tcp_ticks, pcb->tmr, (u16_t)pcb->keep_cnt_sent));
- p = tcp_output_alloc_header(pcb, 0, 0, htonl(pcb->snd_nxt - 1));
+ p = tcp_output_alloc_header(pcb, 0, 0, lwip_htonl(pcb->snd_nxt - 1));
if (p == NULL) {
LWIP_DEBUGF(TCP_DEBUG,
("tcp_keepalive: could not allocate memory for pbuf\n"));
@@ -1537,6 +1591,7 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
struct tcp_seg *seg;
u16_t len;
u8_t is_fin;
+ u32_t snd_nxt;
struct netif *netif;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to "));
@@ -1581,6 +1636,12 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len);
}
+ /* The byte may be acknowledged without the window being opened. */
+ snd_nxt = lwip_ntohl(seg->tcphdr->seqno) + 1;
+ if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
+ pcb->snd_nxt = snd_nxt;
+ }
+
netif = ip_route(&pcb->local_ip, &pcb->remote_ip);
if (netif == NULL) {
err = ERR_RTE;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/timeouts.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/core/timeouts.c b/net/ip/lwip_base/src/core/timeouts.c
index fcba0a1..227d71f 100644
--- a/net/ip/lwip_base/src/core/timeouts.c
+++ b/net/ip/lwip_base/src/core/timeouts.c
@@ -179,7 +179,7 @@ void sys_timeouts_init(void)
for (i = 1; i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) {
/* we have to cast via size_t to get rid of const warning
(this is OK as cyclic_timer() casts back to const* */
- sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, (void*)(size_t)&lwip_cyclic_timers[i]);
+ sys_timeout(lwip_cyclic_timers[i].interval_ms, cyclic_timer, LWIP_CONST_CAST(void*, &lwip_cyclic_timers[i]));
}
/* Initialise timestamp for sys_check_timeouts */
@@ -360,7 +360,6 @@ sys_check_timeouts(void)
}
}
-#if NO_SYS
/** Set back the timestamp of the last call to sys_check_timeouts()
* This is necessary if sys_check_timeouts() hasn't been called for a long
* time (e.g. while saving energy) to prevent all timer functions of that
@@ -371,7 +370,6 @@ sys_restart_timeouts(void)
{
timeouts_last_time = sys_now();
}
-#endif /* NO_SYS */
/** Return the time left before the next timeout is due. If no timeouts are
* enqueued, returns 0xffffffff
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/udp.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/core/udp.c b/net/ip/lwip_base/src/core/udp.c
index 20e97da..ce2e3d2 100644
--- a/net/ip/lwip_base/src/core/udp.c
+++ b/net/ip/lwip_base/src/core/udp.c
@@ -116,24 +116,6 @@ again:
}
}
return udp_port;
-#if 0
- struct udp_pcb *ipcb = udp_pcbs;
- while ((ipcb != NULL) && (udp_port != UDP_LOCAL_PORT_RANGE_END)) {
- if (ipcb->local_port == udp_port) {
- /* port is already used by another udp_pcb */
- udp_port++;
- /* restart scanning all udp pcbs */
- ipcb = udp_pcbs;
- } else {
- /* go on with next udp pcb */
- ipcb = ipcb->next;
- }
- }
- if (ipcb != NULL) {
- return 0;
- }
- return udp_port;
-#endif
}
/** Common code to see if the current input packet matches the pcb
@@ -178,15 +160,8 @@ udp_input_local_match(struct udp_pcb *pcb, struct netif *inp, u8_t broadcast)
}
} else
#endif /* LWIP_IPV4 */
- /* Handle IPv4 and IPv6: all, multicast or exact match */
- if (ip_addr_isany(&pcb->local_ip) ||
-#if LWIP_IPV6_MLD
- (ip_current_is_v6() && ip6_addr_ismulticast(ip6_current_dest_addr())) ||
-#endif /* LWIP_IPV6_MLD */
-#if LWIP_IGMP
- (!ip_current_is_v6() && ip4_addr_ismulticast(ip4_current_dest_addr())) ||
-#endif /* LWIP_IGMP */
- ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) {
+ /* Handle IPv4 and IPv6: all or exact match */
+ if (ip_addr_isany(&pcb->local_ip) || ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr())) {
return 1;
}
}
@@ -242,17 +217,17 @@ udp_input(struct pbuf *p, struct netif *inp)
LWIP_DEBUGF(UDP_DEBUG, ("udp_input: received datagram of length %"U16_F"\n", p->tot_len));
/* convert src and dest ports to host byte order */
- src = ntohs(udphdr->src);
- dest = ntohs(udphdr->dest);
+ src = lwip_ntohs(udphdr->src);
+ dest = lwip_ntohs(udphdr->dest);
udp_debug_print(udphdr);
/* print the UDP source and destination */
LWIP_DEBUGF(UDP_DEBUG, ("udp ("));
ip_addr_debug_print(UDP_DEBUG, ip_current_dest_addr());
- LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", ntohs(udphdr->dest)));
+ LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F") <-- (", lwip_ntohs(udphdr->dest)));
ip_addr_debug_print(UDP_DEBUG, ip_current_src_addr());
- LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", ntohs(udphdr->src)));
+ LWIP_DEBUGF(UDP_DEBUG, (", %"U16_F")\n", lwip_ntohs(udphdr->src)));
pcb = NULL;
prev = NULL;
@@ -331,7 +306,7 @@ udp_input(struct pbuf *p, struct netif *inp)
#if LWIP_UDPLITE
if (ip_current_header_proto() == IP_PROTO_UDPLITE) {
/* Do the UDP Lite checksum */
- u16_t chklen = ntohs(udphdr->len);
+ u16_t chklen = lwip_ntohs(udphdr->len);
if (chklen < sizeof(struct udp_hdr)) {
if (chklen == 0) {
/* For UDP-Lite, checksum length of 0 means checksum
@@ -429,7 +404,7 @@ udp_input(struct pbuf *p, struct netif *inp)
destination address was broadcast/multicast. */
if (!broadcast && !ip_addr_ismulticast(ip_current_dest_addr())) {
/* move payload pointer back to ip header */
- pbuf_header_force(p, ip_current_header_tot_len() + UDP_HLEN);
+ pbuf_header_force(p, (s16_t)(ip_current_header_tot_len() + UDP_HLEN));
icmp_port_unreach(ip_current_is_v6(), p);
}
#endif /* LWIP_ICMP || LWIP_ICMP6 */
@@ -571,7 +546,12 @@ udp_sendto_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip,
#endif /* LWIP_IPV6 || (LWIP_IPV4 && LWIP_MULTICAST_TX_OPTIONS) */
/* find the outgoing network interface for this packet */
- netif = ip_route(&pcb->local_ip, dst_ip_route);
+ if(IP_IS_ANY_TYPE_VAL(pcb->local_ip)) {
+ /* Don't call ip_route() with IP_ANY_TYPE */
+ netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(dst_ip_route)), dst_ip_route);
+ } else {
+ netif = ip_route(&pcb->local_ip, dst_ip_route);
+ }
/* no outgoing network interface could be found? */
if (netif == NULL) {
@@ -662,7 +642,7 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_i
* this could be an old address if netif->ip_addr has changed */
if (!ip4_addr_cmp(ip_2_ip4(&(pcb->local_ip)), netif_ip4_addr(netif))) {
/* local_ip doesn't match, drop the packet */
- return ERR_VAL;
+ return ERR_RTE;
}
/* use UDP PCB local IP address as source address */
src_ip = &pcb->local_ip;
@@ -752,8 +732,8 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d
(q->len >= sizeof(struct udp_hdr)));
/* q now represents the packet to be sent */
udphdr = (struct udp_hdr *)q->payload;
- udphdr->src = htons(pcb->local_port);
- udphdr->dest = htons(dst_port);
+ udphdr->src = lwip_htons(pcb->local_port);
+ udphdr->dest = lwip_htons(dst_port);
/* in UDP, 0 checksum means 'no checksum' */
udphdr->chksum = 0x0000;
@@ -786,7 +766,7 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d
chklen_hdr = 0;
chklen = q->tot_len;
}
- udphdr->len = htons(chklen_hdr);
+ udphdr->len = lwip_htons(chklen_hdr);
/* calculate checksum */
#if CHECKSUM_GEN_UDP
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) {
@@ -817,7 +797,7 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d
#endif /* LWIP_UDPLITE */
{ /* UDP */
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP packet length %"U16_F"\n", q->tot_len));
- udphdr->len = htons(q->tot_len);
+ udphdr->len = lwip_htons(q->tot_len);
/* calculate checksum */
#if CHECKSUM_GEN_UDP
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) {
@@ -883,7 +863,7 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d
* Bind an UDP PCB.
*
* @param pcb UDP PCB to be bound with a local address ipaddr and port.
- * @param ipaddr local IP address to bind with. Use IP_ADDR_ANY to
+ * @param ipaddr local IP address to bind with. Use IP4_ADDR_ANY to
* bind to all local interfaces.
* @param port local UDP port to bind with. Use 0 to automatically bind
* to a random port between UDP_LOCAL_PORT_RANGE_START and
@@ -907,12 +887,12 @@ udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
#if LWIP_IPV4
/* Don't propagate NULL pointer (IPv4 ANY) to subsequent functions */
if (ipaddr == NULL) {
- ipaddr = IP_ADDR_ANY;
+ ipaddr = IP4_ADDR_ANY;
}
#endif /* LWIP_IPV4 */
/* still need to check for ipaddr == NULL in IPv6 only case */
- if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr)) {
+ if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL;
}
@@ -1002,7 +982,7 @@ udp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port)
{
struct udp_pcb *ipcb;
- if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
+ if ((pcb == NULL) || (ipaddr == NULL)) {
return ERR_VAL;
}
@@ -1143,7 +1123,7 @@ udp_new(void)
* @ingroup udp_raw
* Create a UDP PCB for specific IP type.
*
- * @param type IP address type, see IPADDR_TYPE_XX definitions.
+ * @param type IP address type, see @ref lwip_ip_addr_type definitions.
* If you want to listen to IPv4 and IPv6 (dual-stack) packets,
* supply @ref IPADDR_TYPE_ANY as argument and bind to @ref IP_ANY_TYPE.
* @return The UDP PCB which was created. NULL if the PCB data structure
@@ -1200,10 +1180,10 @@ udp_debug_print(struct udp_hdr *udphdr)
LWIP_DEBUGF(UDP_DEBUG, ("UDP header:\n"));
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | %5"U16_F" | (src port, dest port)\n",
- ntohs(udphdr->src), ntohs(udphdr->dest)));
+ lwip_ntohs(udphdr->src), lwip_ntohs(udphdr->dest)));
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
LWIP_DEBUGF(UDP_DEBUG, ("| %5"U16_F" | 0x%04"X16_F" | (len, chksum)\n",
- ntohs(udphdr->len), ntohs(udphdr->chksum)));
+ lwip_ntohs(udphdr->len), lwip_ntohs(udphdr->chksum)));
LWIP_DEBUGF(UDP_DEBUG, ("+-------------------------------+\n"));
}
#endif /* UDP_DEBUG */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/netif/ethernet.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/netif/ethernet.c b/net/ip/lwip_base/src/netif/ethernet.c
index 621838e..52ea423 100644
--- a/net/ip/lwip_base/src/netif/ethernet.c
+++ b/net/ip/lwip_base/src/netif/ethernet.c
@@ -56,6 +56,10 @@
#include "netif/ppp/pppoe.h"
#endif /* PPPOE_SUPPORT */
+#ifdef LWIP_HOOK_FILENAME
+#include LWIP_HOOK_FILENAME
+#endif
+
const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
const struct eth_addr ethzero = {{0,0,0,0,0,0}};
@@ -69,9 +73,9 @@ const struct eth_addr ethzero = {{0,0,0,0,0,0}};
* @param p the received packet, p->payload pointing to the ethernet header
* @param netif the network interface on which the packet was received
*
- * @see @ref LWIP_HOOK_UNKNOWN_ETH_PROTOCOL,
- * @ref ETHARP_SUPPORT_VLAN and
- * @ref LWIP_HOOK_VLAN_CHECK.
+ * @see LWIP_HOOK_UNKNOWN_ETH_PROTOCOL
+ * @see ETHARP_SUPPORT_VLAN
+ * @see LWIP_HOOK_VLAN_CHECK
*/
err_t
ethernet_input(struct pbuf *p, struct netif *netif)
@@ -98,7 +102,7 @@ ethernet_input(struct pbuf *p, struct netif *netif)
(unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5],
(unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2],
(unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5],
- htons(ethhdr->type)));
+ lwip_htons(ethhdr->type)));
type = ethhdr->type;
#if ETHARP_SUPPORT_VLAN
@@ -130,7 +134,7 @@ ethernet_input(struct pbuf *p, struct netif *netif)
#endif /* ETHARP_SUPPORT_VLAN */
#if LWIP_ARP_FILTER_NETIF
- netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, htons(type));
+ netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, lwip_htons(type));
#endif /* LWIP_ARP_FILTER_NETIF*/
if (ethhdr->dest.addr[0] & 1) {
@@ -247,7 +251,7 @@ free_and_return:
* Send an ethernet packet on the network using netif->linkoutput().
* The ethernet header is filled in before sending.
*
- * @see @ref LWIP_HOOK_VLAN_SET
+ * @see LWIP_HOOK_VLAN_SET
*
* @param netif the lwIP network interface on which to send the packet
* @param p the packet to send. pbuf layer must be @ref PBUF_LINK.
@@ -262,7 +266,7 @@ ethernet_output(struct netif* netif, struct pbuf* p,
u16_t eth_type)
{
struct eth_hdr* ethhdr;
- u16_t eth_type_be = htons(eth_type);
+ u16_t eth_type_be = lwip_htons(eth_type);
#if ETHARP_SUPPORT_VLAN && defined(LWIP_HOOK_VLAN_SET)
s32_t vlan_prio_vid = LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type);
@@ -276,7 +280,7 @@ ethernet_output(struct netif* netif, struct pbuf* p,
}
vlanhdr = (struct eth_vlan_hdr*)(((u8_t*)p->payload) + SIZEOF_ETH_HDR);
vlanhdr->tpid = eth_type_be;
- vlanhdr->prio_vid = htons((u16_t)vlan_prio_vid);
+ vlanhdr->prio_vid = lwip_htons((u16_t)vlan_prio_vid);
eth_type_be = PP_HTONS(ETHTYPE_VLAN);
} else