NetBSD Problem Report #53566

From www@NetBSD.org  Sat Sep  1 23:22:02 2018
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 93BA97A19F
	for <gnats-bugs@gnats.NetBSD.org>; Sat,  1 Sep 2018 23:22:02 +0000 (UTC)
Message-Id: <20180901232201.57E847A1FA@mollari.NetBSD.org>
Date: Sat,  1 Sep 2018 23:22:01 +0000 (UTC)
From: coypu@sdf.org
Reply-To: coypu@sdf.org
To: gnats-bugs@NetBSD.org
Subject: rtwn's use of m_defrag can't work
X-Send-Pr-Version: www-1.0

>Number:         53566
>Category:       kern
>Synopsis:       rtwn's use of m_defrag can't work
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Sep 01 23:25:00 +0000 2018
>Originator:     coypu
>Release:        NetBSD 8.99.21
>Organization:
>Environment:
NetBSD planets 8.99.21 NetBSD 8.99.21 (GENERIC) #0: Fri Jul 13 14:49:46 IDT 2018  fly@planets:/tmp/build3/sys/arch/amd64/compile/GENERIC amd64
>Description:
Looking at rtwn, it looks like it can only do 1 tx descriptor

    529 		error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
    530 		    0, BUS_DMA_NOWAIT, &rx_data->map);

so it can only handle one mbuf at a time.
on some packets, the mbuf chain length will be >1.
to work around it, rtwn tries to use m_defrag:


   1962 	error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m,
   1963 	    BUS_DMA_NOWAIT | BUS_DMA_WRITE);
   1964 	if (error && error != EFBIG) {
   1965 		aprint_error_dev(sc->sc_dev, "can't map mbuf (error %d)\n",
   1966 		    error);
   1967 		m_freem(m);
   1968 		return error;
   1969 	}
   1970 	if (error != 0) {
   1971 		/* Too many DMA segments, linearize mbuf. */
   1972 		struct mbuf *newm = m_defrag(m, M_DONTWAIT);
   1973 		if (newm == NULL) {
   1974 			aprint_error_dev(sc->sc_dev, "can't defrag mbuf\n");
   1975 			m_freem(m);
   1976 			return ENOBUFS;
   1977 		}
   1978 		m = newm;
   1979 
   1980 		error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, m,
   1981 		    BUS_DMA_NOWAIT | BUS_DMA_WRITE);

this won't work, because m_defrag doesn't guarantee the result is in one mbuf (it in fact guarantees a minimum of two).

>How-To-Repeat:
a way of testing it is using ping -s for various sizes. some will fail.
This is by code inspection, I don't have an rtwn.
>Fix:
replace m_defrag use by an API which can make a guarantee that the result fits in as many mbufs as we want (or fails).

a similar problem was fixed in:
https://mail-index.netbsd.org/source-changes/2018/09/01/msg098767.html

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.43 2018/01/16 07:36:43 maya Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2017 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.