]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
conf: parser/formatter/rng for <forward mode='hostdev'>
authorShradha Shah <sshah@solarflare.com>
Thu, 16 Aug 2012 15:41:41 +0000 (16:41 +0100)
committerLaine Stump <laine@laine.org>
Fri, 17 Aug 2012 19:43:26 +0000 (15:43 -0400)
This patch introduces the new forward mode='hostdev' along with
attribute managed. Includes updates to the network RNG and new xml
parser/formatter code.

Signed-off-by: Shradha Shah <sshah@solarflare.com>
13 files changed:
docs/schemas/basictypes.rng
docs/schemas/domaincommon.rng
docs/schemas/network.rng
src/conf/network_conf.c
src/conf/network_conf.h
src/esx/esx_network_driver.c
src/network/bridge_driver.c
tests/networkxml2xmlin/hostdev-pf.xml [new file with mode: 0644]
tests/networkxml2xmlin/hostdev.xml [new file with mode: 0644]
tests/networkxml2xmlin/passthrough-pf.xml
tests/networkxml2xmlout/hostdev-pf.xml [new file with mode: 0644]
tests/networkxml2xmlout/hostdev.xml [new file with mode: 0644]
tests/networkxml2xmltest.c

index 9dbda4a6cc77d4bd571a1efbb6a8c0eff8264059..766f9a08f5673c5f75ed68846626aec7733c5694 100644 (file)
     </choice>
   </define>
 
+  <define name="pciaddress">
+    <optional>
+      <attribute name="domain">
+        <ref name="pciDomain"/>
+      </attribute>
+    </optional>
+    <attribute name="bus">
+      <ref name="pciBus"/>
+    </attribute>
+    <attribute name="slot">
+      <ref name="pciSlot"/>
+    </attribute>
+    <attribute name="function">
+      <ref name="pciFunc"/>
+    </attribute>
+    <optional>
+      <attribute name="multifunction">
+        <choice>
+          <value>on</value>
+          <value>off</value>
+        </choice>
+      </attribute>
+    </optional>
+  </define>
+
   <!-- a 6 byte MAC address in ASCII-hex format, eg "12:34:56:78:9A:BC" -->
   <!-- The lowest bit of the 1st byte is the "multicast" bit. a         -->
   <!-- uniMacAddr requires that bit to be 0, and a multiMacAddr         -->
     <ref name='unsignedLong'/>
   </define>
 
+  <define name="pciDomain">
+    <data type="string">
+      <param name="pattern">(0x)?[0-9a-fA-F]{1,4}</param>
+    </data>
+  </define>
+  <define name="pciBus">
+    <data type="string">
+      <param name="pattern">(0x)?[0-9a-fA-F]{1,2}</param>
+    </data>
+  </define>
+  <define name="pciSlot">
+    <data type="string">
+      <param name="pattern">(0x)?[0-1]?[0-9a-fA-F]</param>
+    </data>
+  </define>
+  <define name="pciFunc">
+    <data type="string">
+      <param name="pattern">(0x)?[0-7]</param>
+    </data>
+  </define>
+
 </grammar>
index 4903ca69e34c4fe1866cbf6d23881af36ccd0d76..35e9f825650de679b8695e023d2a48d49ca45745 100644 (file)
       </attribute>
     </optional>
   </define>
-  <define name="pciaddress">
-    <optional>
-      <attribute name="domain">
-        <ref name="pciDomain"/>
-      </attribute>
-    </optional>
-    <attribute name="bus">
-      <ref name="pciBus"/>
-    </attribute>
-    <attribute name="slot">
-      <ref name="pciSlot"/>
-    </attribute>
-    <attribute name="function">
-      <ref name="pciFunc"/>
-    </attribute>
-    <optional>
-      <attribute name="multifunction">
-        <choice>
-          <value>on</value>
-          <value>off</value>
-        </choice>
-      </attribute>
-    </optional>
-  </define>
   <define name="driveaddress">
     <optional>
       <attribute name="controller">
       <param name="pattern">((0x)?[0-9a-fA-F]{1,3}\.){0,3}(0x)?[0-9a-fA-F]{1,3}</param>
     </data>
   </define>
-  <define name="pciDomain">
-    <data type="string">
-      <param name="pattern">(0x)?[0-9a-fA-F]{1,4}</param>
-    </data>
-  </define>
-  <define name="pciBus">
-    <data type="string">
-      <param name="pattern">(0x)?[0-9a-fA-F]{1,2}</param>
-    </data>
-  </define>
-  <define name="pciSlot">
-    <data type="string">
-      <param name="pattern">(0x)?[0-1]?[0-9a-fA-F]</param>
-    </data>
-  </define>
-  <define name="pciFunc">
-    <data type="string">
-      <param name="pattern">(0x)?[0-7]</param>
-    </data>
-  </define>
   <define name="driveController">
     <data type="string">
       <param name="pattern">[0-9]{1,2}</param>
