ÿØÿà JFIF      ÿÛ C      

!"$"$ÿÛ C  ÿÂ p " ÿÄ              ÿÄ             ÿÚ    ÕÔË®
(%	aA*‚XYD¡(J„¡E¢RE,P€XYae )(E¤²€B¤R¥	BQ¤¢ X«)X…€¤   @  

  ..............................................................................................................................................................................
.............................................................................                                                  
                                                                                                                                                                                     ÿØÿà JFIF      ÿÛ C      

!"$"$ÿÛ C  ÿÂ p " ÿÄ              ÿÄ             ÿÚ    ÕÔË®
(%	aA*‚XYD¡(J„¡E¢RE,P€XYae )(E¤²€B¤R¥	BQ¤¢ X«)X…€¤   @  

  ..............................................................................................................................................................................
.............................................................................                                                  
                                                                                                                                                                                     o
    )b	N                     @   s   d dl Z d dlZd dlZd dlZd dlmZ d dlm  mZ d dl	m
Z
 d dlmZ d dlZG dd deZdeje fddZdeje d	eje fd
dZdd Zdd Zdd Zdd Zdd ZdddZdddZdS )    N)defaultdict)ConfigurationErrorc                   @   s   e Zd ZdZdefddZedefddZedefdd	Zd
edefddZ	edefddZ
edefddZedefddZedefddZedefddZedefddZdededefddZdefddZd S )!	PCIDevicez.Helper class for interaction with a PCI devicepci_addrc                 C   s
   || _ dS )znInitialise a new PCI device handler
        :param pci_addr: PCI address of device
        :type: str
        Nr   )selfr    r   '/usr/share/netplan/netplan/cli/sriov.py__init__'   s   
zPCIDevice.__init__returnc                 C   s   dS )zusysfs path (can be overridden for testing)
        :return: full path to /sys filesystem
        :rtype: str
        z/sysr   r   r   r   r	   sys.   s   zPCIDevice.sysc                 C   s   t j| jd| jS )zq/sys path for PCI device
        :return: full path to PCI device in /sys filesystem
        :rtype: str
        zbus/pci/devices)ospathjoinr   r   r   r   r   r	   r   6   s   zPCIDevice.pathsubpathc                 C   s   t j| j|S )z/sys subpath helper for PCI device
        :param subpath: subpath to construct path for
        :type: str
        :return: self.path + subpath
        :rtype: str
        )r   r   r   )r   r   r   r   r	   r   >   s   zPCIDevice.subpathc                 C   s2   d}t j| drt jt | d}|S )zjKernel driver for PCI device
        :return: kernel driver in use for device
        :rtype: str
         driver)r   r   existsr   basenamereadlink)r   r   r   r   r	   r   G   s   zPCIDevice.driverc                 C      t j| dS )zDetermine if device is bound to a kernel driver
        :return: whether device is bound to a kernel driver
        :rtype: bool
        r   r   r   r   r   r   r   r   r	   boundR      zPCIDevice.boundc                 C   r   )zwDetermine if device is a SR-IOV Physical Function
        :return: whether device is a PF
        :rtype: bool
        sriov_numvfsr   r   r   r   r	   is_pfZ   r   zPCIDevice.is_pfc                 C   r   )zvDetermine if device is a SR-IOV Virtual Function
        :return: whether device is a VF
        :rtype: bool
        Zphysfnr   r   r   r   r	   is_vfb   r   zPCIDevice.is_vfc                 C   sR   g }d}	 z| tjt| d| W n
 ty#   Y |S w |d7 }q)zList Virtual Function addresses associated with a Physical Function
        :return: List of PCI addresses of Virtual Functions
        :rtype: list[str]
        r   Tzvirtfn{}   )appendr   r   r   r   r   formatFileNotFoundError)r   vf_addrsir   r   r	   r"   j   s   zPCIDevice.vf_addrsc                 C   s   dd | j D S )zList Virtual Function associated with a Physical Function
        :return: List of PCI devices of Virtual Functions
        :rtype: list[PCIDevice]
        c                 S   s   g | ]}t |qS r   )r   ).0addrr   r   r	   
