]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdown2/addons/ethtool.py
SONAR: fix iface.py: Import only needed names or import the module and then use its...
[mirror_ifupdown2.git] / ifupdown2 / addons / ethtool.py
CommitLineData
35681c06 1#!/usr/bin/env python3
15ef32ea 2#
d486dd0d 3# Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved.
15ef32ea
RP
4# Author: Roopa Prabhu, roopa@cumulusnetworks.com
5#
d486dd0d
JF
6
7import os
15ef32ea
RP
8
9try:
223ba5af
JF
10 from ifupdown2.lib.addon import Addon
11
da991539 12 import ifupdown2.ifupdown.ifupdownflags as ifupdownflags
d486dd0d 13 import ifupdown2.ifupdown.policymanager as policymanager
ebd1f306 14 import ifupdown2.ifupdown.statemanager as statemanager
d486dd0d 15
421e9573 16 from ifupdown2.ifupdown.iface import ifaceLinkPrivFlags
d486dd0d
JF
17 from ifupdown2.ifupdown.utils import utils
18 from ifupdown2.ifupdown.exceptions import moduleNotSupported
19
20 from ifupdown2.ifupdownaddons.utilsbase import *
d486dd0d 21 from ifupdown2.ifupdownaddons.modulebase import moduleBase
bd441a51 22except (ImportError, ModuleNotFoundError):
223ba5af
JF
23 from lib.addon import Addon
24
d486dd0d
JF
25 import ifupdown.ifupdownflags as ifupdownflags
26 import ifupdown.policymanager as policymanager
ebd1f306 27 import ifupdown.statemanager as statemanager
d486dd0d 28
421e9573 29 from ifupdown.iface import ifaceLinkPrivFlags
a193d8d1 30 from ifupdown.utils import utils
d486dd0d
JF
31 from ifupdown.exceptions import moduleNotSupported
32
3d44fbd0 33 from ifupdownaddons.utilsbase import *
d486dd0d
JF
34 from ifupdownaddons.modulebase import moduleBase
35
15ef32ea 36
223ba5af 37class ethtool(Addon, moduleBase):
15ef32ea
RP
38 """ ifupdown2 addon module to configure ethtool attributes """
39
2771a88e 40 _modinfo = {
223ba5af
JF
41 "mhelp": "ethtool configuration module for interfaces",
42 "attrs": {
43 "link-speed": {
44 "help": "set link speed",
45 "validvals": [
46 "10",
47 "100",
48 "1000",
49 "10000",
50 "25000",
51 "40000",
52 "50000",
f343240c 53 "100000",
54 "200000",
55 "400000"
223ba5af
JF
56 ],
57 "example": ["link-speed 1000"],
58 "default": "varies by platform and port"
59 },
60 "link-duplex": {
61 "help": "set link duplex",
62 "example": ["link-duplex full"],
63 "validvals": ["half", "full"],
64 "default": "full"
65 },
66 "link-autoneg": {
67 "help": "set autonegotiation",
68 "example": ["link-autoneg on"],
69 "validvals": ["yes", "no", "on", "off"],
70 "default": "varies by platform and port"
71 },
72 "link-fec": {
73 "help": "set forward error correction mode",
74 "example": ["link-fec rs"],
75 "validvals": ["rs", "baser", "auto", "off"],
76 "default": "varies by platform and port"
da991539
JF
77 },
78 'gro-offload': {
79 'help': 'Generic Receive Offload',
80 'example': ['gro-offload on'],
81 'validvals': ['on', 'off'],
82 'default': 'varies by interface'
83 },
84 'lro-offload': {
85 'help': 'Large Receive Offload',
86 'example': ['lro-offload on'],
87 'validvals': ['on', 'off'],
88 'default': 'varies by interface'
89 },
90 'gso-offload': {
91 'help': 'Generic Segmentation Offload',
92 'example': ['tso-offload on'],
93 'validvals': ['on', 'off'],
94 'default': 'varies by interface'
95 },
96 'tso-offload': {
97 'help': 'TCP Segmentation Offload',
98 'example': ['tso-offload on'],
99 'validvals': ['on', 'off'],
100 'default': 'varies by interface'
101 },
102 'ufo-offload': {
103 'help': 'UDP Fragmentation Offload',
104 'example': ['ufo-offload on'],
105 'validvals': ['on', 'off'],
106 'default': 'varies by interface'
107 },
108 'tx-offload': {
109 'help': 'TX Checksum Offload',
110 'example': ['tx-offload on'],
111 'validvals': ['on', 'off'],
112 'default': 'varies by interface'
113 },
114 'rx-offload': {
115 'help': 'RX Checksum Offload',
116 'example': ['rx-offload on'],
117 'validvals': ['on', 'off'],
118 'default': 'varies by interface'
119 },
8c35c09d 120 'ring-rx': {
121 'help': 'Ring RX Parameter',
122 'example': ['ring-rx 512'],
70bd0e86 123 'validvals': ['max', '<number>'],
8c35c09d 124 'default': 'varies by interface'
125 },
126 'ring-tx': {
127 'help': 'Ring TX Parameter',
128 'example': ['ring-tx 512'],
70bd0e86 129 'validvals': ['max', '<number>'],
8c35c09d 130 'default': 'varies by interface'
131 },
223ba5af
JF
132 }
133 }
15ef32ea
RP
134
135 def __init__(self, *args, **kargs):
223ba5af 136 Addon.__init__(self)
15ef32ea 137 moduleBase.__init__(self, *args, **kargs)
d486dd0d
JF
138 if not os.path.exists(utils.ethtool_cmd):
139 raise moduleNotSupported('module init failed: %s: not found' % utils.ethtool_cmd)
7444feea
ST
140 # keep a list of iface objects who have modified link attributes
141 self.ifaceobjs_modified_configs = []
ebd1f306
SA
142 # Cache for features
143 self.feature_cache = None
15ef32ea 144
223ba5af
JF
145 self.ethtool_ignore_errors = policymanager.policymanager_api.get_module_globals(
146 module_name=self.__class__.__name__,
147 attr='ethtool_ignore_errors'
148 )
149
8c35c09d 150 def do_ring_settings(self, ifaceobj, attr_name, option):
151 # Get the current configuration value and default value for the specified attribute
152 config_val = ifaceobj.get_attr_value_first(attr_name)
153 default_val = policymanager.policymanager_api.get_iface_default(
154 module_name='ethtool',
155 ifname=ifaceobj.name,
156 attr=attr_name)
157
70bd0e86 158 # Check which variable to use, config_val > default_val. If none are set, return.
159 value = config_val or default_val
160 if not value:
8c35c09d 161 return
162
70bd0e86 163 if value == "max":
164 # Get the maximum value for the specified attribute
165 max_val = self.get_max_attr(attr_name, ifaceobj)
166 if not max_val:
167 return
168 value = max_val
169
8c35c09d 170 # Get the current running value
171 running_val = self.get_running_attr(attr_name, ifaceobj)
172
8c35c09d 173
70bd0e86 174 # If the value is the same as the running value, do nothing
175 if value == running_val:
8c35c09d 176 return
177
178 # Generate the ethtool command
70bd0e86 179 cmd = ('%s --set-ring %s %s %s' %
180 (utils.ethtool_cmd, ifaceobj.name, option, value))
8c35c09d 181
70bd0e86 182 # Execute the ethtool command if command is generated
8c35c09d 183 if cmd:
184 try:
185 utils.exec_command(cmd)
186 except Exception as e:
187 self.log_error('%s: %s' %(ifaceobj.name, str(e)), ifaceobj)
188
ebd1f306
SA
189 def do_offload_settings(self, ifaceobj, attr_name, eth_name):
190 default = 'default_' + eth_name
191 config_val = ifaceobj.get_attr_value_first(attr_name)
192 # Default
193 default_val = None
194 saved_ifaceobjs = statemanager.statemanager_api.get_ifaceobjs(ifaceobj.name)
195 if saved_ifaceobjs:
196 default_val = saved_ifaceobjs[0].get_attr_value_first(default)
197 if config_val or default_val:
198
199 # get running value
200 running_val = str(self.get_running_attr(eth_name, ifaceobj)).lower()
201 # Save default value
202 # Load state data
203 if not default_val:
204 ifaceobj.config[default] = [running_val]
205 elif config_val:
206 # resave for state
207 ifaceobj.config[default] = [default_val]
208
209 if not config_val:
210 config_val = default_val
211
212 if config_val and config_val != running_val:
213 try:
214 cmd = ('%s -K %s %s %s' %
215 (utils.ethtool_cmd, ifaceobj.name, eth_name, config_val))
216 utils.exec_command(cmd)
447796a6 217 except Exception as e:
ebd1f306 218 self.log_error('%s: %s' %(ifaceobj.name, str(e)), ifaceobj)
15ef32ea 219
c1b6ffc7
JF
220 self.ethtool_ignore_errors = policymanager.policymanager_api.get_module_globals(
221 module_name=self.__class__.__name__,
222 attr='ethtool_ignore_errors'
223 )
224
d486dd0d 225 def do_fec_settings(self, ifaceobj):
d8b6aad0 226 feccmd = ''
3d44fbd0 227
d486dd0d
JF
228 # attribute existed before but we must reset to default
229 config_val = ifaceobj.get_attr_value_first('link-fec')
230 default_val = policymanager.policymanager_api.get_iface_default(
231 module_name='ethtool',
232 ifname=ifaceobj.name,
233 attr='link-fec')
594fb088 234
d486dd0d
JF
235 if not default_val and not config_val:
236 # there is no point in checking the running config
237 # if we have no default and the user did not have settings
238 return
7444feea 239
fc0026de 240 # use only lowercase values
6328de59 241 running_val = str(self.get_running_attr('fec', ifaceobj)).lower()
fc0026de 242
fc0026de
JF
243 if config_val:
244 config_val = config_val.lower()
245 if default_val:
246 default_val = default_val.lower()
247
248 # check running values
d486dd0d
JF
249 if config_val and config_val == running_val:
250 return
7444feea 251
d486dd0d
JF
252 if not config_val and default_val and default_val == running_val:
253 # nothing configured but the default is running
254 return
7444feea 255
d486dd0d
JF
256 # if we got this far, we need to change it
257 if config_val and (config_val != running_val):
258 # if the configured value is not set, set it
259 feccmd = ' %s %s' % ("encoding", config_val)
260 elif default_val and (default_val != running_val):
261 # or if it has a default not equal to running value, set it
262 feccmd = ' %s %s' % ("encoding", default_val)
d8b6aad0 263
d486dd0d 264 if feccmd:
15ef32ea 265 try:
d486dd0d
JF
266 feccmd = ('%s --set-fec %s %s' %
267 (utils.ethtool_cmd, ifaceobj.name, feccmd))
268 utils.exec_command(feccmd)
3b01ed76 269 except Exception as e:
223ba5af
JF
270 if not self.ethtool_ignore_errors:
271 self.log_error('%s: %s' %(ifaceobj.name, str(e)), ifaceobj)
3d44fbd0
ST
272 else:
273 pass
274
d486dd0d
JF
275 def do_speed_settings(self, ifaceobj, operation='post_up'):
276 cmd = ''
277
278 autoneg_to_configure = None
279 speed_to_configure = None
280 duplex_to_configure = None
281
282 config_speed = ifaceobj.get_attr_value_first('link-speed')
283 config_duplex = ifaceobj.get_attr_value_first('link-duplex')
284 config_autoneg = ifaceobj.get_attr_value_first('link-autoneg')
285
286 default_speed = policymanager.policymanager_api.get_iface_default(
287 module_name='ethtool',
288 ifname=ifaceobj.name,
289 attr='link-speed'
290 )
291
292 default_duplex = policymanager.policymanager_api.get_iface_default(
293 module_name='ethtool',
294 ifname=ifaceobj.name,
295 attr='link-duplex'
296 )
297
298 default_autoneg = policymanager.policymanager_api.get_iface_default(
299 module_name='ethtool',
300 ifname=ifaceobj.name,
301 attr='link-autoneg'
302 )
303
304 # autoneg wins if provided by user and is on
305 if config_autoneg and utils.get_boolean_from_string(config_autoneg):
306 autoneg_to_configure = config_autoneg
307 speed_to_configure = None
308 duplex_to_configure = None
309 elif config_speed:
310 # Any speed settings configured by the user wins
311 autoneg_to_configure = None
312 speed_to_configure = config_speed
313 duplex_to_configure = config_duplex
314 if not config_duplex:
315 duplex_to_configure = default_duplex
316 else:
317 # if user given autoneg config is off, we must respect that and
318 # override any default autoneg config
319 if config_autoneg and not utils.get_boolean_from_string(config_autoneg):
320 default_autoneg = 'off'
321
322 if default_autoneg and utils.get_boolean_from_string(default_autoneg):
323 autoneg_to_configure = utils.get_onoff_bool(default_autoneg)
324 speed_to_configure = None
325 duplex_to_configure = None
326 else:
327 autoneg_to_configure = None
328 speed_to_configure = default_speed
329 duplex_to_configure = default_duplex
330
331 if autoneg_to_configure:
332 autoneg_to_configure = utils.get_onoff_bool(autoneg_to_configure)
333 # check running values
334 running_val = self.get_running_attr('autoneg', ifaceobj)
335 if autoneg_to_configure != running_val:
336 # if the configured value is not set, set it
337 cmd += ' autoneg %s' % autoneg_to_configure
338 else:
339 force_set = False
340 if speed_to_configure:
341 # check running values
342 if utils.get_boolean_from_string(self.get_running_attr('autoneg', ifaceobj) or 'off'):
343 cmd = 'autoneg off'
344 # if we are transitioning from autoneg 'on' to 'off'
345 # don't check running speed
346 force_set = True
347
348 running_val = self.get_running_attr('speed', ifaceobj)
349 if force_set or (speed_to_configure != running_val):
350 # if the configured value is not set, set it
351 cmd += ' speed %s' % speed_to_configure
352
353 if duplex_to_configure:
354 # check running values
355 running_val = self.get_running_attr('duplex', ifaceobj)
356 if force_set or (duplex_to_configure != running_val):
357 # if the configured value is not set, set it
358 cmd += ' duplex %s' % duplex_to_configure
359
360 if cmd:
d8b6aad0 361 try:
d486dd0d
JF
362 cmd = ('%s -s %s %s' % (utils.ethtool_cmd, ifaceobj.name, cmd))
363 utils.exec_command(cmd)
3b01ed76 364 except Exception as e:
223ba5af
JF
365 if not self.ethtool_ignore_errors:
366 self.log_error('%s: %s' % (ifaceobj.name, str(e)), ifaceobj)
d486dd0d
JF
367
368 def _pre_up(self, ifaceobj, operation='post_up'):
369 """
370 _pre_up and _pre_down will reset the layer 2 attributes to default policy
371 settings.
372 """
223ba5af 373 if not self.cache.link_exists(ifaceobj.name):
d486dd0d
JF
374 return
375
376 self.do_speed_settings(ifaceobj)
377 self.do_fec_settings(ifaceobj)
8c35c09d 378 self.do_ring_settings(ifaceobj, 'ring-rx', 'rx')
379 self.do_ring_settings(ifaceobj, 'ring-tx', 'tx')
ebd1f306
SA
380 self.do_offload_settings(ifaceobj, 'gro-offload', 'gro')
381 self.do_offload_settings(ifaceobj, 'lro-offload', 'lro')
382 self.do_offload_settings(ifaceobj, 'gso-offload', 'gso')
383 self.do_offload_settings(ifaceobj, 'tso-offload', 'tso')
384 self.do_offload_settings(ifaceobj, 'ufo-offload', 'ufo')
385 self.do_offload_settings(ifaceobj, 'tx-offload', 'tx')
386 self.do_offload_settings(ifaceobj, 'rx-offload', 'rx')
d8b6aad0 387
3d44fbd0
ST
388 def _pre_down(self, ifaceobj):
389 pass #self._post_up(ifaceobj,operation="_pre_down")
15ef32ea 390
6e16e5ae 391 def _query_check(self, ifaceobj, ifaceobjcurr):
e74d01e1 392 """
3d44fbd0
ST
393 _query_check() needs to compare the configured (or running)
394 attribute with the running attribute.
395
396 If there is nothing configured, we compare the default attribute with
397 the running attribute and FAIL if they are different.
398 This is because a reboot will lose their running attribute
399 (the default will get set).
400 """
d8b6aad0 401 for attr in ['speed', 'duplex', 'autoneg', 'fec']:
97202602
ST
402 configured = ifaceobj.get_attr_value_first('link-%s'%attr)
403 # if there is nothing configured, do not check
404 if not configured:
6e16e5ae 405 if not ifupdownflags.flags.WITHDEFAULTS:
669b422a 406 continue
3d44fbd0
ST
407 default = policymanager.policymanager_api.get_iface_default(
408 module_name='ethtool',
409 ifname=ifaceobj.name,
410 attr='link-%s'%attr)
8d60ab41
ST
411 # if we have no default, do not bother checking
412 # this avoids ethtool calls on virtual interfaces
413 if not default:
414 continue
415 # autoneg comes from ethtool whereas speed and duplex from /sys/class
416 running_attr = self.get_running_attr(attr, ifaceobj)
b2a87e4e
JF
417 if not running_attr:
418 if not configured:
419 continue
420 ifaceobjcurr.update_config_with_status('link-%s' % attr,
421 'unknown', 1)
3d44fbd0
ST
422 continue
423
594fb088
JF
424 if attr == 'autoneg':
425 if configured == 'yes' and running_attr == 'on':
426 running_attr = 'yes'
427 elif configured == 'no' and running_attr == 'off':
428 running_attr = 'no'
429
3d44fbd0
ST
430 # we make sure we can get a running value first
431 if (running_attr and configured and running_attr == configured):
d8b6aad0 432 # PASS since running is what is configured
3d44fbd0
ST
433 ifaceobjcurr.update_config_with_status('link-%s'%attr,
434 running_attr, 0)
435 elif (running_attr and configured and running_attr != configured):
436 # We show a FAIL since it is not the configured or default
437 ifaceobjcurr.update_config_with_status('link-%s'%attr,
438 running_attr, 1)
439 elif (running_attr and default and running_attr == default):
440 # PASS since running is default
441 ifaceobjcurr.update_config_with_status('link-%s'%attr,
442 running_attr, 0)
443 elif (default or configured):
444 # We show a FAIL since it is not the configured or default
445 ifaceobjcurr.update_config_with_status('link-%s'%attr,
446 running_attr, 1)
447 return
448
449 def get_autoneg(self,ethtool_output=None):
450 """
451 get_autoneg simply calls the ethtool command and parses out
452 the autoneg value.
453 """
454 ethtool_attrs = ethtool_output.split()
455 if ('Auto-negotiation:' in ethtool_attrs):
456 return(ethtool_attrs[ethtool_attrs.index('Auto-negotiation:')+1])
457 else:
458 return(None)
459
d8b6aad0
VSR
460 def get_fec_encoding(self,ethtool_output=None):
461 """
462 get_fec_encoding simply calls the ethtool show-fec command and parses out
463 the fec encoding value.
464 """
465 try:
466 for attr in ethtool_output.splitlines():
223ba5af 467 if attr.startswith('Configured FEC encodings:'):
d8b6aad0 468 fec_attrs = attr.split()
223ba5af 469 return(fec_attrs[fec_attrs.index('encodings:')+1])
d8b6aad0
VSR
470 except Exception as e:
471 self.logger.debug('ethtool: problems in ethtool set-fec output'
472 ' %s: %s' %(ethtool_output.splitlines(), str(e)))
473
474 return(None)
475
ebd1f306
SA
476 def get_offload_setting(self, ethtool_output, setting):
477
478 value = None
479
480 for line in ethtool_output.splitlines():
481 if setting in line:
482 if 'on' in line:
483 value = 'on'
484 elif 'off' in line:
485 value = 'off'
486
487 break
488
489 return value
490
70bd0e86 491 def get_ring_setting(self, ethtool_output, setting, get_ring_max=False):
8c35c09d 492 value = None
8c35c09d 493
70bd0e86 494 if get_ring_max:
495 settings = ethtool_output.split('Current hardware settings:', 1)[0]
496 else:
497 settings = ethtool_output.split('Current hardware settings:', 1)[1]
498
499 for line in settings.splitlines():
8c35c09d 500 if line.startswith(setting):
501 value = line.split(':', 1)[1]
502 return value.strip()
503
504 return value
505
70bd0e86 506 def get_attr_value(self,attr='',ifaceobj=None,get_max=False):
d2431a3d
ST
507 if not ifaceobj or not attr:
508 return
70bd0e86 509 attr_value = None
d2431a3d
ST
510 try:
511 if attr == 'autoneg':
d486dd0d 512 output = utils.exec_commandl([utils.ethtool_cmd, ifaceobj.name])
70bd0e86 513 attr_value = self.get_autoneg(ethtool_output=output)
8c35c09d 514 elif attr == 'ring-rx':
515 output = utils.exec_command('%s --show-ring %s'%
516 (utils.ethtool_cmd, ifaceobj.name))
70bd0e86 517 attr_value = self.get_ring_setting(ethtool_output=output, setting='RX:', get_ring_max=get_max)
8c35c09d 518 elif attr == 'ring-tx':
519 output = utils.exec_command('%s --show-ring %s'%
520 (utils.ethtool_cmd, ifaceobj.name))
70bd0e86 521 attr_value = self.get_ring_setting(ethtool_output=output, setting='TX:', get_ring_max=get_max)
d8b6aad0 522 elif attr == 'fec':
d486dd0d
JF
523 output = utils.exec_command('%s --show-fec %s'%
524 (utils.ethtool_cmd, ifaceobj.name))
70bd0e86 525 attr_value = self.get_fec_encoding(ethtool_output=output)
ebd1f306
SA
526 elif attr == 'gro':
527 if not self.feature_cache:
528 self.feature_cache = utils.exec_command('%s --show-features %s'%
529 (utils.ethtool_cmd, ifaceobj.name))
70bd0e86 530 attr_value = self.get_offload_setting(ethtool_output=self.feature_cache, setting='generic-receive-offload')
ebd1f306
SA
531 elif attr == 'lro':
532 if not self.feature_cache:
533 self.feature_cache = utils.exec_command('%s --show-features %s'%
534 (utils.ethtool_cmd, ifaceobj.name))
70bd0e86 535 attr_value = self.get_offload_setting(ethtool_output=self.feature_cache, setting='large-receive-offload')
ebd1f306
SA
536 elif attr == 'gso':
537 if not self.feature_cache:
538 self.feature_cache = utils.exec_command('%s --show-features %s'%
539 (utils.ethtool_cmd, ifaceobj.name))
70bd0e86 540 attr_value = self.get_offload_setting(ethtool_output=self.feature_cache, setting='generic-segmentation-offload')
ebd1f306
SA
541 elif attr == 'tso':
542 if not self.feature_cache:
543 self.feature_cache = utils.exec_command('%s --show-features %s'%
544 (utils.ethtool_cmd, ifaceobj.name))
70bd0e86 545 attr_value = self.get_offload_setting(ethtool_output=self.feature_cache, setting='tcp-segmentation-offload')
ebd1f306
SA
546 elif attr == 'ufo':
547 if not self.feature_cache:
548 self.feature_cache = utils.exec_command('%s --show-features %s'%
549 (utils.ethtool_cmd, ifaceobj.name))
70bd0e86 550 attr_value = self.get_offload_setting(ethtool_output=self.feature_cache, setting='udp-fragmentation-offload')
ebd1f306
SA
551 elif attr == 'rx':
552 if not self.feature_cache:
553 self.feature_cache = utils.exec_command('%s --show-features %s'%
554 (utils.ethtool_cmd, ifaceobj.name))
70bd0e86 555 attr_value = self.get_offload_setting(ethtool_output=self.feature_cache, setting='rx-checksumming')
ebd1f306
SA
556 elif attr == 'tx':
557 if not self.feature_cache:
558 self.feature_cache = utils.exec_command('%s --show-features %s'%
559 (utils.ethtool_cmd, ifaceobj.name))
70bd0e86 560 attr_value = self.get_offload_setting(ethtool_output=self.feature_cache, setting='tx-checksumming')
d2431a3d 561 else:
70bd0e86 562 attr_value = self.io.read_file_oneline('/sys/class/net/%s/%s' % \
d2431a3d 563 (ifaceobj.name, attr))
a193d8d1 564 except Exception as e:
223ba5af
JF
565 if not self.ethtool_ignore_errors:
566 # for nonexistent interfaces, we get an error (rc = 256 or 19200)
567 self.logger.debug('ethtool: problems calling ethtool or reading'
568 ' /sys/class on iface %s for attr %s: %s' %
569 (ifaceobj.name, attr, str(e)))
70bd0e86 570 return attr_value
571
572 def get_running_attr(self,attr='',ifaceobj=None):
573 return self.get_attr_value(attr=attr, ifaceobj=ifaceobj, get_max=False)
d2431a3d 574
70bd0e86 575 def get_max_attr(self,attr='',ifaceobj=None):
576 return self.get_attr_value(attr=attr, ifaceobj=ifaceobj, get_max=True)
d2431a3d 577
3d44fbd0
ST
578 def _query_running(self, ifaceobj, ifaceobj_getfunc=None):
579 """
580 _query_running looks at the speed and duplex from /sys/class
581 and retreives autoneg from ethtool. We do not report autoneg
582 if speed is not available because this usually means the link is
583 down and the autoneg value is not reliable when the link is down.
584 """
585 # do not bother showing swp ifaces that are not up for the speed
586 # duplex and autoneg are not reliable.
223ba5af 587 if not self.cache.link_is_up(ifaceobj.name):
e74d01e1 588 return
3d44fbd0 589 for attr in ['speed', 'duplex', 'autoneg']:
8d60ab41
ST
590 default_val = policymanager.policymanager_api.get_iface_default(
591 module_name='ethtool',
592 ifname=ifaceobj.name,
593 attr='link-%s'%attr)
594 # do not continue if we have no defaults
595 # this avoids ethtool calls on virtual interfaces
596 if not default_val:
597 continue
d2431a3d 598 running_attr = self.get_running_attr(attr, ifaceobj)
d8b6aad0 599
16e30aab
ST
600 # Only show the link attributes if they differ from defaults
601 # to see the defaults, we should implement another flag (--with-defaults)
602 if default_val == running_attr:
603 continue
151d8024
RP
604
605 # do not proceed if speed = 0
606 if attr == 'speed' and running_attr and running_attr == '0':
607 return
8d60ab41 608 if running_attr:
3d44fbd0 609 ifaceobj.update_config('link-%s'%attr, running_attr)
15ef32ea 610
15ef32ea
RP
611 return
612
baa909c6
N
613 def _query(self, ifaceobj, **kwargs):
614 """ add default policy attributes supported by the module """
d8b6aad0 615 for attr in ['speed', 'duplex', 'autoneg', 'fec']:
baa909c6
N
616 if ifaceobj.get_attr_value_first('link-%s'%attr):
617 continue
618 default = policymanager.policymanager_api.get_iface_default(
619 module_name='ethtool',
620 ifname=ifaceobj.name,
621 attr='link-%s' %attr)
622 if not default:
623 continue
624 ifaceobj.update_config('link-%s' %attr, default)
625
3d44fbd0 626 _run_ops = {'pre-down' : _pre_down,
d486dd0d 627 'pre-up' : _pre_up,
3d44fbd0 628 'query-checkcurr' : _query_check,
baa909c6
N
629 'query-running' : _query_running,
630 'query' : _query}
15ef32ea
RP
631
632 def get_ops(self):
633 """ returns list of ops supported by this module """
3b01ed76 634 return list(self._run_ops.keys())
15ef32ea 635
84ca006f 636 def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args):
15ef32ea
RP
637 """ run ethtool configuration on the interface object passed as
638 argument
639
640 Args:
641 **ifaceobj** (object): iface object
642
643 **operation** (str): any of 'post-up', 'query-checkcurr',
644 'query-running'
645 Kwargs:
646 **query_ifaceobj** (object): query check ifaceobject. This is only
647 valid when op is 'query-checkcurr'. It is an object same as
648 ifaceobj, but contains running attribute values and its config
649 status. The modules can use it to return queried running state
650 of interfaces. status is success if the running state is same
651 as user required state in ifaceobj. error otherwise.
652 """
6ceda69e
JF
653 if (ifaceobj.link_kind or
654 ifaceobj.link_privflags & ifaceLinkPrivFlags.LOOPBACK):
d07b5a9f 655 return
15ef32ea
RP
656 op_handler = self._run_ops.get(operation)
657 if not op_handler:
658 return
15ef32ea 659 if operation == 'query-checkcurr':
6e16e5ae 660 op_handler(self, ifaceobj, query_ifaceobj)
15ef32ea
RP
661 else:
662 op_handler(self, ifaceobj)