
    gR                        S SK r S SKrS SKrS SKrS SKrS SKJrJrJrJr  SSK	J
r
  SSKJr  S SKr " S S\5      rS	\R                   \   4S
 jrS	\R                   \   S\R                   \   4S jrS\R&                  S\S\4S jrS\R&                  S\\   4S jrS rS\R2                  S\\\4   4S jrS\R2                  S\\\4   4S jrS\R2                  S\\   4S jrS rS rSS jr SS jr!g)    N)DictListOptionalSet   )utils   )ConfigurationErrorc                   *   \ rS rSrSrS\4S jr\S\4S j5       r\S\4S j5       r	S\S\4S	 jr
\S\4S
 j5       r\S\4S j5       r\S\4S j5       r\S\4S j5       r\S\4S j5       r\S\4S j5       rS\S\S\4S jrS\4S jrS\4S jrSrg)	PCIDevice"   z.Helper class for interaction with a PCI devicepci_addrc                     Xl         g)zVInitialise a new PCI device handler
:param pci_addr: PCI address of device
:type: str
Nr   )selfr   s     +/usr/share/netplan/netplan_cli/cli/sriov.py__init__PCIDevice.__init__%   s	    
 !    returnc                     g)z]sysfs path (can be overridden for testing)
:return: full path to /sys filesystem
:rtype: str
z/sys r   s    r   sysPCIDevice.sys,   s     r   c                 l    [         R                  R                  U R                  SU R                  5      $ )zY/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   s    r   r   PCIDevice.path4   s$     ww||DHH&7GGr   subpathc                 V    [         R                  R                  U R                  U5      $ )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!   s     r   r!   PCIDevice.subpath<   s     ww||DIIw//r   c                     Sn[         R                  R                  U R                  S5      5      (       aB  [         R                  R	                  [         R
                  " U R                  S5      5      5      nU$ )zRKernel driver for PCI device
:return: kernel driver in use for device
:rtype: str
 driver)r   r   existsr!   basenamereadlink)r   r&   s     r   r&   PCIDevice.driverE   sP     77>>$,,x011WW%%bkk$,,x2H&IJFr   c                 ^    [         R                  R                  U R                  S5      5      $ )zqDetermine 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   s    r   boundPCIDevice.boundP         ww~~dll8455r   c                 ^    [         R                  R                  U R                  S5      5      $ )z_Determine if device is a SR-IOV Physical Function
