]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
conf: add trustGuestRxFilters attribute to network and domain interface
authorLaine Stump <laine@laine.org>
Tue, 23 Sep 2014 18:19:08 +0000 (14:19 -0400)
committerLaine Stump <laine@laine.org>
Mon, 6 Oct 2014 15:49:10 +0000 (11:49 -0400)
This new attribute will control whether or not libvirt will pay
attention to guest notifications about changes to network device mac
addresses and receive filters. The default for this is 'no' (for
security reasons). If it is set to 'yes' *and* the specified device
model and connection support it (currently only macvtap+virtio) then
libvirt will watch for NIC_RX_FILTER_CHANGED events, and when it
receives one, it will issue a query-rx-filter command, retrieve the
result, and modify the host-side macvtap interface's mac address and
unicast/multicast filters accordingly.

The functionality behind this attribute will be in a later patch. This
patch merely adds the attribute to the top-level of a domain's
<interface> as well as to <network> and <portgroup>, and adds
documentation and schema/xml2xml tests. Rather than adding even more
test files, I've just added the net attribute in various applicable
places of existing test files.

12 files changed:
docs/formatdomain.html.in
docs/formatnetwork.html.in
docs/schemas/domaincommon.rng
docs/schemas/network.rng
src/conf/domain_conf.c
src/conf/domain_conf.h
src/conf/network_conf.c
src/conf/network_conf.h
src/libvirt_private.syms
tests/networkxml2xmlin/vepa-net.xml
tests/networkxml2xmlout/vepa-net.xml
tests/qemuxml2argvdata/qemuxml2argv-net-virtio-network-portgroup.xml

index 45b0f618b9b41ca9170fe1e1837c0fa46c77f0d8..0099ce7f4662b0ccedcab7fc7a07a48789ecc50e 100644 (file)
 <pre>
   ...
   &lt;devices&gt;
-    &lt;interface type='bridge'&gt;
-      &lt;source bridge='xenbr0'/&gt;
-      &lt;mac address='00:16:3e:5d:c7:9e'/&gt;
-      &lt;script path='vif-bridge'/&gt;
+    &lt;interface type='direct' trustGuestRxFilters='yes'&gt;
+      &lt;source dev='eth0'/&gt;
+      &lt;mac address='52:54:00:5d:c7:9e'/&gt;
       &lt;boot order='1'/&gt;
       &lt;rom bar='off'/&gt;
     &lt;/interface&gt;
     <p>
       There are several possibilities for specifying a network
       interface visible to the guest.  Each subsection below provides
-      more details about common setup options.  Additionally,
-      each <code>&lt;interface&gt;</code> element has an
+      more details about common setup options.
+    </p>
+    <p>
+      <span class="since">Since 1.2.10</span>),
+      the <code>interface</code> element
+      property <code>trustGuestRxFilters</code> provides the
+      capability for the host to detect and trust reports from the
+      guest regarding changes to the interface mac address and receive
+      filters by setting the attribute to <code>yes</code>. The default
+      setting for the attribute is <code>no</code> for security
+      reasons and support depends on the guest network device model as
+      well as the type of connection on the host - currently it is
+      only supported for the virtio ddevice model and for macvtap
+      connections on the host.
+    </p>
+    <p>
+      Each <code>&lt;interface&gt;</code> element has an
       optional <code>&lt;address&gt;</code> sub-element that can tie
       the interface to a particular pci slot, with
       attribute <code>type='pci'</code>
       being the default mode. The individual modes cause the delivery of
       packets to behave as follows:
     </p>
+    <p>
+      If the model type is set to <code>virtio</code> and
+      interface's <code>trustGuestRxFilters</code> attribute is set
+      to <code>yes</code>, changes made to the interface mac address,
+      unicast/multicast receive filters, and vlan settings in the
+      guest will be monitored and propagated to the associated macvtap
+      device on the host (<span class="since">Since
+      1.2.10</span>). If <code>trustGuestRxFilters</code> is not set,
+      or is not supported for the device model in use, an attempted
+      change to the mac address originating from the guest side will
+      result in a non-working network connection.
+    </p>
 
     <dl>
       <dt><code>vepa</code></dt>
   ...
   &lt;devices&gt;
     ...
-    &lt;interface type='direct'&gt;
+    &lt;interface type='direct' trustGuestRxFilters='no'&gt;
       &lt;source dev='eth0' mode='vepa'/&gt;
     &lt;/interface&gt;
   &lt;/devices&gt;
