Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F108592656
D38065.id115156.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D38065.id115156.diff
View Options
diff --git a/sys/dev/netmap/netmap_freebsd.c b/sys/dev/netmap/netmap_freebsd.c
--- a/sys/dev/netmap/netmap_freebsd.c
+++ b/sys/dev/netmap/netmap_freebsd.c
@@ -405,15 +405,20 @@
* addr and len identify the netmap buffer, m is the (preallocated)
* mbuf to use for transmissions.
*
- * We should add a reference to the mbuf so the m_freem() at the end
- * of the transmission does not consume resources.
+ * Zero-copy transmission is possible if netmap is attached directly to a
+ * hardware interface: when cleaning we simply wait for the mbuf cluster
+ * refcount to decrement to 1, indicating that the driver has completed
+ * transmission and is done with the buffer. However, this approach can
+ * lead to queue deadlocks when attaching to software interfaces (e.g.,
+ * if_bridge) since we cannot rely on member ports to promptly reclaim
+ * transmitted mbufs. Since there is no easy way to distinguish these
+ * cases, we currently always copy the buffer.
*
- * On FreeBSD, and on multiqueue cards, we can force the queue using
+ * On multiqueue cards, we can force the queue using
* if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE)
* i = m->m_pkthdr.flowid % adapter->num_queues;
* else
* i = curcpu % adapter->num_queues;
- *
*/
int
nm_os_generic_xmit_frame(struct nm_os_gen_arg *a)
@@ -423,16 +428,18 @@
struct ifnet *ifp = a->ifp;
struct mbuf *m = a->m;
- /* Link the external storage to
- * the netmap buffer, so that no copy is necessary. */
- m->m_ext.ext_buf = m->m_data = a->addr;
- m->m_ext.ext_size = len;
+ if (MBUF_REFCNT(m) != 1) {
+ nm_prerr("invalid refcnt %d for %p", MBUF_REFCNT(m), m);
+ panic("in generic_xmit_frame");
+ }
+ if (unlikely(m->m_ext.ext_size < len)) {
+ nm_prlim(2, "size %d < len %d", m->m_ext.ext_size, len);
+ len = m->m_ext.ext_size;
+ }
+ memcpy(m->m_data, a->addr, len);
m->m_flags |= M_PKTHDR;
m->m_len = m->m_pkthdr.len = len;
-
- /* mbuf refcnt is not contended, no need to use atomic
- * (a memory barrier is enough). */
SET_MBUF_REFCNT(m, 2);
M_HASHTYPE_SET(m, M_HASHTYPE_OPAQUE);
m->m_pkthdr.flowid = a->ring_nr;
@@ -443,7 +450,6 @@
return ret ? -1 : 0;
}
-
struct netmap_adapter *
netmap_getna(if_t ifp)
{
diff --git a/sys/dev/netmap/netmap_generic.c b/sys/dev/netmap/netmap_generic.c
--- a/sys/dev/netmap/netmap_generic.c
+++ b/sys/dev/netmap/netmap_generic.c
@@ -537,10 +537,12 @@
}
/* The event has been consumed, we can go
* ahead. */
-
} else if (MBUF_REFCNT(m) != 1) {
- /* This mbuf is still busy: its refcnt is 2. */
- break;
+ /* This mbuf has been submitted but is still busy
+ * (refcount is 2).
+ * Leave it to the driver and replenish. */
+ m_freem(m);
+ tx_pool[nm_i] = NULL;
}
}
@@ -631,10 +633,8 @@
/* Decrement the refcount. This will free it if we lose the race
* with the driver. */
m_freem(m);
- smp_mb();
}
-
/*
* generic_netmap_txsync() transforms netmap buffers into mbufs
* and passes them to the standard device driver
@@ -698,7 +698,7 @@
/* Tale a mbuf from the tx pool (replenishing the pool
* entry if necessary) and copy in the user packet. */
m = kring->tx_pool[nm_i];
- if (unlikely(m == NULL)) {
+ if (m == NULL) {
kring->tx_pool[nm_i] = m =
nm_os_get_mbuf(ifp, NETMAP_BUF_SIZE(na));
if (m == NULL) {
diff --git a/sys/dev/netmap/netmap_kern.h b/sys/dev/netmap/netmap_kern.h
--- a/sys/dev/netmap/netmap_kern.h
+++ b/sys/dev/netmap/netmap_kern.h
@@ -2394,7 +2394,7 @@
* has a KASSERT(), checking that the mbuf dtor function is not NULL.
*/
-static void void_mbuf_dtor(struct mbuf *m) { }
+static inline void void_mbuf_dtor(struct mbuf *m) { }
#define SET_MBUF_DESTRUCTOR(m, fn) do { \
(m)->m_ext.ext_free = (fn != NULL) ? \
@@ -2402,22 +2402,9 @@
} while (0)
static inline struct mbuf *
-nm_os_get_mbuf(struct ifnet *ifp, int len)
+nm_os_get_mbuf(struct ifnet *ifp __unused, int len)
{
- struct mbuf *m;
-
- (void)ifp;
- (void)len;
-
- m = m_gethdr(M_NOWAIT, MT_DATA);
- if (m == NULL) {
- return m;
- }
-
- m_extadd(m, NULL /* buf */, 0 /* size */, void_mbuf_dtor,
- NULL, NULL, 0, EXT_NET_DRV);
-
- return m;
+ return (m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, len));
}
#endif /* __FreeBSD__ */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Jan 27, 6:02 PM (5 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16202683
Default Alt Text
D38065.id115156.diff (4 KB)
Attached To
Mode
D38065: netmap: Fix queue stalls on generic interfaces
Attached
Detach File
Event Timeline
Log In to Comment