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