<listcomp>   s    z!PCIDevice.vfs.<locals>.<listcomp>)r"   r   r   r   r	   vfs~   s   zPCIDevice.vfsobj_namepropvaluec              	   C   s$   t dd|dd| j||g dS )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/devlinkdevsetzpci/{}N)
subprocess
check_callr    r   )r   r(   r)   r*   r   r   r	   devlink_set   s   	
zPCIDevice.devlink_setc                 C   s   | j S )zbString represenation of object
        :return: PCI address of string
        :rtype: str
        r   r   r   r   r	   __str__   s   zPCIDevice.__str__N)__name__
__module____qualname____doc__strr
   propertyr   r   r   r   boolr   r   r   listr"   r'   r/   r0   r   r   r   r	   r   $   s,    	
r   r'   c              	   C   s^   g }| D ](}|j s,td|d}||j || W d   n1 s'w   Y  q|S )zBind unbound VFs to driver.z/sys/bus/pci/drivers/{}/bindwtNr   openr    writer   r   )r'   r   Z	bound_vfsvffr   r   r	   bind_vfs      r?   r   c              	   C   s^   g }| D ](}|j r,td|d}||j || W d   n1 s'w   Y  q|S )zUnbind bound VFs from driver.z/sys/bus/pci/drivers/{}/unbindr9   Nr:   )r'   r   Zunbound_vfsr=   r>   r   r   r	   
unbind_vfs   r@   rA   c                 C   s   ||vrd|j | }|d}|r\|d}|r || v r |||< nD|d}|d}|d}	| D ])}
|r;t|
|rK|rCt|
|rK|	rLt|
|	sLq1||v rVtd| |
||< q1n|| v rd|||< ||d S )Nmatchzset-namename
macaddressr   z3matched more than one interface for a PF device: %s)	ethernetsgetutilsis_interface_matching_name is_interface_matching_macaddress!is_interface_matching_driver_namer   )
interfacesconfig_managerpf_linkpfsZpf_devZpf_matchset_nameby_nameZby_macZ	by_driver	interfacer   r   r	   _get_target_interface   s8   









rR   c              
   C   s   t jd| d}z?t|0}d}| D ]}| }|dr3|ddd }|  W  d   W S qW d   W dS 1 s@w   Y  W dS  ty] } z
t	d| t
|f d}~ww )	z5
    Read PCI slot name for given interface name
    /sys/class/netzdevice/ueventNzPCI_SLOT_NAME==   r   z'failed parsing PCI slot name for %s: %s)r   r   r   r;   	readlinesstrip
startswithsplitIOErrorRuntimeErrorr5   )ZnetdevZuevent_pathr>   Zpci_slot_namelineer   r   r	   _get_pci_slot_name   s"   

&r^   c                 C   s   i }|j  D ]O\}}|sq|dkrq|d}|r(t| |||}	|	r'|||	< q|d}
|
rV|
|j v rVt| ||
| |
|v rJ|||
   d7  < ntd|
  qd||< q| D ]\}	}|	|v rs||	 |krstd||	 |f |||	< q[dS )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.
    rendererzvirtual-function-countlinkr   z9could not match physical interface for the defined PF: %sNz;more VFs allocated than the explicit size declared: %s > %s)rE   itemsrF   rR   loggingwarningr   )rK   rL   	vf_countsr'   rN   Zexplicit_countsZethernetsettingsZexplicit_numpfrM   countr   r   r	   get_vf_count_and_functions   s8   


rh   c           
      C   s"  |dkrt d| |f tjd| d}tj|d}tj|d}zt|}t|  }W d   n1 s:w   Y  W n" tyV } z
t	d| t
|f d}~w tyb   t	d	|  w ||krpt d
| ||f z!t|d}|t
| W d   W dS 1 sw   Y  W dS  ty } zrd}|jdkrtd|   z8t|d}|d W d   n1 sw   Y  t|d}|t
| W d   n1 sw   Y  W n ty }	 z|	}W Y d}	~	nd}	~	ww d}|rt	d|| t
|f W Y d}~dS d}~ww )zB
    Allocate the required number of VFs for the selected PF.
       zDcannot allocate more VFs for PF %s than the SR-IOV maximum: %s > 256rS   devicer   Zsriov_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)wT   zLdevice or resource busy while setting sriov_numvfs for %s, trying workaround0Fz,failed setting sriov_numvfs to %s for %s: %s)r   r   r   r   r;   intreadrW   rZ   r[   r5   
ValueErrorr<   errnorb   rc   )
rf   vf_countdevdirZnumvfs_pathZtotalvfs_pathr>   Zvf_maxr]   ZbailZe_innerr   r   r	   set_numvfs_for_pf"  sh   



