Handle varialble length polling intervals; fix bug of last checkin

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@376 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2007-11-07 22:54:51 +00:00
parent 22cd175fd7
commit d622214165
14 changed files with 259 additions and 137 deletions

6
TODO
View File

@ -50,13 +50,11 @@ o Network
support multiple network devices, this means we will have to add some infrastructure
to map to device.
- uIP polling issues:
(1) uIP expects a single driver to poll at a 500ms interval (dm90x0 currently
polls a 5sec).
(2) Current logic will not support multiple ethernet drivers. Each driver should
(1) Current logic will not support multiple ethernet drivers. Each driver should
poll on TCP connections connect on the network supported by the driver; UDP
polling should respond with TX data only if the UDP packet is intended for the
the network supported by the driver.
(3) If there were multiple drivers, polling would occur at double the rate.
(2) If there were multiple drivers, polling would occur at double the rate.
- TCP Bug:
When TCP data is received with no read in place, it appears that uIP ACKs the data
even though it was not taken accepted. We must either (1) buffer incoming data, or

View File

@ -263,6 +263,7 @@
/* TX poll deley = 5 seconds. CLK_TCK is the number of clock ticks per second */
#define DM6X_WDDELAY (5*CLK_TCK)
#define DM6X_POLLHSEC (5*2)
/* TX timeout = 1 minute */
@ -1074,7 +1075,7 @@ static void dm9x_txdone(struct dm9x_driver_s *dm9x)
/* Then poll uIP for new XMIT data */
(void)uip_poll(&dm9x->dm_dev, dm9x_uiptxpoll, UIP_DRV_POLL);
(void)uip_poll(&dm9x->dm_dev, dm9x_uiptxpoll);
}
/****************************************************************************
@ -1219,7 +1220,9 @@ static void dm9x_txtimeout(int argc, uint32 arg, ...)
#endif
dbg(" TX packet count: %d\n", dm9x->dm_ntxpending);
#if defined(CONFIG_DM9X_STATS)
dbg(" TX timeouts: %d\n", dm9x->dm_ntxtimeouts);
#endif
dbg(" TX read pointer address: 0x%02x:%02x\n",
getreg(DM9X_TRPAH), getreg(DM9X_TRPAL));
dbg(" Memory data write address: 0x%02x:%02x (DM9010)\n",
@ -1231,7 +1234,7 @@ static void dm9x_txtimeout(int argc, uint32 arg, ...)
/* Then poll uIP for new XMIT data */
(void)uip_poll(&dm9x->dm_dev, dm9x_uiptxpoll, UIP_DRV_POLL);
(void)uip_poll(&dm9x->dm_dev, dm9x_uiptxpoll);
}
/****************************************************************************
@ -1273,9 +1276,9 @@ static void dm9x_polltimer(int argc, uint32 arg, ...)
if (dm9x->dm_ntxpending < 1 || (dm9x->dm_b100M && dm9x->dm_ntxpending < 2))
{
/* If so, poll uIP for new XMIT data */
/* If so, update TCP timing states and poll uIP for new XMIT data */
(void)uip_poll(&dm9x->dm_dev, dm9x_uiptxpoll, UIP_DRV_TIMER);
(void)uip_timer(&dm9x->dm_dev, dm9x_uiptxpoll, DM6X_POLLHSEC);
}
/* Setup the watchdog poll timer again */
@ -1565,7 +1568,9 @@ static void dm9x_reset(struct dm9x_driver_s *dm9x)
save = (uint8)DM9X_INDEX;
#if defined(CONFIG_DM9X_STATS)
dm9x->dm_nresets++;
#endif
dm9x_bringup(dm9x);
/* Wait up to 1 second for the link to be OK */

View File

