diff options
20 files changed, 316 insertions, 0 deletions
@@ -36,6 +36,7 @@ interface_definitions: $(BUILD_DIR) $(obj) rm -f $(TMPL_DIR)/interfaces/node.def rm -f $(TMPL_DIR)/interfaces/bonding/node.tag/ip/node.def rm -f $(TMPL_DIR)/interfaces/bonding/node.tag/vif/node.tag/ip/node.def + rm -f $(TMPL_DIR)/interfaces/bonding/node.tag/vif-s/node.tag/ip/node.def rm -f $(TMPL_DIR)/interfaces/bridge/node.tag/ip/node.def rm -f $(TMPL_DIR)/interfaces/ethernet/node.tag/ip/node.def rm -f $(TMPL_DIR)/interfaces/ethernet/node.tag/vif/node.tag/ip/node.def @@ -43,6 +44,7 @@ interface_definitions: $(BUILD_DIR) $(obj) rm -f $(TMPL_DIR)/interfaces/ethernet/node.tag/vif-s/node.tag/vif-c/node.tag/ip/node.def rm -f $(TMPL_DIR)/interfaces/vxlan/node.tag/ip/node.def rm -f $(TMPL_DIR)/interfaces/wireless/node.tag/vif/node.tag/ip/node.def + rm -f $(TMPL_DIR)/interfaces/wireless/node.tag/ip/node.def rm -f $(TMPL_DIR)/protocols/node.def rm -f $(TMPL_DIR)/protocols/static/node.def rm -f $(TMPL_DIR)/system/node.def diff --git a/interface-definitions/include/interface-disable-arp-filter.xml.i b/interface-definitions/include/interface-disable-arp-filter.xml.i new file mode 100644 index 000000000..ec3f51b2d --- /dev/null +++ b/interface-definitions/include/interface-disable-arp-filter.xml.i @@ -0,0 +1,6 @@ +<leafNode name="disable-arp-filter"> + <properties> + <help>Disable ARP filter on this interface</help> + <valueless/> + </properties> +</leafNode> diff --git a/interface-definitions/include/interface-enable-arp-accept.xml.i b/interface-definitions/include/interface-enable-arp-accept.xml.i new file mode 100644 index 000000000..69f26b322 --- /dev/null +++ b/interface-definitions/include/interface-enable-arp-accept.xml.i @@ -0,0 +1,6 @@ +<leafNode name="enable-arp-accept"> + <properties> + <help>Enable ARP accept on this interface</help> + <valueless/> + </properties> +</leafNode> diff --git a/interface-definitions/include/interface-enable-arp-announce.xml.i b/interface-definitions/include/interface-enable-arp-announce.xml.i new file mode 100644 index 000000000..8d51874c1 --- /dev/null +++ b/interface-definitions/include/interface-enable-arp-announce.xml.i @@ -0,0 +1,6 @@ +<leafNode name="enable-arp-announce"> + <properties> + <help>Enable ARP announce on this interface</help> + <valueless/> + </properties> +</leafNode> diff --git a/interface-definitions/include/interface-enable-arp-ignore.xml.i b/interface-definitions/include/interface-enable-arp-ignore.xml.i new file mode 100644 index 000000000..9adc0f17e --- /dev/null +++ b/interface-definitions/include/interface-enable-arp-ignore.xml.i @@ -0,0 +1,6 @@ +<leafNode name="enable-arp-ignore"> + <properties> + <help>Enable ARP ignore on this interface</help> + <valueless/> + </properties> +</leafNode> diff --git a/interface-definitions/include/vif-s.xml.i b/interface-definitions/include/vif-s.xml.i index cb0943162..2120aa32d 100644 --- a/interface-definitions/include/vif-s.xml.i +++ b/interface-definitions/include/vif-s.xml.i @@ -32,6 +32,14 @@ <constraintErrorMessage>Ethertype must be 0x88A8 or 0x8100</constraintErrorMessage> </properties> </leafNode> + <node name="ip"> + <children> + #include <include/interface-disable-arp-filter.xml.i> + #include <include/interface-enable-arp-accept.xml.i> + #include <include/interface-enable-arp-announce.xml.i> + #include <include/interface-enable-arp-ignore.xml.i> + </children> + </node> #include <include/interface-mac.xml.i> #include <include/interface-mtu-68-9000.xml.i> <tagNode name="vif-c"> diff --git a/interface-definitions/include/vif.xml.i b/interface-definitions/include/vif.xml.i index 7c8a29a93..85e901852 100644 --- a/interface-definitions/include/vif.xml.i +++ b/interface-definitions/include/vif.xml.i @@ -43,6 +43,10 @@ <node name="ip"> <children> #include <include/interface-arp-cache-timeout.xml.i> + #include <include/interface-disable-arp-filter.xml.i> + #include <include/interface-enable-arp-accept.xml.i> + #include <include/interface-enable-arp-announce.xml.i> + #include <include/interface-enable-arp-ignore.xml.i> #include <include/interface-enable-proxy-arp.xml.i> </children> </node> diff --git a/interface-definitions/interfaces-bonding.xml.in b/interface-definitions/interfaces-bonding.xml.in index e6557a967..55f0f148f 100644 --- a/interface-definitions/interfaces-bonding.xml.in +++ b/interface-definitions/interfaces-bonding.xml.in @@ -80,6 +80,10 @@ <node name="ip"> <children> #include <include/interface-arp-cache-timeout.xml.i> + #include <include/interface-disable-arp-filter.xml.i> + #include <include/interface-enable-arp-accept.xml.i> + #include <include/interface-enable-arp-announce.xml.i> + #include <include/interface-enable-arp-ignore.xml.i> #include <include/interface-enable-proxy-arp.xml.i> #include <include/interface-proxy-arp-pvlan.xml.i> </children> diff --git a/interface-definitions/interfaces-bridge.xml.in b/interface-definitions/interfaces-bridge.xml.in index 6e4531a7e..8351723cf 100644 --- a/interface-definitions/interfaces-bridge.xml.in +++ b/interface-definitions/interfaces-bridge.xml.in @@ -79,6 +79,10 @@ <node name="ip"> <children> #include <include/interface-arp-cache-timeout.xml.i> + #include <include/interface-enable-arp-accept.xml.i> + #include <include/interface-enable-arp-announce.xml.i> + #include <include/interface-enable-arp-ignore.xml.i> + #include <include/interface-disable-arp-filter.xml.i> </children> </node> #include <include/interface-mac.xml.i> diff --git a/interface-definitions/interfaces-ethernet.xml.in b/interface-definitions/interfaces-ethernet.xml.in index 7fa20ac18..b85b55e95 100644 --- a/interface-definitions/interfaces-ethernet.xml.in +++ b/interface-definitions/interfaces-ethernet.xml.in @@ -70,6 +70,10 @@ <node name="ip"> <children> #include <include/interface-arp-cache-timeout.xml.i> + #include <include/interface-disable-arp-filter.xml.i> + #include <include/interface-enable-arp-accept.xml.i> + #include <include/interface-enable-arp-announce.xml.i> + #include <include/interface-enable-arp-ignore.xml.i> #include <include/interface-enable-proxy-arp.xml.i> #include <include/interface-proxy-arp-pvlan.xml.i> </children> diff --git a/interface-definitions/interfaces-vxlan.xml.in b/interface-definitions/interfaces-vxlan.xml.in index ec15a806a..ceb75cb34 100644 --- a/interface-definitions/interfaces-vxlan.xml.in +++ b/interface-definitions/interfaces-vxlan.xml.in @@ -38,6 +38,10 @@ <node name="ip"> <children> #include <include/interface-arp-cache-timeout.xml.i> + #include <include/interface-disable-arp-filter.xml.i> + #include <include/interface-enable-arp-accept.xml.i> + #include <include/interface-enable-arp-announce.xml.i> + #include <include/interface-enable-arp-ignore.xml.i> #include <include/interface-enable-proxy-arp.xml.i> </children> </node> diff --git a/interface-definitions/interfaces-wireless.xml.in b/interface-definitions/interfaces-wireless.xml.in index 53c448930..e76a193a0 100644 --- a/interface-definitions/interfaces-wireless.xml.in +++ b/interface-definitions/interfaces-wireless.xml.in @@ -460,6 +460,14 @@ <valueless/> </properties> </leafNode> + <node name="ip"> + <children> + #include <include/interface-disable-arp-filter.xml.i> + #include <include/interface-enable-arp-accept.xml.i> + #include <include/interface-enable-arp-announce.xml.i> + #include <include/interface-enable-arp-ignore.xml.i> + </children> + </node> <leafNode name="hw-id"> <properties> <help>Media Access Control (MAC) address</help> 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 diff --git a/src/conf_mode/interfaces-bonding.py b/src/conf_mode/interfaces-bonding.py index 6c5362956..c798fd44e 100755 --- a/src/conf_mode/interfaces-bonding.py +++ b/src/conf_mode/interfaces-bonding.py @@ -42,6 +42,10 @@ default_config_data = { 'disable_link_detect': 1, 'hash_policy': 'layer2', 'ip_arp_cache_tmo': 30, + 'ip_disable_arp_filter': 1, + 'ip_enable_arp_accept': 0, + 'ip_enable_arp_announce': 0, + 'ip_enable_arp_ignore': 0, 'ip_proxy_arp': 0, 'ip_proxy_arp_pvlan': 0, 'intf': '', @@ -159,6 +163,22 @@ def get_config(): if conf.exists('ip arp-cache-timeout'): bond['ip_arp_cache_tmo'] = int(conf.return_value('ip arp-cache-timeout')) + # ARP filter configuration + if conf.exists('ip disable-arp-filter'): + bond['ip_disable_arp_filter'] = 0 + + # ARP enable accept + if conf.exists('ip enable-arp-accept'): + bond['ip_enable_arp_accept'] = 1 + + # ARP enable announce + if conf.exists('ip enable-arp-announce'): + bond['ip_enable_arp_announce'] = 1 + + # ARP enable ignore + if conf.exists('ip enable-arp-ignore'): + bond['ip_enable_arp_ignore'] = 1 + # Enable proxy-arp on this interface if conf.exists('ip enable-proxy-arp'): bond['ip_proxy_arp'] = 1 @@ -387,6 +407,14 @@ def apply(bond): b.set_hash_policy(bond['hash_policy']) # configure ARP cache timeout in milliseconds b.set_arp_cache_tmo(bond['ip_arp_cache_tmo']) + # configure ARP filter configuration + b.set_arp_filter(bond['ip_disable_arp_filter']) + # configure ARP accept + b.set_arp_accept(bond['ip_enable_arp_accept']) + # configure ARP announce + b.set_arp_announce(bond['ip_enable_arp_announce']) + # configure ARP ignore + b.set_arp_ignore(bond['ip_enable_arp_ignore']) # Enable proxy-arp on this interface b.set_proxy_arp(bond['ip_proxy_arp']) # Enable private VLAN proxy ARP on this interface diff --git a/src/conf_mode/interfaces-bridge.py b/src/conf_mode/interfaces-bridge.py index d152384f7..a3213f309 100755 --- a/src/conf_mode/interfaces-bridge.py +++ b/src/conf_mode/interfaces-bridge.py @@ -41,6 +41,10 @@ default_config_data = { 'disable_link_detect': 1, 'forwarding_delay': 14, 'hello_time': 2, + 'ip_disable_arp_filter': 1, + 'ip_enable_arp_accept': 0, + 'ip_enable_arp_announce': 0, + 'ip_enable_arp_ignore': 0, 'igmp_querier': 0, 'intf': '', 'mac' : '', @@ -130,6 +134,22 @@ def get_config(): if conf.exists('ip arp-cache-timeout'): bridge['arp_cache_tmo'] = int(conf.return_value('ip arp-cache-timeout')) + # ARP filter configuration + if conf.exists('ip disable-arp-filter'): + bridge['ip_disable_arp_filter'] = 0 + + # ARP enable accept + if conf.exists('ip enable-arp-accept'): + bridge['ip_enable_arp_accept'] = 1 + + # ARP enable announce + if conf.exists('ip enable-arp-announce'): + bridge['ip_enable_arp_announce'] = 1 + + # ARP enable ignore + if conf.exists('ip enable-arp-ignore'): + bridge['ip_enable_arp_ignore'] = 1 + # Media Access Control (MAC) address if conf.exists('mac'): bridge['mac'] = conf.return_value('mac') @@ -220,6 +240,14 @@ def apply(bridge): br.set_forward_delay(bridge['forwarding_delay']) # set hello time br.set_hello_time(bridge['hello_time']) + # configure ARP filter configuration + br.set_arp_filter(bridge['ip_disable_arp_filter']) + # configure ARP accept + br.set_arp_accept(bridge['ip_enable_arp_accept']) + # configure ARP announce + br.set_arp_announce(bridge['ip_enable_arp_announce']) + # configure ARP ignore + br.set_arp_ignore(bridge['ip_enable_arp_ignore']) # set max message age br.set_max_age(bridge['max_age']) # set bridge priority diff --git a/src/conf_mode/interfaces-ethernet.py b/src/conf_mode/interfaces-ethernet.py index cd75e1257..e4f6e5ff2 100755 --- a/src/conf_mode/interfaces-ethernet.py +++ b/src/conf_mode/interfaces-ethernet.py @@ -41,6 +41,10 @@ default_config_data = { 'flow_control': 'on', 'hw_id': '', 'ip_arp_cache_tmo': 30, + 'ip_disable_arp_filter': 1, + 'ip_enable_arp_accept': 0, + 'ip_enable_arp_announce': 0, + 'ip_enable_arp_ignore': 0, 'ip_proxy_arp': 0, 'ip_proxy_arp_pvlan': 0, 'intf': '', @@ -137,6 +141,22 @@ def get_config(): if conf.exists('ip arp-cache-timeout'): eth['ip_arp_cache_tmo'] = int(conf.return_value('ip arp-cache-timeout')) + # ARP filter configuration + if conf.exists('ip disable-arp-filter'): + eth['ip_disable_arp_filter'] = 0 + + # ARP enable accept + if conf.exists('ip enable-arp-accept'): + eth['ip_enable_arp_accept'] = 1 + + # ARP enable announce + if conf.exists('ip enable-arp-announce'): + eth['ip_enable_arp_announce'] = 1 + + # ARP enable ignore + if conf.exists('ip enable-arp-ignore'): + eth['ip_enable_arp_ignore'] = 1 + # Enable proxy-arp on this interface if conf.exists('ip enable-proxy-arp'): eth['ip_proxy_arp'] = 1 @@ -292,6 +312,14 @@ def apply(eth): e.set_flow_control(eth['flow_control']) # configure ARP cache timeout in milliseconds e.set_arp_cache_tmo(eth['ip_arp_cache_tmo']) + # configure ARP filter configuration + e.set_arp_filter(eth['ip_disable_arp_filter']) + # configure ARP accept + e.set_arp_accept(eth['ip_enable_arp_accept']) + # configure ARP announce + e.set_arp_announce(eth['ip_enable_arp_announce']) + # configure ARP ignore + e.set_arp_ignore(eth['ip_enable_arp_ignore']) # Enable proxy-arp on this interface e.set_proxy_arp(eth['ip_proxy_arp']) # Enable private VLAN proxy ARP on this interface diff --git a/src/conf_mode/interfaces-vxlan.py b/src/conf_mode/interfaces-vxlan.py index c1fedc824..7f1ac6c31 100755 --- a/src/conf_mode/interfaces-vxlan.py +++ b/src/conf_mode/interfaces-vxlan.py @@ -32,6 +32,10 @@ default_config_data = { 'group': '', 'intf': '', 'ip_arp_cache_tmo': 30, + 'ip_disable_arp_filter': 1, + 'ip_enable_arp_accept': 0, + 'ip_enable_arp_announce': 0, + 'ip_enable_arp_ignore': 0, 'ip_proxy_arp': 0, 'link': '', 'mtu': 1450, @@ -79,6 +83,22 @@ def get_config(): if conf.exists('ip arp-cache-timeout'): vxlan['ip_arp_cache_tmo'] = int(conf.return_value('ip arp-cache-timeout')) + # ARP filter configuration + if conf.exists('ip disable-arp-filter'): + vxlan['ip_disable_arp_filter'] = 0 + + # ARP enable accept + if conf.exists('ip enable-arp-accept'): + vxlan['ip_enable_arp_accept'] = 1 + + # ARP enable announce + if conf.exists('ip enable-arp-announce'): + vxlan['ip_enable_arp_announce'] = 1 + + # ARP enable ignore + if conf.exists('ip enable-arp-ignore'): + vxlan['ip_enable_arp_ignore'] = 1 + # Enable proxy-arp on this interface if conf.exists('ip enable-proxy-arp'): vxlan['ip_proxy_arp'] = 1 @@ -168,6 +188,14 @@ def apply(vxlan): # configure ARP cache timeout in milliseconds v.set_arp_cache_tmo(vxlan['ip_arp_cache_tmo']) + # configure ARP filter configuration + v.set_arp_filter(bond['ip_disable_arp_filter']) + # configure ARP accept + v.set_arp_accept(bond['ip_enable_arp_accept']) + # configure ARP announce + v.set_arp_announce(bond['ip_enable_arp_announce']) + # configure ARP ignore + v.set_arp_ignore(bond['ip_enable_arp_ignore']) # Enable proxy-arp on this interface v.set_proxy_arp(vxlan['ip_proxy_arp']) diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py index 0df0b3ba4..162aaf463 100755 --- a/src/conf_mode/interfaces-wireless.py +++ b/src/conf_mode/interfaces-wireless.py @@ -816,6 +816,10 @@ default_config_data = { 'hw_id' : '', 'intf': '', 'isolate_stations' : False, + 'ip_disable_arp_filter': 1, + 'ip_enable_arp_accept': 0, + 'ip_enable_arp_announce': 0, + 'ip_enable_arp_ignore': 0, 'mac' : '', 'max_stations' : '', 'mgmt_frame_protection' : 'disabled', @@ -1112,6 +1116,22 @@ def get_config(): if conf.exists('isolate-stations'): wifi['isolate_stations'] = True + # ARP filter configuration + if conf.exists('ip disable-arp-filter'): + wifi['ip_disable_arp_filter'] = 0 + + # ARP enable accept + if conf.exists('ip enable-arp-accept'): + wifi['ip_enable_arp_accept'] = 1 + + # ARP enable announce + if conf.exists('ip enable-arp-announce'): + wifi['ip_enable_arp_announce'] = 1 + + # ARP enable ignore + if conf.exists('ip enable-arp-ignore'): + wifi['ip_enable_arp_ignore'] = 1 + # Media Access Control (MAC) address if conf.exists('mac'): wifi['mac'] = conf.return_value('mac') @@ -1373,6 +1393,15 @@ def apply(wifi): else: w.set_mac(wifi['hw_id']) + # configure ARP filter configuration + w.set_arp_filter(wifi['ip_disable_arp_filter']) + # configure ARP accept + w.set_arp_accept(wifi['ip_enable_arp_accept']) + # configure ARP announce + w.set_arp_announce(wifi['ip_enable_arp_announce']) + # configure ARP ignore + w.set_arp_ignore(wifi['ip_enable_arp_ignore']) + # enable interface if not wifi['disable']: w.set_state('up') |