:return: whether device is a PF
:rtype: bool
sriov_numvfsr,   r   s    r   is_pfPCIDevice.is_pfX   s      ww~~dll>:;;r   c                 ^    [         R                  R                  U R                  S5      5      $ )z^Determine if device is a SR-IOV Virtual Function
:return: whether device is a VF
:rtype: bool
physfnr,   r   s    r   is_vfPCIDevice.is_vf`   r/   r   c                     / nSn  UR                  [        R                  R                  [        R                  " U R                  SR                  U5      5      5      5      5        US-  nMh  ! [         a     U$ f = f)zList Virtual Function addresses associated with a Physical Function
:return: List of PCI addresses of Virtual Functions
:rtype: list[str]
r   zvirtfn{}r   )appendr   r   r(   r)   r!   formatFileNotFoundError)r   vf_addrsis      r   r<   PCIDevice.vf_addrsh   s}     GG$$DLL1B1B11E$FG FA  % s   A A. .
A<;A<c                 X    U R                    Vs/ s H  n[        U5      PM     sn$ s  snf )zList Virtual Function associated with a Physical Function
:return: List of PCI devices of Virtual Functions
:rtype: list[PCIDevice]
)r<   r   )r   addrs     r   vfsPCIDevice.vfs|   s$     -1MM:MD	$M:::s   'obj_namepropvaluec           	      p    [         R                  " SSUSSR                  U R                  5      UU/5        g)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
/sbin/devlinkdevsetzpci/{}N)
subprocess
check_callr:   r   )r   rC   rD   rE   s       r   devlink_setPCIDevice.devlink_set   s9     	.
	
r   c                 8   SU R                    3n [        R                  " SSSSSU/[        R                  S9n[
        R                  " U5      nUR                  S0 5      R                  U0 5      R                  S	S5      $ ! [        R                   a     gf = f)
zQuery eswitch mode via devlink for the PCI device
:return: the eswitch mode or '__undetermined' if it can't be retrieved
:rtype: str
zpci/rG   z-jrH   eswitchshow)stderr__undeterminedmode)r   rJ   check_outputDEVNULLCalledProcessErrorjsonloadsget)r   pcioutputjson_outputs       r   devlink_eswitch_modePCIDevice.devlink_eswitch_mode   s    
 T]]O$	$,,# "))
F jj( ub)--c26::6CSTT ,, 	$#	$s   )B BBc                     U R                   $ )zJString represenation of object
:return: PCI address of string
:rtype: str
r   r   s    r   __str__PCIDevice.__str__   s    
 }}r   r   N)__name__
__module____qualname____firstlineno____doc__strr   propertyr   r   r!   r&   boolr-   r2   r6   listr<   rA   rL   r]   r`   __static_attributes__r   r   r   r   r   "   s3   8! ! S   Hc H H0s 0s 0    6t 6 6 <t < < 6t 6 6 $  & ;T ; ;
C 
s 
3 
*Uc U: r   r   rA   c                    / nU  Hf  nUR                   (       a  M  [        SR                  U5      S5       nUR                  UR                  5        UR                  U5        SSS5        Mh     U$ ! , (       d  f       M{  = f)zBind unbound VFs to driver.z/sys/bus/pci/drivers/{}/bindwtNr-   openr:   writer   r9   )rA   r&   	bound_vfsvffs        r   bind_vfsrt      sk    Ixxx4;;FCTJa$  $ KJ 
  KJ   -A11
B 	r   c                    / nU  Hf  nUR                   (       d  M  [        SR                  U5      S5       nUR                  UR                  5        UR                  U5        SSS5        Mh     U$ ! , (       d  f       M{  = f)zUnbind bound VFs from driver.z/sys/bus/pci/drivers/{}/unbindrm   Nrn   )rA   r&   unbound_vfsrr   rs   s        r   
unbind_vfsrx      sl    K8886==fEtLPQ$""2& ML 
  MLru   netdef	interfacec                 t    U R                  U[        R                  " U5      [        R                  " U5      S9$ )N)
iface_nameiface_driver	iface_mac)_match_interfacer   get_interface_driver_nameget_interface_macaddress)ry   rz   s     r   _interface_matchesr      s9    ""44Y?00; # = =r   c                    [         R                  " 5       nU R                  (       a  U R                  nU(       a  X!;   a  U$ [	        5       nU HM  n[        X5      (       d  M  [        U5      S:  a  [        SU R                  -  5      eUR                  U5        MO     U(       a  [        U5      S   $  gU R                  U;   a  U R                  $ g)zz
Try to match a netdef with the real system network interface.
Throws ConfigurationError if there is more than one match.
r   z3matched more than one interface for a PF device: %sr   N)r   get_interfaces
_has_matchset_namerI   r   lenr
   idaddrj   )ry   
interfacesr   matchesrz   s        r   _get_interface_name_for_netdefr      s    
 "002J. O #G (	)&<< w<!#,-bekenen-nooI& ( G}Q''   99
