summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile20
-rw-r--r--interface-definitions/include/ipv6-address.xml.i22
-rw-r--r--interface-definitions/include/ipv6-disable-forwarding.xml.i6
-rw-r--r--interface-definitions/include/ipv6-dup-addr-detect-transmits.xml.i16
-rw-r--r--interface-definitions/include/vif.xml.i7
-rw-r--r--interface-definitions/interfaces-bonding.xml.in7
-rw-r--r--interface-definitions/interfaces-bridge.xml.in7
-rw-r--r--interface-definitions/interfaces-ethernet.xml.in7
-rw-r--r--interface-definitions/interfaces-l2tpv3.xml.in7
-rw-r--r--interface-definitions/interfaces-openvpn.xml.in7
-rw-r--r--interface-definitions/interfaces-pseudo-ethernet.xml.in7
-rw-r--r--interface-definitions/interfaces-tunnel.xml.in24
-rw-r--r--interface-definitions/interfaces-vxlan.xml.in7
-rw-r--r--interface-definitions/interfaces-wireless.xml.in7
-rw-r--r--python/vyos/configdict.py15
-rw-r--r--python/vyos/ifconfig/bond.py6
-rw-r--r--python/vyos/ifconfig/control.py10
-rw-r--r--python/vyos/ifconfig/geneve.py2
-rw-r--r--python/vyos/ifconfig/interface.py158
-rw-r--r--python/vyos/ifconfig/l2tpv3.py4
-rw-r--r--python/vyos/ifconfig/tunnel.py4
-rw-r--r--python/vyos/ifconfig_vlan.py10
-rw-r--r--python/vyos/util.py50
-rwxr-xr-xsrc/conf_mode/interfaces-bonding.py34
-rwxr-xr-xsrc/conf_mode/interfaces-bridge.py32
-rwxr-xr-xsrc/conf_mode/interfaces-dummy.py4
-rwxr-xr-xsrc/conf_mode/interfaces-ethernet.py32
-rwxr-xr-xsrc/conf_mode/interfaces-geneve.py2
-rwxr-xr-xsrc/conf_mode/interfaces-l2tpv3.py30
-rwxr-xr-xsrc/conf_mode/interfaces-openvpn.py35
-rwxr-xr-xsrc/conf_mode/interfaces-pseudo-ethernet.py32
-rwxr-xr-xsrc/conf_mode/interfaces-tunnel.py2
-rwxr-xr-xsrc/conf_mode/interfaces-vxlan.py30
-rwxr-xr-xsrc/conf_mode/interfaces-wireguard.py2
-rwxr-xr-xsrc/conf_mode/interfaces-wireless.py30
-rwxr-xr-xsrc/helpers/vyos-merge-config.py5
36 files changed, 589 insertions, 91 deletions
diff --git a/Makefile b/Makefile
index f859f2f45..71c28f220 100644
--- a/Makefile
+++ b/Makefile
@@ -36,22 +36,40 @@ interface_definitions: $(BUILD_DIR) $(obj)
rm -f $(TMPL_DIR)/firewall/node.def
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/ipv6/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/node.tag/ipv6/node.def
rm -f $(TMPL_DIR)/interfaces/bonding/node.tag/vif-s/node.tag/ip/node.def
+ rm -f $(TMPL_DIR)/interfaces/bonding/node.tag/vif-s/node.tag/ipv6/node.def
rm -f $(TMPL_DIR)/interfaces/bridge/node.tag/ip/node.def
+ rm -f $(TMPL_DIR)/interfaces/bridge/node.tag/ipv6/node.def
rm -f $(TMPL_DIR)/interfaces/ethernet/node.tag/ip/node.def
+ rm -f $(TMPL_DIR)/interfaces/ethernet/node.tag/ipv6/node.def
rm -f $(TMPL_DIR)/interfaces/ethernet/node.tag/vif/node.tag/ip/node.def
+ rm -f $(TMPL_DIR)/interfaces/ethernet/node.tag/vif/node.tag/ipv6/node.def
rm -f $(TMPL_DIR)/interfaces/ethernet/node.tag/vif-s/node.tag/ip/node.def
+ rm -f $(TMPL_DIR)/interfaces/ethernet/node.tag/vif-s/node.tag/ipv6/node.def
rm -f $(TMPL_DIR)/interfaces/ethernet/node.tag/vif-s/node.tag/vif-c/node.tag/ip/node.def
+ rm -f $(TMPL_DIR)/interfaces/ethernet/node.tag/vif-s/node.tag/vif-c/node.tag/ipv6/node.def
+ rm -f $(TMPL_DIR)/interfaces/l2tpv3/node.tag/ipv6/node.def
+ rm -f $(TMPL_DIR)/interfaces/openvpn/node.tag/ipv6/node.def
rm -f $(TMPL_DIR)/interfaces/pppoe/node.tag/ip/node.def
rm -f $(TMPL_DIR)/interfaces/pppoe/node.tag/ipv6/node.def
rm -f $(TMPL_DIR)/interfaces/pseudo-ethernet/node.tag/ip/node.def
+ rm -f $(TMPL_DIR)/interfaces/pseudo-ethernet/node.tag/ipv6/node.def
rm -f $(TMPL_DIR)/interfaces/pseudo-ethernet/node.tag/vif/node.tag/ip/node.def
+ rm -f $(TMPL_DIR)/interfaces/pseudo-ethernet/node.tag/vif/node.tag/ipv6/node.def
rm -f $(TMPL_DIR)/interfaces/pseudo-ethernet/node.tag/vif-s/node.tag/ip/node.def
+ rm -f $(TMPL_DIR)/interfaces/pseudo-ethernet/node.tag/vif-s/node.tag/ipv6/node.def
rm -f $(TMPL_DIR)/interfaces/pseudo-ethernet/node.tag/vif-s/node.tag/vif-c/node.tag/ip/node.def
+ rm -f $(TMPL_DIR)/interfaces/pseudo-ethernet/node.tag/vif-s/node.tag/vif-c/node.tag/ipv6/node.def
+ rm -f $(TMPL_DIR)/interfaces/tunnel/node.tag/ipv6/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/vxlan/node.tag/ipv6/node.def
rm -f $(TMPL_DIR)/interfaces/wireless/node.tag/ip/node.def
+ rm -f $(TMPL_DIR)/interfaces/wireless/node.tag/ipv6/node.def
+ rm -f $(TMPL_DIR)/interfaces/wireless/node.tag/vif/node.tag/ip/node.def
+ rm -f $(TMPL_DIR)/interfaces/wireless/node.tag/vif/node.tag/ipv6/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/ipv6-address.xml.i b/interface-definitions/include/ipv6-address.xml.i
new file mode 100644
index 000000000..507d5dcc1
--- /dev/null
+++ b/interface-definitions/include/ipv6-address.xml.i
@@ -0,0 +1,22 @@
+<node name="address">
+ <children>
+ <leafNode name="autoconf">
+ <properties>
+ <help>Enable acquisition of IPv6 address using stateless autoconfig (SLAAC)</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="eui64">
+ <properties>
+ <help>ssign IPv6 address using EUI-64 based on MAC address</help>
+ <valueHelp>
+ <format>ipv6net</format>
+ <description>IPv6 address and prefix length</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv6-prefix"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
diff --git a/interface-definitions/include/ipv6-disable-forwarding.xml.i b/interface-definitions/include/ipv6-disable-forwarding.xml.i
new file mode 100644
index 000000000..3f90c7e34
--- /dev/null
+++ b/interface-definitions/include/ipv6-disable-forwarding.xml.i
@@ -0,0 +1,6 @@
+<leafNode name="disable-forwarding">
+ <properties>
+ <help>Disable IPv6 forwarding on this interface</help>
+ <valueless/>
+ </properties>
+</leafNode>
diff --git a/interface-definitions/include/ipv6-dup-addr-detect-transmits.xml.i b/interface-definitions/include/ipv6-dup-addr-detect-transmits.xml.i
new file mode 100644
index 000000000..728187560
--- /dev/null
+++ b/interface-definitions/include/ipv6-dup-addr-detect-transmits.xml.i
@@ -0,0 +1,16 @@
+<leafNode name="dup-addr-detect-transmits">
+ <properties>
+ <help>Number of NS messages to send while performing DAD (default: 1)</help>
+ <valueHelp>
+ <format>1-n</format>
+ <description>Number of NS messages to send while performing DAD</description>
+ </valueHelp>
+ <valueHelp>
+ <format>0</format>
+ <description>Disable Duplicate Address Dectection (DAD)</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--non-negative"/>
+ </constraint>
+ </properties>
+</leafNode>
diff --git a/interface-definitions/include/vif.xml.i b/interface-definitions/include/vif.xml.i
index 88693e0d3..819534dc1 100644
--- a/interface-definitions/include/vif.xml.i
+++ b/interface-definitions/include/vif.xml.i
@@ -51,6 +51,13 @@
#include <include/interface-enable-proxy-arp.xml.i>
</children>
</node>
+ <node name="ipv6">
+ <children>
+ #include <include/ipv6-address.xml.i>
+ #include <include/ipv6-disable-forwarding.xml.i>
+ #include <include/ipv6-dup-addr-detect-transmits.xml.i>
+ </children>
+ </node>
#include <include/interface-mac.xml.i>
#include <include/interface-mtu-68-9000.xml.i>
</children>
diff --git a/interface-definitions/interfaces-bonding.xml.in b/interface-definitions/interfaces-bonding.xml.in
index 80943a1fd..166f23285 100644
--- a/interface-definitions/interfaces-bonding.xml.in
+++ b/interface-definitions/interfaces-bonding.xml.in
@@ -89,6 +89,13 @@
#include <include/interface-proxy-arp-pvlan.xml.i>
</children>
</node>
+ <node name="ipv6">
+ <children>
+ #include <include/ipv6-address.xml.i>
+ #include <include/ipv6-disable-forwarding.xml.i>
+ #include <include/ipv6-dup-addr-detect-transmits.xml.i>
+ </children>
+ </node>
#include <include/interface-mac.xml.i>
<leafNode name="mode">
<properties>
diff --git a/interface-definitions/interfaces-bridge.xml.in b/interface-definitions/interfaces-bridge.xml.in
index d36a1abbc..f41110a3f 100644
--- a/interface-definitions/interfaces-bridge.xml.in
+++ b/interface-definitions/interfaces-bridge.xml.in
@@ -86,6 +86,13 @@
#include <include/interface-disable-arp-filter.xml.i>
</children>
</node>
+ <node name="ipv6">
+ <children>
+ #include <include/ipv6-address.xml.i>
+ #include <include/ipv6-disable-forwarding.xml.i>
+ #include <include/ipv6-dup-addr-detect-transmits.xml.i>
+ </children>
+ </node>
#include <include/interface-mac.xml.i>
<leafNode name="max-age">
<properties>
diff --git a/interface-definitions/interfaces-ethernet.xml.in b/interface-definitions/interfaces-ethernet.xml.in
index 5728d2f37..2b461cfaa 100644
--- a/interface-definitions/interfaces-ethernet.xml.in
+++ b/interface-definitions/interfaces-ethernet.xml.in
@@ -79,6 +79,13 @@
#include <include/interface-proxy-arp-pvlan.xml.i>
</children>
</node>
+ <node name="ipv6">
+ <children>
+ #include <include/ipv6-address.xml.i>
+ #include <include/ipv6-disable-forwarding.xml.i>
+ #include <include/ipv6-dup-addr-detect-transmits.xml.i>
+ </children>
+ </node>
#include <include/interface-mac.xml.i>
#include <include/interface-mtu-68-9000.xml.i>
<node name="offload-options">
diff --git a/interface-definitions/interfaces-l2tpv3.xml.in b/interface-definitions/interfaces-l2tpv3.xml.in
index a408e58c1..161a37df8 100644
--- a/interface-definitions/interfaces-l2tpv3.xml.in
+++ b/interface-definitions/interfaces-l2tpv3.xml.in
@@ -51,6 +51,13 @@
<constraintErrorMessage>Encapsulation must be UDP or IP</constraintErrorMessage>
</properties>
</leafNode>
+ <node name="ipv6">
+ <children>
+ #include <include/ipv6-address.xml.i>
+ #include <include/ipv6-disable-forwarding.xml.i>
+ #include <include/ipv6-dup-addr-detect-transmits.xml.i>
+ </children>
+ </node>
<leafNode name="local-ip">
<properties>
<help>Local IP address for L2TPv3 tunnel</help>
diff --git a/interface-definitions/interfaces-openvpn.xml.in b/interface-definitions/interfaces-openvpn.xml.in
index cac0ee417..cd5b5f29e 100644
--- a/interface-definitions/interfaces-openvpn.xml.in
+++ b/interface-definitions/interfaces-openvpn.xml.in
@@ -162,6 +162,13 @@
</leafNode>
</children>
</node>
+ <node name="ipv6">
+ <children>
+ #include <include/ipv6-address.xml.i>
+ #include <include/ipv6-disable-forwarding.xml.i>
+ #include <include/ipv6-dup-addr-detect-transmits.xml.i>
+ </children>
+ </node>
<leafNode name="hash">
<properties>
<help>Hashing Algorithm</help>
diff --git a/interface-definitions/interfaces-pseudo-ethernet.xml.in b/interface-definitions/interfaces-pseudo-ethernet.xml.in
index e6e8fd20c..772056bd2 100644
--- a/interface-definitions/interfaces-pseudo-ethernet.xml.in
+++ b/interface-definitions/interfaces-pseudo-ethernet.xml.in
@@ -33,6 +33,13 @@
#include <include/interface-proxy-arp-pvlan.xml.i>
</children>
</node>
+ <node name="ipv6">
+ <children>
+ #include <include/ipv6-address.xml.i>
+ #include <include/ipv6-disable-forwarding.xml.i>
+ #include <include/ipv6-dup-addr-detect-transmits.xml.i>
+ </children>
+ </node>
<leafNode name="link">
<properties>
<help>Lower link device</help>
diff --git a/interface-definitions/interfaces-tunnel.xml.in b/interface-definitions/interfaces-tunnel.xml.in
index c66628ec8..fe4a81f92 100644
--- a/interface-definitions/interfaces-tunnel.xml.in
+++ b/interface-definitions/interfaces-tunnel.xml.in
@@ -15,7 +15,6 @@
<description>Tunnel interface name</description>
</valueHelp>
</properties>
-
<children>
#include <include/interface-description.xml.i>
#include <include/address-ipv4-ipv6.xml.i>
@@ -23,7 +22,13 @@
#include <include/interface-disable-link-detect.xml.i>
#include <include/interface-vrf.xml.i>
#include <include/interface-mtu-64-8024.xml.i>
-
+ <node name="ipv6">
+ <children>
+ #include <include/ipv6-address.xml.i>
+ #include <include/ipv6-disable-forwarding.xml.i>
+ #include <include/ipv6-dup-addr-detect-transmits.xml.i>
+ </children>
+ </node>
<leafNode name="local-ip">
<properties>
<help>Local IP address for this tunnel</help>
@@ -44,7 +49,6 @@
</constraint>
</properties>
</leafNode>
-
<leafNode name="remote-ip">
<properties>
<help>Remote IP address for this tunnel</help>
@@ -62,7 +66,6 @@
</constraint>
</properties>
</leafNode>
-
<leafNode name="6rd-prefix">
<properties>
<help>6rd network prefix</help>
@@ -75,7 +78,6 @@
</constraint>
</properties>
</leafNode>
-
<leafNode name="6rd-relay-prefix">
<properties>
<help>6rd relay prefix</help>
@@ -88,7 +90,6 @@
</constraint>
</properties>
</leafNode>
-
<leafNode name="dhcp-interface">
<properties>
<help>dhcp interface</help>
@@ -104,7 +105,6 @@
</constraint>
</properties>
</leafNode>
-
<leafNode name="encapsulation">
<properties>
<help>Ignore link state changes</help>
@@ -141,7 +141,6 @@
<constraintErrorMessage>Must be one of 'gre' 'gre-bridge' 'ipip' 'sit' 'ipip6' 'ip6ip6' 'ip6gre'</constraintErrorMessage>
</properties>
</leafNode>
-
<leafNode name="multicast">
<properties>
<help>Multicast operation over tunnel</help>
@@ -162,12 +161,10 @@
<constraintErrorMessage>Must be 'disable' or 'enable'</constraintErrorMessage>
</properties>
</leafNode>
-
<node name="parameters">
<properties>
<help>Tunnel parameters</help>
</properties>
-
<children>
<node name="ip">
<properties>
@@ -187,7 +184,6 @@
<constraintErrorMessage>TTL must be between 0 and 255</constraintErrorMessage>
</properties>
</leafNode>
-
<leafNode name="tos">
<properties>
<help>Type of Service (TOS)</help>
@@ -201,7 +197,6 @@
<constraintErrorMessage>TOS must be between 0 and 99</constraintErrorMessage>
</properties>
</leafNode>
-
<leafNode name="key">
<properties>
<help>Tunnel key</help>
@@ -217,12 +212,10 @@
</leafNode>
</children>
</node>
-
<node name="ipv6">
<properties>
<help>IPv6 specific tunnel parameters</help>
</properties>
-
<children>
<leafNode name="encaplimit">
<properties>
@@ -237,7 +230,6 @@
<constraintErrorMessage>key must be between 0-255</constraintErrorMessage>
</properties>
</leafNode>
-
<leafNode name="flowlabel">
<properties>
<help>Flowlabel</help>
@@ -251,7 +243,6 @@
<constraintErrorMessage>Must be 'inherit' or a number</constraintErrorMessage>
</properties>
</leafNode>
-
<leafNode name="hoplimit">
<properties>
<help>Hoplimit</help>
@@ -265,7 +256,6 @@
<constraintErrorMessage>hoplimit must be between 0-255</constraintErrorMessage>
</properties>
</leafNode>
-
<leafNode name="tclass">
<properties>
<help>Traffic class (Tclass)</help>
diff --git a/interface-definitions/interfaces-vxlan.xml.in b/interface-definitions/interfaces-vxlan.xml.in
index 16cb2c169..70c45d1fd 100644
--- a/interface-definitions/interfaces-vxlan.xml.in
+++ b/interface-definitions/interfaces-vxlan.xml.in
@@ -45,6 +45,13 @@
#include <include/interface-enable-proxy-arp.xml.i>
</children>
</node>
+ <node name="ipv6">
+ <children>
+ #include <include/ipv6-address.xml.i>
+ #include <include/ipv6-disable-forwarding.xml.i>
+ #include <include/ipv6-dup-addr-detect-transmits.xml.i>
+ </children>
+ </node>
<leafNode name="link">
<properties>
<help>Underlay device of VXLAN interface</help>
diff --git a/interface-definitions/interfaces-wireless.xml.in b/interface-definitions/interfaces-wireless.xml.in
index 8632bb881..2c224987e 100644
--- a/interface-definitions/interfaces-wireless.xml.in
+++ b/interface-definitions/interfaces-wireless.xml.in
@@ -469,6 +469,13 @@
#include <include/interface-enable-arp-ignore.xml.i>
</children>
</node>
+ <node name="ipv6">
+ <children>
+ #include <include/ipv6-address.xml.i>
+ #include <include/ipv6-disable-forwarding.xml.i>
+ #include <include/ipv6-dup-addr-detect-transmits.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 a1499479a..66da52ff3 100644
--- a/python/vyos/configdict.py
+++ b/python/vyos/configdict.py
@@ -123,6 +123,9 @@ def vlan_to_dict(conf):
'ip_enable_arp_accept': 0,
'ip_enable_arp_announce': 0,
'ip_enable_arp_ignore': 0,
+ 'ipv6_autoconf': 0,
+ 'ipv6_forwarding': 1,
+ 'ipv6_dup_addr_detect': 1,
'ingress_qos': '',
'ingress_qos_changed': False,
'mac': '',
@@ -187,6 +190,18 @@ def vlan_to_dict(conf):
if conf.exists('ip enable-arp-ignore'):
vlan['ip_enable_arp_ignore'] = 1
+ # Enable acquisition of IPv6 address using stateless autoconfig (SLAAC)
+ if conf.exists('ipv6 address autoconf'):
+ vlan['ipv6_autoconf'] = 1
+
+ # Disable IPv6 forwarding on this interface
+ if conf.exists('ipv6 disable-forwarding'):
+ vlan['ipv6_forwarding'] = 0
+
+ # IPv6 Duplicate Address Detection (DAD) tries
+ if conf.exists('ipv6 dup-addr-detect-transmits'):
+ vlan['ipv6_dup_addr_detect'] = int(conf.return_value('ipv6 dup-addr-detect-transmits'))
+
# Media Access Control (MAC) address
if conf.exists('mac'):
vlan['mac'] = conf.return_value('mac')
diff --git a/python/vyos/ifconfig/bond.py b/python/vyos/ifconfig/bond.py
index 3c26b9b95..e2ff71490 100644
--- a/python/vyos/ifconfig/bond.py
+++ b/python/vyos/ifconfig/bond.py
@@ -101,7 +101,7 @@ class BondIf(Interface):
for s in self.get_slaves():
slave = {
'ifname': s,
- 'state': Interface(s).get_state()
+ 'state': Interface(s).get_admin_state()
}
slave_list.append(slave)
@@ -112,7 +112,7 @@ class BondIf(Interface):
# physical interface
for slave in slave_list:
i = Interface(slave['ifname'])
- i.set_state(slave['state'])
+ i.set_admin_state(slave['state'])
def set_hash_policy(self, mode):
"""
@@ -211,7 +211,7 @@ class BondIf(Interface):
# An interface can only be added to a bond if it is in 'down' state. If
# interface is in 'up' state, the following Kernel error will be thrown:
# bond0: eth1 is up - this may be due to an out of date ifenslave.
- Interface(interface).set_state('down')
+ Interface(interface).set_admin_state('down')
return self.set_interface('bond_add_port', f'+{interface}')
def del_port(self, interface):
diff --git a/python/vyos/ifconfig/control.py b/python/vyos/ifconfig/control.py
index f7b032478..1c9f7e284 100644
--- a/python/vyos/ifconfig/control.py
+++ b/python/vyos/ifconfig/control.py
@@ -49,15 +49,12 @@ class Control(Register):
Using the defined names, set data write to sysfs.
"""
cmd = self._command_get[name]['shellcmd'].format(**config)
- return self._cmd(cmd)
+ return self._command_get[name].get('format', lambda _: _)(self._cmd(cmd))
def _set_command(self, config, name, value):
"""
Using the defined names, set data write to sysfs.
"""
- if not value and not self._command_set[name].get('force', False):
- return None
-
# the code can pass int as int
value = str(value)
@@ -75,7 +72,7 @@ class Control(Register):
config = {**config, **{'value': value}}
cmd = self._command_set[name]['shellcmd'].format(**config)
- return self._cmd(cmd)
+ return self._command_set[name].get('format', lambda _: _)(self._cmd(cmd))
_sysfs_get = {}
_sysfs_set = {}
@@ -115,9 +112,6 @@ class Control(Register):
"""
Using the defined names, set data write to sysfs.
"""
- if not value and not self._sysfs_set[name].get('force', False):
- return None
-
# the code can pass int as int
value = str(value)
diff --git a/python/vyos/ifconfig/geneve.py b/python/vyos/ifconfig/geneve.py
index f27786417..0c1cdade9 100644
--- a/python/vyos/ifconfig/geneve.py
+++ b/python/vyos/ifconfig/geneve.py
@@ -49,7 +49,7 @@ class GeneveIf(Interface):
self._cmd(cmd)
# interface is always A/D down. It needs to be enabled explicitly
- self.set_state('down')
+ self.set_admin_state('down')
@classmethod
def get_config(cls):
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py
index f2b43fd35..8b41d6158 100644
--- a/python/vyos/ifconfig/interface.py
+++ b/python/vyos/ifconfig/interface.py
@@ -21,10 +21,10 @@ import time
from copy import deepcopy
from vyos.validate import * # should not * include
-from vyos.config import Config # not used anymore
+from vyos.util import mac2eui64
from vyos import ConfigError
-from ipaddress import IPv4Network, IPv6Address
+from ipaddress import IPv4Network, IPv6Address, IPv6Network
from netifaces import ifaddresses, AF_INET, AF_INET6
from time import sleep
from os.path import isfile
@@ -49,8 +49,15 @@ class Interface(DHCP):
'bridgeable': False,
}
+ _command_get = {
+ 'admin_state': {
+ 'shellcmd': 'ip -json link show dev {ifname}',
+ 'format': lambda j: 'up' if 'UP' in json.loads(j)[0]['flags'] else 'down',
+ }
+ }
+
_command_set = {
- 'state': {
+ 'admin_state': {
'validate': lambda v: assert_list(v, ['up', 'down']),
'shellcmd': 'ip link set dev {ifname} {value}',
},
@@ -59,19 +66,24 @@ class Interface(DHCP):
'shellcmd': 'ip link set dev {ifname} address {value}',
},
'vrf': {
- 'force': True,
'convert': lambda v: f'master {v}' if v else 'nomaster',
'shellcmd': 'ip link set dev {ifname} {value}',
},
}
_sysfs_get = {
+ 'alias': {
+ 'location': '/sys/class/net/{ifname}/ifalias',
+ },
'mac': {
'location': '/sys/class/net/{ifname}/address',
},
'mtu': {
'location': '/sys/class/net/{ifname}/mtu',
},
+ 'oper_state':{
+ 'location': '/sys/class/net/{ifname}/operstate',
+ },
}
_sysfs_set = {
@@ -103,6 +115,18 @@ class Interface(DHCP):
'validate': assert_boolean,
'location': '/proc/sys/net/ipv4/conf/{ifname}/arp_ignore',
},
+ 'ipv6_autoconf': {
+ 'validate': lambda fwd: assert_range(fwd,0,2),
+ 'location': '/proc/sys/net/ipv6/conf/{ifname}/autoconf',
+ },
+ 'ipv6_forwarding': {
+ 'validate': lambda fwd: assert_range(fwd,0,2),
+ 'location': '/proc/sys/net/ipv6/conf/{ifname}/forwarding',
+ },
+ 'ipv6_dad_transmits': {
+ 'validate': assert_positive,
+ 'location': '/proc/sys/net/ipv6/conf/{ifname}/dad_transmits',
+ },
'proxy_arp': {
'validate': assert_boolean,
'location': '/proc/sys/net/ipv4/conf/{ifname}/proxy_arp',
@@ -249,7 +273,7 @@ class Interface(DHCP):
>>> Interface('eth0').get_mac()
'00:50:ab:cd:ef:00'
"""
- self.get_interface('mac')
+ return self.get_interface('mac')
def set_mac(self, mac):
"""
@@ -265,9 +289,9 @@ class Interface(DHCP):
return None
# MAC address can only be changed if interface is in 'down' state
- prev_state = self.get_state()
+ prev_state = self.get_admin_state()
if prev_state == 'up':
- self.set_state('down')
+ self.set_admin_state('down')
self.set_interface('mac', mac)
@@ -362,6 +386,81 @@ class Interface(DHCP):
"""
return self.set_interface('arp_ignore', arp_ignore)
+ def set_ipv6_autoconf(self, autoconf):
+ """
+ Autoconfigure addresses using Prefix Information in Router
+ Advertisements.
+ """
+ return self.set_interface('ipv6_autoconf', autoconf)
+
+ def set_ipv6_eui64_address(self, prefix):
+ """
+ Extended Unique Identifier (EUI), as per RFC2373, allows a host to
+ assign iteslf a unique IPv6 address based on a given IPv6 prefix.
+
+ If prefix is passed address is assigned, if prefix is '' address is
+ removed from interface.
+ """
+ # if prefix is an empty string convert it to None so mac2eui64 works
+ # as expected
+ if not prefix:
+ prefix = None
+
+ eui64 = mac2eui64(self.get_mac(), prefix)
+
+ if not prefix:
+ # if prefix is empty - thus removed - we need to walk through all
+ # interface IPv6 addresses and find the one with the calculated
+ # EUI-64 identifier. The address is then removed
+ for addr in self.get_addr():
+ addr_wo_prefix = addr.split('/')[0]
+ if is_ipv6(addr_wo_prefix):
+ if eui64 in IPv6Address(addr_wo_prefix).exploded:
+ self.del_addr(addr)
+
+ return None
+
+ # calculate and add EUI-64 IPv6 address
+ if IPv6Network(prefix):
+ # we also need to take the subnet length into account
+ prefix = prefix.split('/')[1]
+ eui64 = f'{eui64}/{prefix}'
+ self.add_addr(eui64 )
+
+ def set_ipv6_forwarding(self, forwarding):
+ """
+ Configure IPv6 interface-specific Host/Router behaviour.
+
+ False:
+
+ By default, Host behaviour is assumed. This means:
+
+ 1. IsRouter flag is not set in Neighbour Advertisements.
+ 2. If accept_ra is TRUE (default), transmit Router
+ Solicitations.
+ 3. If accept_ra is TRUE (default), accept Router
+ Advertisements (and do autoconfiguration).
+ 4. If accept_redirects is TRUE (default), accept Redirects.
+
+ True:
+
+ If local forwarding is enabled, Router behaviour is assumed.
+ This means exactly the reverse from the above:
+
+ 1. IsRouter flag is set in Neighbour Advertisements.
+ 2. Router Solicitations are not sent unless accept_ra is 2.
+ 3. Router Advertisements are ignored unless accept_ra is 2.
+ 4. Redirects are ignored.
+ """
+ return self.set_interface('ipv6_forwarding', forwarding)
+
+ def set_ipv6_dad_messages(self, dad):
+ """
+ The amount of Duplicate Address Detection probes to send.
+ Default: 1
+ """
+ return self.set_interface('ipv6_dad_transmits', dad)
+
def set_link_detect(self, link_filter):
"""
Configure kernel response in packets received on interfaces that are 'down'
@@ -384,6 +483,16 @@ class Interface(DHCP):
"""
return self.set_interface('link_detect', link_filter)
+ def get_alias(self):
+ """
+ Get interface alias name used by e.g. SNMP
+
+ Example:
+ >>> Interface('eth0').get_alias()
+ 'interface description as set by user'
+ """
+ return self.get_interface('alias')
+
def set_alias(self, ifalias=''):
"""
Set interface alias name used by e.g. SNMP
@@ -398,36 +507,41 @@ class Interface(DHCP):
"""
self.set_interface('alias', ifalias)
- def get_state(self):
+ def get_admin_state(self):
"""
Get interface administrative state. Function will return 'up' or 'down'
Example:
>>> from vyos.ifconfig import Interface
- >>> Interface('eth0').get_state()
+ >>> Interface('eth0').get_admin_state()
'up'
"""
- cmd = 'ip -json link show dev {}'.format(self.config['ifname'])
- tmp = self._cmd(cmd)
- out = json.loads(tmp)
-
- state = 'down'
- if 'UP' in out[0]['flags']:
- state = 'up'
+ return self.get_interface('admin_state')
- return state
-
- def set_state(self, state):
+ def set_admin_state(self, state):
"""
Set interface administrative state to be 'up' or 'down'
Example:
>>> from vyos.ifconfig import Interface
- >>> Interface('eth0').set_state('down')
- >>> Interface('eth0').get_state()
+ >>> Interface('eth0').set_admin_state('down')
+ >>> Interface('eth0').get_admin_state()
'down'
"""
- return self.set_interface('state', state)
+ return self.set_interface('admin_state', state)
+
+ def get_oper_state(self):
+ """
+ Get interface operational state
+
+ Example:
+ >>> from vyos.ifconfig import Interface
+ >>> Interface('eth0').get_oper_sate()
+ 'up'
+ """
+ # https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-net
+ # "unknown", "notpresent", "down", "lowerlayerdown", "testing", "dormant", "up"
+ return self.get_interface('oper_state')
def set_proxy_arp(self, enable):
"""
diff --git a/python/vyos/ifconfig/l2tpv3.py b/python/vyos/ifconfig/l2tpv3.py
index fbfab4c6e..07f1cf8a3 100644
--- a/python/vyos/ifconfig/l2tpv3.py
+++ b/python/vyos/ifconfig/l2tpv3.py
@@ -62,7 +62,7 @@ class L2TPv3If(Interface):
self._cmd(cmd)
# interface is always A/D down. It needs to be enabled explicitly
- self.set_state('down')
+ self.set_admin_state('down')
def remove(self):
"""
@@ -76,7 +76,7 @@ class L2TPv3If(Interface):
if os.path.exists('/sys/class/net/{}'.format(self.config['ifname'])):
# interface is always A/D down. It needs to be enabled explicitly
- self.set_state('down')
+ self.set_admin_state('down')
if self._config['tunnel_id'] and self._config['session_id']:
cmd = 'ip l2tp del session tunnel_id {} '.format(
diff --git a/python/vyos/ifconfig/tunnel.py b/python/vyos/ifconfig/tunnel.py
index a49bdd51c..1bbb9eb6a 100644
--- a/python/vyos/ifconfig/tunnel.py
+++ b/python/vyos/ifconfig/tunnel.py
@@ -98,10 +98,10 @@ class _Tunnel(Interface):
options = " ".join(["{} {}".format(k, self.config[k])
for k in self.options if k in self.config and self.config[k]])
self._cmd('{} {}'.format(self.create.format(**self.config), options))
- self.set_interface('state', 'down')
+ self.set_admin_state('down')
def _delete(self):
- self.set_interface('state', 'down')
+ self.set_admin_state('down')
cmd = self.delete.format(**self.config)
return self._cmd(cmd)
diff --git a/python/vyos/ifconfig_vlan.py b/python/vyos/ifconfig_vlan.py
index 2b934cdfc..00270cf58 100644
--- a/python/vyos/ifconfig_vlan.py
+++ b/python/vyos/ifconfig_vlan.py
@@ -64,6 +64,12 @@ def apply_vlan_config(vlan, config):
vlan.set_arp_announce(config['ip_enable_arp_announce'])
# configure ARP ignore
vlan.set_arp_ignore(config['ip_enable_arp_ignore'])
+ # IPv6 address autoconfiguration
+ vlan.set_ipv6_autoconf(config['ipv6_autoconf'])
+ # IPv6 forwarding
+ vlan.set_ipv6_forwarding(config['ipv6_forwarding'])
+ # IPv6 Duplicate Address Detection (DAD) tries
+ vlan.set_ipv6_dad_messages(config['ipv6_dup_addr_detect'])
# Maximum Transmission Unit (MTU)
vlan.set_mtu(config['mtu'])
@@ -76,9 +82,9 @@ def apply_vlan_config(vlan, config):
# enable/disable VLAN interface
if config['disable']:
- vlan.set_state('down')
+ vlan.set_admin_state('down')
else:
- vlan.set_state('up')
+ vlan.set_admin_state('up')
# Configure interface address(es)
# - not longer required addresses get removed first
diff --git a/python/vyos/util.py b/python/vyos/util.py
index 67a602f7a..635b11ee5 100644
--- a/python/vyos/util.py
+++ b/python/vyos/util.py
@@ -15,16 +15,16 @@
import os
import re
-import getpass
-import grp
-import time
-import subprocess
import sys
-
import psutil
import vyos.defaults
+from getpass import getuser
+from grp import getgrnam
+from time import sleep
+from subprocess import check_output
+from ipaddress import ip_network
def read_file(path):
""" Read a file to string """
@@ -32,6 +32,7 @@ def read_file(path):
data = f.read().strip()
return data
+
def colon_separated_to_dict(data_string, uniquekeys=False):
""" Converts a string containing newline-separated entries
of colon-separated key-value pairs into a dict.
@@ -80,12 +81,14 @@ def colon_separated_to_dict(data_string, uniquekeys=False):
return data
+
def process_running(pid_file):
""" Checks if a process with PID in pid_file is running """
with open(pid_file, 'r') as f:
pid = f.read().strip()
return psutil.pid_exists(int(pid))
+
def seconds_to_human(s, separator=""):
""" Converts number of seconds passed to a human-readable
interval such as 1w4d18h35m59s
@@ -125,10 +128,12 @@ def seconds_to_human(s, separator=""):
return result
+
def get_cfg_group_id():
- group_data = grp.getgrnam(vyos.defaults.cfg_group)
+ group_data = getgrnam(vyos.defaults.cfg_group)
return group_data.gr_gid
+
def file_is_persistent(path):
if not re.match(r'^(/config|/opt/vyatta/etc/config)', os.path.dirname(path)):
warning = "Warning: file {0} is outside the /config directory\n".format(path)
@@ -137,6 +142,7 @@ def file_is_persistent(path):
else:
return (True, None)
+
def commit_in_progress():
""" Not to be used in normal op mode scripts! """
@@ -154,7 +160,7 @@ def commit_in_progress():
# Since this will be used in scripts that modify the config outside of the CLI
# framework, those knowingly have root permissions.
# For everything else, we add a safeguard.
- id = subprocess.check_output(['/usr/bin/id', '-u']).decode().strip()
+ id = check_output(['/usr/bin/id', '-u']).decode().strip()
if id != '0':
raise OSError("This functions needs root permissions to return correct results")
@@ -171,12 +177,14 @@ def commit_in_progress():
# Default case
return False
+
def wait_for_commit_lock():
""" Not to be used in normal op mode scripts! """
# Very synchronous approach to multiprocessing
while commit_in_progress():
- time.sleep(1)
+ sleep(1)
+
def ask_yes_no(question, default=False) -> bool:
"""Ask a yes/no question via input() and return their answer."""
@@ -196,6 +204,28 @@ def ask_yes_no(question, default=False) -> bool:
def is_admin() -> bool:
"""Look if current user is in sudo group"""
- current_user = getpass.getuser()
- (_, _, _, admin_group_members) = grp.getgrnam('sudo')
+ current_user = getuser()
+ (_, _, _, admin_group_members) = getgrnam('sudo')
return current_user in admin_group_members
+
+
+def mac2eui64(mac, prefix=None):
+ '''
+ Convert a MAC address to a EUI64 address or, with prefix provided, a full
+ IPv6 address.
+ Thankfully copied from https://gist.github.com/wido/f5e32576bb57b5cc6f934e177a37a0d3
+ '''
+ # http://tools.ietf.org/html/rfc4291#section-2.5.1
+ eui64 = re.sub(r'[.:-]', '', mac).lower()
+ eui64 = eui64[0:6] + 'fffe' + eui64[6:]
+ eui64 = hex(int(eui64[0:2], 16) ^ 2)[2:].zfill(2) + eui64[2:]
+
+ if prefix is None:
+ return ':'.join(re.findall(r'.{4}', eui64))
+ else:
+ try:
+ net = ip_network(prefix, strict=False)
+ euil = int('0x{0}'.format(eui64), 16)
+ return str(net[euil])
+ except: # pylint: disable=bare-except
+ return
diff --git a/src/conf_mode/interfaces-bonding.py b/src/conf_mode/interfaces-bonding.py
index 03df6e16a..cc119b91a 100755
--- a/src/conf_mode/interfaces-bonding.py
+++ b/src/conf_mode/interfaces-bonding.py
@@ -48,6 +48,10 @@ default_config_data = {
'ip_enable_arp_ignore': 0,
'ip_proxy_arp': 0,
'ip_proxy_arp_pvlan': 0,
+ 'ipv6_autoconf': 0,
+ 'ipv6_eui64_prefix': '',
+ 'ipv6_forwarding': 1,
+ 'ipv6_dup_addr_detect': 1,
'intf': '',
'mac': '',
'mode': '802.3ad',
@@ -189,6 +193,22 @@ def get_config():
if conf.exists('ip proxy-arp-pvlan'):
bond['ip_proxy_arp_pvlan'] = 1
+ # Enable acquisition of IPv6 address using stateless autoconfig (SLAAC)
+ if conf.exists('ipv6 address autoconf'):
+ bond['ipv6_autoconf'] = 1
+
+ # Get prefix for IPv6 addressing based on MAC address (EUI-64)
+ if conf.exists('ipv6 address eui64'):
+ bond['ipv6_eui64_prefix'] = conf.return_value('ipv6 address eui64')
+
+ # Disable IPv6 forwarding on this interface
+ if conf.exists('ipv6 disable-forwarding'):
+ bond['ipv6_forwarding'] = 0
+
+ # IPv6 Duplicate Address Detection (DAD) tries
+ if conf.exists('ipv6 dup-addr-detect-transmits'):
+ bond['ipv6_dup_addr_detect'] = int(conf.return_value('ipv6 dup-addr-detect-transmits'))
+
# Media Access Control (MAC) address
if conf.exists('mac'):
bond['mac'] = conf.return_value('mac')
@@ -416,6 +436,14 @@ def apply(bond):
b.set_proxy_arp(bond['ip_proxy_arp'])
# Enable private VLAN proxy ARP on this interface
b.set_proxy_arp_pvlan(bond['ip_proxy_arp_pvlan'])
+ # IPv6 address autoconfiguration
+ b.set_ipv6_autoconf(bond['ipv6_autoconf'])
+ # IPv6 EUI-based address
+ b.set_ipv6_eui64_address(bond['ipv6_eui64_prefix'])
+ # IPv6 forwarding
+ b.set_ipv6_forwarding(bond['ipv6_forwarding'])
+ # IPv6 Duplicate Address Detection (DAD) tries
+ b.set_ipv6_dad_messages(bond['ipv6_dup_addr_detect'])
# Change interface MAC address
if bond['mac']:
@@ -431,7 +459,7 @@ def apply(bond):
# Some parameters can not be changed when the bond is up.
if bond['shutdown_required']:
# Disable bond prior changing of certain properties
- b.set_state('down')
+ b.set_admin_state('down')
# The bonding mode can not be changed when there are interfaces enslaved
# to this bond, thus we will free all interfaces from the bond first!
@@ -449,9 +477,9 @@ def apply(bond):
# parameters we will only re-enable the interface if it is not
# administratively disabled
if not bond['disable']:
- b.set_state('up')
+ b.set_admin_state('up')
else:
- b.set_state('down')
+ b.set_admin_state('down')
# Configure interface address(es)
# - not longer required addresses get removed first
diff --git a/src/conf_mode/interfaces-bridge.py b/src/conf_mode/interfaces-bridge.py
index c45ab13a8..28e5957e4 100755
--- a/src/conf_mode/interfaces-bridge.py
+++ b/src/conf_mode/interfaces-bridge.py
@@ -46,6 +46,10 @@ default_config_data = {
'ip_enable_arp_accept': 0,
'ip_enable_arp_announce': 0,
'ip_enable_arp_ignore': 0,
+ 'ipv6_autoconf': 0,
+ 'ipv6_eui64_prefix': '',
+ 'ipv6_forwarding': 1,
+ 'ipv6_dup_addr_detect': 1,
'igmp_querier': 0,
'intf': '',
'mac' : '',
@@ -152,6 +156,22 @@ def get_config():
if conf.exists('ip enable-arp-ignore'):
bridge['ip_enable_arp_ignore'] = 1
+ # Enable acquisition of IPv6 address using stateless autoconfig (SLAAC)
+ if conf.exists('ipv6 address autoconf'):
+ bridge['ipv6_autoconf'] = 1
+
+ # Get prefix for IPv6 addressing based on MAC address (EUI-64)
+ if conf.exists('ipv6 address eui64'):
+ bridge['ipv6_eui64_prefix'] = conf.return_value('ipv6 address eui64')
+
+ # Disable IPv6 forwarding on this interface
+ if conf.exists('ipv6 disable-forwarding'):
+ bridge['ipv6_forwarding'] = 0
+
+ # IPv6 Duplicate Address Detection (DAD) tries
+ if conf.exists('ipv6 dup-addr-detect-transmits'):
+ bridge['ipv6_dup_addr_detect'] = int(conf.return_value('ipv6 dup-addr-detect-transmits'))
+
# Media Access Control (MAC) address
if conf.exists('mac'):
bridge['mac'] = conf.return_value('mac')
@@ -243,7 +263,7 @@ def apply(bridge):
br.remove()
else:
# enable interface
- br.set_state('up')
+ br.set_admin_state('up')
# set ageing time
br.set_ageing_time(bridge['aging'])
# set bridge forward delay
@@ -258,6 +278,14 @@ def apply(bridge):
br.set_arp_announce(bridge['ip_enable_arp_announce'])
# configure ARP ignore
br.set_arp_ignore(bridge['ip_enable_arp_ignore'])
+ # IPv6 address autoconfiguration
+ br.set_ipv6_autoconf(bridge['ipv6_autoconf'])
+ # IPv6 EUI-based address
+ br.set_ipv6_eui64_address(bridge['ipv6_eui64_prefix'])
+ # IPv6 forwarding
+ br.set_ipv6_forwarding(bridge['ipv6_forwarding'])
+ # IPv6 Duplicate Address Detection (DAD) tries
+ br.set_ipv6_dad_messages(bridge['ipv6_dup_addr_detect'])
# set max message age
br.set_max_age(bridge['max_age'])
# set bridge priority
@@ -313,7 +341,7 @@ def apply(bridge):
# up/down interface
if bridge['disable']:
- br.set_state('down')
+ br.set_admin_state('down')
# Configure interface address(es)
# - not longer required addresses get removed first
diff --git a/src/conf_mode/interfaces-dummy.py b/src/conf_mode/interfaces-dummy.py
index bf55b13ec..b7b75517d 100755
--- a/src/conf_mode/interfaces-dummy.py
+++ b/src/conf_mode/interfaces-dummy.py
@@ -110,9 +110,9 @@ def apply(dummy):
# disable interface on demand
if dummy['disable']:
- d.set_state('down')
+ d.set_admin_state('down')
else:
- d.set_state('up')
+ d.set_admin_state('up')
return None
diff --git a/src/conf_mode/interfaces-ethernet.py b/src/conf_mode/interfaces-ethernet.py
index 2f5d796b4..286cab88e 100755
--- a/src/conf_mode/interfaces-ethernet.py
+++ b/src/conf_mode/interfaces-ethernet.py
@@ -48,6 +48,10 @@ default_config_data = {
'ip_enable_arp_ignore': 0,
'ip_proxy_arp': 0,
'ip_proxy_arp_pvlan': 0,
+ 'ipv6_autoconf': 0,
+ 'ipv6_eui64_prefix': '',
+ 'ipv6_forwarding': 1,
+ 'ipv6_dup_addr_detect': 1,
'intf': '',
'mac': '',
'mtu': 1500,
@@ -167,6 +171,22 @@ def get_config():
if conf.exists('ip proxy-arp-pvlan'):
eth['ip_proxy_arp_pvlan'] = 1
+ # Enable acquisition of IPv6 address using stateless autoconfig (SLAAC)
+ if conf.exists('ipv6 address autoconf'):
+ eth['ipv6_autoconf'] = 1
+
+ # Get prefix for IPv6 addressing based on MAC address (EUI-64)
+ if conf.exists('ipv6 address eui64'):
+ eth['ipv6_eui64_prefix'] = conf.return_value('ipv6 address eui64')
+
+ # Disable IPv6 forwarding on this interface
+ if conf.exists('ipv6 disable-forwarding'):
+ eth['ipv6_forwarding'] = 0
+
+ # IPv6 Duplicate Address Detection (DAD) tries
+ if conf.exists('ipv6 dup-addr-detect-transmits'):
+ eth['ipv6_dup_addr_detect'] = int(conf.return_value('ipv6 dup-addr-detect-transmits'))
+
# Media Access Control (MAC) address
if conf.exists('mac'):
eth['mac'] = conf.return_value('mac')
@@ -326,6 +346,14 @@ def apply(eth):
e.set_proxy_arp(eth['ip_proxy_arp'])
# Enable private VLAN proxy ARP on this interface
e.set_proxy_arp_pvlan(eth['ip_proxy_arp_pvlan'])
+ # IPv6 address autoconfiguration
+ e.set_ipv6_autoconf(eth['ipv6_autoconf'])
+ # IPv6 EUI-based address
+ e.set_ipv6_eui64_address(eth['ipv6_eui64_prefix'])
+ # IPv6 forwarding
+ e.set_ipv6_forwarding(eth['ipv6_forwarding'])
+ # IPv6 Duplicate Address Detection (DAD) tries
+ e.set_ipv6_dad_messages(eth['ipv6_dup_addr_detect'])
# Change interface MAC address - re-set to real hardware address (hw-id)
# if custom mac is removed
@@ -357,9 +385,9 @@ def apply(eth):
# Enable/Disable interface
if eth['disable']:
- e.set_state('down')
+ e.set_admin_state('down')
else:
- e.set_state('up')
+ e.set_admin_state('up')
# Configure interface address(es)
# - not longer required addresses get removed first
diff --git a/src/conf_mode/interfaces-geneve.py b/src/conf_mode/interfaces-geneve.py
index 8278b54b0..eaa678d3e 100755
--- a/src/conf_mode/interfaces-geneve.py
+++ b/src/conf_mode/interfaces-geneve.py
@@ -148,7 +148,7 @@ def apply(geneve):
# parameters we will only re-enable the interface if it is not
# administratively disabled
if not geneve['disable']:
- g.set_state('up')
+ g.set_admin_state('up')
return None
diff --git a/src/conf_mode/interfaces-l2tpv3.py b/src/conf_mode/interfaces-l2tpv3.py
index 3bc3faca8..af1d3f482 100755
--- a/src/conf_mode/interfaces-l2tpv3.py
+++ b/src/conf_mode/interfaces-l2tpv3.py
@@ -33,6 +33,10 @@ default_config_data = {
'local_address': '',
'local_port': 5000,
'intf': '',
+ 'ipv6_autoconf': 0,
+ 'ipv6_eui64_prefix': '',
+ 'ipv6_forwarding': 1,
+ 'ipv6_dup_addr_detect': 1,
'mtu': 1488,
'peer_session_id': '',
'peer_tunnel_id': '',
@@ -101,6 +105,22 @@ def get_config():
if conf.exists('local-ip'):
l2tpv3['local_address'] = conf.return_value('local-ip')
+ # Enable acquisition of IPv6 address using stateless autoconfig (SLAAC)
+ if conf.exists('ipv6 address autoconf'):
+ l2tpv3['ipv6_autoconf'] = 1
+
+ # Get prefix for IPv6 addressing based on MAC address (EUI-64)
+ if conf.exists('ipv6 address eui64'):
+ l2tpv3['ipv6_eui64_prefix'] = conf.return_value('ipv6 address eui64')
+
+ # Disable IPv6 forwarding on this interface
+ if conf.exists('ipv6 disable-forwarding'):
+ l2tpv3['ipv6_forwarding'] = 0
+
+ # IPv6 Duplicate Address Detection (DAD) tries
+ if conf.exists('ipv6 dup-addr-detect-transmits'):
+ l2tpv3['ipv6_dup_addr_detect'] = int(conf.return_value('ipv6 dup-addr-detect-transmits'))
+
# Maximum Transmission Unit (MTU)
if conf.exists('mtu'):
l2tpv3['mtu'] = int(conf.return_value('mtu'))
@@ -193,6 +213,14 @@ def apply(l2tpv3):
l.set_alias(l2tpv3['description'])
# Maximum Transfer Unit (MTU)
l.set_mtu(l2tpv3['mtu'])
+ # IPv6 address autoconfiguration
+ l.set_ipv6_autoconf(l2tpv3['ipv6_autoconf'])
+ # IPv6 EUI-based address
+ l.set_ipv6_eui64_address(l2tpv3['ipv6_eui64_prefix'])
+ # IPv6 forwarding
+ l.set_ipv6_forwarding(l2tpv3['ipv6_forwarding'])
+ # IPv6 Duplicate Address Detection (DAD) tries
+ l.set_ipv6_dad_messages(l2tpv3['ipv6_dup_addr_detect'])
# Configure interface address(es) - no need to implicitly delete the
# old addresses as they have already been removed by deleting the
@@ -204,7 +232,7 @@ def apply(l2tpv3):
# we will only re-enable the interface if it is not administratively
# disabled
if not l2tpv3['disable']:
- l.set_state('up')
+ l.set_admin_state('up')
return None
diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py
index 155101f1d..17aa4697f 100755
--- a/src/conf_mode/interfaces-openvpn.py
+++ b/src/conf_mode/interfaces-openvpn.py
@@ -294,6 +294,10 @@ default_config_data = {
'encryption': '',
'hash': '',
'intf': '',
+ 'ipv6_autoconf': 0,
+ 'ipv6_eui64_prefix': '',
+ 'ipv6_forwarding': 1,
+ 'ipv6_dup_addr_detect': 1,
'ping_restart': '60',
'ping_interval': '10',
'local_address': '',
@@ -490,6 +494,22 @@ def get_config():
if conf.exists('local-port'):
openvpn['local_port'] = conf.return_value('local-port')
+ # Enable acquisition of IPv6 address using stateless autoconfig (SLAAC)
+ if conf.exists('ipv6 address autoconf'):
+ openvpn['ipv6_autoconf'] = 1
+
+ # Get prefix for IPv6 addressing based on MAC address (EUI-64)
+ if conf.exists('ipv6 address eui64'):
+ openvpn['ipv6_eui64_prefix'] = conf.return_value('ipv6 address eui64')
+
+ # Disable IPv6 forwarding on this interface
+ if conf.exists('ipv6 disable-forwarding'):
+ openvpn['ipv6_forwarding'] = 0
+
+ # IPv6 Duplicate Address Detection (DAD) tries
+ if conf.exists('ipv6 dup-addr-detect-transmits'):
+ openvpn['ipv6_dup_addr_detect'] = int(conf.return_value('ipv6 dup-addr-detect-transmits'))
+
# OpenVPN operation mode
if conf.exists('mode'):
mode = conf.return_value('mode')
@@ -1036,14 +1056,25 @@ def apply(openvpn):
try:
# we need to catch the exception if the interface is not up due to
# reason stated above
- VTunIf(openvpn['intf']).set_alias(openvpn['description'])
+ o = VTunIf(openvpn['intf'])
+ # update interface description used e.g. within SNMP
+ o.set_alias(openvpn['description'])
+ # IPv6 address autoconfiguration
+ o.set_ipv6_autoconf(openvpn['ipv6_autoconf'])
+ # IPv6 EUI-based address
+ o.set_ipv6_eui64_address(openvpn['ipv6_eui64_prefix'])
+ # IPv6 forwarding
+ o.set_ipv6_forwarding(openvpn['ipv6_forwarding'])
+ # IPv6 Duplicate Address Detection (DAD) tries
+ o.set_ipv6_dad_messages(openvpn['ipv6_dup_addr_detect'])
+
except:
pass
# TAP interface needs to be brought up explicitly
if openvpn['type'] == 'tap':
if not openvpn['disable']:
- VTunIf(openvpn['intf']).set_state('up')
+ VTunIf(openvpn['intf']).set_admin_state('up')
return None
diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py
index 0afae8388..56d4fdfc3 100755
--- a/src/conf_mode/interfaces-pseudo-ethernet.py
+++ b/src/conf_mode/interfaces-pseudo-ethernet.py
@@ -45,6 +45,10 @@ default_config_data = {
'ip_enable_arp_ignore': 0,
'ip_proxy_arp': 0,
'ip_proxy_arp_pvlan': 0,
+ 'ipv6_autoconf': 0,
+ 'ipv6_eui64_prefix': '',
+ 'ipv6_forwarding': 1,
+ 'ipv6_dup_addr_detect': 1,
'intf': '',
'link': '',
'link_changed': False,
@@ -145,6 +149,22 @@ def get_config():
if conf.exists(['ip', 'proxy-arp-pvlan']):
peth['ip_proxy_arp_pvlan'] = 1
+ # Enable acquisition of IPv6 address using stateless autoconfig (SLAAC)
+ if conf.exists('ipv6 address autoconf'):
+ peth['ipv6_autoconf'] = 1
+
+ # Get prefix for IPv6 addressing based on MAC address (EUI-64)
+ if conf.exists('ipv6 address eui64'):
+ peth['ipv6_eui64_prefix'] = conf.return_value('ipv6 address eui64')
+
+ # Disable IPv6 forwarding on this interface
+ if conf.exists('ipv6 disable-forwarding'):
+ peth['ipv6_forwarding'] = 0
+
+ # IPv6 Duplicate Address Detection (DAD) tries
+ if conf.exists('ipv6 dup-addr-detect-transmits'):
+ peth['ipv6_dup_addr_detect'] = int(conf.return_value('ipv6 dup-addr-detect-transmits'))
+
# Lower link device
if conf.exists(['link']):
peth['link'] = conf.return_value(['link'])
@@ -296,6 +316,14 @@ def apply(peth):
p.set_proxy_arp(peth['ip_proxy_arp'])
# Enable private VLAN proxy ARP on this interface
p.set_proxy_arp_pvlan(peth['ip_proxy_arp_pvlan'])
+ # IPv6 address autoconfiguration
+ p.set_ipv6_autoconf(peth['ipv6_autoconf'])
+ # IPv6 EUI-based address
+ p.set_ipv6_eui64_address(peth['ipv6_eui64_prefix'])
+ # IPv6 forwarding
+ p.set_ipv6_forwarding(peth['ipv6_forwarding'])
+ # IPv6 Duplicate Address Detection (DAD) tries
+ p.set_ipv6_dad_messages(peth['ipv6_dup_addr_detect'])
# assign/remove VRF
p.set_vrf(peth['vrf'])
@@ -309,9 +337,9 @@ def apply(peth):
# Enable/Disable interface
if peth['disable']:
- p.set_state('down')
+ p.set_admin_state('down')
else:
- p.set_state('up')
+ p.set_admin_state('up')
# Configure interface address(es)
# - not longer required addresses get removed first
diff --git a/src/conf_mode/interfaces-tunnel.py b/src/conf_mode/interfaces-tunnel.py
index 90c1f8f71..4cbb51f4a 100755
--- a/src/conf_mode/interfaces-tunnel.py
+++ b/src/conf_mode/interfaces-tunnel.py
@@ -478,7 +478,7 @@ def apply(conf):
tunnel.add_addr(addr)
# now bring it up (or not)
- tunnel.set_state(options['state'])
+ tunnel.set_admin_state(options['state'])
if __name__ == '__main__':
diff --git a/src/conf_mode/interfaces-vxlan.py b/src/conf_mode/interfaces-vxlan.py
index c9ef0fe9c..3d2638c6f 100755
--- a/src/conf_mode/interfaces-vxlan.py
+++ b/src/conf_mode/interfaces-vxlan.py
@@ -37,6 +37,10 @@ default_config_data = {
'ip_enable_arp_announce': 0,
'ip_enable_arp_ignore': 0,
'ip_proxy_arp': 0,
+ 'ipv6_autoconf': 0,
+ 'ipv6_eui64_prefix': '',
+ 'ipv6_forwarding': 1,
+ 'ipv6_dup_addr_detect': 1,
'link': '',
'mtu': 1450,
'remote': '',
@@ -103,6 +107,22 @@ def get_config():
if conf.exists('ip enable-proxy-arp'):
vxlan['ip_proxy_arp'] = 1
+ # Enable acquisition of IPv6 address using stateless autoconfig (SLAAC)
+ if conf.exists('ipv6 address autoconf'):
+ vxlan['ipv6_autoconf'] = 1
+
+ # Get prefix for IPv6 addressing based on MAC address (EUI-64)
+ if conf.exists('ipv6 address eui64'):
+ vxlan['ipv6_eui64_prefix'] = conf.return_value('ipv6 address eui64')
+
+ # Disable IPv6 forwarding on this interface
+ if conf.exists('ipv6 disable-forwarding'):
+ vxlan['ipv6_forwarding'] = 0
+
+ # IPv6 Duplicate Address Detection (DAD) tries
+ if conf.exists('ipv6 dup-addr-detect-transmits'):
+ vxlan['ipv6_dup_addr_detect'] = int(conf.return_value('ipv6 dup-addr-detect-transmits'))
+
# VXLAN underlay interface
if conf.exists('link'):
vxlan['link'] = conf.return_value('link')
@@ -201,6 +221,14 @@ def apply(vxlan):
v.set_arp_ignore(vxlan['ip_enable_arp_ignore'])
# Enable proxy-arp on this interface
v.set_proxy_arp(vxlan['ip_proxy_arp'])
+ # IPv6 address autoconfiguration
+ v.set_ipv6_autoconf(vxlan['ipv6_autoconf'])
+ # IPv6 EUI-based address
+ v.set_ipv6_eui64_address(vxlan['ipv6_eui64_prefix'])
+ # IPv6 forwarding
+ v.set_ipv6_forwarding(vxlan['ipv6_forwarding'])
+ # IPv6 Duplicate Address Detection (DAD) tries
+ v.set_ipv6_dad_messages(vxlan['ipv6_dup_addr_detect'])
# Configure interface address(es) - no need to implicitly delete the
# old addresses as they have already been removed by deleting the
@@ -212,7 +240,7 @@ def apply(vxlan):
# parameters we will only re-enable the interface if it is not
# administratively disabled
if not vxlan['disable']:
- v.set_state('up')
+ v.set_admin_state('up')
return None
diff --git a/src/conf_mode/interfaces-wireguard.py b/src/conf_mode/interfaces-wireguard.py
index 0d6373d89..d8c327e19 100755
--- a/src/conf_mode/interfaces-wireguard.py
+++ b/src/conf_mode/interfaces-wireguard.py
@@ -269,7 +269,7 @@ def apply(c):
intfc.update()
# interface state
- intfc.set_state(c['state'])
+ intfc.set_admin_state(c['state'])
return None
diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py
index 2d05e722d..2c67c39ae 100755
--- a/src/conf_mode/interfaces-wireless.py
+++ b/src/conf_mode/interfaces-wireless.py
@@ -827,6 +827,10 @@ default_config_data = {
'ip_enable_arp_accept': 0,
'ip_enable_arp_announce': 0,
'ip_enable_arp_ignore': 0,
+ 'ipv6_autoconf': 0,
+ 'ipv6_eui64_prefix': '',
+ 'ipv6_forwarding': 1,
+ 'ipv6_dup_addr_detect': 1,
'mac' : '',
'max_stations' : '',
'mgmt_frame_protection' : 'disabled',
@@ -1136,10 +1140,26 @@ def get_config():
if conf.exists('ip enable-arp-announce'):
wifi['ip_enable_arp_announce'] = 1
+ # Enable acquisition of IPv6 address using stateless autoconfig (SLAAC)
+ if conf.exists('ipv6 address autoconf'):
+ wifi['ipv6_autoconf'] = 1
+
+ # Get prefix for IPv6 addressing based on MAC address (EUI-64)
+ if conf.exists('ipv6 address eui64'):
+ wifi['ipv6_eui64_prefix'] = conf.return_value('ipv6 address eui64')
+
# ARP enable ignore
if conf.exists('ip enable-arp-ignore'):
wifi['ip_enable_arp_ignore'] = 1
+ # Disable IPv6 forwarding on this interface
+ if conf.exists('ipv6 disable-forwarding'):
+ wifi['ipv6_forwarding'] = 0
+
+ # IPv6 Duplicate Address Detection (DAD) tries
+ if conf.exists('ipv6 dup-addr-detect-transmits'):
+ wifi['ipv6_dup_addr_detect'] = int(conf.return_value('ipv6 dup-addr-detect-transmits'))
+
# Wireless physical device
if conf.exists('physical-device'):
wifi['phy'] = conf.return_value('physical-device')
@@ -1487,6 +1507,14 @@ def apply(wifi):
w.set_arp_announce(wifi['ip_enable_arp_announce'])
# configure ARP ignore
w.set_arp_ignore(wifi['ip_enable_arp_ignore'])
+ # IPv6 address autoconfiguration
+ w.set_ipv6_autoconf(wifi['ipv6_autoconf'])
+ # IPv6 EUI-based address
+ w.set_ipv6_eui64_address(wifi['ipv6_eui64_prefix'])
+ # IPv6 forwarding
+ w.set_ipv6_forwarding(wifi['ipv6_forwarding'])
+ # IPv6 Duplicate Address Detection (DAD) tries
+ w.set_ipv6_dad_messages(wifi['ipv6_dup_addr_detect'])
# Configure interface address(es)
# - not longer required addresses get removed first
@@ -1518,7 +1546,7 @@ def apply(wifi):
# Enable/Disable interface - interface is always placed in
# administrative down state in WiFiIf class
if not wifi['disable']:
- w.set_state('up')
+ w.set_admin_state('up')
# Physical interface is now configured. Proceed by starting hostapd or
# wpa_supplicant daemon. When type is monitor we can just skip this.
diff --git a/src/helpers/vyos-merge-config.py b/src/helpers/vyos-merge-config.py
index 7ae62cfb3..c5216daa6 100755
--- a/src/helpers/vyos-merge-config.py
+++ b/src/helpers/vyos-merge-config.py
@@ -70,10 +70,7 @@ with tempfile.NamedTemporaryFile() as file_to_migrate:
merge_config_tree = ConfigTree(config_file)
effective_config = Config()
-
-output_effective_config = effective_config.show_config()
-
-effective_config_tree = ConfigTree(output_effective_config)
+effective_config_tree = effective_config._running_config
effective_cmds = effective_config_tree.to_commands()
merge_cmds = merge_config_tree.to_commands()