2
0
mirror of https://github.com/xcat2/xNBA.git synced 2024-11-26 19:29:04 +00:00

[tcp] Allow out-of-order receive queue to be discarded

Allow packets in the receive queue to be discarded in order to free up
memory.  This avoids a potential deadlock condition in which the
missing packet can never be received because the receive queue is
occupying all of the memory available for further RX buffers.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2010-07-21 12:01:50 +01:00
parent 9dc51afa2c
commit 1d3b6619e5
2 changed files with 50 additions and 3 deletions

View File

@ -162,6 +162,18 @@ static inline int list_empty ( const struct list_head *head ) {
&pos->member != (head); \
pos = list_entry ( pos->member.next, typeof ( *pos ), member ) )
/**
* Iterate over entries in a list in reverse order
*
* @v pos The type * to use as a loop counter
* @v head The head for your list
* @v member The name of the list_struct within the struct
*/
#define list_for_each_entry_reverse( pos, head, member ) \
for ( pos = list_entry ( (head)->prev, typeof ( *pos ), member ); \
&pos->member != (head); \
pos = list_entry ( pos->member.prev, typeof ( *pos ), member ) )
/**
* Iterate over entries in a list, safe against deletion of entries
*

View File

@ -1004,14 +1004,21 @@ static void tcp_rx_enqueue ( struct tcp_connection *tcp, uint32_t seq,
*/
static void tcp_process_rx_queue ( struct tcp_connection *tcp ) {
struct io_buffer *iobuf;
struct io_buffer *tmp;
struct tcp_rx_queued_header *tcpqhdr;
uint32_t seq;
unsigned int flags;
size_t len;
/* Process all applicable received buffers */
list_for_each_entry_safe ( iobuf, tmp, &tcp->rx_queue, list ) {
/* Process all applicable received buffers. Note that we
* cannot use list_for_each_entry() to iterate over the RX
* queue, since tcp_discard() may remove packets from the RX
* queue while we are processing.
*/
while ( ! list_empty ( &tcp->rx_queue ) ) {
list_for_each_entry ( iobuf, &tcp->rx_queue, list )
break;
/* Stop processing when we hit the first gap */
tcpqhdr = iobuf->data;
if ( tcp_cmp ( tcpqhdr->seq, tcp->rcv_ack ) > 0 )
break;
@ -1183,6 +1190,34 @@ struct tcpip_protocol tcp_protocol __tcpip_protocol = {
.tcpip_proto = IP_TCP,
};
/**
* Discard some cached TCP data
*
* @ret discarded Number of cached items discarded
*/
static unsigned int tcp_discard ( void ) {
struct tcp_connection *tcp;
struct io_buffer *iobuf;
unsigned int discarded = 0;
/* Try to drop one queued RX packet from each connection */
list_for_each_entry ( tcp, &tcp_conns, list ) {
list_for_each_entry_reverse ( iobuf, &tcp->rx_queue, list ) {
list_del ( &iobuf->list );
free_iob ( iobuf );
discarded++;
break;
}
}
return discarded;
}
/** TCP cache discarder */
struct cache_discarder tcp_cache_discarder __cache_discarder = {
.discard = tcp_discard,
};
/***************************************************************************
*
* Data transfer interface