"99r   c           	         [         R                  R                  SU S5      n [        U5       nSnUR	                  5        HK  nUR                  5       nUR                  S5      (       d  M+  UR                  SS5      S   nUs  sSSS5        $    SSS5        g! , (       d  f       g= f! [         a!  n[        SU < S	[        U5      < 35      eSnAff = f)
z-
Read PCI slot name for given interface name
/sys/class/netzdevice/ueventNzPCI_SLOT_NAME==r	   r   z!failed parsing PCI slot name for : )r   r   r   ro   	readlinesstrip
startswithsplitIOErrorRuntimeErrorrg   )netdevuevent_pathrs   pci_slot_namelinees         r   _get_pci_slot_namer      s     '',,/IK	Y+! Mzz|??#344$(JJsA$6q$9M(( %   YPSTUPVWXXYsF   B* :B,B	B* BB* 
B'#B* 'B* *
C4CCnp_statec                     0 nU R                   R                  5        H  nUR                  R                  S5      =n(       a0  [	        XR
                     5      =n(       a  XAUR
                  '   MS  MU  UR                  (       a   [	        U5      =n(       a  XAUR
                  '    UR                  nUS:  d  M  [	        U5      =n(       d  M  XAUR
                  '   M     U$ ! [        R                   a  n[        [        U5      5      eSnAff = f)zz
Go through the list of netplan ethernet devices and identify which are
PFs matching them with actual network interfaces.
sriovNr   )	ethernetsvalueslinksrY   r   r   _embedded_switch_mode	_vf_countnetplanNetplanExceptionr
   rg   )r   pfsry   linkifacecountr   s          r   _get_physical_functionsr     s    
 C$$++-<<##G,,4,6x7HIIuI$DGG J
 ++:6BB5B%*		N1(( qy:6BB5B%*		N' .* J ++ 1(Q001s   $C  D4DDc                    0 nU R                   R                  5        H0  n UR                  nUS:  d  M  [        U5      =n(       d  M,  X1U'   M2     U$ ! [        R                   a  n[        [        U5      5      eSnAff = f)z
Go through the list of netplan ethernet devices and identify which ones
have VFs. netdef._vf_count ultimately calls _netplan_state_get_vf_count_for_def
from libnetplan which return MAX(sriov_explicit_vf_count, number of VF netdefs).
Nr   )r   r   r   r   r   r
   rg   r   )r   	vf_countsry   r   r   r   s         r   _get_vf_number_per_pfr   .  s     I$$++-	-$$E 196v>>u>#(%  .  '' 	-$SV,,	-s   AB 'A;;B c                    [        5       nU R                  R                  5        H`  nUR                  R	                  S5      =n(       d  M'  [        XR                     5      (       d  ME  UR                  UR                  5        Mb     U$ )z_
Go through the list of netplan ethernet devices and identify which ones
are virtual functions
r   )rI   r   r   r   rY   r   r   r   )r   rA   ry   r   s       r   _get_virtual_functionsr   A  sg    
 %C$$++-<<##G,,4,-hww.?@@		"	 .
 Jr   c                    US:  a  [        SU < SU< S35      e[        R                  R                  SU S5      n[        R                  R                  US5      n[        R                  R                  US5      n [	        U5       n[        UR                  5       R                  5       5      nS	S	S	5        UW:  a  [        SU < SU< SU< S35      e [	        US5       nUR                  [        U5      5        S	S	S	5        g! , (       d  f       N]= f! [         a!  n[        S
U < S[        U5      < 35      eS	nAf[         a    [        SU -  5      ef = f! , (       d  f       g= f! [         a  nSnUR                  S:X  a  [        R                  " SU -  5         [	        US5       nUR                  S5        S	S	S	5        O! , (       d  f       O= f[	        US5       nUR                  [        U5      5        S	S	S	5        O! , (       d  f       O= fSnO! [         a  n	U	n S	n	A	OS	n	A	ff = fU(       a   [        SU< SU < S[        U5      < 35      e S	nAgS	nAff = f)z:
Allocate the required number of VFs for the selected PF.
   z cannot allocate more VFs for PF z than the SR-IOV maximum: z > 256r   devicer1   sriov_totalvfsNz"failed parsing sriov_totalvfs for r   z#invalid sriov_totalvfs value for %sz than supported: z > z (sriov_totalvfs)wT   zLdevice or resource busy while setting sriov_numvfs for %s, trying workaround0Fzfailed setting sriov_numvfs to z for )r
   r   r   r   ro   intreadr   r   r   rg   
ValueErrorrp   errnologgingwarning)
pfvf_countdevdirnumvfs_pathtotalvfs_pathrs   vf_maxr   baile_inners
             r   set_numvfs_for_pfr   O  s
    #~ VXZbce 	e WW\\*B9F'',,v~6KGGLL)9:MG- A)*F ! & ]_aikqrt 	th+s#qGGCM" $( A !  VSQRVTUU G@2EFFG $#( %  h77b=OOjmoop
 +s+qGGCL ,+++s+qGGCM* ,++
    QY[]_bcd_efgg  %hs   =D (D0D E. #E>E. 
DD D 
E"D>>E
E+'E. +E. .
I*8+I%$H 0G	H 
G	H (H	H 
H	H I% 
H6*H1,I%1H66*I%%I*c           	      j   [         R                  R                  SU S5      n [        [         R                  R                  US5      5       nUR	                  5       R                  5       SS nSSS5        [        [         R                  R                  US5      5       nUR	                  5       R                  5       SS nSSS5        SR                  WW/5      nS	nXg;   a  gg! , (       d  f       N}= f! , (       d  f       N;= f! [         a!  n[        SU < S[        U5      < 35      eSnAff = f)
zu
Perform any hardware-specific quirks for the given SR-IOV device to make
sure all the VF-count changes are applied.
r   r   vendorr	   Nz,could not determine vendor and device ID of r   :r   )	r   r   r   ro   r   r   r   r   rg   )r   r   rs   	device_id	vendor_idr   combined_idquirk_devicess           r    perform_hardware_specific_quirksr   ~  s    
 WW\\*B9F`"'',,vx01Q(,I 2"'',,vx01Q(,I 2
 ((Iy12KM# 	 $ 2111 `SUWZ[\W]^__`sM   )D "C%.1D "C6D %
C3/D 6
D D D 
D2D--D2c                    Sn[         R                  R                  USUS5      n[         R                  R                  [         R                  " U5      5      n[         R                  R                  USU S5      n[         R
                  " U5       Hi  n	SU	;   d  M  [         R                  R                  X5      n
[         R                  R                  [         R                  " U
5      5      nX:X  d  Md  U	SS n  O   U(       d  [        SU< SU< 35      e [        R                  " SS	S
SU SUS[        U5      /	[        R                  [        R                  S9  g! [        R                   a    [        SU-  5      ef = f)z8
Apply the hardware VLAN filtering for the selected VF.
Nzsys/class/netr   virtfn   z%could not determine the VF index for z while configuring vlan ipr   rI   rH   rr   vlan)stdoutrQ   zJfailed setting SR-IOV VLAN filter for vlan %s (ip link set command failed))r   r   r   r(   r)   listdirr   rJ   rK   rg   rU   rV   )r   rr   	vlan_namevlan_idprefixvf_index	vf_devdir	vf_dev_id	pf_devdirrs   dev_pathdev_ids               r   apply_vlan_filter_for_vfr     sG    HV_b(CI  Y!78IV_b(CIZZ	"q=ww||I1HWW%%bkk(&;<F"QR5 # SUW`ac 	c	ftVU$b#X%s7|5 &0%7%7%/%7%7	9 (( fX[ddf 	ffs   AE #F c           
         U R                  5         [        R                  " 5       nU R                  n[	        U5      n[        U5      n[        U5      n/ nU(       a<  UR                  5        H(  u  p[        X5      (       d  M  UR                  U5        M*     U(       a)  U H  n[        U5        M     [        R                  " 5       n0 n
U Hd  nX;   nUR                  (       aA  U H9  nUR                  US9(       d  M  X;   a  X   (       a  [        SU-  5      eXU'   M;     MY  X;   d  M`  XU'   Mf     UR                  5        GH;  u  pX>   nUR                  nUS;   d  M  [        U5      n[!        U5      nUR#                  5       nUU:w  d  ML  UR$                  (       d  M_  [&        R(                  " SR+                  UUR,                  5      5        UR.                  (       a!   [1        UR.                  UR2                  5        [&        R(                  " SU S	U S
U 35        UR;                  SSU5        UR.                  (       d  GM  UR<                  (       a  GM  [?        UR.                  UR2                  5        GM>     [A        5       nURB                  R                  5        GH  u  nnURD                  (       d  M  URF                  RI                  S5      nURJ                  nU
RI                  URL                  5      nU(       d+  [&        R6                  " SU< SURL                  < S35        M  URI                  URF                  RI                  S5      RL                  5      nUU;   a"  [        SU< SURL                  < SU< S35      e[O        XUU5        URQ                  U5        GM     g! [4         a0  n[&        R6                  " SU S[9        U5       35         SnAGNSnAff = f)zs
Go through all interfaces, identify which ones are SR-IOV VFs, create
them and perform all other necessary setup.
)r|   z3matched more than one interface for a VF device: %s)	switchdevlegacyzFound VFs of {}: {}zUnbinding of VFs for z	 failed: NzChanging eswitch mode from z to z for: rO   rS   r   zSR-IOV vlan defined for z
 but link z% is either not a VF or has no matchesr   z
interface z for netplan device z (z$) already has an SR-IOV vlan defined))parser   r   r   r   r   r   itemsr   r9   r   r   r   r
   r   r   r   r]   r2   r   debugr:   r<   rA   rx   r&   	Exceptionr   rg   rL   _delay_virtual_functions_rebindrt   rI   vlans_has_sriov_vlan_filterr   rY   _vlan_idr   r   r   )config_managerrootdirr   r   r   vfs_setr   vf_count_changedr   r   rA   rr   ry   rz   	netdef_idr   eswitch_moder   pcidevcurrent_eswitch_mode_systemr   filtered_vlans_setr   r   r   s                            r   apply_sriov_configr     sT   
 %%'J&&H &h/I %X.G
!(
+C
 %OO-LB$R22##B'	 .  #B,R0 #
 ))+
 C
 (	**i*@@ySW01fik1kll'G	 ( B "  IIK	$3322)%0Hx(F*0*E*E*G'::<<<MM"7">">vv"WXzzb&vzz6==A MM$?@[?\\`am`nntu~t  #A  B&&y&,Gzzz%EEE$VZZ?+ (.  ,,.f (((<<##F+DooG!B eikokrkrsu
 0334B''(dfhlhohoquvx x %RT7;""2&9 /  ) b#OO.CI;iX[\]X^W_,`aabs   % N66
O0 %O++O0)/)"rW   r   r   rJ   typingr   r   r   r   r%   r   configmanagerr
   r   objectr   Iterablert   rx   NetDefinitionrg   ri   r   r   r   Stater   r   r   r   r   r   r   r   r   r   r   <module>r      s#  &   	   , ,  . Y Yx&//), FOOI. 6??9;U =w44 = = =!7+@+@ !Xc] !HY"gmm S#X <GMM d38n &W]] s3x ,^:$fNs'r   