index 1a8ad8e8d693e78f53f91dbb733c46bda3a19dea..dc438aee862205bb79986cdab8ce8e78c10a4e75 100644 (file)
@@ -35,7 +35,7 @@
     </p>
 
     <pre>
-      &lt;network ipv6='yes'&gt;
+      &lt;network ipv6='yes' trustGuestRxFilters='no'&gt;
         &lt;name&gt;default&lt;/name&gt;
         &lt;uuid&gt;3e3fce45-4f53-4fa7-bb32-11f34168b82b&lt;/uuid&gt;
         ...</pre>
         to have guest-to-guest communications.  For further information,
         see the example below for the example with no gateway addresses.
         <span class="since">Since 1.0.1</span></dd>
+      <dt><code>trustGuestRxFilters='yes'</code></dt>
+      <dd>The optional parameter <code>trustGuestRxFilters</code> can
+        be used to set that attribute of the same name for each domain
+        interface connected to this network (<span class="since">since
+        1.2.10</span>). See
+        the <a href="formatdomain.html#elementSNICS">Network
+        interfaces</a> section of the domain XML documentation for
+        more details. Note that an explicit setting of this attribute
+        in a portgroup or the individual domain interface will
+        override the setting in the network.</dd>
     </dl>
 
     <h3><a name="elementsConnect">Connectivity</a></h3>
       &lt;outbound average='1000' peak='5000' burst='5120'/&gt;
     &lt;/bandwidth&gt;
   &lt;/portgroup&gt;</b>
-  <b>&lt;portgroup name='sales'&gt;
+  <b>&lt;portgroup name='sales' trustGuestRxFilters='no'&gt;
     &lt;virtualport type='802.1Qbh'&gt;
       &lt;parameters profileid='salestest'/&gt;
     &lt;/virtualport&gt;
       network can have multiple portgroup elements (and one of those
       can optionally be designated as the 'default' portgroup for the
       network), and each portgroup has a name, as well as various
-      subelements associated with it. The currently supported
+      attributes and subelements associated with it. The currently supported
       subelements are <code>&lt;bandwidth&gt;</code>
       (described <a href="formatnetwork.html#elementQoS">here</a>)
       and <code>&lt;virtualport&gt;</code>
       considered an error, and will prevent the interface from
       starting.
     </p>
+    <p>
+      portgroups also support the optional
+      parameter <code>trustGuestRxFilters</code> which can be used to
+      set that attribute of the same name for each domain interface
+      using this portgroup (<span class="since">since
+      1.2.10</span>). See
+      the <a href="formatdomain.html#elementSNICS">Network
+      interfaces</a> section of the domain XML documentation for more
+      details. Note that an explicit setting of this attribute in the
+      portgroup overrides the network-wide setting, and an explicit
+      setting in the individual domain interface will override the
+      setting in the portgroup.
+    </p>
 
     <h5><a name="elementsStaticroute">Static Routes</a></h5>
     <p>
index 6b69fd1bac3d1b27d570a00eaa83c316cd2a75d7..20d81ae2d60562cae2a08da64d92a82bbfa2a803 100644 (file)
           </interleave>
         </group>
       </choice>
+      <optional>
+        <attribute name="trustGuestRxFilters">
+          <ref name="virYesNo"/>
+        </attribute>
+      </optional>
     </element>
   </define>
   <!--
index dc732b42db5325a3b6b092c10be0fff1a0ec49a5..4546f80375800c7924ce0c84419dcb8b86f5dcf5 100644 (file)
           <ref name="virYesNo"/>
         </attribute>
       </optional>
+      <optional>
+        <attribute name="trustGuestRxFilters">
+          <ref name="virYesNo"/>
+        </attribute>
+      </optional>
       <interleave>
 
         <!-- The name of the network, used to refer to it through the API
                 <ref name="virYesNo"/>
               </attribute>
             </optional>
+            <optional>
+              <attribute name="trustGuestRxFilters">
+                <ref name="virYesNo"/>
+              </attribute>
+            </optional>
             <interleave>
               <optional>
                 <ref name="virtualPortProfile"/>
index a9c6f05d57d706b81fd9b7d4748e00da673f438f..2810c05cbca6bb386e645b3278237ca7e739d6a3 100644 (file)
@@ -6784,6 +6784,7 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
     char *type = NULL;
     char *mode = NULL;
     char *addrtype = NULL;
+    char *trustGuestRxFilters = NULL;
 
     if (VIR_ALLOC(actual) < 0)
         return -1;
