diff options
Diffstat (limited to 'python/vyos/ifconfig')
-rw-r--r-- | python/vyos/ifconfig/__init__.py | 1 | ||||
-rw-r--r-- | python/vyos/ifconfig/ethernet.py | 17 | ||||
-rwxr-xr-x | python/vyos/ifconfig/interface.py | 92 | ||||
-rw-r--r-- | python/vyos/ifconfig/section.py | 10 | ||||
-rw-r--r-- | python/vyos/ifconfig/vxlan.py | 11 | ||||
-rw-r--r-- | python/vyos/ifconfig/wwan.py | 17 |
6 files changed, 111 insertions, 37 deletions
diff --git a/python/vyos/ifconfig/__init__.py b/python/vyos/ifconfig/__init__.py index 2d3e406ac..a37615c8f 100644 --- a/python/vyos/ifconfig/__init__.py +++ b/python/vyos/ifconfig/__init__.py @@ -26,6 +26,7 @@ from vyos.ifconfig.ethernet import EthernetIf from vyos.ifconfig.geneve import GeneveIf from vyos.ifconfig.loopback import LoopbackIf from vyos.ifconfig.macvlan import MACVLANIf +from vyos.ifconfig.input import InputIf from vyos.ifconfig.vxlan import VXLANIf from vyos.ifconfig.wireguard import WireGuardIf from vyos.ifconfig.vtun import VTunIf diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py index 2e59a7afc..9d54dc78e 100644 --- a/python/vyos/ifconfig/ethernet.py +++ b/python/vyos/ifconfig/ethernet.py @@ -80,6 +80,23 @@ class EthernetIf(Interface): super().__init__(ifname, **kargs) self.ethtool = Ethtool(ifname) + def remove(self): + """ + Remove interface from config. Removing the interface deconfigures all + assigned IP addresses. + Example: + >>> from vyos.ifconfig import WWANIf + >>> i = EthernetIf('eth0') + >>> i.remove() + """ + + if self.exists(self.ifname): + # interface is placed in A/D state when removed from config! It + # will remain visible for the operating system. + self.set_admin_state('down') + + super().remove() + def set_flow_control(self, enable): """ Changes the pause parameters of the specified Ethernet device. diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 58d130ef6..91c7f0c33 100755 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -37,6 +37,7 @@ 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.util import get_interface_namespace from vyos.util import is_systemd_service_active from vyos.template import is_ipv4 from vyos.template import is_ipv6 @@ -135,6 +136,9 @@ class Interface(Control): 'validate': assert_mtu, 'shellcmd': 'ip link set dev {ifname} mtu {value}', }, + 'netns': { + 'shellcmd': 'ip link set dev {ifname} netns {value}', + }, 'vrf': { 'convert': lambda v: f'master {v}' if v else 'nomaster', 'shellcmd': 'ip link set dev {ifname} {value}', @@ -512,6 +516,35 @@ class Interface(Control): if prev_state == 'up': self.set_admin_state('up') + def del_netns(self, netns): + """ + Remove interface from given NETNS. + """ + + # If NETNS does not exist then there is nothing to delete + if not os.path.exists(f'/run/netns/{netns}'): + return None + + # As a PoC we only allow 'dummy' interfaces + if 'dum' not in self.ifname: + return None + + # Check if interface realy exists in namespace + if get_interface_namespace(self.ifname) != None: + self._cmd(f'ip netns exec {get_interface_namespace(self.ifname)} ip link del dev {self.ifname}') + return + + def set_netns(self, netns): + """ + Add interface from given NETNS. + + Example: + >>> from vyos.ifconfig import Interface + >>> Interface('dum0').set_netns('foo') + """ + + self.set_interface('netns', netns) + def set_vrf(self, vrf): """ Add/Remove interface from given VRF instance. @@ -544,6 +577,15 @@ class Interface(Control): return None return self.set_interface('arp_cache_tmo', tmo) + def _cleanup_mss_rules(self, table, ifname): + commands = [] + results = self._cmd(f'nft -a list chain {table} VYOS_TCP_MSS').split("\n") + for line in results: + if f'oifname "{ifname}"' in line: + handle_search = re.search('handle (\d+)', line) + if handle_search: + self._cmd(f'nft delete rule {table} VYOS_TCP_MSS handle {handle_search[1]}') + def set_tcp_ipv4_mss(self, mss): """ Set IPv4 TCP MSS value advertised when TCP SYN packets leave this @@ -555,22 +597,14 @@ class Interface(Control): >>> from vyos.ifconfig import Interface >>> Interface('eth0').set_tcp_ipv4_mss(1340) """ - iptables_bin = 'iptables' - base_options = f'-A FORWARD -o {self.ifname} -p tcp -m tcp --tcp-flags SYN,RST SYN' - out = self._cmd(f'{iptables_bin}-save -t mangle') - for line in out.splitlines(): - if line.startswith(base_options): - # remove OLD MSS mangling configuration - line = line.replace('-A FORWARD', '-D FORWARD') - self._cmd(f'{iptables_bin} -t mangle {line}') - - cmd_mss = f'{iptables_bin} -t mangle {base_options} --jump TCPMSS' + self._cleanup_mss_rules('raw', self.ifname) + nft_prefix = 'nft add rule raw VYOS_TCP_MSS' + base_cmd = f'oifname "{self.ifname}" tcp flags & (syn|rst) == syn' if mss == 'clamp-mss-to-pmtu': - self._cmd(f'{cmd_mss} --clamp-mss-to-pmtu') + self._cmd(f"{nft_prefix} '{base_cmd} tcp option maxseg size set rt mtu'") elif int(mss) > 0: - # probably add option to clamp only if bigger: low_mss = str(int(mss) + 1) - self._cmd(f'{cmd_mss} -m tcpmss --mss {low_mss}:65535 --set-mss {mss}') + self._cmd(f"{nft_prefix} '{base_cmd} tcp option maxseg size {low_mss}-65535 tcp option maxseg size set {mss}'") def set_tcp_ipv6_mss(self, mss): """ @@ -583,22 +617,14 @@ class Interface(Control): >>> from vyos.ifconfig import Interface >>> Interface('eth0').set_tcp_mss(1320) """ - iptables_bin = 'ip6tables' - base_options = f'-A FORWARD -o {self.ifname} -p tcp -m tcp --tcp-flags SYN,RST SYN' - out = self._cmd(f'{iptables_bin}-save -t mangle') - for line in out.splitlines(): - if line.startswith(base_options): - # remove OLD MSS mangling configuration - line = line.replace('-A FORWARD', '-D FORWARD') - self._cmd(f'{iptables_bin} -t mangle {line}') - - cmd_mss = f'{iptables_bin} -t mangle {base_options} --jump TCPMSS' + self._cleanup_mss_rules('ip6 raw', self.ifname) + nft_prefix = 'nft add rule ip6 raw VYOS_TCP_MSS' + base_cmd = f'oifname "{self.ifname}" tcp flags & (syn|rst) == syn' if mss == 'clamp-mss-to-pmtu': - self._cmd(f'{cmd_mss} --clamp-mss-to-pmtu') + self._cmd(f"{nft_prefix} '{base_cmd} tcp option maxseg size set rt mtu'") elif int(mss) > 0: - # probably add option to clamp only if bigger: low_mss = str(int(mss) + 1) - self._cmd(f'{cmd_mss} -m tcpmss --mss {low_mss}:65535 --set-mss {mss}') + self._cmd(f"{nft_prefix} '{base_cmd} tcp option maxseg size {low_mss}-65535 tcp option maxseg size set {mss}'") def set_arp_filter(self, arp_filter): """ @@ -1271,8 +1297,8 @@ class Interface(Control): source_if = next(iter(self._config['is_mirror_intf'])) config = self._config['is_mirror_intf'][source_if].get('mirror', None) - # Check configuration stored by old perl code before delete T3782 - if not 'redirect' in self._config: + # Check configuration stored by old perl code before delete T3782/T4056 + if not 'redirect' in self._config and not 'traffic_policy' in self._config: # Please do not clear the 'set $? = 0 '. It's meant to force a return of 0 # Remove existing mirroring rules delete_tc_cmd = f'tc qdisc del dev {source_if} handle ffff: ingress 2> /dev/null;' @@ -1353,6 +1379,16 @@ class Interface(Control): if mac: self.set_mac(mac) + # If interface is connected to NETNS we don't have to check all other + # settings like MTU/IPv6/sysctl values, etc. + # Since the interface is pushed onto a separate logical stack + # Configure NETNS + if dict_search('netns', config) != None: + self.set_netns(config.get('netns', '')) + return + else: + self.del_netns(config.get('netns', '')) + # Update interface description self.set_alias(config.get('description', '')) diff --git a/python/vyos/ifconfig/section.py b/python/vyos/ifconfig/section.py index 0e4447b9e..91f667b65 100644 --- a/python/vyos/ifconfig/section.py +++ b/python/vyos/ifconfig/section.py @@ -52,12 +52,12 @@ class Section: name: name of the interface vlan: if vlan is True, do not stop at the vlan number """ - name = name.rstrip('0123456789') - name = name.rstrip('.') - if vlan: - name = name.rstrip('0123456789.') if vrrp: - name = name.rstrip('0123456789v') + name = re.sub(r'\d(\d|v|\.)*$', '', name) + elif vlan: + name = re.sub(r'\d(\d|\.)*$', '', name) + else: + name = re.sub(r'\d+$', '', name) return name @classmethod diff --git a/python/vyos/ifconfig/vxlan.py b/python/vyos/ifconfig/vxlan.py index d73fb47b8..0c5282db4 100644 --- a/python/vyos/ifconfig/vxlan.py +++ b/python/vyos/ifconfig/vxlan.py @@ -54,18 +54,21 @@ class VXLANIf(Interface): # arguments used by iproute2. For more information please refer to: # - https://man7.org/linux/man-pages/man8/ip-link.8.html mapping = { - 'source_address' : 'local', - 'source_interface' : 'dev', - 'remote' : 'remote', 'group' : 'group', + 'external' : 'external', + 'gpe' : 'gpe', 'parameters.ip.dont_fragment': 'df set', 'parameters.ip.tos' : 'tos', 'parameters.ip.ttl' : 'ttl', 'parameters.ipv6.flowlabel' : 'flowlabel', 'parameters.nolearning' : 'nolearning', + 'remote' : 'remote', + 'source_address' : 'local', + 'source_interface' : 'dev', + 'vni' : 'id', } - cmd = 'ip link add {ifname} type {type} id {vni} dstport {port}' + cmd = 'ip link add {ifname} type {type} dstport {port}' 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 diff --git a/python/vyos/ifconfig/wwan.py b/python/vyos/ifconfig/wwan.py index f18959a60..845c9bef9 100644 --- a/python/vyos/ifconfig/wwan.py +++ b/python/vyos/ifconfig/wwan.py @@ -26,3 +26,20 @@ class WWANIf(Interface): 'eternal': 'wwan[0-9]+$', }, } + + def remove(self): + """ + Remove interface from config. Removing the interface deconfigures all + assigned IP addresses. + Example: + >>> from vyos.ifconfig import WWANIf + >>> i = WWANIf('wwan0') + >>> i.remove() + """ + + if self.exists(self.ifname): + # interface is placed in A/D state when removed from config! It + # will remain visible for the operating system. + self.set_admin_state('down') + + super().remove() |