index e55105a144fbf53d5d6528596967597ab5d640d8..4abfd915dd719842041fdc1d0b241bda7f4f3cca 100644 (file)
                   <value>passthrough</value>
                   <value>private</value>
                   <value>vepa</value>
+                  <value>hostdev</value>
+                </choice>
+              </attribute>
+            </optional>
+
+            <optional>
+              <attribute name="managed">
+                <choice>
+                  <value>yes</value>
+                  <value>no</value>
                 </choice>
               </attribute>
             </optional>
             <interleave>
-              <zeroOrMore>
-                <element name='interface'>
-                  <attribute name='dev'>
-                    <ref name='deviceName'/>
-                  </attribute>
-                  <optional>
-                    <attribute name="connections">
-                      <data type="unsignedInt"/>
-                    </attribute>
-                  </optional>
-                </element>
-              </zeroOrMore>
+              <choice>
+                <group>
+                  <zeroOrMore>
+                    <element name='interface'>
+                      <attribute name='dev'>
+                        <ref name='deviceName'/>
+                      </attribute>
+                      <optional>
+                        <attribute name="connections">
+                          <data type="unsignedInt"/>
+                        </attribute>
+                      </optional>
+                    </element>
+                  </zeroOrMore>
+                </group>
+                <group>
+                  <zeroOrMore>
+                    <element name='address'>
+                      <attribute name='type'>
+                        <value>pci</value>
+                      </attribute>
+                      <ref name="pciaddress"/>
+                      <optional>
+                        <attribute name="connections">
+                          <data type="unsignedInt"/>
+                        </attribute>
+                      </optional>
+                    </element>
+                  </zeroOrMore>
+                </group>
+              </choice>
               <optional>
                 <element name='pf'>
                   <attribute name='dev'>
index db8c62f4ee10898f93a0b629652cf385404156d0..9d53d8e76f8206c8dac623f191d7dfd712507030 100644 (file)
 
 VIR_ENUM_IMPL(virNetworkForward,
               VIR_NETWORK_FORWARD_LAST,
-              "none", "nat", "route", "bridge", "private", "vepa", "passthrough" )
+              "none", "nat", "route", "bridge", "private", "vepa", "passthrough", "hostdev")
+
+VIR_ENUM_DECL(virNetworkForwardHostdevDevice)
+VIR_ENUM_IMPL(virNetworkForwardHostdevDevice,
+              VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_LAST,
+              "none", "pci", "netdev")
 
 virNetworkObjPtr virNetworkFindByUUID(const virNetworkObjListPtr nets,
                                       const unsigned char *uuid)
@@ -96,7 +101,8 @@ virPortGroupDefClear(virPortGroupDefPtr def)
 static void
 virNetworkForwardIfDefClear(virNetworkForwardIfDefPtr def)
 {
-    VIR_FREE(def->dev);
+    if (def->type == VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV)
+        VIR_FREE(def->device.dev);
 }
 
 static void
@@ -943,11 +949,14 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
     xmlNodePtr *portGroupNodes = NULL;
     xmlNodePtr *forwardIfNodes = NULL;
     xmlNodePtr *forwardPfNodes = NULL;
+    xmlNodePtr *forwardAddrNodes = NULL;
     xmlNodePtr dnsNode = NULL;
     xmlNodePtr virtPortNode = NULL;
     xmlNodePtr forwardNode = NULL;
-    int nIps, nPortGroups, nForwardIfs, nForwardPfs;
+    int nIps, nPortGroups, nForwardIfs, nForwardPfs, nForwardAddrs;
     char *forwardDev = NULL;
+    char *forwardManaged = NULL;
+    char *type = NULL;
     xmlNodePtr save = ctxt->node;
     xmlNodePtr bandwidthNode = NULL;
     xmlNodePtr vlanNode;
@@ -1100,17 +1109,35 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
         }
 
         forwardDev = virXPathString("string(./@dev)", ctxt);
+        forwardManaged = virXPathString("string(./@managed)", ctxt);
+        if(forwardManaged != NULL) {
+            if (STRCASEEQ(forwardManaged, "yes"))
+                def->managed = 1;
+        }
 
         /* all of these modes can use a pool of physical interfaces */
         nForwardIfs = virXPathNodeSet("./interface", ctxt, &forwardIfNodes);
         nForwardPfs = virXPathNodeSet("./pf", ctxt, &forwardPfNodes);
+        nForwardAddrs = virXPathNodeSet("./address", ctxt, &forwardAddrNodes);
 