@ -57,21 +57,6 @@
* Definitions
****************************************************************************/
/* The following flags are passed as an argument to the uip_poll()
* function. They are used to distinguish between the two cases where
* uip_poll() is called. It can be called either because we have
* incoming data that should be processed, or because the periodic
* timer has fired.
*
* UIP_DRV_TIMER - Called periodically from driver to service timeout-
* related activities to and to get timeout-related
* responses (e.g., reset)
* UIP_DRV_POLL - Poll TCP for data to be transmitted
*/
#define UIP_DRV_TIMER 1
#define UIP_DRV_POLL 2
/****************************************************************************
* Public Types
****************************************************************************/
@ -237,27 +222,24 @@ struct uip_driver_s
extern void uip_input(struct uip_driver_s *dev);
/* Polling of connections.
/* Polling of connections
*
* This function will traverse each active uIP connection structure and
* perform uip_input with the specified event. After each polling each
* active uIP connection structure, this function will call the provided
* callback function if the poll resulted in new data to be send. The poll
* will continue until all connections have been polled or until the user-
* suplied function returns a non-zero value (which is would do only if
* it cannot accept further write data).
* These functions will traverse each active uIP connection structure and
* perform appropriate operatios: uip_timer() will perform TCP timer
* operations (and UDP polling operations); uip_poll() will perform TCP
* and UDP polling operations. The CAN driver MUST implement logic to
* periodically call uip_timer(); uip_poll() may be called asychronously
* from the network driver can accept another outgoing packet.
*
* This function should be called periodically with event == UIP_DRV_TIMER
* to perform TCP. This function may also be called with UIP_DRV_POLL to
* obtain pending TX data.
*
* This function is called from the CAN device driver and may be called from
* the timer interrupt/watchdog handle level.
* In both cases, these functions will call the provided callback function
* for every active connection. Polling will continue until all connections
* have been polled or until the user-suplied function returns a non-zero
* value (which it should do only if it cannot accept further write data).
*
* When the callback function is called, there may be an outbound packet
* waiting for service in the uIP packet buffer, and if so the d_len field
* is set to a value larger than zero. The device driver should be called to
* send out the packet.
* is set to a value larger than zero. The device driver should then send
* out the packet.
*
* Example:
* int driver_callback(struct uip_driver_dev *dev)
@ -271,7 +253,7 @@ extern void uip_input(struct uip_driver_s *dev);
* }
*
* ...
* uip_poll(dev, driver_callback, UIP_DRV_TIMER);
* uip_poll(dev, driver_callback);
*
* Note: If you are writing a uIP device driver that needs ARP (Address
* Resolution Protocol), e.g., when running uIP over Ethernet, you will
@ -291,11 +273,8 @@ extern void uip_input(struct uip_driver_s *dev);
*/
typedef int (*uip_poll_callback_t)(struct uip_driver_s *dev);
extern int uip_poll(struct uip_driver_s *dev, uip_poll_callback_t callback, int event);
/* uip_poll helper functions */
#define uip_periodic(dev,cb) uip_poll(dev, db, UIP_DRV_TIMER);
extern int uip_poll(struct uip_driver_s *dev, uip_poll_callback_t callback);
extern int uip_timer(struct uip_driver_s *dev, uip_poll_callback_t callback, int hsec);
/* By defining UIP_ARCH_CHKSUM, the architecture can replace the following
* functions with hardware assisted solutions.

View File

@ -45,7 +45,6 @@
struct uip_eth_hdr
{
uint8 dest[6]; /* Ethernet destination address (6 bytes) */
uint8 src[6]; /* Ethernet source address (6 bytes) */
uint16 type; /* Type code (2 bytes) */

View File

@ -180,7 +180,7 @@ struct uip_conn
* variable. */
uint8 rto; /* Retransmission time-out. */
uint8 tcpstateflags; /* TCP state and flags. */
uint8 timer; /* The retransmission timer. */
uint8 timer; /* The retransmission timer (units: half-seconds). */
uint8 nrtx; /* The number of retransmissions for the last
* segment sent. */

View File

@ -108,10 +108,11 @@
#define UIP_REASSEMBLY 0
/* The maximum time an IP fragment should wait in the reassembly
* buffer before it is dropped.
* buffer before it is dropped. Units are deci-seconds, the range
* of the timer is 8-bits.
*/
#define UIP_REASS_MAXAGE 40
#define UIP_REASS_MAXAGE (20*10) /* 20 seconds */
/* UDP configuration options */
@ -218,10 +219,10 @@
/* How long a connection should stay in the TIME_WAIT state.
*
* This configiration option has no real implication, and it should be
* left untouched.
* left untouched. Units: half second.
*/
#define UIP_TIME_WAIT_TIMEOUT 120
#define UIP_TIME_WAIT_TIMEOUT (60*2)
/* ARP configuration options */