@@ -6811,6 +6812,16 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
         goto error;
     }
 
+    trustGuestRxFilters = virXMLPropString(node, "trustGuestRxFilters");
+    if (trustGuestRxFilters &&
+        ((actual->trustGuestRxFilters
+          = virTristateBoolTypeFromString(trustGuestRxFilters)) <= 0)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("unknown trustGuestRxFilters value '%s'"),
+                       trustGuestRxFilters);
+        goto error;
+    }
+
     virtPortNode = virXPathNode("./virtualport", ctxt);
     if (virtPortNode) {
         if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
@@ -6906,6 +6917,7 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
     VIR_FREE(type);
     VIR_FREE(mode);
     VIR_FREE(addrtype);
+    VIR_FREE(trustGuestRxFilters);
     virDomainActualNetDefFree(actual);
 
     ctxt->node = save_ctxt;
@@ -6957,6 +6969,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
     char *vhostuser_mode = NULL;
     char *vhostuser_path = NULL;
     char *vhostuser_type = NULL;
+    char *trustGuestRxFilters = NULL;
     virNWFilterHashTablePtr filterparams = NULL;
     virDomainActualNetDefPtr actual = NULL;
     xmlNodePtr oldnode = ctxt->node;
@@ -6978,6 +6991,16 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
         def->type = VIR_DOMAIN_NET_TYPE_USER;
     }
 
+    trustGuestRxFilters = virXMLPropString(node, "trustGuestRxFilters");
+    if (trustGuestRxFilters &&
+        ((def->trustGuestRxFilters
+          = virTristateBoolTypeFromString(trustGuestRxFilters)) <= 0)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("unknown trustGuestRxFilters value '%s'"),
+                       trustGuestRxFilters);
+        goto error;
+    }
+
     cur = node->children;
     while (cur != NULL) {
         if (cur->type == XML_ELEMENT_NODE) {
@@ -7617,6 +7640,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
     VIR_FREE(mode);
     VIR_FREE(linkstate);
     VIR_FREE(addrtype);
+    VIR_FREE(trustGuestRxFilters);
     virNWFilterHashTableFree(filterparams);
 
     return def;
@@ -16740,6 +16764,9 @@ virDomainActualNetDefFormat(virBufferPtr buf,
         if  (hostdef && hostdef->managed)
             virBufferAddLit(buf, " managed='yes'");
     }
+    if (def->trustGuestRxFilters)
+        virBufferAsprintf(buf, " trustGuestRxFilters='%s'",
+                          virTristateBoolTypeToString(def->trustGuestRxFilters));
     virBufferAddLit(buf, ">\n");
 
     virBufferAdjustIndent(buf, 2);
@@ -16897,6 +16924,9 @@ virDomainNetDefFormat(virBufferPtr buf,
     virBufferAsprintf(buf, "<interface type='%s'", typeStr);
     if (hostdef && hostdef->managed)
         virBufferAddLit(buf, " managed='yes'");
+    if (def->trustGuestRxFilters)
+        virBufferAsprintf(buf, " trustGuestRxFilters='%s'",
+                          virTristateBoolTypeToString(def->trustGuestRxFilters));
     virBufferAddLit(buf, ">\n");
 
     virBufferAdjustIndent(buf, 2);
@@ -20371,6 +20401,18 @@ virDomainNetGetActualVlan(virDomainNetDefPtr iface)
     return NULL;
 }
 
+
+bool
+virDomainNetGetActualTrustGuestRxFilters(virDomainNetDefPtr iface)
+{
+    if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
+        iface->data.network.actual)
+        return (iface->data.network.actual->trustGuestRxFilters
+                == VIR_TRISTATE_BOOL_YES);
+    return iface->trustGuestRxFilters == VIR_TRISTATE_BOOL_YES;
+}
+
+
 /* Return listens[i] from the appropriate union for the graphics
  * type, or NULL if this is an unsuitable type, or the index is out of
  * bounds. If force0 is TRUE, i == 0, and there is no listen array,
index d73d65428207a0df0d742de10a6374d85dc2293e..afa3da62da50cfdb6fb7993077695c07a13528c4 100644 (file)
@@ -885,6 +885,7 @@ struct _virDomainActualNetDef {
     virNetDevVPortProfilePtr virtPortProfile;
     virNetDevBandwidthPtr bandwidth;
     virNetDevVlan vlan;
+    int trustGuestRxFilters; /* enum virTristateBool */
     unsigned int class_id; /* class ID for bandwidth 'floor' */
 };
 
