From 410ac0dac8400aae1523a51184726ff7606dc5fd Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 3 Jan 2020 16:26:42 +0100 Subject: ifconfig: T1939: provide abstraction for interface "ip" option Provide an XML/Python abstraction to * ip disable-arp-filter * ip enable-arp-accept * ip enable-arp-announce * ip enable-arp-ignore The old implementation can co-exist until the last interfaces have been migrated. --- python/vyos/configdict.py | 20 +++++++++++ python/vyos/ifconfig.py | 85 ++++++++++++++++++++++++++++++++++++++++++++ python/vyos/ifconfig_vlan.py | 8 +++++ 3 files changed, 113 insertions(+) (limited to 'python') diff --git a/python/vyos/configdict.py b/python/vyos/configdict.py index 7f5ae3db9..80e199907 100644 --- a/python/vyos/configdict.py +++ b/python/vyos/configdict.py @@ -119,6 +119,10 @@ def vlan_to_dict(conf): 'disable_link_detect': 1, 'egress_qos': '', 'egress_qos_changed': False, + 'ip_disable_arp_filter': 1, + 'ip_enable_arp_accept': 0, + 'ip_enable_arp_announce': 0, + 'ip_enable_arp_ignore': 0, 'ingress_qos': '', 'ingress_qos_changed': False, 'mac': '', @@ -166,6 +170,22 @@ def vlan_to_dict(conf): if conf.exists('disable'): vlan['disable'] = True + # ARP filter configuration + if conf.exists('ip disable-arp-filter'): + vlan['ip_disable_arp_filter'] = 0 + + # ARP enable accept + if conf.exists('ip enable-arp-accept'): + vlan['ip_enable_arp_accept'] = 1 + + # ARP enable announce + if conf.exists('ip enable-arp-announce'): + vlan['ip_enable_arp_announce'] = 1 + + # ARP enable ignore + if conf.exists('ip enable-arp-ignore'): + vlan['ip_enable_arp_ignore'] = 1 + # Media Access Control (MAC) address if conf.exists('mac'): vlan['mac'] = conf.return_value('mac') diff --git a/python/vyos/ifconfig.py b/python/vyos/ifconfig.py index 36bd8c57c..90b8fc169 100644 --- a/python/vyos/ifconfig.py +++ b/python/vyos/ifconfig.py @@ -261,6 +261,91 @@ class Interface: return self._write_sysfs('/proc/sys/net/ipv4/neigh/{0}/base_reachable_time_ms' .format(self._ifname), (int(tmo) * 1000)) + def set_arp_filter(self, arp_filter): + """ + Filter ARP requests + + 1 - Allows you to have multiple network interfaces on the same + subnet, and have the ARPs for each interface be answered + based on whether or not the kernel would route a packet from + the ARP'd IP out that interface (therefore you must use source + based routing for this to work). In other words it allows control + of which cards (usually 1) will respond to an arp request. + + 0 - (default) The kernel can respond to arp requests with addresses + from other interfaces. This may seem wrong but it usually makes + sense, because it increases the chance of successful communication. + IP addresses are owned by the complete host on Linux, not by + particular interfaces. Only for more complex setups like load- + balancing, does this behaviour cause problems. + """ + if int(arp_filter) >= 0 and int(arp_filter) <= 1: + return self._write_sysfs('/proc/sys/net/ipv4/conf/{0}/arp_filter' + .format(self._ifname), arp_filter) + else: + raise ValueError("Value out of range") + + def set_arp_accept(self, arp_accept): + """ + Define behavior for gratuitous ARP frames who's IP is not + already present in the ARP table: + 0 - don't create new entries in the ARP table + 1 - create new entries in the ARP table + + Both replies and requests type gratuitous arp will trigger the + ARP table to be updated, if this setting is on. + + If the ARP table already contains the IP address of the + gratuitous arp frame, the arp table will be updated regardless + if this setting is on or off. + """ + if int(arp_accept) >= 0 and int(arp_accept) <= 1: + return self._write_sysfs('/proc/sys/net/ipv4/conf/{0}/arp_accept' + .format(self._ifname), arp_accept) + else: + raise ValueError("Value out of range") + + def set_arp_announce(self, arp_announce): + """ + Define different restriction levels for announcing the local + source IP address from IP packets in ARP requests sent on + interface: + 0 - (default) Use any local address, configured on any interface + 1 - Try to avoid local addresses that are not in the target's + subnet for this interface. This mode is useful when target + hosts reachable via this interface require the source IP + address in ARP requests to be part of their logical network + configured on the receiving interface. When we generate the + request we will check all our subnets that include the + target IP and will preserve the source address if it is from + such subnet. + + Increasing the restriction level gives more chance for + receiving answer from the resolved target while decreasing + the level announces more valid sender's information. + """ + if int(arp_announce) >= 0 and int(arp_announce) <= 1: + return self._write_sysfs('/proc/sys/net/ipv4/conf/{0}/arp_announce' + .format(self._ifname), arp_announce) + else: + raise ValueError("Value out of range") + + def set_arp_ignore(self, arp_ignore): + """ + Define different modes for sending replies in response to received ARP + requests that resolve local target IP addresses: + + 0 - (default): reply for any local target IP address, configured + on any interface + 1 - reply only if the target IP address is local address + configured on the incoming interface + """ + if int(arp_ignore) >= 0 and int(arp_ignore) <= 1: + return self._write_sysfs('/proc/sys/net/ipv4/conf/{0}/arp_ignore' + .format(self._ifname), arp_ignore) + else: + raise ValueError("Value out of range") + def set_link_detect(self, link_filter): """ Configure kernel response in packets received on interfaces that are 'down' diff --git a/python/vyos/ifconfig_vlan.py b/python/vyos/ifconfig_vlan.py index 1299aa380..8e09db95a 100644 --- a/python/vyos/ifconfig_vlan.py +++ b/python/vyos/ifconfig_vlan.py @@ -55,6 +55,14 @@ def apply_vlan_config(vlan, config): vlan.set_alias(config['description']) # ignore link state changes vlan.set_link_detect(config['disable_link_detect']) + # configure ARP filter configuration + vlan.set_arp_filter(config['ip_disable_arp_filter']) + # configure ARP accept + vlan.set_arp_accept(config['ip_enable_arp_accept']) + # configure ARP announce + vlan.set_arp_announce(config['ip_enable_arp_announce']) + # configure ARP ignore + vlan.set_arp_ignore(config['ip_enable_arp_ignore']) # Maximum Transmission Unit (MTU) vlan.set_mtu(config['mtu']) # Change VLAN interface MAC address -- cgit v1.2.3