NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/53566: rtwn's use of m_defrag can't work



>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



Home | Main Index | Thread Index | Old Index