summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Mangin <thomas.mangin@exa.net.uk>2020-06-23 18:24:29 +0100
committerThomas Mangin <thomas.mangin@exa.net.uk>2020-06-23 18:24:29 +0100
commitfba3e4b624529576cbfe59f10dfc1bb3df80634f (patch)
treebad69c9e8914e932df7f628478ffdc124d95669c
parent70d45cdec4263a0eff1146656ae8e8012ab125b6 (diff)
downloadvyos-1x-fba3e4b624529576cbfe59f10dfc1bb3df80634f.tar.gz
vyos-1x-fba3e4b624529576cbfe59f10dfc1bb3df80634f.zip
validation: T2630: bound to interface mtu if available
-rw-r--r--python/vyos/ifconfig/control.py34
-rw-r--r--python/vyos/validate.py31
2 files changed, 60 insertions, 5 deletions
diff --git a/python/vyos/ifconfig/control.py b/python/vyos/ifconfig/control.py
index 0958be642..a6fc8ac6c 100644
--- a/python/vyos/ifconfig/control.py
+++ b/python/vyos/ifconfig/control.py
@@ -15,6 +15,8 @@
import os
+from inspect import signature
+from inspect import _empty
from vyos import debug
from vyos.util import popen
@@ -25,6 +27,7 @@ from vyos.ifconfig.section import Section
class Control(Section):
_command_get = {}
_command_set = {}
+ _signature = {}
def __init__(self, **kargs):
# some commands (such as operation comands - show interfaces, etc.)
@@ -54,6 +57,30 @@ class Control(Section):
cmd = self._command_get[name]['shellcmd'].format(**config)
return self._command_get[name].get('format', lambda _: _)(self._cmd(cmd))
+ def _values(self, name, validate, value):
+ """
+ looks at the validation function "validate"
+ for the interface sysfs or command and
+ returns a dict with the right options to call it
+ """
+ if name not in self._signature:
+ self._signature[name] = signature(validate)
+
+ values = {}
+
+ for k in self._signature[name].parameters:
+ default = self._signature[name].parameters[k].default
+ if default is not _empty:
+ continue
+ if k == 'self':
+ values[k] = self
+ elif k == 'ifname':
+ values[k] = self.ifname
+ else:
+ values[k] = value
+
+ return values
+
def _set_command(self, config, name, value):
"""
Using the defined names, set data write to sysfs.
@@ -64,7 +91,7 @@ class Control(Section):
validate = self._command_set[name].get('validate', None)
if validate:
try:
- validate(value)
+ validate(**self._values(name, validate, value))
except Exception as e:
raise e.__class__(f'Could not set {name}. {e}')
@@ -124,7 +151,10 @@ class Control(Section):
validate = self._sysfs_set[name].get('validate', None)
if validate:
- validate(value)
+ try:
+ validate(**self._values(name, validate, value))
+ except Exception as e:
+ raise e.__class__(f'Could not set {name}. {e}')
config = {**config, **{'value': value}}
diff --git a/python/vyos/validate.py b/python/vyos/validate.py
index 6304fa8de..9072c5817 100644
--- a/python/vyos/validate.py
+++ b/python/vyos/validate.py
@@ -13,10 +13,23 @@
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
+import json
import socket
import netifaces
import ipaddress
+from vyos.util import cmd
+
+# Important note when you are adding new validation functions:
+#
+# The Control class will analyse the signature of the function in this file
+# and will build the parameters to be passed to it.
+#
+# The parameter names "ifname" and "self" will get the Interface name and class
+# parameters with default will be left unset
+# all other paramters will receive the value to check
+
+
def is_ip(addr):
"""
Check addr if it is an IPv4 or IPv6 address
@@ -208,10 +221,21 @@ def assert_positive(n, smaller=0):
raise ValueError(f'{n} is smaller than {smaller}')
-def assert_mtu(mtu, min=68, max=9000):
+def assert_mtu(mtu, ifname):
assert_number(mtu)
- if int(mtu) < min or int(mtu) > max:
- raise ValueError(f'Invalid MTU size: "{mtu}"')
+
+ out = cmd(f'ip -j -d link show dev {ifname}')
+ # [{"ifindex":2,"ifname":"eth0","flags":["BROADCAST","MULTICAST","UP","LOWER_UP"],"mtu":1500,"qdisc":"pfifo_fast","operstate":"UP","linkmode":"DEFAULT","group":"default","txqlen":1000,"link_type":"ether","address":"08:00:27:d9:5b:04","broadcast":"ff:ff:ff:ff:ff:ff","promiscuity":0,"min_mtu":46,"max_mtu":16110,"inet6_addr_gen_mode":"none","num_tx_queues":1,"num_rx_queues":1,"gso_max_size":65536,"gso_max_segs":65535}]
+ parsed = json.loads(out)[0]
+ min_mtu = int(parsed.get('min_mtu', '0'))
+ # cur_mtu = parsed.get('mtu',0),
+ max_mtu = int(parsed.get('max_mtu', '0'))
+ cur_mtu = int(mtu)
+
+ if (min_mtu and cur_mtu < min_mtu) or cur_mtu < 68:
+ raise ValueError(f'MTU is too small for interface "{ifname}": {mtu} < {min_mtu}')
+ if (max_mtu and cur_mtu > max_mtu) or cur_mtu > 65536:
+ raise ValueError(f'MTU is too small for interface "{ifname}": {mtu} > {max_mtu}')
def assert_mac(m):
@@ -241,6 +265,7 @@ def assert_mac(m):
if octets[:5] == (0, 0, 94, 0, 1):
raise ValueError(f'{m} is a VRRP MAC address')
+
def is_member(conf, interface, intftype=None):
"""
Checks if passed interface is member of other interface of specified type.