2014-11-21 93 views
2

netmap/virtio_net驅動程序不起作用(Linux 3.10內核)。有兩個問題。對於Linux 3.10,我需要做些什麼改變才能使netmap/virtio_net工作?

在kernel.org的3.10.60內核上,virtio_net.c的補丁沒有工作,修補程序的一部分被拒絕了。這很容易修復。

更嚴重的是,virtio初始化代碼不起作用,也沒有 做的數據包接收代碼。基本問題是未能正確初始化 指數,並且未能保持 頭部/尾部指數之間的1時隙間隔。 (同樣的問題代碼中的2個位置。)

通過創建帶有 netmap/virtio_net驅動程序的KVM來賓並簡單地從主機ping來賓,可以很容易地看到此問題。 使用客人的 上的pkt-gen工具可以輕鬆監控接收流量。

第255坪將正常工作,當指數打255,那麼 數據包接收失敗,並會繼續每一次失敗的插槽255

回答

1

我已經包含在這兩個問題的修補源代碼 的希望將被更新,而其他人將不必找到這些問題。

首先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); 
     } 
+0

不幸的是,提議的補丁違反NETMAP內部API。該問題已在上游解決,請參閱https://github.com/luigirizzo/netmap/issues/365。 – user3484681 2017-09-18 01:38:33

相關問題