Re: Virtio Devices Patch

Eric Shubert <[email protected]> Fri, 26 Apr 2013 11:57:21 -0700
Newsgroups gmane.comp.security.ipcop.devel
Organization Eric Shubert & Associates
Message-ID <[email protected]>
On 04/18/2013 11:42 PM, [email protected] wrote:
>
>
> ----- Mail original -----
>> De: "Eric Shubert" <[email protected]>
>> À: [email protected]
>> Envoyé: Jeudi 18 Avril 2013 22:29:03
>> Objet: [IPCop-devel] Virtio Devices Patch
>>
>> A fellow developer (Justin H) and I have successfully built the
>> latest
>> (7001) IPCop with support for Virtio (paravirtualized KVM) disk and
>> network devices. These drivers are part of the kernel, and provide
>> significant performance improvements for IPCop virtual hosts running
>> under Linux KVM.
>>
>> The svn diff patch file is attached. It's fairly simple. The code is
>> replicated and tailored from existing IPCop code, and existing code
>> is pretty much untouched.
>>
> Thank for the patch.
> I will care to integrate.
>
> Index: src/installer/partition.c
> ===================================================================
> --- src/installer/partition.c	(revision 7001)
> +++ src/installer/partition.c	(working copy)
> @@ -622,6 +622,8 @@
>       /* TODO be more specific which modules to include */
>       fprintf(handle, "ext3\njbd\n");
>       fprintf(handle, "ehci-hcd\nohci-hcd\nuhci-hcd\nhid\nusbhid\n");
> +    // include virtio so se can boot from a virtio disk.
> +    fprintf(handle, "virtio\nvirtio_pci\nvirtio_blk\n");
>
> Appart of the typo, maybe we could detect boot from KVM?
>
> http://www.dmo.ca/blog/detecting-virtualization-on-linux/
> say 'dmesg | grep -i virtual' detect for all virtualized cases.
>
> To be specific for KVM, I suppose this should do the trick.
> dmesg | grep -i 'paravirtualized kernel on KVM'
>
> Could you confirm?
>
> Gilles
>
> ------------------------------------------------------------------------------

Gilles,

That particular string doesn't work for me, but I found one ('virtual 
kernel memory layout') which tests out ok. I also included a similar 
test ('virtio-pci') when checking for the virtio_net device.

FWIW, I'm still seeing cpu utilization that I think is a little higher 
than it needs to be (8% or so when idling). I'll look into this when I 
get a chance to see if that can be reduced. It might take a newer kernel 
though.

Many thanks for including this in the stock IPCop, Gilles. I'm hoping it 
will make it in the 2.1 release.

(this time with patch attached)

-- 
-Eric 'shubes'

-- 
-Eric 'shubes'

------------------------------------------------------------------------------
Try New Relic Now & We'll Send You this Cool Shirt
New Relic is the only SaaS-based application performance monitoring service 
that delivers powerful full stack analytics. Optimize and monitor your
browser, app, & servers with just a few lines of code. Try New Relic
and get this awesome Nerd Life shirt! http://p.sf.net/sfu/newrelic_d2d_apr

_______________________________________________
IPCop-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ipcop-devel
ipcop-virtio-detect-r7001.patch (text/x-patch, 7.8 KB)
Index: lfs/initramfs
===================================================================
--- lfs/initramfs	(revision 7001)
+++ lfs/initramfs	(working copy)
@@ -255,6 +255,10 @@
 	# a few of them are not needed there as configuration is later than initramfs/install
 	rm -rf $(INITRAMFS_DIR)/lib/modules/$(KVER)/kernel/drivers/net/{bonding,bsd_comp.ko.gz,ppp*,tun.ko,usb,wireless}
 
