Merge pull request #37 from olysonek/plugin_net_pr
plugin_net: Implement setting 'pause' and 'ring' parameters
This commit is contained in:
commit
320a704232
1 changed files with 84 additions and 23 deletions
|
|
@ -104,13 +104,28 @@ class NetTuningPlugin(base.Plugin):
|
|||
"sample-interval": None
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def _get_config_options_pause(cls):
|
||||
return { "autoneg": None,
|
||||
"rx": None,
|
||||
"tx": None }
|
||||
|
||||
@classmethod
|
||||
def _get_config_options_ring(cls):
|
||||
return { "rx": None,
|
||||
"rx-mini": None,
|
||||
"rx-jumbo": None,
|
||||
"tx": None }
|
||||
|
||||
@classmethod
|
||||
def _get_config_options(cls):
|
||||
return {
|
||||
"wake_on_lan": None,
|
||||
"nf_conntrack_hashsize": None,
|
||||
"features": None,
|
||||
"coalesce": None
|
||||
"coalesce": None,
|
||||
"pause": None,
|
||||
"ring": None,
|
||||
}
|
||||
|
||||
def _init_stats_and_idle(self, instance, device):
|
||||
|
|
@ -243,45 +258,83 @@ class NetTuningPlugin(base.Plugin):
|
|||
return None
|
||||
|
||||
# d is dict: {parameter: value}
|
||||
def _check_coalesce_parameters(self, d):
|
||||
sck = set(d.keys())
|
||||
sck_supported = set(self._get_config_options_coalesce().keys())
|
||||
if not sck.issubset(sck_supported):
|
||||
log.error("unknown coalesce parameter(s): %s" % str(sck - sck_supported))
|
||||
def _check_parameters(self, context, d):
|
||||
if context == "features":
|
||||
return True
|
||||
params = set(d.keys())
|
||||
supported_getter = { "coalesce": self._get_config_options_coalesce, \
|
||||
"pause": self._get_config_options_pause, \
|
||||
"ring": self._get_config_options_ring }
|
||||
supported = set(supported_getter[context]().keys())
|
||||
if not params.issubset(supported):
|
||||
log.error("unknown %s parameter(s): %s" % (context, str(params - supported)))
|
||||
return False
|
||||
return True
|
||||
|
||||
def _get_device_parameters(self, coalesce, device):
|
||||
ret, value = self._cmd.execute(["ethtool", "-c" if coalesce else "-k", device])
|
||||
# parse output of ethtool -a
|
||||
def _parse_pause_parameters(self, s):
|
||||
s = self._cmd.multiple_re_replace(\
|
||||
{"Autonegotiate": "autoneg",
|
||||
"RX": "rx",
|
||||
"TX": "tx"}, s)
|
||||
l = s.split("\n")[1:]
|
||||
l = filter(lambda x: x != '' and not re.search(r"\[fixed\]", x), l)
|
||||
return dict(filter(lambda x: len(x) == 2, map(lambda x: re.split(r":\s*", x), l)))
|
||||
|
||||
# parse output of ethtool -g
|
||||
def _parse_ring_parameters(self, s):
|
||||
a = re.split(r"^Current hardware settings:$", s, flags=re.MULTILINE)
|
||||
s = a[1]
|
||||
s = self._cmd.multiple_re_replace(\
|
||||
{"RX": "rx",
|
||||
"RX Mini": "rx-mini",
|
||||
"RX Jumbo": "rx-jumbo",
|
||||
"TX": "tx"}, s)
|
||||
l = s.split("\n")
|
||||
l = filter(lambda x: x != '', l)
|
||||
l = filter(lambda x: len(x) == 2, map(lambda x: re.split(r":\s*", x), l))
|
||||
return dict(l)
|
||||
|
||||
def _get_device_parameters(self, context, device):
|
||||
context2opt = { "coalesce": "-c", "features": "-k", "pause": "-a", "ring": "-g" }
|
||||
opt = context2opt[context]
|
||||
ret, value = self._cmd.execute(["ethtool", opt, device])
|
||||
if ret != 0 or len(value) == 0:
|
||||
return None
|
||||
d = self._parse_device_parameters(value)
|
||||
if coalesce and not self._check_coalesce_parameters(d):
|
||||
context2parser = { "coalesce": self._parse_device_parameters, \
|
||||
"features": self._parse_device_parameters, \
|
||||
"pause": self._parse_pause_parameters, \
|
||||
"ring": self._parse_ring_parameters }
|
||||
parser = context2parser[context]
|
||||
d = parser(value)
|
||||
if context == "coalesce" and not self._check_parameters(context, d):
|
||||
return None
|
||||
return d
|
||||
|
||||
def _set_device_parameters(self, coalesce, value, device, sim):
|
||||
def _set_device_parameters(self, context, value, device, sim):
|
||||
if value is None or len(value) == 0:
|
||||
return None
|
||||
d = self._parse_config_parameters(value, "coalesce" if coalesce else "features")
|
||||
if d is None or (coalesce and not self._check_coalesce_parameters(d)):
|
||||
d = self._parse_config_parameters(value, context)
|
||||
if d is None or not self._check_parameters(context, d):
|
||||
return None
|
||||
if not sim:
|
||||
log.debug("setting %s: %s" % ("coalesce" if coalesce else "features", str(d)))
|
||||
log.debug("setting %s: %s" % (context, str(d)))
|
||||
# ignore ethtool return code 80, it means parameter is already set
|
||||
self._cmd.execute(["ethtool", "-C" if coalesce else "-K", device] + self._cmd.dict2list(d), no_errors = [80])
|
||||
context2opt = { "coalesce": "-C", "features": "-K", "pause": "-A", "ring": "-G" }
|
||||
opt = context2opt[context]
|
||||
self._cmd.execute(["ethtool", opt, device] + self._cmd.dict2list(d), no_errors = [80])
|
||||
return d
|
||||
|
||||
def _custom_parameters(self, coalesce, start, value, device, verify):
|
||||
storage_key = self._storage_key("coalesce" if coalesce else "features", device)
|
||||
def _custom_parameters(self, context, start, value, device, verify):
|
||||
storage_key = self._storage_key(context, device)
|
||||
if start:
|
||||
cd = self._get_device_parameters(coalesce, device)
|
||||
d = self._set_device_parameters(coalesce, value, device, verify)
|
||||
cd = self._get_device_parameters(context, device)
|
||||
d = self._set_device_parameters(context, value, device, verify)
|
||||
# backup only parameters which are changed
|
||||
sd = dict(filter(lambda (k, v): k in d, cd.items()))
|
||||
if len(d) != len(sd):
|
||||
log.error("unable to save previous %s, wanted to save: '%s', but read: '%s'" % \
|
||||
("coalesce" if coalesce else "features", str(d.keys()), str(cd.items())))
|
||||
(context, str(d.keys()), str(cd.items())))
|
||||
return False
|
||||
if verify:
|
||||
return self._cmd.dict2list(d) == self._cmd.dict2list(sd)
|
||||
|
|
@ -289,13 +342,21 @@ class NetTuningPlugin(base.Plugin):
|
|||
else:
|
||||
if not verify:
|
||||
original_value = self._storage.get(storage_key)
|
||||
self._set_device_parameters(coalesce, original_value, device, False)
|
||||
self._set_device_parameters(context, original_value, device, False)
|
||||
return None
|
||||
|
||||
@command_custom("features", per_device = True)
|
||||
def _features(self, start, value, device, verify, ignore_missing):
|
||||
return self._custom_parameters(False, start, value, device, verify)
|
||||
return self._custom_parameters("features", start, value, device, verify)
|
||||
|
||||
@command_custom("coalesce", per_device = True)
|
||||
def _coalesce(self, start, value, device, verify, ignore_missing):
|
||||
return self._custom_parameters(True, start, value, device, verify)
|
||||
return self._custom_parameters("coalesce", start, value, device, verify)
|
||||
|
||||
@command_custom("pause", per_device = True)
|
||||
def _pause(self, start, value, device, verify, ignore_missing):
|
||||
return self._custom_parameters("pause", start, value, device, verify)
|
||||
|
||||
@command_custom("ring", per_device = True)
|
||||
def _ring(self, start, value, device, verify, ignore_missing):
|
||||
return self._custom_parameters("ring", start, value, device, verify)
|
||||
|
|
|
|||
Loading…
Reference in a new issue