[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Libvir] [PATCH] Allow selection of the NIC model in QEMU/KVM



This patch allows selection of the NIC model for QEMU/KVM domains.
The selection is done by adding a <model/> element to the XML, as in
this example:

    <interface type='user'>
      <mac address='00:16:3e:33:b8:d3'/>
      <model type='ne2k_pci'/>
    </interface>

The model type string is only checked to make sure it's a short
alpha-numeric + underscore, since it seems impractical to extract the
actual list of supported models.

If you choose a supported model then QEMU starts up with this extra
-nic parameter:

  /usr/bin/qemu-kvm -M pc -m 500 -smp 1 -monitor pty \
    -boot c -hda /var/lib/xen/images/rhel51x32kvm.img \
    -net nic,macaddr=00:16:3e:33:b8:d3,vlan=0,model=ne2k_pci -net user,vlan=0 \
    -usb -vnc 127.0.0.1:0

If you choose a non-existant model then you get the error:

  libvir: QEMU error : internal error QEMU quit during monitor startup

Rich.

-- 
Richard Jones, Emerging Technologies, Red Hat  http://et.redhat.com/~rjones
virt-top is 'top' for virtual machines.  Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://et.redhat.com/~rjones/virt-top
Index: docs/libvir.html
===================================================================
RCS file: /data/cvs/libvirt/docs/libvir.html,v
retrieving revision 1.114
diff -u -r1.114 libvir.html
--- docs/libvir.html	7 Apr 2008 10:54:40 -0000	1.114
+++ docs/libvir.html	8 Apr 2008 12:57:20 -0000
@@ -1096,6 +1096,14 @@
   &lt;mac address="11:22:33:44:55:66"/&gt;
 &lt;/interface&gt;
     </pre>
+    <pre>
+&lt;interface type='user'&gt;
+  &lt;mac address="11:22:33:44:55:66"/&gt;
+  &lt;model type="ne2k_pci"/&gt;
+&lt;/interface&gt;
+    </pre>
+    <p>(where the network card model is one of those supported by
+      QEMU or KVM - see the relevant manual pages).</p>
   </li>
   <li>Virtual network
     <p>Provides a virtual network using a bridge device in the host.
Index: src/qemu_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_conf.c,v
retrieving revision 1.46
diff -u -r1.46 qemu_conf.c
--- src/qemu_conf.c	28 Mar 2008 20:38:21 -0000	1.46
+++ src/qemu_conf.c	8 Apr 2008 12:57:23 -0000
@@ -706,6 +706,7 @@
     xmlChar *script = NULL;
     xmlChar *address = NULL;
     xmlChar *port = NULL;
+    xmlChar *model = NULL;
 
     net->type = QEMUD_NET_USER;
 
@@ -767,6 +768,8 @@
                        (net->type == QEMUD_NET_ETHERNET) &&
                        xmlStrEqual(cur->name, BAD_CAST "script")) {
                 script = xmlGetProp(cur, BAD_CAST "path");
+            } else if (xmlStrEqual (cur->name, BAD_CAST "model")) {
+                model = xmlGetProp (cur, BAD_CAST "type");
             }
         }
         cur = cur->next;
@@ -926,6 +929,38 @@
         xmlFree(address);
     }
 
+    /* NIC model (see -net nic,model=?).  We only check that it looks
+     * reasonable, not that it is a supported NIC type.  FWIW kvm
+     * supports these types as of April 2008:
+     * i82551 i82557b i82559er ne2k_pci pcnet rtl8139 e1000 virtio
+     */
+    if (model != NULL) {
+        int i, len, char_ok;
+
+        len = xmlStrlen (model);
+        if (len >= QEMUD_MODEL_MAX_LEN) {
+            qemudReportError (conn, NULL, NULL, VIR_ERR_INVALID_ARG,
+                              _("Model name '%s' is too long"), model);
+            goto error;
+        }
+        for (i = 0; i < len; ++i) {
+            char_ok =
+                (model[i] >= '0' && model[i] <= '9') ||
+                (model[i] >= 'a' && model[i] <= 'z') ||
+                (model[i] >= 'A' && model[i] <= 'Z') || model[i] == '_';
+            if (!char_ok) {
+                qemudReportError (conn, NULL, NULL, VIR_ERR_INVALID_ARG,
+                                  _("Model name contains invalid characters"));
+                goto error;
+            }
+        }
+        strncpy (net->model, BAD_CAST model, len);
+        net->model[len] = '\0';
+
+        xmlFree (model);
+    } else
+        net->model[0] = '\0';
+
     return 0;
 
  error:
@@ -941,6 +976,8 @@
         xmlFree(script);
     if (bridge)
         xmlFree(bridge);
+    if (model)
+        xmlFree(model);
     return -1;
 }
 
@@ -1829,13 +1866,22 @@
     } else {
         int vlan = 0;
         while (net) {
+            char model[100];
             char nic[100];
 
-            if (snprintf(nic, sizeof(nic), "nic,macaddr=%02x:%02x:%02x:%02x:%02x:%02x,vlan=%d",
+            if (net->model[0] != '\0') {
+                if (snprintf (model, sizeof (model), ",model=%s", net->model)
+                    >= sizeof (model))
+                    goto error;
+            } else
+                model[0] = '\0';
+
+            if (snprintf(nic, sizeof(nic),
+                         "nic,macaddr=%02x:%02x:%02x:%02x:%02x:%02x,vlan=%d%s",
                          net->mac[0], net->mac[1],
                          net->mac[2], net->mac[3],
                          net->mac[4], net->mac[5],
-                         vlan) >= sizeof(nic))
+                         vlan, model) >= sizeof(nic))
                 goto error;
 
             if (!((*argv)[++n] = strdup("-net")))
Index: src/qemu_conf.h
===================================================================
RCS file: /data/cvs/libvirt/src/qemu_conf.h,v
retrieving revision 1.21
diff -u -r1.21 qemu_conf.h
--- src/qemu_conf.h	28 Mar 2008 20:38:21 -0000	1.21
+++ src/qemu_conf.h	8 Apr 2008 12:57:23 -0000
@@ -68,6 +68,7 @@
 };
 
 #define QEMUD_MAC_ADDRESS_LEN 6
+#define QEMUD_MODEL_MAX_LEN 10
 #define QEMUD_OS_TYPE_MAX_LEN 10
 #define QEMUD_OS_ARCH_MAX_LEN 10
 #define QEMUD_OS_MACHINE_MAX_LEN 10
@@ -97,6 +98,7 @@
 struct qemud_vm_net_def {
     int type;
     unsigned char mac[QEMUD_MAC_ADDRESS_LEN];
+    char model[QEMUD_MODEL_MAX_LEN];
     union {
         struct {
             char ifname[BR_IFNAME_MAXLEN];

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]