acrn-hypervisor/misc/config_tools/library/rdt.py
Chenli Wei a75660be58 misc: refine the vCPU sort for cpu_affinity and CAT
The current code sort cpu list by string order, this is an issue when
we want to assign more then 10 vCPUs for some VM.

So this patch rewrite the sort of these list, now the cpu list order
by int type.

Tracked-On: #6690
Signed-off-by: Chenli Wei <chenli.wei@linux.intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
2022-08-30 16:36:53 +08:00

192 lines
6.9 KiB
Python

#!/usr/bin/env python3
#
# Copyright (C) 2022 Intel Corporation.
#
# SPDX-License-Identifier: BSD-3-Clause
#
import sys, os
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'library'))
import common
import re
from collections import defaultdict
from collections import namedtuple
policy_owner = namedtuple("policy_owner", ["vm_name", "vcpu", "cache_type"])
class Policy:
def __init__(self, cache_id, clos_mask):
self.cache_id = cache_id
self.clos_mask = clos_mask
def get_cache_id(self):
return self.cache_id
def get_clos_mask(self):
return self.clos_mask
def match_policy(self, src):
return (self.clos_mask == None) or (src.clos_mask == None) or (self.clos_mask == src.clos_mask)
class L3Policy(Policy):
def __init__(self, policy):
self.cache_id = policy.get_cache_id()
self.clos_mask = policy.get_clos_mask()
def merge_policy(self, src):
return self.match_policy(src)
class L2Policy:
cache2_id_list = []
def __init__(self, policy):
self.policy_list = []
for index,cache2_id in enumerate(self.cache2_id_list):
if cache2_id == policy.cache_id:
self.policy_list.append(policy)
else:
self.policy_list.append(Policy(None, None))
def get_cache_id(self, index):
return self.policy_list[index].get_cache_id()
def get_clos_mask(self, index):
return self.policy_list[index].get_clos_mask()
def match_policy(self, src):
for index in range(0, len(self.policy_list)):
if not self.policy_list[index].match_policy(src.policy_list[index]):
return False
return True
def merge_policy(self, src):
if self.match_policy(src):
for index in range(0, len(self.policy_list)):
if self.policy_list[index].clos_mask is None:
self.policy_list[index].clos_mask = src.policy_list[index].clos_mask
return True
return False
class RdtPolicy:
def __init__(self, policy_list, policy_owner):
cache2_id = None
cache3_id = None
l2_mask = None
l3_mask = None
for policy in policy_list:
cache_level = common.get_node("../CACHE_LEVEL/text()", policy)
cache_id = common.get_node("../CACHE_ID/text()", policy)
clos_mask = common.get_node("./CLOS_MASK/text()", policy)
if cache_level == "2":
l2_mask = clos_mask
cache2_id = cache_id
else:
l3_mask = clos_mask
cache3_id = cache_id
self.l2policy = L2Policy(Policy(cache2_id, l2_mask))
self.l3policy = L3Policy(Policy(cache3_id, l3_mask))
# a list stored the vCPU or VM info
self.policy_owner_list = [policy_owner]
def match_policy(self, src):
return self.l2policy.match_policy(src.l2policy) and self.l3policy.match_policy(src.l3policy)
#check whether the src could be merged, if yes, add the src owner to policy_owner_list list and return True
def merge_policy(self, src):
if self.match_policy(src):
self.l2policy.merge_policy(src.l2policy)
self.l3policy.merge_policy(src.l3policy)
self.policy_owner_list += src.policy_owner_list
return True
return False
#check whether a VM/vCPU could use this policy
def find_policy_owner(self, policy_owner):
return policy_owner in self.policy_owner_list
class vCatPolicy(RdtPolicy):
def merge_policy(self, src):
return False
class CdpPolicy():
def __init__(self,data_list, code_list, owner):
self.data_policy = RdtPolicy(data_list, policy_owner(owner.vm_name, owner.vcpu, "Data"))
self.code_policy = RdtPolicy(code_list, policy_owner(owner.vm_name, owner.vcpu, "Code"))
def merge_policy(self, src):
if self.code_policy.match_policy(src.code_policy) and self.data_policy.match_policy(src.data_policy):
self.code_policy.merge_policy(src.code_policy)
self.data_policy.merge_policy(src.data_policy)
return True
return False
def merge_policy_list(policy_list):
result_list = []
for index,p in enumerate(policy_list):
merged = False
for result in result_list:
if result.merge_policy(p):
merged = True
break;
if not merged:
result_list.append(p)
return result_list
def gen_policy_owner_list(scenario_etree):
policy_owner_list = []
vm_list = scenario_etree.xpath("//POLICY/VM")
for vm in vm_list:
vm_name = common.get_node("./text()", vm)
vcpu = common.get_node("../VCPU/text()", vm)
cache_type = common.get_node("../TYPE/text()", vm)
policy_owner_list.append(policy_owner(vm_name, int(vcpu), cache_type))
return policy_owner_list
def vm_vcat_enable(scenario_etree, vm_name):
vcat_enable = common.get_node(f"//VCAT_ENABLED/text()", scenario_etree)
virtual_cat_support = common.get_node(f"//vm[name = '{vm_name}']/virtual_cat_support/text()", scenario_etree)
return (vcat_enable == "y") and (virtual_cat_support == "y")
def cdp_enable(scenario_etree):
cdp_enable = common.get_node(f"//CDP_ENABLED/text()", scenario_etree)
return cdp_enable == "y"
def convert_cdp_to_normal(cdp_policy_list):
policy_list = []
for cdp_policy in cdp_policy_list:
policy_list.append(cdp_policy.data_policy)
policy_list.append(cdp_policy.code_policy)
return policy_list
def get_policy_list(scenario_etree):
init_cache2_id_list(scenario_etree)
policy_owner_list = gen_policy_owner_list(scenario_etree)
result_list = []
for policy_owner in policy_owner_list:
dict_tmp = {}
policy_list = scenario_etree.xpath(f"//POLICY[VM = '{policy_owner.vm_name}' and VCPU = '{policy_owner.vcpu}']")
if cdp_enable(scenario_etree):
data_list = scenario_etree.xpath(f"//POLICY[VM = '{policy_owner.vm_name}' and VCPU = '{policy_owner.vcpu}' and TYPE = 'Data']")
code_list = scenario_etree.xpath(f"//POLICY[VM = '{policy_owner.vm_name}' and VCPU = '{policy_owner.vcpu}' and TYPE = 'Code']")
if policy_owner.cache_type == "Code":
continue
elif policy_owner.cache_type == "Data":
result_list.append(CdpPolicy(data_list, code_list, policy_owner))
elif vm_vcat_enable(scenario_etree, policy_owner.vm_name):
result_list.append(vCatPolicy(policy_list, policy_owner))
else:
result_list.append(RdtPolicy(policy_list, policy_owner))
result_list = merge_policy_list(result_list)
if cdp_enable(scenario_etree):
result_list = convert_cdp_to_normal(result_list)
return result_list
def init_cache2_id_list(scenario_etree):
cache2_id_list = scenario_etree.xpath("//CACHE_ALLOCATION[CACHE_LEVEL = 2]/CACHE_ID/text()")
cache2_id_list.sort()
L2Policy.cache2_id_list = cache2_id_list