summaryrefslogtreecommitdiff
path: root/python/vyos/ifconfig
diff options
context:
space:
mode:
Diffstat (limited to 'python/vyos/ifconfig')
-rw-r--r--python/vyos/ifconfig/bond.py34
-rw-r--r--python/vyos/ifconfig/interface.py97
-rw-r--r--python/vyos/ifconfig/tunnel.py1
-rw-r--r--python/vyos/ifconfig/vti.py32
4 files changed, 149 insertions, 15 deletions
diff --git a/python/vyos/ifconfig/bond.py b/python/vyos/ifconfig/bond.py
index bfa3b0025..233d53688 100644
--- a/python/vyos/ifconfig/bond.py
+++ b/python/vyos/ifconfig/bond.py
@@ -51,6 +51,10 @@ class BondIf(Interface):
'validate': assert_positive,
'location': '/sys/class/net/{ifname}/bonding/min_links',
},
+ 'bond_lacp_rate': {
+ 'validate': lambda v: assert_list(v, ['slow', 'fast']),
+ 'location': '/sys/class/net/{ifname}/bonding/lacp_rate',
+ },
'bond_miimon': {
'validate': assert_positive,
'location': '/sys/class/net/{ifname}/bonding/miimon'
@@ -152,6 +156,26 @@ class BondIf(Interface):
"""
self.set_interface('bond_min_links', number)
+ def set_lacp_rate(self, slow_fast):
+ """
+ Option specifying the rate in which we'll ask our link partner
+ to transmit LACPDU packets in 802.3ad mode. Possible values
+ are:
+
+ slow or 0
+ Request partner to transmit LACPDUs every 30 seconds
+
+ fast or 1
+ Request partner to transmit LACPDUs every 1 second
+
+ The default is slow.
+
+ Example:
+ >>> from vyos.ifconfig import BondIf
+ >>> BondIf('bond0').set_lacp_rate('slow')
+ """
+ self.set_interface('bond_lacp_rate', slow_fast)
+
def set_arp_interval(self, interval):
"""
Specifies the ARP link monitoring frequency in milliseconds.
@@ -382,9 +406,13 @@ class BondIf(Interface):
if not dict_search(f'member.interface_remove.{interface}.disable', config):
Interface(interface).set_admin_state('up')
- # Bonding policy/mode
- value = config.get('mode')
- if value: self.set_mode(value)
+ # Bonding policy/mode - default value, always present
+ mode = config.get('mode')
+ self.set_mode(mode)
+
+ # LACPDU transmission rate - default value
+ if mode == '802.3ad':
+ self.set_lacp_rate(config.get('lacp_rate'))
# Add (enslave) interfaces to bond
value = dict_search('member.interface', config)
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py
index ff05cab0e..6a66d958f 100644
--- a/python/vyos/ifconfig/interface.py
+++ b/python/vyos/ifconfig/interface.py
@@ -36,6 +36,7 @@ from vyos.template import render
from vyos.util import mac2eui64
from vyos.util import dict_search
from vyos.util import read_file
+from vyos.util import get_interface_config
from vyos.template import is_ipv4
from vyos.validate import is_intf_addr_assigned
from vyos.validate import is_ipv6_link_local
@@ -743,28 +744,37 @@ class Interface(Control):
"""
self.set_interface('proxy_arp_pvlan', enable)
- def get_addr(self):
+ def get_addr_v4(self):
"""
- Retrieve assigned IPv4 and IPv6 addresses from given interface.
+ Retrieve assigned IPv4 addresses from given interface.
This is done using the netifaces and ipaddress python modules.
Example:
>>> from vyos.ifconfig import Interface
- >>> Interface('eth0').get_addrs()
- ['172.16.33.30/24', 'fe80::20c:29ff:fe11:a174/64']
+ >>> Interface('eth0').get_addr_v4()
+ ['172.16.33.30/24']
"""
-
ipv4 = []
- ipv6 = []
-
- if AF_INET in ifaddresses(self.config['ifname']).keys():
+ if AF_INET in ifaddresses(self.config['ifname']):
for v4_addr in ifaddresses(self.config['ifname'])[AF_INET]:
# we need to manually assemble a list of IPv4 address/prefix
prefix = '/' + \
str(IPv4Network('0.0.0.0/' + v4_addr['netmask']).prefixlen)
ipv4.append(v4_addr['addr'] + prefix)
+ return ipv4
+
+ def get_addr_v6(self):
+ """
+ Retrieve assigned IPv6 addresses from given interface.
+ This is done using the netifaces and ipaddress python modules.
- if AF_INET6 in ifaddresses(self.config['ifname']).keys():
+ Example:
+ >>> from vyos.ifconfig import Interface
+ >>> Interface('eth0').get_addr_v6()
+ ['fe80::20c:29ff:fe11:a174/64']
+ """
+ ipv6 = []
+ if AF_INET6 in ifaddresses(self.config['ifname']):
for v6_addr in ifaddresses(self.config['ifname'])[AF_INET6]:
# Note that currently expanded netmasks are not supported. That means
# 2001:db00::0/24 is a valid argument while 2001:db00::0/ffff:ff00:: not.
@@ -777,8 +787,18 @@ class Interface(Control):
# addresses
v6_addr['addr'] = v6_addr['addr'].split('%')[0]
ipv6.append(v6_addr['addr'] + prefix)
+ return ipv6
- return ipv4 + ipv6
+ def get_addr(self):
+ """
+ Retrieve assigned IPv4 and IPv6 addresses from given interface.
+
+ Example:
+ >>> from vyos.ifconfig import Interface
+ >>> Interface('eth0').get_addr()
+ ['172.16.33.30/24', 'fe80::20c:29ff:fe11:a174/64']
+ """
+ return self.get_addr_v4() + self.get_addr_v6()
def add_addr(self, addr):
"""
@@ -1289,6 +1309,16 @@ class Interface(Control):
vif_s_ifname = f'{ifname}.{vif_s_id}'
vif_s_config['ifname'] = vif_s_ifname
+
+ # It is not possible to change the VLAN encapsulation protocol
+ # "on-the-fly". For this "quirk" we need to actively delete and
+ # re-create the VIF-S interface.
+ if self.exists(vif_s_ifname):
+ cur_cfg = get_interface_config(vif_s_ifname)
+ protocol = dict_search('linkinfo.info_data.protocol', cur_cfg).lower()
+ if protocol != vif_s_config['protocol']:
+ VLANIf(vif_s_ifname).remove()
+
s_vlan = VLANIf(vif_s_ifname, **tmp)
s_vlan.update(vif_s_config)
@@ -1315,12 +1345,55 @@ class Interface(Control):
# create/update 802.1q VLAN interfaces
for vif_id, vif_config in config.get('vif', {}).items():
+
+ vif_ifname = f'{ifname}.{vif_id}'
+ vif_config['ifname'] = vif_ifname
+
tmp = deepcopy(VLANIf.get_config())
tmp['source_interface'] = ifname
tmp['vlan_id'] = vif_id
+
+ # We need to ensure that the string format is consistent, and we need to exclude redundant spaces.
+ sep = ' '
+ if 'egress_qos' in vif_config:
+ # Unwrap strings into arrays
+ egress_qos_array = vif_config['egress_qos'].split()
+ # The split array is spliced according to the fixed format
+ tmp['egress_qos'] = sep.join(egress_qos_array)
+
+ if 'ingress_qos' in vif_config:
+ # Unwrap strings into arrays
+ ingress_qos_array = vif_config['ingress_qos'].split()
+ # The split array is spliced according to the fixed format
+ tmp['ingress_qos'] = sep.join(ingress_qos_array)
+
+ # Since setting the QoS control parameters in the later stage will
+ # not completely delete the old settings,
+ # we still need to delete the VLAN encapsulation interface in order to
+ # ensure that the changed settings are effective.
+ cur_cfg = get_interface_config(vif_ifname)
+ qos_str = ''
+ tmp2 = dict_search('linkinfo.info_data.ingress_qos', cur_cfg)
+ if 'ingress_qos' in tmp and tmp2:
+ for item in tmp2:
+ from_key = item['from']
+ to_key = item['to']
+ qos_str += f'{from_key}:{to_key} '
+ if qos_str != tmp['ingress_qos']:
+ if self.exists(vif_ifname):
+ VLANIf(vif_ifname).remove()
+
+ qos_str = ''
+ tmp2 = dict_search('linkinfo.info_data.egress_qos', cur_cfg)
+ if 'egress_qos' in tmp and tmp2:
+ for item in tmp2:
+ from_key = item['from']
+ to_key = item['to']
+ qos_str += f'{from_key}:{to_key} '
+ if qos_str != tmp['egress_qos']:
+ if self.exists(vif_ifname):
+ VLANIf(vif_ifname).remove()
- vif_ifname = f'{ifname}.{vif_id}'
- vif_config['ifname'] = vif_ifname
vlan = VLANIf(vif_ifname, **tmp)
vlan.update(vif_config)
diff --git a/python/vyos/ifconfig/tunnel.py b/python/vyos/ifconfig/tunnel.py
index 2a266fc9f..64c735824 100644
--- a/python/vyos/ifconfig/tunnel.py
+++ b/python/vyos/ifconfig/tunnel.py
@@ -62,6 +62,7 @@ class TunnelIf(Interface):
mapping_ipv4 = {
'parameters.ip.key' : 'key',
'parameters.ip.no_pmtu_discovery' : 'nopmtudisc',
+ 'parameters.ip.ignore_df' : 'ignore-df',
'parameters.ip.tos' : 'tos',
'parameters.ip.ttl' : 'ttl',
'parameters.erspan.direction' : 'erspan_dir',
diff --git a/python/vyos/ifconfig/vti.py b/python/vyos/ifconfig/vti.py
index e2090c889..9eafcd11b 100644
--- a/python/vyos/ifconfig/vti.py
+++ b/python/vyos/ifconfig/vti.py
@@ -14,6 +14,7 @@
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
from vyos.ifconfig.interface import Interface
+from vyos.util import dict_search
@Interface.register
class VTIIf(Interface):
@@ -25,3 +26,34 @@ class VTIIf(Interface):
'prefixes': ['vti', ],
},
}
+
+ def _create(self):
+ # This table represents a mapping from VyOS internal config dict to
+ # arguments used by iproute2. For more information please refer to:
+ # - https://man7.org/linux/man-pages/man8/ip-link.8.html
+ # - https://man7.org/linux/man-pages/man8/ip-tunnel.8.html
+ mapping = {
+ 'source_address' : 'local',
+ 'source_interface' : 'dev',
+ 'remote' : 'remote',
+ 'key' : 'key',
+ }
+
+ cmd = 'ip link add {ifname} type vti'
+ for vyos_key, iproute2_key in mapping.items():
+ # dict_search will return an empty dict "{}" for valueless nodes like
+ # "parameters.nolearning" - thus we need to test the nodes existence
+ # by using isinstance()
+ tmp = dict_search(vyos_key, self.config)
+ if isinstance(tmp, dict):
+ cmd += f' {iproute2_key}'
+ elif tmp != None:
+ cmd += f' {iproute2_key} {tmp}'
+
+ self._cmd(cmd.format(**self.config))
+ self.set_interface('admin_state', 'down')
+
+ def set_admin_state(self, state):
+ # function is not implemented for VTI interfaces as this is entirely
+ # handled by the ipsec up/down scripts
+ pass