View File

@ -87,8 +87,6 @@ static WDOG_ID g_arptimer; /* ARP timer */
static void arptimer_poll(int argc, uint32 arg, ...)
{
dbg("ARP timer expiration\n");
/* Call the ARP timer function every 10 seconds. */
uip_arp_timer();

View File

@ -98,6 +98,8 @@ const uip_ipaddr_t all_zeroes_addr =
{0x00000000};
#endif
/* Reassembly timer (units: deci-seconds) */
#if UIP_REASSEMBLY && !defined(CONFIG_NET_IPv6)
uint8 uip_reasstmr;
#endif

View File

@ -147,12 +147,12 @@ static uint8 uip_reass(void)
uint16 offset, len;
uint16 i;
/* If ip_reasstmr is zero, no packet is present in the buffer, so we
/* If uip_reasstmr is zero, no packet is present in the buffer, so we
* write the IP header of the fragment into the reassembly
* buffer. The timer is updated with the maximum age.
*/
if (uip_reasstmr == 0)
if (!uip_reasstmr)
{
memcpy(uip_reassbuf, &BUF->vhl, UIP_IPH_LEN);
uip_reasstmr = UIP_REASS_MAXAGE;

View File

@ -101,6 +101,8 @@ extern const uip_ipaddr_t all_zeroes_addr;
extern uint16 g_ipid;
/* Reassembly timer (units: deci-seconds) */
#if UIP_REASSEMBLY && !defined(CONFIG_NET_IPv6)
extern uint8 uip_reasstmr;
#endif
@ -131,7 +133,7 @@ EXTERN void uip_tcppoll(struct uip_driver_s *dev, struct uip_conn *conn);
/* Defined in uip-udptimer.c ************************************************/
EXTERN void uip_udptimer(struct uip_driver_s *dev, struct uip_conn *conn);
EXTERN void uip_tcptimer(struct uip_driver_s *dev, struct uip_conn *conn, int hsec);
/* Defined in uip_listen.c **************************************************/

View File

@ -58,6 +58,119 @@
* Private Functions
****************************************************************************/
/****************************************************************************
* Function: uip_polludpconnections
*
* Description:
* Poll all UDP connections for available packets to send.
*
* Assumptions:
* This function is called from the CAN device driver and may be called from
* the timer interrupt/watchdog handle level.
*
****************************************************************************/
#ifdef CONFIG_NET_UDP
static int uip_polludpconnections(struct uip_driver_s *dev,
uip_poll_callback_t callback)
{
struct uip_udp_conn *udp_conn = NULL;
int bstop = 0;
/* Traverse all of the allocated UDP connections and perform the poll action */
while (!bstop && (udp_conn = uip_nextudpconn(udp_conn)))
{
/* Perform the UDP TX poll */
uip_udp_conn = udp_conn;
uip_udppoll(dev, udp_conn);
/* Call back into the driver */
bstop = callback(dev);
}
uip_udp_conn = NULL;
return bstop;
}
#else
# define uip_polludpconnections(dev,callback) (0)
#endif /* CONFIG_NET_UDP */
/****************************************************************************
* Function: uip_polltcpconnections
*
* Description:
* Poll all UDP connections for available packets to send.
*
* Assumptions:
* This function is called from the CAN device driver and may be called from
* the timer interrupt/watchdog handle level.
*
****************************************************************************/
static inline int uip_polltcpconnections(struct uip_driver_s *dev,
uip_poll_callback_t callback)
{
struct uip_conn *conn = NULL;
int bstop = 0;
/* Traverse all of the active TCP connections and perform the poll action */
while (!bstop && (conn = uip_nexttcpconn(conn)))
{
/* Perform the TCP TX poll */
uip_conn = conn;
uip_tcppoll(dev, conn);
/* Call back into the driver */
bstop = callback(dev);
}
uip_conn = NULL;
return bstop;
}
/****************************************************************************
* Function: uip_polltcptimer
*
* Description:
* The TCP timer has expired. Update TCP timing state in each active,
* TCP connection.
*
* Assumptions:
* This function is called from the CAN device driver and may be called from
* the timer interrupt/watchdog handle level.
*
****************************************************************************/
static inline int uip_polltcptimer(struct uip_driver_s *dev,
uip_poll_callback_t callback, int hsec)
{
struct uip_conn *conn = NULL;
int bstop = 0;
/* Traverse all of the active TCP connections and perform the poll action */
while (!bstop && (conn = uip_nexttcpconn(conn)))
{
/* Perform the TCP timer poll */
uip_conn = conn;
uip_tcptimer(dev, conn, hsec);
/* Call back into the driver */
bstop = callback(dev);
}
uip_conn = NULL;
return bstop;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -67,21 +180,18 @@
*
* Description:
* This function will traverse each active uIP connection structure and
* perform uip_interrupt with the specified event. After each polling each
* active uIP connection structure, this function will call the provided
* callback function if the poll resulted in new data to be send. The poll
* will continue until all connections have been polled or until the user-
* suplied function returns a non-zero value (which is would do only if
* it cannot accept further write data).
* will perform TCP and UDP polling operations. uip_poll() may be called
* asychronously with the network drvier can accept another outgoing packet.
*
* This function should be called periodically with event == UIP_DRV_TIMER
* to perform period TCP processing. This function may also be called
* with UIP_DRV_POLL obtain queue TX data.
* This function will call the provided callback function for every active
* connection. Polling will continue until all connections have been polled
* or until the user-suplied function returns a non-zero value (which it
* should do only if it cannot accept further write data).
*
* When the callback function is called, there may be an outbound packet
* waiting for service in the uIP packet buffer, and if so the d_len field
* is set to a value larger than zero. The device driver should be called to
* send out the packet.
* is set to a value larger than zero. The device driver should then send
* out the packet.
*
* Assumptions:
* This function is called from the CAN device driver and may be called from
@ -89,58 +199,71 @@
*
****************************************************************************/
int uip_poll(struct uip_driver_s *dev, uip_poll_callback_t callback, int event)
int uip_poll(struct uip_driver_s *dev, uip_poll_callback_t callback)
{
struct uip_conn *conn;
#ifdef CONFIG_NET_UDP
struct uip_udp_conn *udp_conn;
#endif
irqstate_t flags;
/* Interrupts must be disabled while traversing the active connection list */
flags = irqsave();
int bstop;
/* Traverse all of the active TCP connections and perform the poll action */
conn = NULL;
while ((conn = uip_nexttcpconn(conn)))
bstop = uip_polltcpconnections(dev, callback);
if (!bstop)
{
uip_conn = conn;
if (event == UIP_DRV_POLL)
{
uip_tcppoll(dev, conn);
}
else
{
uip_tcptimer(dev, conn);
/* Traverse all of the allocated UDP connections and perform the poll action */
bstop = uip_polludpconnections(dev, callback);
}
if (callback(dev))
{
irqrestore(flags);
return 1;
return bstop;
}
}
uip_conn = NULL;
#ifdef CONFIG_NET_UDP
/* Traverse all of the allocated UDP connections and perform a poll action */
/****************************************************************************
* Function: uip_timer
*
* Description:
* These function will traverse each active uIP connection structure and
* perform TCP timer operations (and UDP polling operations). The CAN
* driver MUST implement logic to periodically call uip_timer().
*
* This function will call the provided callback function for every active
* connection. Polling will continue until all connections have been polled
* or until the user-suplied function returns a non-zero value (which it
* should do only if it cannot accept further write data).
*
* When the callback function is called, there may be an outbound packet
* waiting for service in the uIP packet buffer, and if so the d_len field
* is set to a value larger than zero. The device driver should then send
* out the packet.
*
* Assumptions:
* This function is called from the CAN device driver and may be called from
* the timer interrupt/watchdog handle level.
*
****************************************************************************/
udp_conn = NULL;
while ((udp_conn = uip_nextudpconn(udp_conn)))
int uip_timer(struct uip_driver_s *dev, uip_poll_callback_t callback, int hsec)
{
uip_udppoll(dev, udp_conn);
if (callback(dev))
{
irqrestore(flags);
return 1;
}
}
#endif /* CONFIG_NET_UDP */
int bstop;
irqrestore(flags);
return 0;
/* Increment the timer used by the IP reassembly logic */
#if UIP_REASSEMBLY
if (uip_reasstmr != 0 && uip_reasstmr < UIP_REASS_MAXAGE)
{
uip_reasstmr += hsec;
}
#endif /* UIP_REASSEMBLY */
/* Traverse all of the active TCP connections and perform the timer action */
bstop = uip_polltcptimer(dev, callback, hsec);
if (!bstop)
{
/* Traverse all of the allocated UDP connections and perform the poll action */
bstop = uip_polludpconnections(dev, callback);
}
return bstop;
}
#endif /* CONFIG_NET */

View File

@ -106,6 +106,9 @@ void uip_tcppoll(struct uip_driver_s *dev, struct uip_conn *conn)
dev->d_snddata = &dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
dev->d_appdata = &dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
dev->d_len = 0;
dev->d_sndlen = 0;
/* Perfom the callback */
uip_flags = UIP_POLL;

View File

@ -83,6 +83,7 @@
* Parameters:
* dev - The device driver structure to use in the send operation
* conn - The TCP "connection" to poll for TX data
* hsed - The polling interval in halves of a second
*
* Return:
* None
@ -92,20 +93,11 @@
*
****************************************************************************/
void uip_tcptimer(struct uip_driver_s *dev, struct uip_conn *conn)
void uip_tcptimer(struct uip_driver_s *dev, struct uip_conn *conn, int hsec)
{
dev->d_snddata = &dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
dev->d_appdata = &dev->d_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
/* Increment the timer used by the reassembly logic */
#if UIP_REASSEMBLY
if (uip_reasstmr != 0)
{
uip_reasstmr++;
}
#endif /* UIP_REASSEMBLY */
/* Increase the TCP sequence number */
uip_tcpnextsequence();
@ -123,8 +115,10 @@ void uip_tcptimer(struct uip_driver_s *dev, struct uip_conn *conn)
if (conn->tcpstateflags == UIP_TIME_WAIT || conn->tcpstateflags == UIP_FIN_WAIT_2)
{
(conn->timer)++;
if (conn->timer == UIP_TIME_WAIT_TIMEOUT)
/* Increment the connection timer */
(conn->timer) += hsec;
if (conn->timer >= UIP_TIME_WAIT_TIMEOUT)
{
conn->tcpstateflags = UIP_CLOSED;
vdbg("TCP state: UIP_CLOSED\n");
@ -132,15 +126,29 @@ void uip_tcptimer(struct uip_driver_s *dev, struct uip_conn *conn)
}
else if (conn->tcpstateflags != UIP_CLOSED)
{
/* If the connection has outstanding data, we increase the
* connection's timer and see if it has reached the RTO value
* in which case we retransmit.
/* If the connection has outstanding data, we increase the connection's
* timer and see if it has reached the RTO value in which case we
* retransmit.
*/
if (uip_outstanding(conn))
{
if (conn->timer-- == 0)
/* The connection has outstanding data */
if (conn->timer > hsec)
{
/* Will not yet decrement to zero */
conn->timer -= hsec;
}
else
{
/* Will decrement to zero */
conn->timer = 0;
/* Should we close the connection? */
if (conn->nrtx == UIP_MAXRTX ||
((conn->tcpstateflags == UIP_SYN_SENT ||
conn->tcpstateflags == UIP_SYN_RCVD) &&
@ -166,7 +174,7 @@ void uip_tcptimer(struct uip_driver_s *dev, struct uip_conn *conn)
/* Exponential backoff. */
conn->timer = UIP_RTO << (conn->nrtx > 4 ? 4: conn->nrtx);
++(conn->nrtx);
(conn->nrtx)++;
/* Ok, so we need to retransmit. We do this differently
* depending on which state we are in. In ESTABLISHED, we
@ -216,6 +224,9 @@ void uip_tcptimer(struct uip_driver_s *dev, struct uip_conn *conn)
}
}
}
/* The connection does not have outstanding data */
else if ((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED)
{
/* If there was no need for a retransmission, we poll the

View File

@ -105,6 +105,7 @@ void uip_udppoll(struct uip_driver_s *dev, struct uip_udp_conn *conn)
dev->d_appdata = &dev->d_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
dev->d_snddata = &dev->d_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN];
dev->d_len = 0;
dev->d_sndlen = 0;