git: 6871de9363e5 - main - netisr: serialize/restore m_pkthdr.rcvif when queueing mbufs

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Thu, 27 Jan 2022 06:00:05 UTC
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=6871de9363e559fef6765f0e49acc47f77544999

commit 6871de9363e559fef6765f0e49acc47f77544999
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2022-01-27 05:58:50 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2022-01-27 05:58:50 +0000

    netisr: serialize/restore m_pkthdr.rcvif when queueing mbufs
    
    Reviewed by:            kp
    Differential revision:  https://reviews.freebsd.org/D33268
---
 sys/net/netisr.c | 18 ++++++++++++++----
 1 file 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;