]> xenbits.xensource.com Git - libvirt.git/commitdiff
conf: Add memory bandwidth allocation capability of host
authorBing Niu <bing.niu@intel.com>
Mon, 30 Jul 2018 03:12:41 +0000 (11:12 +0800)
committerJohn Ferlan <jferlan@redhat.com>
Mon, 13 Aug 2018 18:19:41 +0000 (14:19 -0400)
Add new XML section to report host's memory bandwidth allocation
capability. The format as below example:

 <host>
 .....
   <memory_bandwidth>
     <node id='0' cpus='0-19'>
       <control granularity='10' min ='10' maxAllocs='8'/>
     </node>
   </memory_bandwidth>
</host>

granularity   ---- granularity of memory bandwidth, unit percentage.
min           ---- minimum memory bandwidth allowed, unit percentage.
maxAllocs     ---- maximum memory bandwidth allocation group supported.

Signed-off-by: Bing Niu <bing.niu@intel.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
docs/schemas/capability.rng
src/conf/capabilities.c
src/conf/capabilities.h
src/util/virresctrl.c
src/util/virresctrl.h
tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/bandwidth_gran [new file with mode: 0644]
tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/min_bandwidth [new file with mode: 0644]
tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/num_closids [new file with mode: 0644]
tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml
tests/virresctrldata/resctrl.schemata

index 52164d5ecb8b869cace2739b4b7ad62a0c5d7e3c..d61515ccbe4be6bb26753bfef409c52cb8d16346 100644 (file)
@@ -51,6 +51,9 @@
       <optional>
         <ref name='cache'/>
       </optional>
+      <optional>
+        <ref name='memory_bandwidth'/>
+      </optional>
       <zeroOrMore>
         <ref name='secmodel'/>
       </zeroOrMore>
     </attribute>
   </define>
 
+  <define name='memory_bandwidth'>
+    <element name='memory_bandwidth'>
+      <oneOrMore>
+        <element name='node'>
+          <attribute name='id'>
+            <ref name='unsignedInt'/>
+          </attribute>
+          <attribute name='cpus'>
+            <ref name='cpuset'/>
+          </attribute>
+          <zeroOrMore>
+            <element name='control'>
+              <attribute name='granularity'>
+                <ref name='unsignedInt'/>
+              </attribute>
+            <optional>
+              <attribute name='min'>
+                <ref name='unsignedInt'/>
+            </attribute>
+            </optional>
+              <attribute name='maxAllocs'>
+                <ref name='unsignedInt'/>
+              </attribute>
+            </element>
+          </zeroOrMore>
+        </element>
+      </oneOrMore>
+    </element>
+  </define>
+
   <define name='guestcaps'>
     <element name='guest'>
       <ref name='ostype'/>
index a5187c69b3a6b201ccad3b68014d61e27bb25c63..6b60fbc94dec9278fae2c6c15d304772d6abd649 100644 (file)
@@ -197,6 +197,16 @@ virCapabilitiesFreeNUMAInfo(virCapsPtr caps)
     caps->host.nnumaCell = 0;
 }
 