@@ -974,6 +975,7 @@ struct _virDomainNetDef {
     virNWFilterHashTablePtr filterparams;
     virNetDevBandwidthPtr bandwidth;
     virNetDevVlan vlan;
+    int trustGuestRxFilters; /* enum virTristateBool */
     int linkstate;
 };
 
@@ -2510,6 +2512,7 @@ virDomainNetGetActualVirtPortProfile(virDomainNetDefPtr iface);
 virNetDevBandwidthPtr
 virDomainNetGetActualBandwidth(virDomainNetDefPtr iface);
 virNetDevVlanPtr virDomainNetGetActualVlan(virDomainNetDefPtr iface);
+bool virDomainNetGetActualTrustGuestRxFilters(virDomainNetDefPtr iface);
 
 int virDomainControllerInsert(virDomainDefPtr def,
                               virDomainControllerDefPtr controller)
index 892bd8a2c38bed9e060be373bbcb96c2a5bd8d6a..3bad07da086430ffbd60fe305e9db9b17181ddfa 100644 (file)
@@ -1615,6 +1615,7 @@ virNetworkPortGroupParseXML(virPortGroupDefPtr def,
     xmlNodePtr vlanNode;
     xmlNodePtr bandwidth_node;
     char *isDefault = NULL;
+    char *trustGuestRxFilters = NULL;
 
     int result = -1;
 
@@ -1632,6 +1633,18 @@ virNetworkPortGroupParseXML(virPortGroupDefPtr def,
     isDefault = virXPathString("string(./@default)", ctxt);
     def->isDefault = isDefault && STRCASEEQ(isDefault, "yes");
 
+    trustGuestRxFilters
+        = virXPathString("string(./@trustGuestRxFilters)", ctxt);
+    if (trustGuestRxFilters) {
+        if ((def->trustGuestRxFilters
+             = virTristateBoolTypeFromString(trustGuestRxFilters)) <= 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("Invalid trustGuestRxFilters setting '%s' "
+                             "in portgroup"), trustGuestRxFilters);
+            goto cleanup;
+        }
+    }
+
     virtPortNode = virXPathNode("./virtualport", ctxt);
     if (virtPortNode &&
         (!(def->virtPortProfile = virNetDevVPortProfileParse(virtPortNode, 0)))) {
@@ -1654,6 +1667,7 @@ virNetworkPortGroupParseXML(virPortGroupDefPtr def,
         virPortGroupDefClear(def);
     }
     VIR_FREE(isDefault);
+    VIR_FREE(trustGuestRxFilters);
 
     ctxt->node = save;
     return result;
@@ -2013,6 +2027,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
     xmlNodePtr virtPortNode = NULL;
     xmlNodePtr forwardNode = NULL;
     char *ipv6nogwStr = NULL;
+    char *trustGuestRxFilters = NULL;
     xmlNodePtr save = ctxt->node;
     xmlNodePtr bandwidthNode = NULL;
     xmlNodePtr vlanNode;
@@ -2061,6 +2076,20 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
         VIR_FREE(ipv6nogwStr);
     }
 
+    trustGuestRxFilters
+        = virXPathString("string(./@trustGuestRxFilters)", ctxt);
+    if (trustGuestRxFilters) {
+        if ((def->trustGuestRxFilters
+             = virTristateBoolTypeFromString(trustGuestRxFilters)) <= 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("Invalid trustGuestRxFilters setting '%s' "
+                             "in network '%s'"),
+                           trustGuestRxFilters, def->name);
+            goto error;
+        }
+        VIR_FREE(trustGuestRxFilters);
+    }
+
     /* Parse network domain information */
     def->domain = virXPathString("string(./domain[1]/@name)", ctxt);
 
@@ -2303,6 +2332,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
     VIR_FREE(ipNodes);
     VIR_FREE(portGroupNodes);
     VIR_FREE(ipv6nogwStr);
+    VIR_FREE(trustGuestRxFilters);
     ctxt->node = save;
     return NULL;
 }
