Skip to content

Commit dfe8153

Browse files
committed
generic: reset mbuf destructor on unregif
This prevents from crashes that happen when mbufs are lazily consumed by drivers. In this case mbuf destructors (which call into netmap) could be invoked when netmap data structures (or netmap module) were gone.
1 parent 0afebf4 commit dfe8153

2 files changed

Lines changed: 19 additions & 6 deletions

File tree

LINUX/bsd_glue.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ struct thread;
199199
*/
200200
#define MBUF_TXQ(m) skb_get_queue_mapping(m)
201201
#define MBUF_RXQ(m) (skb_rx_queue_recorded(m) ? skb_get_rx_queue(m) : 0)
202-
#define SET_MBUF_DESTRUCTOR(m, f) m->destructor = (void *)&f
202+
#define SET_MBUF_DESTRUCTOR(m, f) m->destructor = (void *)f
203203

204204
/* Magic number for sk_buff.priority field, used to take decisions in
205205
* generic_ndo_start_xmit(), linux_generic_rx_handler() and

sys/dev/netmap/netmap_generic.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -359,21 +359,22 @@ generic_netmap_register(struct netmap_adapter *na, int enable)
359359
} else if (na->tx_rings[0].tx_pool) {
360360
/* Disable netmap mode. We enter here only if the previous
361361
generic_netmap_register(na, 1) was successfull.
362-
If it was not, na->tx_rings[0].tx_pool was set to NULL by the
363-
error handling code below. */
362+
If it was not, na->tx_rings[0].tx_pool was set to NULL
363+
by the error handling code below. */
364364
rtnl_lock();
365365

366366
na->na_flags &= ~NAF_NETMAP_ON;
367367

368368
/* Release packet steering control. */
369369
nm_os_catch_tx(gna, 0);
370370

371-
/* Do not intercept packets on the rx path. */
371+
/* Stop intercepting packets on the RX path. */
372372
nm_os_catch_rx(gna, 0);
373373

374374
rtnl_unlock();
375375

376-
/* Free the mbufs going to the netmap rings */
376+
/* Free the mbufs still pending in the RX queues, that
377+
* did not end up into the corresponding netmap RX rings. */
377378
for (r=0; r<na->num_rx_rings; r++) {
378379
mbq_safe_purge(&na->rx_rings[r].rx_queue);
379380
mbq_safe_fini(&na->rx_rings[r].rx_queue);
@@ -383,9 +384,21 @@ generic_netmap_register(struct netmap_adapter *na, int enable)
383384
nm_os_mitigation_cleanup(&gna->mit[r]);
384385
free(gna->mit, M_DEVBUF);
385386

387+
/* Decrement reference counter for the mbufs in the
388+
* TX pools. These mbufs can be still pending in drivers,
389+
* (e.g. this happens with virtio-net driver, which
390+
* does lazy reclaiming of transmitted mbufs).
391+
* Therefore it is necessary to remove the
392+
* destructor (which invokes netmap code), since the
393+
* the netmap module may disappear before pending mbufs
394+
* are consumed. */
386395
for (r=0; r<na->num_tx_rings; r++) {
387396
for (i=0; i<na->num_tx_desc; i++) {
388-
m_freem(na->tx_rings[r].tx_pool[i]);
397+
m = na->tx_rings[r].tx_pool[i];
398+
if (m) {
399+
SET_MBUF_DESTRUCTOR(m, NULL);
400+
m_freem(m);
401+
}
389402
}
390403
free(na->tx_rings[r].tx_pool, M_DEVBUF);
391404
}

0 commit comments

Comments
 (0)