rt   c              
   C   s   t jd| d}zHtt j|d}|  dd }W d   n1 s'w   Y  tt j|d}|  dd }W d   n1 sJw   Y  W n tyf } z
td| t|f d}~ww d||g}d}||v rw	 dS dS )	z
    Perform any hardware-specific quirks for the given SR-IOV device to make
    sure all the VF-count changes are applied.
    rS   rj   ZvendorrU   Nz2could not determine vendor and device ID of %s: %s:r   )	r   r   r   r;   ro   rW   rZ   r[   r5   )rf   rs   r>   Z	device_idZ	vendor_idr]   Zcombined_idZquirk_devicesr   r   r	    perform_hardware_specific_quirksQ  s$   
rv   /c                 C   s   d}t j|d|d}t jt |}t j|d| d}t |D ]"}	d|	v rDt j||	}
t jt |
}||krD|	dd } nq"|sOtd||f ztjddd	d
| d|dt	|g	tj
tj
d W dS  tjyu   td| w )z@
    Apply the hardware VLAN filtering for the selected VF.
    Nzsys/class/netrj   Zvirtfn   zAcould not determine the VF index for %s while configuring vlan %sipr`   r,   r+   r=   vlan)stdoutstderrzJfailed setting SR-IOV VLAN filter for vlan %s (ip link set command failed))r   r   r   r   r   listdirr[   r-   r.   r5   DEVNULLCalledProcessError)rf   r=   Z	vlan_namevlan_idprefixZvf_indexZ	vf_devdirZ	vf_dev_idZ	pf_devdirr>   Zdev_pathZdev_idr   r   r	   apply_vlan_filter_for_vfn  s<   

r   c              
   C   s  t  }|| t  }|| |   t }tt	}i }i }t
|| ||| g }|rB| D ]\}	}
t|	|
s<q2||	 q2|rQ|D ]}	t|	 qFt }|D ]=}| j|}|d}|r|d}|D ]}|rtt||stqi||v r|| rtd| |||< qiqS||v r|||< qS| D ]O\}}|| }|j}|dv rt|}t|}|jrtd||j |jr|j}zt|j|j | dd| W |st!|j|j q|st!|j|j w w qt" }| j# D ]P\}}|dd	kr=|d
}|d}||}|st$d||f  q| j|d
}||}	||v r1td|||f t%|	||| |&| qdS )z
    Go through all interfaces, identify which ones are SR-IOV VFs, create
    them and perform all other necessary setup.
    rB   rC   z3matched more than one interface for a VF device: %s)Z	switchdevZlegacyzFound VFs of {}: {}Zeswitchmoder_   Zsriovr`   idzKSR-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)'
libnetplanParserZload_yaml_hierarchyStateZimport_parser_resultsparse	netifacesrK   r   rn   rh   ra   rt   r   rv   rE   rF   rG   rH   r   Zembedded_switch_moder^   r   r   rb   debugr    r"   r'   Zdelay_virtual_functions_rebindrA   r   r/   r?   r,   vlansrc   r   add)rL   ZrootdirparserZnp_staterK   rd   r'   rN   Zvf_count_changedrf   rr   r=   re   rB   rP   rQ   Z	netdef_idifaceZnetdefZeswitch_moder   ZpcidevZrebind_delayedZfiltered_vlans_setrz   r`   r   Zvf_parent_entryr   r   r	   apply_sriov_config  s   














r   )rw   )rb   r   r-   typingcollectionsr   netplan.cli.utilsclirG   Znetplan.libnetplanr   netplan.configmanagerr   r   objectr   Iterabler?   rA   rR   r^   rh   rt   rv   r   r   r   r   r   r	   <module>   s&   '1/
'