title: Using DPDK Kernel NIC Interface in a virtualized environment
body: <p>I'm going to develop a <a href="http://www.dpdk.org/" rel="nofollow">DPDK</a> Linux application on a laptop, but the laptop's hardware is not supported by DPDK. Furtunately, DPDK <a href="http://www.dpdk.org/doc/nics" rel="nofollow">supports</a> paravirtualized devices including <a href="http://wiki.qemu.org/Main_Page" rel="nofollow">QEMU</a>'s <code>virtio-net</code>.</p>
  
  <p>So I'm trying to configure a QEMU guest for running the <a href="http://dpdk.org/doc/guides/sample_app_ug/kernel_nic_interface.html" rel="nofollow">Kernel NIC Interface(KNI)</a> on a <code>virtio-net-pci</code> device. The problem is that the KNI sample application doesn't accept the <code>virtio-net-pci</code> driver.</p>
  
  <p><strong>QEMU command</strong></p>
  
  <pre><code>exec qemu-system-x86_64 -enable-kvm \
    -cpu host -smp 2 \
    -vga std \
    -mem-prealloc -mem-path /dev/hugepages \
    -drive file=GentooVM.img,if=virtio \
    -netdev user,id=vmnic,hostname=gentoo \
    -device virtio-net-pci,netdev=vmnic \
    -m 1024M \
    -monitor stdio \
    -name "Gentoo VM"
  </code></pre>
  
  <p><strong>Running the KNI sample application in the guest</strong></p>
  
  <pre><code>sudo ./examples/kni/build/app/kni -c 0x3 -n 4 -- \
  -P -p 0x1 --config="(0,0,1)"
  
  EAL: Detected lcore 0 as core 0 on socket 0
  EAL: Detected lcore 1 as core 0 on socket 0
  EAL: Support maximum 128 logical core(s) by configuration.
  EAL: Detected 2 lcore(s)
  EAL: Probing VFIO support...
  EAL:   IOMMU type 1 (Type 1) is supported
  EAL:   IOMMU type 8 (No-IOMMU) is not supported
  EAL: VFIO support initialized
  EAL: Setting up physically contiguous memory...
  ...
  EAL: WARNING: cpu flags constant_tsc=yes nonstop_tsc=no -&gt; using
  unreliable clock cycles !
  EAL: Master lcore 0 is ready (tid=657d58c0;cpuset=[0])
  PMD: rte_igbvf_pmd_init():  &gt;&gt;
  EAL: lcore 1 is ready (tid=305ff700;cpuset=[1])
  EAL: PCI device 0000:00:03.0 on NUMA socket -1
  EAL:   probe driver: 1af4:1000 rte_virtio_pmd
  EAL:   Not managed by a supported kernel driver(0), skipped
  PMD: virtio_read_caps(): failed to map pci device!
  PMD: vtpci_init(): trying with legacy virtio pci.
  Segmentation fault
  </code></pre>
  
  <p><strong>Output of <code>lspci</code> command in the guest</strong></p>
  
  <pre><code>...
  00:03.0 Ethernet controller: Red Hat, Inc Virtio network device
  </code></pre>
  
  <p>I've noticed that <a href="http://dpdk.org/browse/dpdk/tree/lib/librte_eal/linuxapp/eal/eal_pci.c?id=v16.04#n256" rel="nofollow"><code>pci_scan_one()</code></a> function sets <code>dev-&gt;kdrv = RTE_KDRV_NONE</code>, while the driver is detected as <code>virtio-pci</code> (from <code>/sys/bus/pci/devices/0000:00:03.0/driver</code>).</p>
  
  <p><strong>TAP networking</strong></p>
  
  <p>The same issue persists with TAP networking. On the host, I've configured a bridge from Wi-Fi interface, and connected it to a TAP interface:</p>
  
  <pre class="lang-bash prettyprint-override"><code>wifi_iface=wlp3s0
  br_iface=br0
  br_network='172.20.0.1/16'
  br_dhcp_range='172.20.0.2,172.20.255.254'
  tap_iface=tap0
  user=ruslan
  
  ip link add name $br_iface type bridge
  ip addr add "$br_network" dev $br_iface
  ip link set $br_iface up
  dnsmasq --interface=$br_iface --bind-interfaces \
    --dhcp-range=$br_dhcp_range
  
  modprobe tun
  chmod 0666 /dev/net/tun
  
  ip tuntap add dev $tap_iface mode tap user "$user"
  ip link set $tap_iface up promisc on
  ip link set $tap_iface master $br_iface
  
  sysctl net.ipv4.ip_forward=1
  sysctl net.ipv6.conf.default.forwarding=1
  sysctl net.ipv6.conf.all.forwarding=1
  
  iptables -t nat -A POSTROUTING -o $wifi_iface -j MASQUERADE
  iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
  iptables -A FORWARD -i $tap_iface -o $wifi_iface -j ACCEPT
  </code></pre>
  
  <p>QEMU command:</p>
  
  <pre><code>sudo qemu-system-x86_64 -enable-kvm \
    -cpu host -smp 2 \
    -vga std \
    -mem-prealloc -mem-path /dev/hugepages \
    -drive file=GentooVM.img,if=virtio \
    -netdev tap,id=vm1_p1,ifname=tap0,script=no,downscript=no,vhost=on \
    -device virtio-net-pci,netdev=vm1_p1,bus=pci.0,addr=0x3,ioeventfd=on \
    -m 1024M \
    -monitor stdio \
    -name "Gentoo VM" \
    $@
  </code></pre>
  
  <p><code>ifconfig</code> output in the guest:</p>
  
  <pre><code>enp0s3: flags=4163&lt;UP,BROADCAST,RUNNING,MULTICAST&gt;  mtu 1500
          inet 172.20.196.253  netmask 255.255.0.0  broadcast 172.20.255.255
          inet6 fe80::59c1:f175:aeb3:433  prefixlen 64  scopeid 0x20&lt;link&gt;
          ether 52:54:00:12:34:56  txqueuelen 1000  (Ethernet)
          RX packets 9  bytes 1039 (1.0 KiB)
          RX errors 0  dropped 0  overruns 0  frame 0
          TX packets 21  bytes 1802 (1.7 KiB)
          TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
  </code></pre>
  
  <p>The following command fails the same way as in the case of "user" networking above:</p>
  
  <pre><code>sudo ./examples/kni/build/app/kni -c 0x3 -n 4 -- \
  -P -p 0x1 --config="(0,0,1)"
  ...
  EAL: PCI device 0000:00:03.0 on NUMA socket -1
  EAL:   probe driver: 1af4:1000 rte_virtio_pmd
  EAL:   Not managed by a supported kernel driver(0), skipped
  PMD: virtio_read_caps(): failed to map pci device!
  PMD: vtpci_init(): trying with legacy virtio pci.
  </code></pre>
  
  <p><strong>The question</strong></p>
  
  <p>Is it even possible to run <em>KNI</em> with <code>virtio-net-pci</code> device?</p>
  
  <p>If it's impossible, are there other options to develop a <em>DPDK KNI</em> application in a virtualized environment?</p>