-        if (nForwardIfs < 0 || nForwardPfs < 0) {
+        if (nForwardIfs < 0 || nForwardPfs < 0 || nForwardAddrs < 0) {
             virReportError(VIR_ERR_XML_ERROR, "%s",
                            _("No interface pool or SRIOV physical device given"));
             goto error;
         }
 
+        if ((nForwardIfs > 0) && (nForwardAddrs > 0)) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("Address and interface attributes are mutually exclusive"));
+            goto error;
+        }
+
+        if ((nForwardPfs > 0) && ((nForwardIfs > 0) || (nForwardAddrs > 0))) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("Address/interface attributes and Physical function are mutually exclusive "));
+            goto error;
+        }
+
         if (nForwardPfs == 1) {
             if (VIR_ALLOC_N(def->forwardPfs, nForwardPfs) < 0) {
                 virReportOOMError();
@@ -1139,7 +1166,53 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
                            _("Use of more than one physical interface is not allowed"));
             goto error;
         }
-        if (nForwardIfs > 0 || forwardDev) {
+        if (nForwardAddrs > 0) {
+            int ii;
+
+            if (VIR_ALLOC_N(def->forwardIfs, nForwardAddrs) < 0) {
+                virReportOOMError();
+                goto error;
+            }
+
+            if (forwardDev) {
+                virReportError(VIR_ERR_XML_ERROR, "%s",
+                               _("A forward Dev should not be used when using address attribute"));
+                goto error;
+            }
+
+            for (ii = 0; ii < nForwardAddrs; ii++) {
+                type = virXMLPropString(forwardAddrNodes[ii], "type");
+
+                if (type) {
+                    if ((def->forwardIfs[ii].type = virNetworkForwardHostdevDeviceTypeFromString(type)) < 0) {
+                        virReportError(VIR_ERR_XML_ERROR,
+                                       _("unknown address type '%s'"), type);
+                        goto error;
+                    }
+                } else {
+                    virReportError(VIR_ERR_XML_ERROR,
+                                   "%s", _("No type specified for device address"));
+                    goto error;
+                }
+
+                switch (def->forwardIfs[ii].type) {
+                case VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI:
+                    if (virDevicePCIAddressParseXML(forwardAddrNodes[ii], &(def->forwardIfs[ii].device.pci)) < 0)
+                        goto error;
+                    break;
+
+                /* Add USB case here */
+
+                default:
+                    virReportError(VIR_ERR_XML_ERROR,
+                                   _("unknown address type '%s'"), type);
+                    goto error;
+                }
+                VIR_FREE(type);
+                def->nForwardIfs++;
+            }
+        }
+        else if (nForwardIfs > 0 || forwardDev) {
             int ii;
 
             /* allocate array to hold all the portgroups */
@@ -1149,7 +1222,8 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
             }
 
             if (forwardDev) {
-                def->forwardIfs[0].dev = forwardDev;
+                def->forwardIfs[0].device.dev = forwardDev;
+                def->forwardIfs[0].type = VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV;
                 forwardDev = NULL;
                 def->nForwardIfs++;
             }
@@ -1167,10 +1241,10 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
                 if ((ii == 0) && (def->nForwardIfs == 1)) {
                     /* both forwardDev and an interface element are present.
                      * If they don't match, it's an error. */
-                    if (STRNEQ(forwardDev, def->forwardIfs[0].dev)) {
+                    if (STRNEQ(forwardDev, def->forwardIfs[0].device.dev)) {
                         virReportError(VIR_ERR_XML_ERROR,
                                        _("forward dev '%s' must match first interface element dev '%s' in network '%s'"),
-                                       def->forwardIfs[0].dev,
+                                       def->forwardIfs[0].device.dev,
                                        forwardDev, def->name);
                         goto error;
                     }
@@ -1178,15 +1252,18 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
                     continue;
                 }
 
-                def->forwardIfs[ii].dev = forwardDev;
+                def->forwardIfs[ii].device.dev = forwardDev;
                 forwardDev = NULL;
+                def->forwardIfs[ii].type = VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV;
                 def->nForwardIfs++;
             }
         }
+        VIR_FREE(type);
         VIR_FREE(forwardDev);
+        VIR_FREE(forwardManaged);
         VIR_FREE(forwardPfNodes);
         VIR_FREE(forwardIfNodes);
