Abstract inpcb drop logic, previously just setting of INP_DROPPED in TCP,

into in_pcbdrop().  Expand logic to detach the inpcb from its bound
address/port so that dropping a TCP connection releases the inpcb resource
reservation, which since the introduction of socket/pcb reference count
updates, has been persisting until the socket closed rather than being
released implicitly due to prior freeing of the inpcb on TCP drop.

MFC after:	3 months
This commit is contained in:
Robert Watson 2006-04-25 11:17:35 +00:00
parent 2eafb39b67
commit 10702a2840
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=158009
4 changed files with 33 additions and 6 deletions

View File

@ -728,6 +728,34 @@ in_pcbfree(struct inpcb *inp)
uma_zfree(ipi->ipi_zone, inp);
}
/*
* TCP needs to maintain its inpcb structure after the TCP connection has
* been torn down. However, it must be disconnected from the inpcb hashes as
* it must not prevent binding of future connections to the same port/ip
* combination by other inpcbs.
*/
void
in_pcbdrop(struct inpcb *inp)
{
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
INP_INFO_WLOCK_ASSERT(pcbinfo);
INP_LOCK_ASSERT(inp);
inp->inp_vflag |= INP_DROPPED;
if (inp->inp_lport) {
struct inpcbport *phd = inp->inp_phd;
LIST_REMOVE(inp, inp_hash);
LIST_REMOVE(inp, inp_portlist);
if (LIST_FIRST(&phd->phd_pcblist) == NULL) {
LIST_REMOVE(phd, phd_hash);
free(phd, M_PCB);
}
inp->inp_lport = 0;
}
}
struct sockaddr *
in_sockaddr(in_port_t port, struct in_addr *addr_p)
{

View File

@ -352,6 +352,7 @@ int in_pcbconnect_setup(struct inpcb *, struct sockaddr *, in_addr_t *,
struct ucred *);
void in_pcbdetach(struct inpcb *);
void in_pcbdisconnect(struct inpcb *);
void in_pcbdrop(struct inpcb *);
void in_pcbfree(struct inpcb *);
int in_pcbinshash(struct inpcb *);
struct inpcb *

View File

@ -791,8 +791,7 @@ tcp_close(struct tcpcb *tp)
INP_INFO_WLOCK_ASSERT(&tcbinfo);
INP_LOCK_ASSERT(inp);
inp->inp_vflag |= INP_DROPPED;
in_pcbdrop(inp);
tcpstat.tcps_closed++;
KASSERT(inp->inp_socket != NULL, ("tcp_close: inp_socket NULL"));
so = inp->inp_socket;
@ -1852,7 +1851,7 @@ tcp_twclose(struct tcptw *tw, int reuse)
tw->tw_inpcb = NULL;
tcp_timer_2msl_stop(tw);
inp->inp_ppcb = NULL;
inp->inp_vflag |= INP_DROPPED;
in_pcbdrop(inp);
so = inp->inp_socket;
if (so != NULL) {

View File

@ -791,8 +791,7 @@ tcp_close(struct tcpcb *tp)
INP_INFO_WLOCK_ASSERT(&tcbinfo);
INP_LOCK_ASSERT(inp);
inp->inp_vflag |= INP_DROPPED;
in_pcbdrop(inp);
tcpstat.tcps_closed++;
KASSERT(inp->inp_socket != NULL, ("tcp_close: inp_socket NULL"));
so = inp->inp_socket;
@ -1852,7 +1851,7 @@ tcp_twclose(struct tcptw *tw, int reuse)
tw->tw_inpcb = NULL;
tcp_timer_2msl_stop(tw);
inp->inp_ppcb = NULL;
inp->inp_vflag |= INP_DROPPED;
in_pcbdrop(inp);
so = inp->inp_socket;
if (so != NULL) {