我已經包含在這兩個問題的修補源代碼 的希望將被更新,而其他人將不必找到這些問題。
首先virtio_netmap_3.10.60.patch:
# patch is the whole netmap virtio driver patch for 3.10.60 (from
# kernel.org), and it applies correctly.
#
Index: linux-3.10.60/drivers/net/virtio_net.c
===================================================================
--- linux-3.10.60.orig/drivers/net/virtio_net.c 2014-11-14 11:48:23.000000000 -0500
+++ linux-3.10.60/drivers/net/virtio_net.c 2014-11-21 12:54:29.751760095 -0500
@@ -131,6 +131,10 @@
struct notifier_block nb;
};
+#if defined(CONFIG_NETMAP) || defined(CONFIG_NETMAP_MODULE)
+#include <virtio_netmap.h>
+#endif
+
struct skb_vnet_hdr {
union {
struct virtio_net_hdr hdr;
@@ -210,6 +214,10 @@
/* Suppress further interrupts. */
virtqueue_disable_cb(vq);
+#ifdef DEV_NETMAP
+ if (netmap_tx_irq(vi->dev, vq2txq(vq)))
+ return;
+#endif
/* We were probably waiting for more output buffers. */
netif_wake_subqueue(vi->dev, vq2txq(vq));
}
@@ -646,7 +654,16 @@
struct virtnet_info *vi = rq->vq->vdev->priv;
void *buf;
unsigned int r, len, received = 0;
+#ifdef DEV_NETMAP
+ int work_done = 0;
+
+ if (netmap_rx_irq(vi->dev, vq2rxq(rq->vq), &work_done)) {
+ napi_complete(napi);
+ ND("called netmap_rx_irq");
+ return 1;
+ }
+#endif
again:
while (received < budget &&
(buf = virtqueue_get_buf(rq->vq, &len)) != NULL) {
@@ -679,6 +696,16 @@
{
struct virtnet_info *vi = netdev_priv(dev);
int i;
+#ifdef DEV_NETMAP
+ int ok = virtio_netmap_init_buffers(vi);
+
+ netmap_enable_all_rings(dev);
+ if (ok) {
+ for (i = 0; i < vi->max_queue_pairs; i++)
+ virtnet_napi_enable(&vi->rq[i]);
+ return 0;
+ }
+#endif
for (i = 0; i < vi->max_queue_pairs; i++) {
if (i < vi->curr_queue_pairs)
@@ -972,6 +999,9 @@
struct virtnet_info *vi = netdev_priv(dev);
int i;
+#ifdef DEV_NETMAP
+ netmap_disable_all_rings(dev);
+#endif
/* Make sure refill_work doesn't re-enable napi! */
cancel_delayed_work_sync(&vi->refill);
@@ -1644,6 +1674,10 @@
goto free_recv_bufs;
}
+#ifdef DEV_NETMAP
+ virtio_netmap_attach(vi);
+#endif
+
/* Assume link up if device can't report link status,
otherwise get link status from config. */
if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) {
@@ -1690,6 +1724,9 @@
{
struct virtnet_info *vi = vdev->priv;
+#ifdef DEV_NETMAP
+ netmap_detach(vi->dev);
+#endif
unregister_hotcpu_notifier(&vi->nb);
/* Prevent config work handler from accessing the device. */
接下來是virtio_netmap.patch
# There is a problem with the initialization, and during read packet with
# control of the indices .
#
# This problem is easily seen by building a KVM netmap/virtio_net driver, and
# simply pinging it (host pings KVM guest). All goes well, until ring buffer
# reaches index 255, and no packet is actually received. This will fix that
# problem and resulted in a working driver.
#
Index: b/LINUX/virtio_netmap.h
===================================================================
--- a/LINUX/virtio_netmap.h 2014-11-21 16:26:03.951278021 -0500
+++ b/LINUX/virtio_netmap.h 2014-11-21 16:26:25.451386665 -0500
@@ -398,8 +398,8 @@
* Second part: skip past packets that userspace has released.
*/
nm_i = kring->nr_hwcur; /* netmap ring index */
- if (nm_i != head) {
- for (n = 0; nm_i != head; n++) {
+ if (nm_next(nm_i, lim) != head) {
+ for (n = 0; nm_next(nm_i, lim) != head; n++) {
struct netmap_slot *slot = &ring->slot[nm_i];
void *addr = NMB(slot);
int err;
@@ -421,7 +421,7 @@
virtqueue_kick(vq);
nm_i = nm_next(nm_i, lim);
}
- kring->nr_hwcur = head;
+ kring->nr_hwcur = nm_i;
}
/* We have finished processing used RX buffers, so we have to tell
@@ -454,6 +454,7 @@
for (r = 0; r < na->num_rx_rings; r++) {
COMPAT_DECL_SG
struct netmap_ring *ring = na->rx_rings[r].ring;
+ struct netmap_kring *kring = &na->rx_rings[r];
struct virtqueue *vq = GET_RX_VQ(vi, r);
struct scatterlist *sg = GET_RX_SG(vi, r);
struct netmap_slot* slot;
@@ -485,6 +486,7 @@
if (VQ_FULL(vq, err))
break;
}
+ kring->nr_hwcur = i;
D("added %d inbufs on queue %d", i, r);
virtqueue_kick(vq);
}
不幸的是,提議的補丁違反NETMAP內部API。該問題已在上游解決,請參閱https://github.com/luigirizzo/netmap/issues/365。 – user3484681 2017-09-18 01:38:33