-
+        VIR_FREE(forwardAddrNodes);
         switch (def->forwardType) {
         case VIR_NETWORK_FORWARD_ROUTE:
         case VIR_NETWORK_FORWARD_NAT:
@@ -1211,6 +1288,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
         case VIR_NETWORK_FORWARD_PRIVATE:
         case VIR_NETWORK_FORWARD_VEPA:
         case VIR_NETWORK_FORWARD_PASSTHROUGH:
+        case VIR_NETWORK_FORWARD_HOSTDEV:
             if (def->bridge) {
                 virReportError(VIR_ERR_XML_ERROR,
                                _("bridge name not allowed in %s mode (network '%s')"),
@@ -1310,17 +1388,18 @@ virNetworkDNSDefFormat(virBufferPtr buf,
     if (def == NULL)
         goto out;
 
-    virBufferAddLit(buf, "  <dns>\n");
+    virBufferAddLit(buf, "<dns>\n");
+    virBufferAdjustIndent(buf, 2);
 
     for (i = 0 ; i < def->ntxtrecords ; i++) {
-        virBufferAsprintf(buf, "    <txt name='%s' value='%s' />\n",
+        virBufferAsprintf(buf, "<txt name='%s' value='%s' />\n",
                               def->txtrecords[i].name,
                               def->txtrecords[i].value);
     }
 
     for (i = 0 ; i < def->nsrvrecords ; i++) {
         if (def->srvrecords[i].service && def->srvrecords[i].protocol) {
-            virBufferAsprintf(buf, "    <srv service='%s' protocol='%s'",
+            virBufferAsprintf(buf, "<srv service='%s' protocol='%s'",
                                   def->srvrecords[i].service,
                                   def->srvrecords[i].protocol);
 
@@ -1345,18 +1424,19 @@ virNetworkDNSDefFormat(virBufferPtr buf,
         for (ii = 0 ; ii < def->nhosts; ii++) {
             char *ip = virSocketAddrFormat(&def->hosts[ii].ip);
 
-            virBufferAsprintf(buf, "    <host ip='%s'>\n", ip);
-
+            virBufferAsprintf(buf, "<host ip='%s'>\n", ip);
+            virBufferAdjustIndent(buf, 2);
             for (j = 0; j < def->hosts[ii].nnames; j++)
-                virBufferAsprintf(buf, "      <hostname>%s</hostname>\n",
-                                               def->hosts[ii].names[j]);
+                virBufferAsprintf(buf, "<hostname>%s</hostname>\n",
+                                  def->hosts[ii].names[j]);
 
-            virBufferAsprintf(buf, "    </host>\n");
+            virBufferAdjustIndent(buf, -2);
+            virBufferAsprintf(buf, "</host>\n");
             VIR_FREE(ip);
         }
     }
-
-    virBufferAddLit(buf, "  </dns>\n");
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</dns>\n");
 out:
     return result;
 }
@@ -1367,7 +1447,7 @@ virNetworkIpDefFormat(virBufferPtr buf,
 {
     int result = -1;
 
-    virBufferAddLit(buf, "  <ip");
+    virBufferAddLit(buf, "<ip");
 
     if (def->family) {
         virBufferAsprintf(buf, " family='%s'", def->family);
@@ -1390,14 +1470,17 @@ virNetworkIpDefFormat(virBufferPtr buf,
         virBufferAsprintf(buf," prefix='%u'", def->prefix);
     }
     virBufferAddLit(buf, ">\n");
+    virBufferAdjustIndent(buf, 2);
 
     if (def->tftproot) {
-        virBufferEscapeString(buf, "    <tftp root='%s' />\n",
+        virBufferEscapeString(buf, "<tftp root='%s' />\n",
                               def->tftproot);
     }
     if ((def->nranges || def->nhosts)) {
         int ii;
-        virBufferAddLit(buf, "    <dhcp>\n");
+        virBufferAddLit(buf, "<dhcp>\n");
+        virBufferAdjustIndent(buf, 2);
+
         for (ii = 0 ; ii < def->nranges ; ii++) {
             char *saddr = virSocketAddrFormat(&def->ranges[ii].start);
             if (!saddr)
@@ -1407,13 +1490,13 @@ virNetworkIpDefFormat(virBufferPtr buf,
                 VIR_FREE(saddr);
                 goto error;
             }
-            virBufferAsprintf(buf, "      <range start='%s' end='%s' />\n",
+            virBufferAsprintf(buf, "<range start='%s' end='%s' />\n",
                               saddr, eaddr);
             VIR_FREE(saddr);
             VIR_FREE(eaddr);
         }
         for (ii = 0 ; ii < def->nhosts ; ii++) {
-            virBufferAddLit(buf, "      <host ");
+            virBufferAddLit(buf, "<host ");
             if (def->hosts[ii].mac)
                 virBufferAsprintf(buf, "mac='%s' ", def->hosts[ii].mac);
             if (def->hosts[ii].name)
@@ -1428,7 +1511,7 @@ virNetworkIpDefFormat(virBufferPtr buf,
             virBufferAddLit(buf, "/>\n");
         }
         if (def->bootfile) {
-            virBufferEscapeString(buf, "      <bootp file='%s' ",
+            virBufferEscapeString(buf, "<bootp file='%s' ",
                                   def->bootfile);
             if (VIR_SOCKET_ADDR_VALID(&def->bootserver)) {
                 char *ipaddr = virSocketAddrFormat(&def->bootserver);
@@ -1438,12 +1521,15 @@ virNetworkIpDefFormat(virBufferPtr buf,
                 VIR_FREE(ipaddr);
             }
             virBufferAddLit(buf, "/>\n");
+
         }
 
-        virBufferAddLit(buf, "    </dhcp>\n");
+        virBufferAdjustIndent(buf, -2);
+        virBufferAddLit(buf, "</dhcp>\n");
     }
 
-    virBufferAddLit(buf, "  </ip>\n");
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</ip>\n");
 
     result = 0;
 error:
@@ -1454,19 +1540,19 @@ static int
 virPortGroupDefFormat(virBufferPtr buf,
                       const virPortGroupDefPtr def)
 {
-    virBufferAsprintf(buf, "  <portgroup name='%s'", def->name);
+    virBufferAsprintf(buf, "<portgroup name='%s'", def->name);
     if (def->isDefault) {
         virBufferAddLit(buf, " default='yes'");
     }
     virBufferAddLit(buf, ">\n");
-    virBufferAdjustIndent(buf, 4);
+    virBufferAdjustIndent(buf, 2);
     if (virNetDevVlanFormat(&def->vlan, buf) < 0)
         return -1;
     if (virNetDevVPortProfileFormat(def->virtPortProfile, buf) < 0)
         return -1;
     virNetDevBandwidthFormat(def->bandwidth, buf);
-    virBufferAdjustIndent(buf, -4);
-    virBufferAddLit(buf, "  </portgroup>\n");
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</portgroup>\n");
     return 0;
 }
 
@@ -1482,11 +1568,12 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags)
         virBufferAsprintf(&buf, " connections='%d'", def->connections);
     }
     virBufferAddLit(&buf, ">\n");
-    virBufferEscapeString(&buf, "  <name>%s</name>\n", def->name);
+    virBufferAdjustIndent(&buf, 2);
+    virBufferEscapeString(&buf, "<name>%s</name>\n", def->name);
 
     uuid = def->uuid;
     virUUIDFormat(uuid, uuidstr);
-    virBufferAsprintf(&buf, "  <uuid>%s</uuid>\n", uuidstr);
+    virBufferAsprintf(&buf, "<uuid>%s</uuid>\n", uuidstr);
 
     if (def->forwardType != VIR_NETWORK_FORWARD_NONE) {
         const char *dev = NULL;
@@ -1500,38 +1587,57 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags)
                            def->forwardType, def->name);
             goto error;
         }
-        virBufferAddLit(&buf, "  <forward");
+        virBufferAddLit(&buf, "<forward");
         virBufferEscapeString(&buf, " dev='%s'", dev);
-        virBufferAsprintf(&buf, " mode='%s'%s>\n", mode,
+        virBufferAsprintf(&buf, " mode='%s'", mode);
+        if (def->forwardType == VIR_NETWORK_FORWARD_HOSTDEV) {
+            if (def->managed == 1)
+                virBufferAddLit(&buf, " managed='yes'");
+            else
+                virBufferAddLit(&buf, " managed='no'");
+        }
+        virBufferAsprintf(&buf, "%s>\n",
                           (def->nForwardIfs || def->nForwardPfs) ? "" : "/");
+        virBufferAdjustIndent(&buf, 2);
 
         /* For now, hard-coded to at most 1 forwardPfs */
         if (def->nForwardPfs)
-            virBufferEscapeString(&buf, "    <pf dev='%s'/>\n",
+            virBufferEscapeString(&buf, "<pf dev='%s'/>\n",
                                   def->forwardPfs[0].dev);
 
         if (def->nForwardIfs &&
             (!def->nForwardPfs || !(flags & VIR_NETWORK_XML_INACTIVE))) {
             for (ii = 0; ii < def->nForwardIfs; ii++) {
-                virBufferEscapeString(&buf, "    <interface dev='%s'",
-                                      def->forwardIfs[ii].dev);
-                if (!(flags & VIR_NETWORK_XML_INACTIVE) &&
-                    (def->forwardIfs[ii].connections > 0)) {
-                    virBufferAsprintf(&buf, " connections='%d'",
-                                      def->forwardIfs[ii].connections);
+                if (def->forwardType != VIR_NETWORK_FORWARD_HOSTDEV) {
+                    virBufferEscapeString(&buf, "<interface dev='%s'",
+                                          def->forwardIfs[ii].device.dev);
+                    if (!(flags & VIR_NETWORK_XML_INACTIVE) &&
+                        (def->forwardIfs[ii].connections > 0)) {
+                        virBufferAsprintf(&buf, " connections='%d'",
+                                          def->forwardIfs[ii].connections);
+                    }
+                    virBufferAddLit(&buf, "/>\n");
+                }
+                else {
+                    if (def->forwardIfs[ii].type ==  VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI) {
+                        if (virDevicePCIAddressFormat(&buf,
+                                                      def->forwardIfs[ii].device.pci,
+                                                      true) < 0)
+                            goto error;
+                    }
                 }
-                virBufferAddLit(&buf, "/>\n");
             }
         }
+        virBufferAdjustIndent(&buf, -2);
         if (def->nForwardPfs || def->nForwardIfs)
-            virBufferAddLit(&buf, "  </forward>\n");
+            virBufferAddLit(&buf, "</forward>\n");
     }
 
     if (def->forwardType == VIR_NETWORK_FORWARD_NONE ||
          def->forwardType == VIR_NETWORK_FORWARD_NAT ||
          def->forwardType == VIR_NETWORK_FORWARD_ROUTE) {
 
-        virBufferAddLit(&buf, "  <bridge");
+        virBufferAddLit(&buf, "<bridge");
         if (def->bridge)
             virBufferEscapeString(&buf, " name='%s'", def->bridge);
         virBufferAsprintf(&buf, " stp='%s' delay='%ld' />\n",
@@ -1539,43 +1645,40 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags)
                           def->delay);
     } else if (def->forwardType == VIR_NETWORK_FORWARD_BRIDGE &&
                def->bridge) {
-       virBufferEscapeString(&buf, "  <bridge name='%s' />\n", def->bridge);
+       virBufferEscapeString(&buf, "<bridge name='%s' />\n", def->bridge);
     }
 
 
     if (def->mac_specified) {
         char macaddr[VIR_MAC_STRING_BUFLEN];
         virMacAddrFormat(&def->mac, macaddr);
-        virBufferAsprintf(&buf, "  <mac address='%s'/>\n", macaddr);
+        virBufferAsprintf(&buf, "<mac address='%s'/>\n", macaddr);
     }
 
     if (def->domain)
-        virBufferAsprintf(&buf, "  <domain name='%s'/>\n", def->domain);
+        virBufferAsprintf(&buf, "<domain name='%s'/>\n", def->domain);
 
     if (virNetworkDNSDefFormat(&buf, def->dns) < 0)
         goto error;
 
-    virBufferAdjustIndent(&buf, 2);
     if (virNetDevVlanFormat(&def->vlan, &buf) < 0)
         goto error;
     if (virNetDevBandwidthFormat(def->bandwidth, &buf) < 0)
         goto error;
-    virBufferAdjustIndent(&buf, -2);
 
     for (ii = 0; ii < def->nips; ii++) {
         if (virNetworkIpDefFormat(&buf, &def->ips[ii]) < 0)
             goto error;
     }
 
-    virBufferAdjustIndent(&buf, 2);
     if (virNetDevVPortProfileFormat(def->virtPortProfile, &buf) < 0)
         goto error;
-    virBufferAdjustIndent(&buf, -2);
 
     for (ii = 0; ii < def->nPortGroups; ii++)
         if (virPortGroupDefFormat(&buf, &def->portGroups[ii]) < 0)
             goto error;
 
+    virBufferAdjustIndent(&buf, -2);
     virBufferAddLit(&buf, "</network>\n");
 
     if (virBufferError(&buf))
index a029f707048cc605f08812634b140b0bb613d505..f49c3671be953d755dfd2d7441f100695c7e3242 100644 (file)
@@ -37,6 +37,7 @@
 # include "virnetdevvportprofile.h"
 # include "virnetdevvlan.h"
 # include "virmacaddr.h"
+# include "device_conf.h"
 
 enum virNetworkForwardType {
     VIR_NETWORK_FORWARD_NONE   = 0,
@@ -46,10 +47,20 @@ enum virNetworkForwardType {
     VIR_NETWORK_FORWARD_PRIVATE,
     VIR_NETWORK_FORWARD_VEPA,
     VIR_NETWORK_FORWARD_PASSTHROUGH,
+    VIR_NETWORK_FORWARD_HOSTDEV,
 
     VIR_NETWORK_FORWARD_LAST,
 };
 
+enum virNetworkForwardHostdevDeviceType {
+    VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NONE = 0,
+    VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI,
+    VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV,
+    /* USB Device to be added here when supported */
+
+    VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_LAST,
+};
+
 typedef struct _virNetworkDHCPRangeDef virNetworkDHCPRangeDef;
 typedef virNetworkDHCPRangeDef *virNetworkDHCPRangeDefPtr;
 struct _virNetworkDHCPRangeDef {
@@ -132,14 +143,20 @@ struct _virNetworkIpDef {
 typedef struct _virNetworkForwardIfDef virNetworkForwardIfDef;
 typedef virNetworkForwardIfDef *virNetworkForwardIfDefPtr;
 struct _virNetworkForwardIfDef {
-    char *dev;      /* name of device */
-    int   connections; /* how many guest interfaces are connected to this device? */
+    int type;
+    union {
+        virDevicePCIAddress pci; /*PCI Address of device */
+        /* when USB devices are supported a new variable to be added here */
+        char *dev;      /* name of device */
+    }device;
+    int connections; /* how many guest interfaces are connected to this device? */
 };
 
 typedef struct _virNetworkForwardPfDef virNetworkForwardPfDef;
 typedef virNetworkForwardPfDef *virNetworkForwardPfDefPtr;
 struct _virNetworkForwardPfDef {
     char *dev;      /* name of device */
+    int connections; /* how many guest interfaces are connected to this device? */
 };
 
 typedef struct _virPortGroupDef virPortGroupDef;
@@ -168,6 +185,7 @@ struct _virNetworkDef {
     bool mac_specified;
 
     int forwardType;    /* One of virNetworkForwardType constants */
+    int managed;        /* managed attribute for hostdev mode */
 
     /* If there are multiple forward devices (i.e. a pool of
      * interfaces), they will be listed here.
@@ -243,8 +261,9 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags);
 static inline const char *
 virNetworkDefForwardIf(const virNetworkDefPtr def, size_t n)
 {
-    return ((def->forwardIfs && (def->nForwardIfs > n))
-            ? def->forwardIfs[n].dev : NULL);
+    return ((def->forwardIfs && (def->nForwardIfs > n) &&
+             def->forwardIfs[n].type == VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV)
+            ? def->forwardIfs[n].device.dev : NULL);
 }
 
 virPortGroupDefPtr virPortGroupFindByName(virNetworkDefPtr net,
index b42f1d84686e0ac48b4f4a39c0e8da27045b4d62..09d46d36b6f4478f50ea0fbc85270cb8b0226fe9 100644 (file)
@@ -3,7 +3,7 @@
  * esx_network_driver.c: network driver functions for managing VMware ESX
  *                       host networks
  *
- * Copyright (C) 2010-2011 Red Hat, Inc.
+ * Copyright (C) 2010-2012 Red Hat, Inc.
  * Copyright (C) 2010-2012 Matthias Bolte <matthias.bolte@googlemail.com>
  *
  * This library is free software; you can redistribute it and/or
@@ -422,9 +422,18 @@ esxNetworkDefineXML(virConnectPtr conn, const char *xml)
         for (i = 0; i < def->nForwardIfs; ++i) {
             bool found = false;
 
+            if (def->forwardIfs[i].type !=
+                VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("unsupported device type in network %s "
+                                 "interface pool"),
+                               def->name);
+                goto cleanup;
+            }
+
             for (physicalNic = physicalNicList; physicalNic != NULL;
                  physicalNic = physicalNic->_next) {
-                if (STREQ(def->forwardIfs[i].dev, physicalNic->device)) {
+                if (STREQ(def->forwardIfs[i].device.dev, physicalNic->device)) {
                     if (esxVI_String_AppendValueToList
                           (&hostVirtualSwitchBondBridge->nicDevice,
                            physicalNic->key) < 0) {
@@ -439,7 +448,7 @@ esxNetworkDefineXML(virConnectPtr conn, const char *xml)
             if (! found) {
                 virReportError(VIR_ERR_INTERNAL_ERROR,
                                _("Could not find PhysicalNic with name '%s'"),
-                               def->forwardIfs[i].dev);
+                               def->forwardIfs[i].device.dev);
                 goto cleanup;
             }
         }
@@ -742,9 +751,12 @@ esxNetworkGetXMLDesc(virNetworkPtr network_, unsigned int flags)
             for (physicalNic = physicalNicList; physicalNic != NULL;
                  physicalNic = physicalNic->_next) {
                 if (STREQ(physicalNicKey->value, physicalNic->key)) {
-                    def->forwardIfs[def->nForwardIfs].dev = strdup(physicalNic->device);
+                    def->forwardIfs[def->nForwardIfs].type
+                        = VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV;
+                    def->forwardIfs[def->nForwardIfs].device.dev
+                        = strdup(physicalNic->device);
 
-                    if (def->forwardIfs[def->nForwardIfs].dev == NULL) {
+                    if (def->forwardIfs[def->nForwardIfs].device.dev == NULL) {
                         virReportOOMError();
                         goto cleanup;
                     }
index 5619640534f57f558965032455ae1483a4397999..bf809bb31d89237343291261d83e668ee5b8218b 100644 (file)
@@ -2805,8 +2805,8 @@ networkCreateInterfacePool(virNetworkDefPtr netdef) {
     netdef->nForwardIfs = num_virt_fns;
 
     for (ii = 0; ii < netdef->nForwardIfs; ii++) {
-        netdef->forwardIfs[ii].dev = strdup(vfname[ii]);
-        if (!netdef->forwardIfs[ii].dev) {
+        netdef->forwardIfs[ii].device.dev = strdup(vfname[ii]);
+        if (!netdef->forwardIfs[ii].device.dev) {
             virReportOOMError();
             goto finish;
         }
@@ -3057,7 +3057,7 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
                                netdef->name);
                 goto error;
             }
-            iface->data.network.actual->data.direct.linkdev = strdup(dev->dev);
+            iface->data.network.actual->data.direct.linkdev = strdup(dev->device.dev);
             if (!iface->data.network.actual->data.direct.linkdev) {
                 virReportOOMError();
                 goto error;
@@ -3115,7 +3115,7 @@ validate:
         /* we are now assured of success, so mark the allocation */
         dev->connections++;
         VIR_DEBUG("Using physical device %s, %d connections",
-                  dev->dev, dev->connections);
+                  dev->device.dev, dev->connections);
     }
 
     if (netdef) {
@@ -3198,7 +3198,7 @@ networkNotifyActualDevice(virDomainNetDefPtr iface)
         /* find the matching interface and increment its connections */
 
         for (ii = 0; ii < netdef->nForwardIfs; ii++) {
-            if (STREQ(actualDev, netdef->forwardIfs[ii].dev)) {
+            if (STREQ(actualDev, netdef->forwardIfs[ii].device.dev)) {
                 dev = &netdef->forwardIfs[ii];
                 break;
             }
@@ -3229,7 +3229,7 @@ networkNotifyActualDevice(virDomainNetDefPtr iface)
         /* we are now assured of success, so mark the allocation */
         dev->connections++;
         VIR_DEBUG("Using physical device %s, %d connections",
-                  dev->dev, dev->connections);
+                  dev->device.dev, dev->connections);
     }
 
 success:
@@ -3305,7 +3305,7 @@ networkReleaseActualDevice(virDomainNetDefPtr iface)
         virNetworkForwardIfDefPtr dev = NULL;
 
         for (ii = 0; ii < netdef->nForwardIfs; ii++) {
-            if (STREQ(actualDev, netdef->forwardIfs[ii].dev)) {
+            if (STREQ(actualDev, netdef->forwardIfs[ii].device.dev)) {
                 dev = &netdef->forwardIfs[ii];
                 break;
             }
@@ -3320,7 +3320,7 @@ networkReleaseActualDevice(virDomainNetDefPtr iface)
 
         dev->connections--;
         VIR_DEBUG("Releasing physical device %s, %d connections",
-                  dev->dev, dev->connections);
+                  dev->device.dev, dev->connections);
     }
 
 success:
@@ -3410,7 +3410,7 @@ networkGetNetworkAddress(const char *netname, char **netaddr)
     case VIR_NETWORK_FORWARD_VEPA:
     case VIR_NETWORK_FORWARD_PASSTHROUGH:
         if ((netdef->nForwardIfs > 0) && netdef->forwardIfs)
-            dev_name = netdef->forwardIfs[0].dev;
+            dev_name = netdef->forwardIfs[0].device.dev;
 
         if (!dev_name) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
diff --git a/tests/networkxml2xmlin/hostdev-pf.xml b/tests/networkxml2xmlin/hostdev-pf.xml
new file mode 100644 (file)
index 0000000..7bf857d
--- /dev/null
@@ -0,0 +1,7 @@
+<network>
+  <name>hostdev</name>
+  <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+  <forward mode='hostdev' managed='yes'>
+    <pf dev='eth2'/>
+  </forward>
+</network>
diff --git a/tests/networkxml2xmlin/hostdev.xml b/tests/networkxml2xmlin/hostdev.xml
new file mode 100644 (file)
index 0000000..03f1411
--- /dev/null
@@ -0,0 +1,10 @@
+<network>
+  <name>hostdev</name>
+  <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+  <forward mode='hostdev' managed='yes'>
+    <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x1'/>
+    <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x2'/>
+    <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x3'/>
+    <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x4'/>
+  </forward>
+</network>
index e63aae0507c2817f2b208b342a0754839e3416a6..ecdb9533e36a473413e2319cb4680465d427a36b 100644 (file)
@@ -3,8 +3,6 @@
   <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
   <forward mode="passthrough">
     <pf dev='eth0'/>
-    <interface dev='eth10'/>
-    <interface dev='eth11'/>
   </forward>
   <ip address="192.168.122.1" netmask="255.255.255.0"/>
 </network>
diff --git a/tests/networkxml2xmlout/hostdev-pf.xml b/tests/networkxml2xmlout/hostdev-pf.xml
new file mode 100644 (file)
index 0000000..7bf857d
--- /dev/null
@@ -0,0 +1,7 @@
+<network>
+  <name>hostdev</name>
+  <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+  <forward mode='hostdev' managed='yes'>
+    <pf dev='eth2'/>
+  </forward>
+</network>
diff --git a/tests/networkxml2xmlout/hostdev.xml b/tests/networkxml2xmlout/hostdev.xml
new file mode 100644 (file)
index 0000000..03f1411
--- /dev/null
@@ -0,0 +1,10 @@
+<network>
+  <name>hostdev</name>
+  <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+  <forward mode='hostdev' managed='yes'>
+    <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x1'/>
+    <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x2'/>
+    <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x3'/>
+    <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x4'/>
+  </forward>
+</network>
index 5a5531a9dcc7214ab6e2b62b46c80c72665be0a3..e57d1903993e2b69d63014f773707f2129d5a496 100644 (file)
@@ -106,6 +106,8 @@ mymain(void)
     DO_TEST("bandwidth-network");
     DO_TEST("openvswitch-net");
     DO_TEST_FULL("passthrough-pf", VIR_NETWORK_XML_INACTIVE);
+    DO_TEST("hostdev");
+    DO_TEST_FULL("hostdev-pf", VIR_NETWORK_XML_INACTIVE);
 
     return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }