- Add a new function tcp_twrecycleable, which tells us if the ISN which
we will generate for a given ip/port tuple has advanced far enough for the time_wait socket in question to be safely recycled. - Have in_pcblookup_local use tcp_twrecycleable to determine if time_Wait sockets which are hogging local ports can be safely freed. This change preserves proper TIME_WAIT behavior under normal circumstances while allowing for safe and fast recycling whenever ephemeral port space is scarce.
This commit is contained in:
parent
ac8711d28e
commit
96af9ea52b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=121850
@ -950,6 +950,7 @@ in_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay)
|
||||
* First see if this local port is in use by looking on the
|
||||
* port hash list.
|
||||
*/
|
||||
retrylookup:
|
||||
porthash = &pcbinfo->porthashbase[INP_PCBPORTHASH(lport,
|
||||
pcbinfo->porthashmask)];
|
||||
LIST_FOREACH(phd, porthash, phd_hash) {
|
||||
@ -967,6 +968,17 @@ in_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay)
|
||||
if ((inp->inp_vflag & INP_IPV4) == 0)
|
||||
continue;
|
||||
#endif
|
||||
/*
|
||||
* Clean out old time_wait sockets if they
|
||||
* are clogging up needed local ports.
|
||||
*/
|
||||
if ((inp->inp_vflag & INP_TIMEWAIT) != 0) {
|
||||
if (tcp_twrecycleable((struct tcptw *)inp->inp_ppcb)) {
|
||||
tcp_twclose((struct tcptw *)inp->inp_ppcb, 0);
|
||||
match = NULL;
|
||||
goto retrylookup;
|
||||
}
|
||||
}
|
||||
if (inp->inp_faddr.s_addr != INADDR_ANY)
|
||||
wildcard++;
|
||||
if (inp->inp_laddr.s_addr != INADDR_ANY) {
|
||||
|
@ -1637,6 +1637,7 @@ tcp_twstart(tp)
|
||||
|
||||
tw->snd_nxt = tp->snd_nxt;
|
||||
tw->rcv_nxt = tp->rcv_nxt;
|
||||
tw->iss = tp->iss;
|
||||
tw->cc_recv = tp->cc_recv;
|
||||
tw->cc_send = tp->cc_send;
|
||||
tw->t_starttime = tp->t_starttime;
|
||||
@ -1671,6 +1672,24 @@ tcp_twstart(tp)
|
||||
INP_UNLOCK(inp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if the ISN we will generate has advanced beyond the last
|
||||
* sequence number used by the previous connection. If so, indicate
|
||||
* that it is safe to recycle this tw socket by returning 1.
|
||||
*/
|
||||
int
|
||||
tcp_twrecycleable(struct tcptw *tw)
|
||||
{
|
||||
tcp_seq new_isn = tw->iss;
|
||||
|
||||
new_isn += (ticks - tw->t_starttime) * (ISN_BYTES_PER_SECOND / hz);
|
||||
|
||||
if (SEQ_GT(new_isn, tw->snd_nxt))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct tcptw *
|
||||
tcp_twclose(struct tcptw *tw, int reuse)
|
||||
{
|
||||
|
@ -1637,6 +1637,7 @@ tcp_twstart(tp)
|
||||
|
||||
tw->snd_nxt = tp->snd_nxt;
|
||||
tw->rcv_nxt = tp->rcv_nxt;
|
||||
tw->iss = tp->iss;
|
||||
tw->cc_recv = tp->cc_recv;
|
||||
tw->cc_send = tp->cc_send;
|
||||
tw->t_starttime = tp->t_starttime;
|
||||
@ -1671,6 +1672,24 @@ tcp_twstart(tp)
|
||||
INP_UNLOCK(inp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if the ISN we will generate has advanced beyond the last
|
||||
* sequence number used by the previous connection. If so, indicate
|
||||
* that it is safe to recycle this tw socket by returning 1.
|
||||
*/
|
||||
int
|
||||
tcp_twrecycleable(struct tcptw *tw)
|
||||
{
|
||||
tcp_seq new_isn = tw->iss;
|
||||
|
||||
new_isn += (ticks - tw->t_starttime) * (ISN_BYTES_PER_SECOND / hz);
|
||||
|
||||
if (SEQ_GT(new_isn, tw->snd_nxt))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct tcptw *
|
||||
tcp_twclose(struct tcptw *tw, int reuse)
|
||||
{
|
||||
|
@ -246,6 +246,7 @@ struct tcptw {
|
||||
struct inpcb *tw_inpcb; /* XXX back pointer to internet pcb */
|
||||
tcp_seq snd_nxt;
|
||||
tcp_seq rcv_nxt;
|
||||
tcp_seq iss;
|
||||
tcp_cc cc_recv;
|
||||
tcp_cc cc_send;
|
||||
u_short last_win; /* cached window value */
|
||||
@ -471,6 +472,7 @@ void tcp_canceltimers(struct tcpcb *);
|
||||
struct tcpcb *
|
||||
tcp_close(struct tcpcb *);
|
||||
void tcp_twstart(struct tcpcb *);
|
||||
int tcp_twrecycleable(struct tcptw *tw);
|
||||
struct tcptw *
|
||||
tcp_twclose(struct tcptw *_tw, int _reuse);
|
||||
void tcp_ctlinput(int, struct sockaddr *, void *);
|
||||
|
Loading…
Reference in New Issue
Block a user