Page MenuHomeFreeBSD

D19622.id55319.diff
No OneTemporary

D19622.id55319.diff

Index: sys/kern/kern_mbuf.c
===================================================================
--- sys/kern/kern_mbuf.c
+++ sys/kern/kern_mbuf.c
@@ -802,6 +802,13 @@
static void
mb_reclaim(uma_zone_t zone __unused, int pending __unused)
{
+
+ mb_reclaim_from_all_domains(NULL);
+}
+
+void
+mb_reclaim_from_all_domains(struct ifnet *ifp)
+{
struct domain *dp;
struct protosw *pr;
@@ -810,7 +817,7 @@
for (dp = domains; dp != NULL; dp = dp->dom_next)
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
if (pr->pr_drain != NULL)
- (*pr->pr_drain)();
+ (*pr->pr_drain)(ifp);
}
/*
Index: sys/net/if.c
===================================================================
--- sys/net/if.c
+++ sys/net/if.c
@@ -1206,6 +1206,13 @@
finish_vnet_shutdown:
#endif
/*
+ * Make sure all re-assembly mbufs get freed. This prevents
+ * references to our network interface structure after detach
+ * through mb->rcvif .
+ */
+ mb_reclaim_from_all_domains(ifp);
+
+ /*
* We cannot hold the lock over dom_ifdetach calls as they might
* sleep, for example trying to drain a callout, thus open up the
* theoretical race with re-attaching.
Index: sys/netinet/ip_input.c
===================================================================
--- sys/netinet/ip_input.c
+++ sys/netinet/ip_input.c
@@ -93,7 +93,7 @@
/* IP reassembly functions are defined in ip_reass.c. */
extern void ipreass_init(void);
-extern void ipreass_drain(void);
+extern void ipreass_drain(struct ifnet *);
extern void ipreass_slowtimo(void);
#ifdef VIMAGE
extern void ipreass_destroy(void);
@@ -852,17 +852,24 @@
}
void
-ip_drain(void)
+ip_drain(struct ifnet *ifp)
{
- VNET_ITERATOR_DECL(vnet_iter);
- VNET_LIST_RLOCK_NOSLEEP();
- VNET_FOREACH(vnet_iter) {
- CURVNET_SET(vnet_iter);
- ipreass_drain();
+ if (ifp != NULL) {
+ CURVNET_SET(ifp->if_vnet);
+ ipreass_drain(ifp);
CURVNET_RESTORE();
+ } else {
+ VNET_ITERATOR_DECL(vnet_iter);
+
+ VNET_LIST_RLOCK_NOSLEEP();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ ipreass_drain(NULL);
+ CURVNET_RESTORE();
+ }
+ VNET_LIST_RUNLOCK_NOSLEEP();
}
- VNET_LIST_RUNLOCK_NOSLEEP();
}
/*
Index: sys/netinet/ip_reass.c
===================================================================
--- sys/netinet/ip_reass.c
+++ sys/netinet/ip_reass.c
@@ -88,7 +88,7 @@
#define V_ipreass_maxbucketsize VNET(ipreass_maxbucketsize)
void ipreass_init(void);
-void ipreass_drain(void);
+void ipreass_drain(struct ifnet *);
void ipreass_slowtimo(void);
#ifdef VIMAGE
void ipreass_destroy(void);
@@ -592,7 +592,7 @@
* Drain off all datagram fragments.
*/
void
-ipreass_drain(void)
+ipreass_drain(struct ifnet *ifp)
{
for (int i = 0; i < IPREASS_NHASH; i++) {
@@ -614,7 +614,7 @@
ipreass_destroy(void)
{
- ipreass_drain();
+ ipreass_drain(NULL);
uma_zdestroy(V_ipq_zone);
for (int i = 0; i < IPREASS_NHASH; i++)
mtx_destroy(&V_ipq[i].lock);
@@ -712,7 +712,7 @@
V_noreass = 0;
} else if (max == 0) {
V_noreass = 1;
- ipreass_drain();
+ ipreass_drain(NULL);
} else if (max == -1) {
V_noreass = 0;
uma_zone_set_max(V_ipq_zone, 0);
Index: sys/netinet/ip_var.h
===================================================================
--- sys/netinet/ip_var.h
+++ sys/netinet/ip_var.h
@@ -209,7 +209,7 @@
int inp_setmoptions(struct inpcb *, struct sockopt *);
int ip_ctloutput(struct socket *, struct sockopt *sopt);
-void ip_drain(void);
+void ip_drain(struct ifnet *);
int ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
u_long if_hwassist_flags);
void ip_forward(struct mbuf *m, int srcrt);
Index: sys/netinet/sctp_pcb.h
===================================================================
--- sys/netinet/sctp_pcb.h
+++ sys/netinet/sctp_pcb.h
@@ -619,7 +619,7 @@
int sctp_is_vtag_good(uint32_t, uint16_t lport, uint16_t rport, struct timeval *);
-/* void sctp_drain(void); */
+/* void sctp_drain(struct ifnet *); */
int sctp_destination_is_reachable(struct sctp_tcb *, struct sockaddr *);
Index: sys/netinet/sctp_pcb.c
===================================================================
--- sys/netinet/sctp_pcb.c
+++ sys/netinet/sctp_pcb.c
@@ -7051,45 +7051,56 @@
*/
}
+static void
+sctp_drain_sub(struct ifnet *ifp)
+{
+ struct sctp_inpcb *inp;
+ struct sctp_tcb *stcb;
+
+ SCTP_STAT_INCR(sctps_protocol_drain_calls);
+
+ if (ifp == NULL &&
+ SCTP_BASE_SYSCTL(sctp_do_drain) == 0)
+ return;
+
+ SCTP_INP_INFO_RLOCK();
+ LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
+ /* For each endpoint */
+ SCTP_INP_RLOCK(inp);
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ /* For each association */
+ SCTP_TCB_LOCK(stcb);
+ sctp_drain_mbufs(stcb);
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ SCTP_INP_RUNLOCK(inp);
+ }
+ SCTP_INP_INFO_RUNLOCK();
+}
+
void
-sctp_drain()
+sctp_drain(struct ifnet *ifp)
{
- /*
- * We must walk the PCB lists for ALL associations here. The system
- * is LOW on MBUF's and needs help. This is where reneging will
- * occur. We really hope this does NOT happen!
- */
- VNET_ITERATOR_DECL(vnet_iter);
- VNET_LIST_RLOCK_NOSLEEP();
- VNET_FOREACH(vnet_iter) {
- CURVNET_SET(vnet_iter);
- struct sctp_inpcb *inp;
- struct sctp_tcb *stcb;
- SCTP_STAT_INCR(sctps_protocol_drain_calls);
- if (SCTP_BASE_SYSCTL(sctp_do_drain) == 0) {
-#ifdef VIMAGE
- continue;
-#else
- return;
-#endif
+ if (ifp != NULL) {
+ CURVNET_SET(ifp->if_vnet);
+ sctp_drain_sub(ifp);
+ CURVNET_RESTORE();
+ } else {
+ /*
+ * We must walk the PCB lists for ALL associations here. The system
+ * is LOW on MBUF's and needs help. This is where reneging will
+ * occur. We really hope this does NOT happen!
+ */
+ VNET_ITERATOR_DECL(vnet_iter);
+ VNET_LIST_RLOCK_NOSLEEP();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ sctp_drain_sub(ifp);
+ CURVNET_RESTORE();
}
- SCTP_INP_INFO_RLOCK();
- LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
- /* For each endpoint */
- SCTP_INP_RLOCK(inp);
- LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
- /* For each association */
- SCTP_TCB_LOCK(stcb);
- sctp_drain_mbufs(stcb);
- SCTP_TCB_UNLOCK(stcb);
- }
- SCTP_INP_RUNLOCK(inp);
- }
- SCTP_INP_INFO_RUNLOCK();
- CURVNET_RESTORE();
+ VNET_LIST_RUNLOCK_NOSLEEP();
}
- VNET_LIST_RUNLOCK_NOSLEEP();
}
/*
Index: sys/netinet/sctp_var.h
===================================================================
--- sys/netinet/sctp_var.h
+++ sys/netinet/sctp_var.h
@@ -339,7 +339,7 @@
int sctp_input(struct mbuf **, int *, int);
#endif
void sctp_pathmtu_adjustment(struct sctp_tcb *, uint16_t);
-void sctp_drain(void);
+void sctp_drain(struct ifnet *);
void sctp_init(void);
void
sctp_notify(struct sctp_inpcb *, struct sctp_tcb *, struct sctp_nets *,
Index: sys/netinet/tcp_subr.c
===================================================================
--- sys/netinet/tcp_subr.c
+++ sys/netinet/tcp_subr.c
@@ -1994,20 +1994,12 @@
return (tp);
}
-void
-tcp_drain(void)
+static void
+tcp_drain_sub(struct ifnet *ifp)
{
- VNET_ITERATOR_DECL(vnet_iter);
+ struct inpcb *inpb;
+ struct tcpcb *tcpb;
- if (!do_tcpdrain)
- return;
-
- VNET_LIST_RLOCK_NOSLEEP();
- VNET_FOREACH(vnet_iter) {
- CURVNET_SET(vnet_iter);
- struct inpcb *inpb;
- struct tcpcb *tcpb;
-
/*
* Walk the tcpbs, if existing, and flush the reassembly queue,
* if there is one...
@@ -2016,33 +2008,55 @@
* where we're really low on mbufs, this is potentially
* useful.
*/
- INP_INFO_WLOCK(&V_tcbinfo);
- CK_LIST_FOREACH(inpb, V_tcbinfo.ipi_listhead, inp_list) {
- INP_WLOCK(inpb);
- if (inpb->inp_flags & INP_TIMEWAIT) {
- INP_WUNLOCK(inpb);
- continue;
- }
- if ((tcpb = intotcpcb(inpb)) != NULL) {
- tcp_reass_flush(tcpb);
- tcp_clean_sackreport(tcpb);
+
+ INP_INFO_WLOCK(&V_tcbinfo);
+ CK_LIST_FOREACH(inpb, V_tcbinfo.ipi_listhead, inp_list) {
+ INP_WLOCK(inpb);
+ if (inpb->inp_flags & INP_TIMEWAIT) {
+ INP_WUNLOCK(inpb);
+ continue;
+ }
+ if ((tcpb = intotcpcb(inpb)) != NULL) {
+ tcp_reass_flush(tcpb);
+ tcp_clean_sackreport(tcpb);
#ifdef TCP_BLACKBOX
- tcp_log_drain(tcpb);
+ tcp_log_drain(tcpb);
#endif
#ifdef TCPPCAP
- if (tcp_pcap_aggressive_free) {
- /* Free the TCP PCAP queues. */
- tcp_pcap_drain(&(tcpb->t_inpkts));
- tcp_pcap_drain(&(tcpb->t_outpkts));
- }
+ if (tcp_pcap_aggressive_free) {
+ /* Free the TCP PCAP queues. */
+ tcp_pcap_drain(&(tcpb->t_inpkts));
+ tcp_pcap_drain(&(tcpb->t_outpkts));
+ }
#endif
- }
- INP_WUNLOCK(inpb);
}
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_WUNLOCK(inpb);
+ }
+ INP_INFO_WUNLOCK(&V_tcbinfo);
+}
+
+void
+tcp_drain(struct ifnet *ifp)
+{
+
+ if (ifp != NULL) {
+ CURVNET_SET(ifp->if_vnet);
+ tcp_drain_sub(ifp);
CURVNET_RESTORE();
+ } else {
+ VNET_ITERATOR_DECL(vnet_iter);
+
+ if (do_tcpdrain == 0)
+ return;
+
+ VNET_LIST_RLOCK_NOSLEEP();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ tcp_drain_sub(NULL);
+ CURVNET_RESTORE();
+ }
+ VNET_LIST_RUNLOCK_NOSLEEP();
}
- VNET_LIST_RUNLOCK_NOSLEEP();
}
/*
Index: sys/netinet/tcp_var.h
===================================================================
--- sys/netinet/tcp_var.h
+++ sys/netinet/tcp_var.h
@@ -836,7 +836,7 @@
int tcp_ctloutput(struct socket *, struct sockopt *);
struct tcpcb *
tcp_drop(struct tcpcb *, int);
-void tcp_drain(void);
+void tcp_drain(struct ifnet *);
void tcp_init(void);
void tcp_fini(void *);
char *tcp_log_addrs(struct in_conninfo *, struct tcphdr *, void *,
Index: sys/netinet6/frag6.c
===================================================================
--- sys/netinet6/frag6.c
+++ sys/netinet6/frag6.c
@@ -911,33 +911,47 @@
VNET_LIST_RUNLOCK_NOSLEEP();
}
+static void
+frag6_drain_sub(struct ifnet *ifp)
+{
+ struct ip6q *head;
+ int i;
+
+ for (i = 0; i < IP6REASS_NHASH; i++) {
+ if (IP6Q_TRYLOCK(i) == 0)
+ continue;
+ head = IP6Q_HEAD(i);
+ while (head->ip6q_next != head) {
+ IP6STAT_INC(ip6s_fragdropped);
+ /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
+ frag6_freef(head->ip6q_next, i);
+ }
+ IP6Q_UNLOCK(i);
+ }
+}
+
/*
* Drain off all datagram fragments.
*/
void
-frag6_drain(void)
+frag6_drain(struct ifnet *ifp)
{
- VNET_ITERATOR_DECL(vnet_iter);
- struct ip6q *head;
- int i;
- VNET_LIST_RLOCK_NOSLEEP();
- VNET_FOREACH(vnet_iter) {
- CURVNET_SET(vnet_iter);
- for (i = 0; i < IP6REASS_NHASH; i++) {
- if (IP6Q_TRYLOCK(i) == 0)
- continue;
- head = IP6Q_HEAD(i);
- while (head->ip6q_next != head) {
- IP6STAT_INC(ip6s_fragdropped);
- /* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
- frag6_freef(head->ip6q_next, i);
- }
- IP6Q_UNLOCK(i);
+ if (ifp != NULL) {
+ CURVNET_SET(ifp->if_vnet);
+ frag6_drain_sub(ifp);
+ CURVNET_RESTORE();
+ } else {
+ VNET_ITERATOR_DECL(vnet_iter);
+
+ VNET_LIST_RLOCK_NOSLEEP();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ frag6_drain_sub(NULL);
+ CURVNET_RESTORE();
}
- CURVNET_RESTORE();
+ VNET_LIST_RUNLOCK_NOSLEEP();
}
- VNET_LIST_RUNLOCK_NOSLEEP();
}
int
Index: sys/netinet6/ip6_var.h
===================================================================
--- sys/netinet6/ip6_var.h
+++ sys/netinet6/ip6_var.h
@@ -418,7 +418,7 @@
void frag6_init(void);
int frag6_input(struct mbuf **, int *, int);
void frag6_slowtimo(void);
-void frag6_drain(void);
+void frag6_drain(struct ifnet *);
void rip6_init(void);
int rip6_input(struct mbuf **, int *, int);
Index: sys/sys/mbuf.h
===================================================================
--- sys/sys/mbuf.h
+++ sys/sys/mbuf.h
@@ -615,6 +615,7 @@
void mb_dupcl(struct mbuf *, struct mbuf *);
void mb_free_ext(struct mbuf *);
+void mb_reclaim_from_all_domains(struct ifnet *);
void m_adj(struct mbuf *, int);
int m_apply(struct mbuf *, int, int,
int (*)(void *, void *, u_int), void *);
Index: sys/sys/protosw.h
===================================================================
--- sys/sys/protosw.h
+++ sys/sys/protosw.h
@@ -42,6 +42,7 @@
struct sockaddr;
struct socket;
struct sockopt;
+struct ifnet;
/*#ifdef _KERNEL*/
/*
@@ -74,7 +75,7 @@
typedef void pr_init_t (void);
typedef void pr_fasttimo_t (void);
typedef void pr_slowtimo_t (void);
-typedef void pr_drain_t (void);
+typedef void pr_drain_t (struct ifnet *);
struct protosw {
short pr_type; /* socket type used for */

File Metadata

Mime Type
text/plain
Expires
Sat, Dec 21, 4:35 PM (16 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15543345
Default Alt Text
D19622.id55319.diff (12 KB)

Event Timeline