From effcb90fdf29e6475614c84d327bcf2722f854b6 Mon Sep 17 00:00:00 2001 From: goldsimon Date: Mon, 20 Dec 2010 18:03:51 +0000 Subject: [PATCH] Mreged back changes that were lost during the savannah hack 3 weeks ago (using the sources from http://git.infradead.org/users/dwmw2/lwip.git) --- CHANGELOG | 22 ++++++++++++++----- src/api/api_lib.c | 2 ++ src/api/api_msg.c | 8 ++++++- src/api/sockets.c | 6 +++++- src/core/tcp_in.c | 6 ++++-- src/include/lwip/api.h | 5 ++--- src/include/lwip/opt.h | 9 +++++--- src/netif/etharp.c | 48 ++++++++++++++++++++++++------------------ 8 files changed, 71 insertions(+), 35 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index ce6f2e07..3c658d97 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -13,7 +13,7 @@ HISTORY ++ New features: - 2010-06-16: Simon Goldschmidt + 2010-11-21: Simon Goldschmidt * dhcp.c/.h: Added a function to deallocate the struct dhcp from a netif (fixes bug #31525). @@ -233,18 +233,30 @@ HISTORY ++ Bugfixes: - 2010-11-20: Simon Goldschmidt + 2010-12-02: Simon Goldschmidt * err.h: Fixed ERR_IS_FATAL so that ERR_WOULDBLOCK is not fatal. - 2010-11-20: Simon Goldschmidt + 2010-11-23: Simon Goldschmidt + * api.h, api_lib.c, api_msg.c, sockets.c: netconn.recv_avail is only used for + LWIP_SO_RCVBUF and ioctl/FIONREAD. + + 2010-11-23: Simon Goldschmidt + * etharp.c: Fixed bug #31720: ARP-queueing: RFC 1122 recommends to queue at + least 1 packet -> ARP_QUEUEING==0 now queues the most recent packet. + + 2010-11-23: Simon Goldschmidt + * tcp_in.c: Fixed bug #30577: tcp_input: don't discard ACK-only packets after + refusing 'refused_data' again. + + 2010-11-22: Simon Goldschmidt * sockets.c: Fixed bug #31590: getsockopt(... SO_ERROR ...) gives EINPROGRESS after a successful nonblocking connection. - 2010-11-20: Simon Goldschmidt + 2010-11-22: Simon Goldschmidt * etharp.c: Fixed bug #31722: IP packets sent with an AutoIP source addr must be sent link-local - 2010-11-20: Simon Goldschmidt + 2010-11-22: Simon Goldschmidt * timers.c: patch #7329: tcp_timer_needed prototype was ifdef'ed out for LWIP_TIMERS==0 diff --git a/src/api/api_lib.c b/src/api/api_lib.c index f731a2bc..158325b0 100644 --- a/src/api/api_lib.c +++ b/src/api/api_lib.c @@ -408,7 +408,9 @@ netconn_recv_data(struct netconn *conn, void **new_buf) } #endif /* (LWIP_UDP || LWIP_RAW) */ +#if LWIP_SO_RCVBUF SYS_ARCH_DEC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVMINUS, len); diff --git a/src/api/api_msg.c b/src/api/api_msg.c index 7f03e2de..dcb07e9c 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -120,7 +120,9 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, netbuf_delete(buf); return 0; } else { +#if LWIP_SO_RCVBUF SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); } @@ -194,7 +196,9 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, netbuf_delete(buf); return; } else { +#if LWIP_SO_RCVBUF SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); } @@ -248,7 +252,9 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */ return ERR_MEM; } else { +#if LWIP_SO_RCVBUF SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); } @@ -614,7 +620,6 @@ netconn_alloc(enum netconn_type t, netconn_callback callback) conn->socket = -1; #endif /* LWIP_SOCKET */ conn->callback = callback; - conn->recv_avail = 0; #if LWIP_TCP conn->current_msg = NULL; conn->write_offset = 0; @@ -624,6 +629,7 @@ netconn_alloc(enum netconn_type t, netconn_callback callback) #endif /* LWIP_SO_RCVTIMEO */ #if LWIP_SO_RCVBUF conn->recv_bufsize = RECV_BUFSIZE_DEFAULT; + conn->recv_avail = 0; #endif /* LWIP_SO_RCVBUF */ conn->flags = 0; return conn; diff --git a/src/api/sockets.c b/src/api/sockets.c index a05f0aab..33ce5414 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -2252,15 +2252,18 @@ int lwip_ioctl(int s, long cmd, void *argp) { struct lwip_sock *sock = get_socket(s); + u8_t val; +#if LWIP_SO_RCVBUF u16_t buflen = 0; s16_t recv_avail; - u8_t val; +#endif /* LWIP_SO_RCVBUF */ if (!sock) { return -1; } switch (cmd) { +#if LWIP_SO_RCVBUF case FIONREAD: if (!argp) { sock_set_errno(sock, EINVAL); @@ -2288,6 +2291,7 @@ lwip_ioctl(int s, long cmd, void *argp) LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp))); sock_set_errno(sock, 0); return 0; +#endif /* LWIP_SO_RCVBUF */ case FIONBIO: val = 0; diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index 1812fe36..60ade915 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -305,9 +305,10 @@ tcp_input(struct pbuf *p, struct netif *inp) TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err); if (err == ERR_OK) { pcb->refused_data = NULL; - } else { + } else if ((err == ERR_ABRT) || (tcplen > 0)) { /* if err == ERR_ABRT, 'pcb' is already deallocated */ - /* drop incoming packets, because pcb is "full" */ + /* Drop incoming packets because pcb is "full" (only if the incoming + segment contains data). */ LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); TCP_STATS_INC(tcp.drop); snmp_inc_tcpinerrs(); @@ -346,6 +347,7 @@ tcp_input(struct pbuf *p, struct netif *inp) } if (recv_data != NULL) { + LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL); if (pcb->flags & TF_RXCLOSED) { /* received data although already closed -> abort (send RST) to notify the remote host that not all data has been processed */ diff --git a/src/include/lwip/api.h b/src/include/lwip/api.h index 9add7e89..91b9e5d2 100644 --- a/src/include/lwip/api.h +++ b/src/include/lwip/api.h @@ -168,12 +168,11 @@ struct netconn { /** maximum amount of bytes queued in recvmbox not used for TCP: adjust TCP_WND instead! */ int recv_bufsize; -#endif /* LWIP_SO_RCVBUF */ /** number of bytes currently in recvmbox to be received, tested against recv_bufsize to limit bytes on recvmbox - for UDP and RAW - @todo: should only be necessary with LWIP_SO_RCVBUF==1 */ + for UDP and RAW, used for FIONREAD */ s16_t recv_avail; +#endif /* LWIP_SO_RCVBUF */ /** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */ u8_t flags; #if LWIP_TCP diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index 05912003..a1b87658 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -432,11 +432,14 @@ #endif /** - * ARP_QUEUEING==1: Outgoing packets are queued during hardware address - * resolution. + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. */ #ifndef ARP_QUEUEING -#define ARP_QUEUEING 1 +#define ARP_QUEUEING 0 #endif /** diff --git a/src/netif/etharp.c b/src/netif/etharp.c index 2857ee69..a6e2550b 100644 --- a/src/netif/etharp.c +++ b/src/netif/etharp.c @@ -93,6 +93,9 @@ struct etharp_entry { #if ARP_QUEUEING /** Pointer to queue of pending outgoing packets on this ARP entry. */ struct etharp_q_entry *q; +#else /* ARP_QUEUEING */ + /** Pointer to a single pending outgoing packet on this ARP entry. */ + struct pbuf *q; #endif /* ARP_QUEUEING */ ip_addr_t ipaddr; struct eth_addr ethaddr; @@ -154,6 +157,11 @@ free_etharp_q(struct etharp_q_entry *q) memp_free(MEMP_ARP_QUEUE, r); } } +#else /* ARP_QUEUEING */ + +/** Compatibility define: free the queued pbuf */ +#define free_etharp_q(q) pbuf_free(q) + #endif /* ARP_QUEUEING */ /** Clean up ARP table entries */ @@ -162,7 +170,6 @@ free_entry(int i) { /* remove from SNMP ARP index tree */ snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr); -#if ARP_QUEUEING /* and empty packet queue */ if (arp_table[i].q != NULL) { /* remove all queued packets */ @@ -170,7 +177,6 @@ free_entry(int i) free_etharp_q(arp_table[i].q); arp_table[i].q = NULL; } -#endif /* ARP_QUEUEING */ /* recycle entry for re-use */ arp_table[i].state = ETHARP_STATE_EMPTY; #if ETHARP_SUPPORT_STATIC_ENTRIES @@ -254,12 +260,10 @@ find_entry(ip_addr_t *ipaddr, u8_t flags) s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE; s8_t empty = ARP_TABLE_SIZE; u8_t i = 0, age_pending = 0, age_stable = 0; -#if ARP_QUEUEING /* oldest entry with packets on queue */ s8_t old_queue = ARP_TABLE_SIZE; /* its age */ u8_t age_queue = 0; -#endif /* ARP_QUEUEING */ /** * a) do a search through the cache, remember candidates @@ -295,14 +299,12 @@ find_entry(ip_addr_t *ipaddr, u8_t flags) /* pending entry? */ if (state == ETHARP_STATE_PENDING) { /* pending with queued packets? */ -#if ARP_QUEUEING if (arp_table[i].q != NULL) { if (arp_table[i].ctime >= age_queue) { old_queue = i; age_queue = arp_table[i].ctime; } } else -#endif /* ARP_QUEUEING */ /* pending without queued packets? */ { if (arp_table[i].ctime >= age_pending) { @@ -355,22 +357,18 @@ find_entry(ip_addr_t *ipaddr, u8_t flags) /* recycle oldest stable*/ i = old_stable; LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i)); -#if ARP_QUEUEING /* no queued packets should exist on stable entries */ LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); -#endif /* ARP_QUEUEING */ /* 3) found recyclable pending entry without queued packets? */ } else if (old_pending < ARP_TABLE_SIZE) { /* recycle oldest pending */ i = old_pending; LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i)); -#if ARP_QUEUEING /* 4) found recyclable pending entry with queued packets? */ } else if (old_queue < ARP_TABLE_SIZE) { /* recycle oldest pending (queued packets are free in free_entry) */ i = old_queue; LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q))); -#endif /* ARP_QUEUEING */ /* no empty or recyclable entries found */ } else { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty or recyclable entries found\n")); @@ -486,8 +484,8 @@ update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethadd ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr); /* reset time stamp */ arp_table[i].ctime = 0; -#if ARP_QUEUEING /* this is where we will send out queued packets! */ +#if ARP_QUEUEING while (arp_table[i].q != NULL) { struct pbuf *p; /* remember remainder of queue */ @@ -498,12 +496,16 @@ update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethadd p = q->p; /* now queue entry can be freed */ memp_free(MEMP_ARP_QUEUE, q); +#else /* ARP_QUEUEING */ + if (arp_table[i].q != NULL) { + struct pbuf *p = arp_table[i].q; + arp_table[i].q = NULL; +#endif /* ARP_QUEUEING */ /* send the queued IP packet */ etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr); /* free the queued IP packet */ pbuf_free(p); } -#endif /* ARP_QUEUEING */ return ERR_OK; } @@ -1015,7 +1017,7 @@ etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q) result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr)); /* pending entry? (either just created or already pending */ } else if (arp_table[i].state == ETHARP_STATE_PENDING) { -#if ARP_QUEUEING /* queue the given q packet */ + /* entry is still pending, queue the given packet 'q' */ struct pbuf *p; int copy_needed = 0; /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but @@ -1047,6 +1049,7 @@ etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q) /* packet could be taken over? */ if (p != NULL) { /* queue packet ... */ +#if ARP_QUEUEING struct etharp_q_entry *new_entry; /* allocate a new arp queue entry */ new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE); @@ -1071,18 +1074,23 @@ etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q) /* the pool MEMP_ARP_QUEUE is empty */ pbuf_free(p); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); - /* { result == ERR_MEM } through initialization */ + result = ERR_MEM; } +#else /* ARP_QUEUEING */ + /* always queue one packet per ARP request only, freeing a previously queued packet */ + if (arp_table[i].q != NULL) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + pbuf_free(arp_table[i].q); + } + arp_table[i].q = p; + result = ERR_OK; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); +#endif /* ARP_QUEUEING */ } else { ETHARP_STATS_INC(etharp.memerr); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); - /* { result == ERR_MEM } through initialization */ + result = ERR_MEM; } -#else /* ARP_QUEUEING */ - /* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */ - /* { result == ERR_MEM } through initialization */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q)); -#endif /* ARP_QUEUEING */ } return result; }