+	# Copy the VIRTIO modules
+	cp -af /lib/modules/$(KVER)/kernel/drivers/virtio       $(INITRAMFS_DIR)/lib/modules/$(KVER)/kernel/drivers
+	cp -af /lib/modules/$(KVER)/kernel/drivers/block        $(INITRAMFS_DIR)/lib/modules/$(KVER)/kernel/drivers
+
 	# Copy some additional modules and remove those not required by nics and blocks drivers
 	cp -af /lib/modules/$(KVER)/kernel/lib 			$(INITRAMFS_DIR)/lib/modules/$(KVER)/kernel
 	rm -f $(INITRAMFS_DIR)/lib/modules/$(KVER)/kernel/lib/{crc-itu-t,ts_*}.ko.gz
Index: config/kernel/kernel.config.i486
===================================================================
--- config/kernel/kernel.config.i486	(revision 7001)
+++ config/kernel/kernel.config.i486	(working copy)
@@ -1,6 +1,6 @@
 #
 # Automatically generated make config: don't edit
-# Linux/i386 3.0-1 Kernel Configuration
+# Linux/i386 3.0.0 Kernel Configuration
 #
 # CONFIG_64BIT is not set
 CONFIG_X86_32=y
@@ -1001,6 +1001,7 @@
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
+CONFIG_VIRTIO_BLK=m
 # CONFIG_BLK_DEV_HD is not set
 # CONFIG_BLK_DEV_RBD is not set
 # CONFIG_SENSORS_LIS3LV02D is not set
@@ -1013,6 +1014,7 @@
 # CONFIG_TIFM_CORE is not set
 # CONFIG_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_CS5535_MFGPT is not set
 # CONFIG_HP_ILO is not set
 # CONFIG_APDS9802ALS is not set
 # CONFIG_ISL29003 is not set
@@ -1801,6 +1803,7 @@
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
+CONFIG_VIRTIO_NET=m
 # CONFIG_VMXNET3 is not set
 CONFIG_ISDN=y
 CONFIG_ISDN_I4L=m
@@ -2068,6 +2071,7 @@
 # CONFIG_SERIAL_XILINX_PS_UART is not set
 # CONFIG_PRINTER is not set
 CONFIG_PPDEV=m
+# CONFIG_VIRTIO_CONSOLE is not set
 CONFIG_IPMI_HANDLER=m
 CONFIG_IPMI_PANIC_EVENT=y
 # CONFIG_IPMI_PANIC_STRING is not set
@@ -2081,6 +2085,7 @@
 CONFIG_HW_RANDOM_AMD=m
 CONFIG_HW_RANDOM_GEODE=m
 CONFIG_HW_RANDOM_VIA=m
+# CONFIG_HW_RANDOM_VIRTIO is not set
 # CONFIG_NVRAM is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
@@ -3076,7 +3081,14 @@
 CONFIG_CRYPTO_DEV_HIFN_795X=m
 CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y
 CONFIG_HAVE_KVM=y
-# CONFIG_VIRTUALIZATION is not set
+CONFIG_VIRTUALIZATION=y
+# CONFIG_KVM is not set
+# CONFIG_VHOST_NET is not set
+# CONFIG_LGUEST is not set
+CONFIG_VIRTIO=m
+CONFIG_VIRTIO_RING=m
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_BALLOON=m
 # CONFIG_BINARY_PRINTF is not set
 
 #
Index: src/installer/partition.c
===================================================================
--- src/installer/partition.c	(revision 7001)
+++ src/installer/partition.c	(working copy)
@@ -622,6 +622,9 @@
     /* TODO be more specific which modules to include */
     fprintf(handle, "ext3\njbd\n");
     fprintf(handle, "ehci-hcd\nohci-hcd\nuhci-hcd\nhid\nusbhid\n");
+    // include virtio so we can boot from a virtio disk.
+    if (system("dmesg | grep -qi 'virtual kernel memory layout'") == 0)
+        fprintf(handle, "virtio\nvirtio_pci\nvirtio_blk\n");
 
     //add each module to module-list
     for (i = 0; i < numhardwares; i++) {
Index: src/installer/networking.c
===================================================================
--- src/installer/networking.c	(revision 7001)
+++ src/installer/networking.c	(working copy)
@@ -327,6 +327,15 @@
                 }
 
                 /* Check for Vendor / Device ID first */
