o edF@sddlZddlZddlZddlZddlmZddlmmZddl m Z ddl m Z ddl Z GdddeZdejefddZdejed ejefd d Zd d ZddZddZddZddZdddZdddZdS)N) defaultdict)ConfigurationErrorc@seZdZdZdefddZedefddZedefdd Zd edefd d Z edefd dZ ede fddZ ede fddZ ede fddZedefddZedefddZdededefddZdefddZd S)! PCIDevicez.Helper class for interaction with a PCI devicepci_addrcCs ||_dS)znInitialise a new PCI device handler :param pci_addr: PCI address of device :type: str Nr)selfrr'/usr/share/netplan/netplan/cli/sriov.py__init__'s zPCIDevice.__init__returncCsdS)zusysfs path (can be overridden for testing) :return: full path to /sys filesystem :rtype: str z/sysrrrrr sys.sz PCIDevice.syscCstj|jd|jS)zq/sys path for PCI device :return: full path to PCI device in /sys filesystem :rtype: str zbus/pci/devices)ospathjoinr rr rrr r6szPCIDevice.pathsubpathcCstj|j|S)z/sys subpath helper for PCI device :param subpath: subpath to construct path for :type: str :return: self.path + subpath :rtype: str )rrr)rrrrr r>szPCIDevice.subpathcCs2d}tj|drtjt|d}|S)zjKernel driver for PCI device :return: kernel driver in use for device :rtype: str driver)rrexistsrbasenamereadlink)rrrrr rGszPCIDevice.drivercCtj|dS)zDetermine if device is bound to a kernel driver :return: whether device is bound to a kernel driver :rtype: bool rrrrrr rrr boundRzPCIDevice.boundcCr)zwDetermine if device is a SR-IOV Physical Function :return: whether device is a PF :rtype: bool sriov_numvfsrr rrr is_pfZrzPCIDevice.is_pfcCr)zvDetermine if device is a SR-IOV Virtual Function :return: whether device is a VF :rtype: bool physfnrr rrr is_vfbrzPCIDevice.is_vfc CsRg}d} z|tjt|d|Wn ty#Y|Sw|d7}q)zList Virtual Function addresses associated with a Physical Function :return: List of PCI addresses of Virtual Functions :rtype: list[str] rTzvirtfn{})appendrrrrrformatFileNotFoundError)rvf_addrsirrr r#js zPCIDevice.vf_addrscCsdd|jDS)zList Virtual Function associated with a Physical Function :return: List of PCI devices of Virtual Functions :rtype: list[PCIDevice] cSsg|]}t|qSr)r).0addrrrr sz!PCIDevice.vfs..)r#r rrr vfs~sz PCIDevice.vfsobj_namepropvaluec Cs$tdd|dd|j||gdS)zSet devlink options for the PCI device :param obj_name: devlink object to set options on :type: str :param prop: property to set :type: str :param value: value to set for property :type: str z /sbin/devlinkdevsetzpci/{}N) subprocess check_callr!r)rr)r*r+rrr devlink_sets  zPCIDevice.devlink_setcCs|jS)zbString represenation of object :return: PCI address of string :rtype: str rr rrr __str__szPCIDevice.__str__N)__name__ __module__ __qualname____doc__strr propertyr rrrboolrrrlistr#r(r0r1rrrr r$s,  rr(c Cs^g}|D](}|js,td|d}||j||Wdn1s'wYq|S)zBind unbound VFs to driver.z/sys/bus/pci/drivers/{}/bindwtNropenr!writerr )r(r bound_vfsvffrrr bind_vfs  rAr c Cs^g}|D](}|jr,td|d}||j||Wdn1s'wYq|S)zUnbind bound VFs from driver.z/sys/bus/pci/drivers/{}/unbindr:Nr;)r(r unbound_vfsr?r@rrr unbind_vfsrBrDcCs||vrD||}|jr<|j}|r||vr|||<n+|D]}|j|t|t|ds,q||vr6td||||<qn||vrD|||<||dS)N)itf_name itf_driveritf_macz3matched more than one interface for a PF device: %s) has_matchset_namematch_interfaceutilsget_interface_driver_nameget_interface_macaddressrget) interfacesnp_statepf_linkpfspf_devrI interfacerrr _get_target_interfaces(     rUc Cstjd|d}z?t|0}d}|D]}|}|dr3|ddd}|WdWSqWdWdS1s@wYWdSty]}z t d|t |fd}~ww) z5 Read PCI slot name for given interface name /sys/class/netz device/ueventNzPCI_SLOT_NAME==rz'failed parsing PCI slot name for %s: %s) rrrr< readlinesstrip startswithsplitIOError RuntimeErrorr6)netdev uevent_pathr@ pci_slot_namelineerrr _get_pci_slot_names"   &rdc Cs|jD]>\}}|jrt|||jj|rd||<z|j}Wntjy0}zt|j d}~ww|dkr6qt||||} | rC||| <qdS)z Go through the list of netplan ethernet devices and identify which are PFs and VFs, matching the former with actual networking interfaces. Count how many VFs each PF will need. Nr) ethernetsitems sriov_linkrUidvf_count libnetplanLibNetplanExceptionrargs) rOrP vf_countsr(rRnidnetdefcountrcpfrrr get_vf_count_and_functionss   rrc Cs"|dkr td||ftjd|d}tj|d}tj|d}zt|}t|}Wdn1s:wYWn"tyV}z t d|t |fd}~wt ybt d |w||krptd |||fz!t|d }| t |WdWd S1swYWd Sty}zrd }|j d krtd|z8t|d  }| dWdn1swYt|d }| t |Wdn1swYWnty} z| }WYd} ~ nd} ~ wwd}|rt d||t |fWYd}~d Sd}~ww)zB Allocate the required number of VFs for the selected PF. zDcannot allocate more VFs for PF %s than the SR-IOV maximum: %s > 256rVdevicersriov_totalvfsNz(failed parsing sriov_totalvfs for %s: %sz#invalid sriov_totalvfs value for %szKcannot allocate more VFs for PF %s than supported: %s > %s (sriov_totalvfs)wTzLdevice or resource busy while setting sriov_numvfs for %s, trying workaround0Fz,failed setting sriov_numvfs to %s for %s: %s)rrrrr<intreadrZr]r^r6 ValueErrorr=errnologgingwarning) rqridevdir numvfs_path totalvfs_pathr@vf_maxrcbaile_innerrrr set_numvfs_for_pfsh            rc Cstjd|d}zHttj|d}|dd}Wdn1s'wYttj|d}|dd}Wdn1sJwYWntyf}z td|t|fd}~wwd||g}d}||vrw dSdS) z Perform any hardware-specific quirks for the given SR-IOV device to make sure all the VF-count changes are applied. rVrtvendorrXNz2could not determine vendor and device ID of %s: %s:r) rrrr<rzrZr]r^r6)rqrr@ device_id vendor_idrc combined_id quirk_devicesrrr perform_hardware_specific_quirks1s$ r/c Csd}tj|d|d}tjt|}tj|d|d}t|D]"} d| vrDtj|| } tjt| } | |krD| dd}nq"|sOtd||fztjddd d |d |d t |g tj tj d WdStj yutd|w)z@ Apply the hardware VLAN filtering for the selected VF. Nz sys/class/netrtvirtfnzAcould not determine the VF index for %s while configuring vlan %siplinkr-r,r?vlan)stdoutstderrzJfailed setting SR-IOV VLAN filter for vlan %s (ip link set command failed)) rrrrrlistdirr^r.r/r6DEVNULLCalledProcessError) rqr? vlan_namevlan_idprefixvf_index vf_devdir vf_dev_id pf_devdirr@dev_pathdev_idrrr apply_vlan_filter_for_vfNs<    rc CsRt}||t}|||t}|j}t t }i}i}t |||||g}|rE| D]\} } t | | s?q5|| q5|rT|D]} t| qIt}|D]/} || } | jr}|D]} | j| dr{| |vrw|| rwtd| | || <qaqV| |vr| || <qV| D]O\}}||} | j}|dvrt|}t|}|jrtd||j|jr| j}zt|j|j|dd|W|st |j|jq|st |j|jwwqt!}|j" D]D\}} | j#r&| j$}| j%}|&|j'} | st(d||j'fq|&|j)j'} | |vrtd| |j'|ft*| | |||+| qd S) z Go through all interfaces, identify which ones are SR-IOV VFs, create them and perform all other necessary setup. )rEz3matched more than one interface for a VF device: %s) switchdevlegacyzFound VFs of {}: {}eswitchmodezKSR-IOV vlan defined for %s but link %s is either not a VF or has no matcheszJinterface %s for netplan device %s (%s) already has an SR-IOV vlan definedN),rjParserload_yaml_hierarchyStateimport_parser_resultsparse netifacesrOrPrryrrrfrr rrHrJrembedded_switch_moderdrrr}debugr!r#r(delay_virtual_functions_rebindrDrr0rAr-vlanshas_sriov_vlan_filter vlan_linkrrNrhr~rgradd)config_managerrootdirparserrPrOrmr(rRvf_count_changedrqrir?rorT netdef_idiface eswitch_moderpcidevrebind_delayedfiltered_vlans_setrrrrrr apply_sriov_configus            r)r)r}rr.typing collectionsrnetplan.cli.utilsclirKnetplan.libnetplanrjnetplan.configmanagerrrobjectrIterablerArDrUrdrrrrrrrrrr s&     !/ '