aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGleb Smirnoff <glebius@FreeBSD.org>2022-01-27 05:58:50 +0000
committerEd Maste <emaste@FreeBSD.org>2022-05-05 18:38:07 +0000
commit51f798e761b1b30fc2432cce4295271c0689bd1f (patch)
tree281e970161842ddd28a0a1bf6f294958d23e93b4
parent8ef7beb29edd1afc4931424eadb0e1c6a7f3c364 (diff)
downloadsrc-51f798e761b1b30fc2432cce4295271c0689bd1f.tar.gz
src-51f798e761b1b30fc2432cce4295271c0689bd1f.zip
netisr: serialize/restore m_pkthdr.rcvif when queueing mbufs
Reviewed by: kp Differential revision: https://reviews.freebsd.org/D33268 (cherry picked from commit 6871de9363e559fef6765f0e49acc47f77544999)
-rw-r--r--sys/net/netisr.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/sys/net/netisr.c b/sys/net/netisr.c
index e4abea317440..4d0bce3bedfc 100644
--- a/sys/net/netisr.c
+++ b/sys/net/netisr.c
@@ -700,9 +700,11 @@ netisr_register_vnet(const struct netisr_handler *nhp)
static void
netisr_drain_proto_vnet(struct vnet *vnet, u_int proto)
{
+ struct epoch_tracker et;
struct netisr_workstream *nwsp;
struct netisr_work *npwp;
struct mbuf *m, *mp, *n, *ne;
+ struct ifnet *ifp;
u_int i;
KASSERT(vnet != NULL, ("%s: vnet is NULL", __func__));
@@ -723,11 +725,14 @@ netisr_drain_proto_vnet(struct vnet *vnet, u_int proto)
*/
m = npwp->nw_head;
n = ne = NULL;
+ NET_EPOCH_ENTER(et);
while (m != NULL) {
mp = m;
m = m->m_nextpkt;
mp->m_nextpkt = NULL;
- if (mp->m_pkthdr.rcvif->if_vnet != vnet) {
+ if ((ifp = ifnet_byindexgen(mp->m_pkthdr.rcvidx,
+ mp->m_pkthdr.rcvgen)) != NULL &&
+ ifp->if_vnet != vnet) {
if (n == NULL) {
n = ne = mp;
} else {
@@ -736,10 +741,12 @@ netisr_drain_proto_vnet(struct vnet *vnet, u_int proto)
}
continue;
}
- /* This is a packet in the selected vnet. Free it. */
+ /* This is a packet in the selected vnet, or belongs
+ to destroyed interface. Free it. */
npwp->nw_len--;
m_freem(mp);
}
+ NET_EPOCH_EXIT(et);
npwp->nw_head = n;
npwp->nw_tail = ne;
NWS_UNLOCK(nwsp);
@@ -913,8 +920,10 @@ netisr_process_workstream_proto(struct netisr_workstream *nwsp, u_int proto)
if (local_npw.nw_head == NULL)
local_npw.nw_tail = NULL;
local_npw.nw_len--;
- VNET_ASSERT(m->m_pkthdr.rcvif != NULL,
- ("%s:%d rcvif == NULL: m=%p", __func__, __LINE__, m));
+ if (__predict_false(m_rcvif_restore(m) == NULL)) {
+ m_freem(m);
+ continue;
+ }
CURVNET_SET(m->m_pkthdr.rcvif->if_vnet);
netisr_proto[proto].np_handler(m);
CURVNET_RESTORE();
@@ -986,6 +995,7 @@ netisr_queue_workstream(struct netisr_workstream *nwsp, u_int proto,
*dosignalp = 0;
if (npwp->nw_len < npwp->nw_qlimit) {
+ m_rcvif_serialize(m);
m->m_nextpkt = NULL;
if (npwp->nw_head == NULL) {
npwp->nw_head = m;