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:
parent
9dc51afa2c
commit
1d3b6619e5
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user