From owner-svn-src-head@freebsd.org Fri May 19 08:19:52 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 7C473D74D85; Fri, 19 May 2017 08:19:52 +0000 (UTC) (envelope-from royger@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 57AE01F91; Fri, 19 May 2017 08:19:52 +0000 (UTC) (envelope-from royger@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v4J8JpRs003067; Fri, 19 May 2017 08:19:51 GMT (envelope-from royger@FreeBSD.org) Received: (from royger@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v4J8JplS003066; Fri, 19 May 2017 08:19:51 GMT (envelope-from royger@FreeBSD.org) Message-Id: <201705190819.v4J8JplS003066@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: royger set sender to royger@FreeBSD.org using -f From: =?UTF-8?Q?Roger_Pau_Monn=c3=a9?= Date: Fri, 19 May 2017 08:19:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r318523 - head/sys/dev/xen/netfront X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 19 May 2017 08:19:52 -0000 Author: royger Date: Fri May 19 08:19:51 2017 New Revision: 318523 URL: https://svnweb.freebsd.org/changeset/base/318523 Log: xen/netfront: don't drop the ring RX lock with inconsistent ring state Make sure the RX ring lock is only released when the state of the ring is consistent, or else concurrent calls to xn_rxeof might get an inconsistent ring state and thus some packets might be processed twice. Note that this is not very common, and could only happen when an interrupt is delivered while in xn_ifinit. Reported by: cperciva Tested by: cperciva MFC after: 1 week Sponsored by: Citrix Systems R&D Modified: head/sys/dev/xen/netfront/netfront.c Modified: head/sys/dev/xen/netfront/netfront.c ============================================================================== --- head/sys/dev/xen/netfront/netfront.c Fri May 19 08:19:39 2017 (r318522) +++ head/sys/dev/xen/netfront/netfront.c Fri May 19 08:19:51 2017 (r318523) @@ -1161,17 +1161,18 @@ xn_rxeof(struct netfront_rxq *rxq) struct mbufq mbufq_rxq, mbufq_errq; int err, work_to_do; - do { - XN_RX_LOCK_ASSERT(rxq); - if (!netfront_carrier_ok(np)) - return; - - /* XXX: there should be some sane limit. */ - mbufq_init(&mbufq_errq, INT_MAX); - mbufq_init(&mbufq_rxq, INT_MAX); + XN_RX_LOCK_ASSERT(rxq); + + if (!netfront_carrier_ok(np)) + return; + + /* XXX: there should be some sane limit. */ + mbufq_init(&mbufq_errq, INT_MAX); + mbufq_init(&mbufq_rxq, INT_MAX); - ifp = np->xn_ifp; + ifp = np->xn_ifp; + do { rp = rxq->ring.sring->rsp_prod; rmb(); /* Ensure we see queued responses up to 'rp'. */ @@ -1191,7 +1192,7 @@ xn_rxeof(struct netfront_rxq *rxq) } m->m_pkthdr.rcvif = ifp; - if ( rx->flags & NETRXF_data_validated ) { + if (rx->flags & NETRXF_data_validated) { /* * According to mbuf(9) the correct way to tell * the stack that the checksum of an inbound @@ -1214,50 +1215,45 @@ xn_rxeof(struct netfront_rxq *rxq) } (void )mbufq_enqueue(&mbufq_rxq, m); - rxq->ring.rsp_cons = i; } - mbufq_drain(&mbufq_errq); + rxq->ring.rsp_cons = i; - /* - * Process all the mbufs after the remapping is complete. - * Break the mbuf chain first though. - */ - while ((m = mbufq_dequeue(&mbufq_rxq)) != NULL) { - if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); + xn_alloc_rx_buffers(rxq); - /* XXX: Do we really need to drop the rx lock? */ - XN_RX_UNLOCK(rxq); + RING_FINAL_CHECK_FOR_RESPONSES(&rxq->ring, work_to_do); + } while (work_to_do); + + XN_RX_UNLOCK(rxq); + mbufq_drain(&mbufq_errq); + /* + * Process all the mbufs after the remapping is complete. + * Break the mbuf chain first though. + */ + while ((m = mbufq_dequeue(&mbufq_rxq)) != NULL) { + if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); #if (defined(INET) || defined(INET6)) - /* Use LRO if possible */ - if ((ifp->if_capenable & IFCAP_LRO) == 0 || - lro->lro_cnt == 0 || tcp_lro_rx(lro, m, 0)) { - /* - * If LRO fails, pass up to the stack - * directly. - */ - (*ifp->if_input)(ifp, m); - } -#else + /* Use LRO if possible */ + if ((ifp->if_capenable & IFCAP_LRO) == 0 || + lro->lro_cnt == 0 || tcp_lro_rx(lro, m, 0)) { + /* + * If LRO fails, pass up to the stack + * directly. + */ (*ifp->if_input)(ifp, m); -#endif - - XN_RX_LOCK(rxq); } - - rxq->ring.rsp_cons = i; +#else + (*ifp->if_input)(ifp, m); +#endif + } #if (defined(INET) || defined(INET6)) - /* - * Flush any outstanding LRO work - */ - tcp_lro_flush_all(lro); + /* + * Flush any outstanding LRO work + */ + tcp_lro_flush_all(lro); #endif - - xn_alloc_rx_buffers(rxq); - - RING_FINAL_CHECK_FOR_RESPONSES(&rxq->ring, work_to_do); - } while (work_to_do); + XN_RX_LOCK(rxq); } static void