]>
Commit | Line | Data |
---|---|---|
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 | |
7 | import os | |
15ef32ea RP |
8 | |
9 | try: | |
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 | 22 | except (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 | 37 | class 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) |