tcp_kill_prio(): prefer nearly-closed connections (waiting for the last ACK only) over established connections when out of tcp pcbs

This commit is contained in:
goldsimon 2015-01-20 12:45:26 +01:00
parent 28476e3b7b
commit e926a93568
2 changed files with 34 additions and 13 deletions

View File

@ -6,6 +6,10 @@ HISTORY
++ New features: ++ New features:
2015-01-02: Simon Goldschmidt
* tcp.c: tcp_kill_prio(): prefer nearly-closed connections (waiting for the
last ACK only) over established connections when out of tcp pcbs
2015-01-17: Simon Goldschmidt 2015-01-17: Simon Goldschmidt
* api: allow enabling socket API without (public) netconn API - netconn API is * api: allow enabling socket API without (public) netconn API - netconn API is
still used by sockets, but keeping it private (static) should allow better still used by sockets, but keeping it private (static) should allow better

View File

@ -1287,26 +1287,43 @@ tcp_recv_null(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
static void static void
tcp_kill_prio(u8_t prio) tcp_kill_prio(u8_t prio)
{ {
struct tcp_pcb *pcb, *inactive; struct tcp_pcb *pcb, *inactive, *lastack;
u32_t inactivity; u32_t inactivity, inactivity_lastack;
u8_t mprio; u8_t minprio, minprio_lastack;
minprio = prio;
minprio_lastack = prio;
mprio = TCP_PRIO_MAX; /* We kill the oldest active connection that has lower priority than prio.
However, already closed connections waiting for the last ack are closed first
/* We kill the oldest active connection that has lower priority than prio. */ since they don't lose data. */
inactivity = 0; inactivity = 0;
inactive = NULL; inactive = NULL;
inactivity_lastack = 0;
lastack = NULL;
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
if (pcb->prio <= prio && if ((lastack != NULL) || (pcb->state == LAST_ACK) || (pcb->state == CLOSING)) {
pcb->prio <= mprio && /* found at least one pcb in last ack phase */
(u32_t)(tcp_ticks - pcb->tmr) >= inactivity) { if ((pcb->prio < minprio_lastack) ||
inactivity = tcp_ticks - pcb->tmr; (u32_t)(tcp_ticks - pcb->tmr) >= inactivity_lastack) {
inactive = pcb; inactivity_lastack = tcp_ticks - pcb->tmr;
mprio = pcb->prio; lastack = pcb;
minprio_lastack = pcb->prio;
}
} else if (pcb->prio <= minprio) {
if ((pcb->prio < minprio) ||
(u32_t)(tcp_ticks - pcb->tmr) >= inactivity) {
inactivity = tcp_ticks - pcb->tmr;
inactive = pcb;
minprio = pcb->prio;
}
} }
} }
if (inactive != NULL) { if (lastack != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB in LAST_ACK or CLOSING %p (%"S32_F")\n",
(void *)lastack, inactivity_lastack));
tcp_abort(lastack);
} else if (inactive != NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n", LWIP_DEBUGF(TCP_DEBUG, ("tcp_kill_prio: killing oldest PCB %p (%"S32_F")\n",
(void *)inactive, inactivity)); (void *)inactive, inactivity));
tcp_abort(inactive); tcp_abort(inactive);