+static void
+virCapsHostMemBWNodeFree(virCapsHostMemBWNodePtr ptr)
+{
+    if (!ptr)
+        return;
+
+    virBitmapFree(ptr->cpus);
+    VIR_FREE(ptr);
+}
+
 static void
 virCapabilitiesClearSecModel(virCapsHostSecModelPtr secmodel)
 {
@@ -239,6 +249,10 @@ virCapsDispose(void *object)
         virCapsHostCacheBankFree(caps->host.caches[i]);
     VIR_FREE(caps->host.caches);
 
+    for (i = 0; i < caps->host.nnodes; i++)
+        virCapsHostMemBWNodeFree(caps->host.nodes[i]);
+    VIR_FREE(caps->host.nodes);
+
     VIR_FREE(caps->host.netprefix);
     VIR_FREE(caps->host.pagesSize);
     virCPUDefFree(caps->host.cpu);
@@ -946,6 +960,58 @@ virCapabilitiesFormatCaches(virBufferPtr buf,
     return 0;
 }
 
+static int
+virCapabilitiesFormatMemoryBandwidth(virBufferPtr buf,
+                                     size_t nnodes,
+                                     virCapsHostMemBWNodePtr *nodes)
+{
+    size_t i = 0;
+    virBuffer controlBuf = VIR_BUFFER_INITIALIZER;
+
+    if (!nnodes)
+        return 0;
+
+    virBufferAddLit(buf, "<memory_bandwidth>\n");
+    virBufferAdjustIndent(buf, 2);
+
+    for (i = 0; i < nnodes; i++) {
+        virCapsHostMemBWNodePtr node = nodes[i];
+        virResctrlInfoMemBWPerNodePtr control = &node->control;
+        char *cpus_str = virBitmapFormat(node->cpus);
+
+        if (!cpus_str)
+            return -1;
+
+        virBufferAsprintf(buf,
+                          "<node id='%u' cpus='%s'",
+                          node->id, cpus_str);
+        VIR_FREE(cpus_str);
+
+        virBufferSetChildIndent(&controlBuf, buf);
+        virBufferAsprintf(&controlBuf,
+                          "<control granularity='%u' min ='%u' "
+                          "maxAllocs='%u'/>\n",
+                          control->granularity, control->min,
+                          control->max_allocation);
+
+        if (virBufferCheckError(&controlBuf) < 0)
+            return -1;
+
+        if (virBufferUse(&controlBuf)) {
+            virBufferAddLit(buf, ">\n");
+            virBufferAddBuffer(buf, &controlBuf);
+            virBufferAddLit(buf, "</node>\n");
+        } else {
+            virBufferAddLit(buf, "/>\n");
+        }
+    }
+
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</memory_bandwidth>\n");
+
+    return 0;
+}
+
 /**
  * virCapabilitiesFormatXML:
  * @caps: capabilities to format
@@ -1049,6 +1115,10 @@ virCapabilitiesFormatXML(virCapsPtr caps)
                                     caps->host.caches) < 0)
         goto error;
 
+    if (virCapabilitiesFormatMemoryBandwidth(&buf, caps->host.nnodes,
+                                             caps->host.nodes) < 0)
+        goto error;
+
     for (i = 0; i < caps->host.nsecModels; i++) {
         virBufferAddLit(&buf, "<secmodel>\n");
         virBufferAdjustIndent(&buf, 2);
@@ -1591,6 +1661,40 @@ virCapabilitiesInitResctrl(virCapsPtr caps)
 }
 
 
+static int
+virCapabilitiesInitResctrlMemory(virCapsPtr caps)
+{
+    virCapsHostMemBWNodePtr node = NULL;
+    size_t i = 0;
+    int ret = -1;
+
+    for (i = 0; i < caps->host.ncaches; i++) {
+        virCapsHostCacheBankPtr bank = caps->host.caches[i];
+        if (VIR_ALLOC(node) < 0)
+            goto cleanup;
+
+        if (virResctrlInfoGetMemoryBandwidth(caps->host.resctrl,
+                                             bank->level, &node->control) > 0) {
+            node->id = bank->id;
+            if (!(node->cpus = virBitmapNewCopy(bank->cpus)))
+                goto cleanup;
+
+            if (VIR_APPEND_ELEMENT(caps->host.nodes,
+                                   caps->host.nnodes, node) < 0) {
+                goto cleanup;
+            }
+        }
+        virCapsHostMemBWNodeFree(node);
+        node = NULL;
+    }
+
+    ret = 0;
+ cleanup:
+    virCapsHostMemBWNodeFree(node);
+    return ret;
+}
+
+
 int
 virCapabilitiesInitCaches(virCapsPtr caps)
 {
@@ -1720,6 +1824,9 @@ virCapabilitiesInitCaches(virCapsPtr caps)
     qsort(caps->host.caches, caps->host.ncaches,
           sizeof(*caps->host.caches), virCapsHostCacheBankSorter);
 
+    if (virCapabilitiesInitResctrlMemory(caps) < 0)
+        goto cleanup;
+
     ret = 0;
  cleanup:
     VIR_FREE(type);
index fe1b9ea45539efffebda20d1fe983cb95fc0ed00..046e275ac636005c9aa936626a626f2dc5d88c45 100644 (file)
@@ -151,6 +151,14 @@ struct _virCapsHostCacheBank {
     virResctrlInfoPerCachePtr *controls;
 };
 
+typedef struct _virCapsHostMemBWNode virCapsHostMemBWNode;
+typedef virCapsHostMemBWNode *virCapsHostMemBWNodePtr;
+struct _virCapsHostMemBWNode {
+    unsigned int id;
+    virBitmapPtr cpus;  /* All CPUs that belong to this node*/
+    virResctrlInfoMemBWPerNode control;
+};
+
 typedef struct _virCapsHost virCapsHost;
 typedef virCapsHost *virCapsHostPtr;
 struct _virCapsHost {
@@ -175,6 +183,9 @@ struct _virCapsHost {
     size_t ncaches;
     virCapsHostCacheBankPtr *caches;
 
+    size_t nnodes;
+    virCapsHostMemBWNodePtr *nodes;
+
     size_t nsecModels;
     virCapsHostSecModelPtr secModels;
 
index adf36a7c0a728e949e41baee63bb1afdfa987856..4b5442f879366514667ce05240bf8eb74d02a1be 100644 (file)
@@ -629,6 +629,26 @@ virResctrlInfoIsEmpty(virResctrlInfoPtr resctrl)
 }
 
 
+int
+virResctrlInfoGetMemoryBandwidth(virResctrlInfoPtr resctrl,
+                                 unsigned int level,
+                                 virResctrlInfoMemBWPerNodePtr control)
+{
+    virResctrlInfoMemBWPtr membw_info = resctrl->membw_info;
+
+    if (!membw_info)
+        return 0;
+
+    if (membw_info->last_level_cache != level)
+        return 0;
+
+    control->granularity = membw_info->bandwidth_granularity;
+    control->min = membw_info->min_bandwidth;
+    control->max_allocation = membw_info->max_allocation;
+    return 1;
+}
+
+
 int
 virResctrlInfoGetCache(virResctrlInfoPtr resctrl,
                        unsigned int level,
index 8d62517aa175338fbb5d68334bc13fb332bc730d..cfd56ddd067fc325f98162c81bf2b2346afd9a94 100644 (file)
@@ -50,6 +50,17 @@ struct _virResctrlInfoPerCache {
     unsigned int max_allocation;
 };
 
+typedef struct _virResctrlInfoMemBWPerNode virResctrlInfoMemBWPerNode;
+typedef virResctrlInfoMemBWPerNode *virResctrlInfoMemBWPerNodePtr;
+struct _virResctrlInfoMemBWPerNode {
+    /* Smallest possible increase of the allocation bandwidth in percentage */
+    unsigned int granularity;
+    /* Minimal allocatable bandwidth in percentage */
+    unsigned int min;
+    /* Maximum number of simultaneous allocations */
+    unsigned int max_allocation;
+};
+
 typedef struct _virResctrlInfo virResctrlInfo;
 typedef virResctrlInfo *virResctrlInfoPtr;
 
@@ -63,6 +74,10 @@ virResctrlInfoGetCache(virResctrlInfoPtr resctrl,
                        size_t *ncontrols,
                        virResctrlInfoPerCachePtr **controls);
 
+int
+virResctrlInfoGetMemoryBandwidth(virResctrlInfoPtr resctrl,
+                                 unsigned int level,
+                                 virResctrlInfoMemBWPerNodePtr control);
 /* Alloc-related things */
 typedef struct _virResctrlAlloc virResctrlAlloc;
 typedef virResctrlAlloc *virResctrlAllocPtr;
diff --git a/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/bandwidth_gran b/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/bandwidth_gran
new file mode 100644 (file)
index 0000000..f599e28
--- /dev/null
@@ -0,0 +1 @@
+10
diff --git a/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/min_bandwidth b/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/min_bandwidth
new file mode 100644 (file)
index 0000000..f599e28
--- /dev/null
@@ -0,0 +1 @@
+10
diff --git a/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/num_closids b/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/num_closids
new file mode 100644 (file)
index 0000000..b8626c4
--- /dev/null
@@ -0,0 +1 @@
+4
index 4840614e86aa912bd6dfd7aa56be75d1a23658ee..9b00cf099571f7061039def4feea77767ed3a08d 100644 (file)
         <control granularity='768' min='1536' unit='KiB' type='both' maxAllocs='4'/>
       </bank>
     </cache>
+    <memory_bandwidth>
+      <node id='0' cpus='0-5'>
+        <control granularity='10' min ='10' maxAllocs='4'/>
+      </node>
+      <node id='1' cpus='6-11'>
+        <control granularity='10' min ='10' maxAllocs='4'/>
+      </node>
+    </memory_bandwidth>
   </host>
 
 </capabilities>
index fa980e58c9dd2b6d7d2fbb0ad4762f8a998dc7c2..2578822b709dff17b1d6f73439738ae3f3e9c927 100644 (file)
@@ -1 +1,2 @@
 L3:0=000ff;1=000f0
+MB:0=100;1=100