+                    /* shubes: WARNING - virtio network devices point to the subsystem_deviceid
+                       value when retrieving them from the /sys/class/net/<device> branch.
+                       This is due to the way that symlinks are set up for virtio_net devices.
+                       I don't know why that is. I believe it's a bug.
+                       I'll investigate further and file a bug report appropriately.
+                       In the meanwhile, the upshot is that the checks below will not match,
+                       as we store the primary deviceid (0x1000), not the subsystem_deviceid (0x0001)
+                       for virtio_net devices (vendor 0x1af4).
+                    */
                 getkernelmodule(device);
                 if ((strlen(vendorid_buffer) > 0) && (strlen(deviceid_buffer) > 0)) {
                     for (n = 0; !found && (n < numnetwork); n++) {
Index: src/installer/hardware.c
===================================================================
--- src/installer/hardware.c	(revision 7001)
+++ src/installer/hardware.c	(working copy)
@@ -315,6 +315,35 @@
         fclose(f);
     }
 
+
+    /* Look for VIRTIO devices */
+    for (deviceletter = 'a'; deviceletter <= 'z'; deviceletter++) {
+
+        char device[4];
+        sprintf(device, "vd%c", deviceletter);
+        snprintf(model, STRING_SIZE, "Virtio disk");
+        char description[STRING_SIZE] = "Unknown";
+
+        unsigned long drivesize;
+        snprintf(procname, STRING_SIZE, "/sys/block/%s/size", device);
+        drivesize = getdrivesize(procname, strsize);
+        if (drivesize > 0) {
+            snprintf(description, STRING_SIZE, "%-30.30s (%s)", model, strsize);
+            if (drivesize < 32) {
+                /* Discard if too small for installation and too small as target drive */
+                snprintf(logline, STRING_SIZE, "   discard vd%c %-30.30s (%s)\n", deviceletter, model, strsize);
+                fprintf(flog, "%s", logline);
+                fprintf(fhwdetect, "%s", logline);
+            }
+            else if (drivesize < DISK_MINIMUM)
+                /* Too small as target drive but could be installation USB stick */
+                hardwareadd(cdrom, NULL, device, NULL, description, 0, 0);
+            else
+                hardwareadd(harddisk, NULL, device, NULL, description, 0, 0);
+        }
+    }
+
+
     /* Look for SCSI, SATA, USB cdrom */
     for (deviceletter = '0'; deviceletter <= '9'; deviceletter++) {
         snprintf(procname, STRING_SIZE, "/sys/block/sr%c/device/model", deviceletter);
@@ -524,11 +553,25 @@
                 }
             }
             else {
-                /* There is little to add if there is no module */
-                snprintf(logline, STRING_SIZE, "  Skip (no module) %04x %04x:%04x\n",
-                        pcidev->device_class, pcidev->vendor_id, pcidev->device_id);
-                fprintf(flog, "%s", logline);
-                fprintf(fhwdetect, "%s", logline);
+                if ((type == network) && (pcidev->vendor_id == 0x1af4)
+                                      && (pcidev->device_id == 0x1000)
+                    && (system("dmesg | grep -qi 'virtio-pci'") == 0)) {
+                    /* virtio_net device */
+                    snprintf(logline, STRING_SIZE, "  Add  %04x %04x:%04x, %s\n",
+                            pcidev->device_class, pcidev->vendor_id, pcidev->device_id, description);
+                    fprintf(flog, "%s", logline);
+                    fprintf(fhwdetect, "%s", logline);
+
+                    module = "virtio_net";
+                    hardwareadd(type, module, NULL, NULL, description, pcidev->vendor_id, pcidev->device_id);
+                }
+                else {
+                    /* There is little to add if there is no module */
+                    snprintf(logline, STRING_SIZE, "  Skip (no module) %04x %04x:%04x\n",
+                             pcidev->device_class, pcidev->vendor_id, pcidev->device_id);
+                    fprintf(flog, "%s", logline);
+                    fprintf(fhwdetect, "%s", logline);
+                }
             }
         }