On 07/18/2018 03:57 AM, bing.niu@xxxxxxxxx wrote: > From: Bing Niu <bing.niu@xxxxxxxxx> > > 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@xxxxxxxxx> > --- > docs/schemas/capability.rng | 33 +++++++ > src/conf/capabilities.c | 108 +++++++++++++++++++++ > src/conf/capabilities.h | 11 +++ > src/util/virresctrl.c | 20 ++++ > src/util/virresctrl.h | 15 +++ > .../linux-resctrl/resctrl/info/MB/bandwidth_gran | 1 + > .../linux-resctrl/resctrl/info/MB/min_bandwidth | 1 + > .../linux-resctrl/resctrl/info/MB/num_closids | 1 + > tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml | 8 ++ > tests/virresctrldata/resctrl.schemata | 1 + > 10 files changed, 199 insertions(+) > create mode 100644 tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/bandwidth_gran > create mode 100644 tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/min_bandwidth > create mode 100644 tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/num_closids > What about virsh available views? And similar to the RDT series what about domstats? I think you can get some good ideas from the RDT CMT RFC that's posted. Not even sure if it's already done internally - but pointing it out... It doesn't have to be done as part of the series, but eventually it may be nice. I'll give the following a cursory look as I have other tasks needing some attention. I'll leave it in the back of my mind that I have to be more thorough on the next pass once I get here. > diff --git a/docs/schemas/capability.rng b/docs/schemas/capability.rng > index 52164d5..d61515c 100644 > --- a/docs/schemas/capability.rng > +++ b/docs/schemas/capability.rng > @@ -51,6 +51,9 @@ > <optional> > <ref name='cache'/> > </optional> > + <optional> > + <ref name='memory_bandwidth'/> > + </optional> > <zeroOrMore> > <ref name='secmodel'/> > </zeroOrMore> > @@ -326,6 +329,36 @@ > </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'/> > diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c > index 7a810ef..3f52296 100644 > --- a/src/conf/capabilities.c > +++ b/src/conf/capabilities.c > @@ -198,6 +198,16 @@ virCapabilitiesFreeNUMAInfo(virCapsPtr caps) > } > > static void > +virCapsHostMemBWNodeFree(virCapsHostMemBWNodePtr ptr) > +{ > + if (!ptr) > + return; > + > + virBitmapFree(ptr->cpus); > + VIR_FREE(ptr); > +} > + > +static void > virCapabilitiesClearSecModel(virCapsHostSecModelPtr secmodel) > { > size_t i; > @@ -239,6 +249,11 @@ 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); > + > + Remove one of the blank lines. This was the only issue I saw in my quick glance - rest seemed OK. John > VIR_FREE(caps->host.netprefix); > VIR_FREE(caps->host.pagesSize); > virCPUDefFree(caps->host.cpu); > @@ -957,6 +972,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 > @@ -1060,6 +1127,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); > @@ -1602,6 +1673,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) > { > @@ -1731,6 +1836,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); > diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h > index fe1b9ea..046e275 100644 > --- a/src/conf/capabilities.h > +++ b/src/conf/capabilities.h > @@ -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; > > diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c > index bec2afd..c4ccebc 100644 > --- a/src/util/virresctrl.c > +++ b/src/util/virresctrl.c > @@ -633,6 +633,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, > unsigned long long size, > diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h > index d43fd31..4333218 100644 > --- a/src/util/virresctrl.h > +++ b/src/util/virresctrl.h > @@ -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 > index 0000000..f599e28 > --- /dev/null > +++ b/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/bandwidth_gran > @@ -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 > index 0000000..f599e28 > --- /dev/null > +++ b/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/min_bandwidth > @@ -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 > index 0000000..b8626c4 > --- /dev/null > +++ b/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/num_closids > @@ -0,0 +1 @@ > +4 > diff --git a/tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml b/tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml > index 4840614..9b00cf0 100644 > --- a/tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml > +++ b/tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml > @@ -49,6 +49,14 @@ > <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> > diff --git a/tests/virresctrldata/resctrl.schemata b/tests/virresctrldata/resctrl.schemata > index fa980e5..2578822 100644 > --- a/tests/virresctrldata/resctrl.schemata > +++ b/tests/virresctrldata/resctrl.schemata > @@ -1 +1,2 @@ > L3:0=000ff;1=000f0 > +MB:0=100;1=100 > -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list