@@ -2597,6 +2627,9 @@ virPortGroupDefFormat(virBufferPtr buf,
     if (def->isDefault) {
         virBufferAddLit(buf, " default='yes'");
     }
+    if (def->trustGuestRxFilters)
+        virBufferAsprintf(buf, " trustGuestRxFilters='%s'",
+                          virTristateBoolTypeToString(def->trustGuestRxFilters));
     virBufferAddLit(buf, ">\n");
     virBufferAdjustIndent(buf, 2);
     if (virNetDevVlanFormat(&def->vlan, buf) < 0)
@@ -2675,6 +2708,9 @@ virNetworkDefFormatBuf(virBufferPtr buf,
     }
     if (def->ipv6nogw)
         virBufferAddLit(buf, " ipv6='yes'");
+    if (def->trustGuestRxFilters)
+        virBufferAsprintf(buf, " trustGuestRxFilters='%s'",
+                          virTristateBoolTypeToString(def->trustGuestRxFilters));
     virBufferAddLit(buf, ">\n");
     virBufferAdjustIndent(buf, 2);
     virBufferEscapeString(buf, "<name>%s</name>\n", def->name);
index 7ed58cd89bcf4a12852b464a387b5d9306d6e001..660cd2d10cd1096ffb6b9f26d58adcb9c5ad1c28 100644 (file)
@@ -219,6 +219,7 @@ struct _virPortGroupDef {
     virNetDevVPortProfilePtr virtPortProfile;
     virNetDevBandwidthPtr bandwidth;
     virNetDevVlan vlan;
+    int trustGuestRxFilters; /* enum virTristateBool */
 };
 
 typedef struct _virNetworkDef virNetworkDef;
@@ -256,6 +257,7 @@ struct _virNetworkDef {
     virPortGroupDefPtr portGroups;
     virNetDevBandwidthPtr bandwidth;
     virNetDevVlan vlan;
+    int trustGuestRxFilters; /* enum virTristateBool */
 };
 
 typedef struct _virNetworkObj virNetworkObj;
index 7cbc35b2c691e0bc703200c2aea7ad4c6f62e22e..8d8342f351b72b0730a30df4775bc92e1edf2bdc 100644 (file)
@@ -331,6 +331,7 @@ virDomainNetGetActualBridgeName;
 virDomainNetGetActualDirectDev;
 virDomainNetGetActualDirectMode;
 virDomainNetGetActualHostdev;
+virDomainNetGetActualTrustGuestRxFilters;
 virDomainNetGetActualType;
 virDomainNetGetActualVirtPortProfile;
 virDomainNetGetActualVlan;
index 030c1d1621222245b86829eabf02506d9f1cc0ec..07c59c56d9a32a0f4807654b72af03a79afd56d6 100644 (file)
@@ -1,4 +1,4 @@
-<network>
+<network trustGuestRxFilters="no">
   <name>vepa-net</name>
   <uuid>81ff0d90-c91e-6742-64da-4a736edb9a8b</uuid>
   <forward mode="vepa">
@@ -14,7 +14,7 @@
       <parameters typeid="2193047" typeidversion="3"/>
     </virtualport>
   </portgroup>
-  <portgroup name="alice">
+  <portgroup name="alice" trustGuestRxFilters="yes">
     <virtualport type="802.1Qbg">
       <parameters managerid="13"/>
     </virtualport>
index 4d35a8af7bf83723c30b94f11568d81f7015bb98..b26662036d21a3f3e36609ced063dc91eab961fb 100644 (file)
@@ -1,4 +1,4 @@
-<network>
+<network trustGuestRxFilters='no'>
   <name>vepa-net</name>
   <uuid>81ff0d90-c91e-6742-64da-4a736edb9a8b</uuid>
   <forward dev='eth1' mode='vepa'>
@@ -14,7 +14,7 @@
       <parameters typeid='2193047' typeidversion='3'/>
     </virtualport>
   </portgroup>
-  <portgroup name='alice'>
+  <portgroup name='alice' trustGuestRxFilters='yes'>
     <virtualport type='802.1Qbg'>
       <parameters managerid='13'/>
     </virtualport>
index 950a9db18996a2bf86274a8d366ff7c5bf2b1c1f..6cba43923e9fb2cb7454843091c211968f1a0a29 100644 (file)
@@ -22,7 +22,7 @@
     <controller type='usb' index='0'/>
     <controller type='ide' index='0'/>
     <controller type='pci' index='0' model='pci-root'/>
-    <interface type='network'>
+    <interface type='network' trustGuestRxFilters='yes'>
       <mac address='00:11:22:33:44:55'/>
       <source network='rednet' portgroup='bob'/>
       <vlan>
@@ -33,7 +33,7 @@
       </virtualport>
       <model type='virtio'/>
     </interface>
-    <interface type='network'>
+    <interface type='network' trustGuestRxFilters='no'>
       <mac address='10:11:22:33:44:55'/>
       <source network='blue' portgroup='sam'/>
       <virtualport>