diff --git a/interface-definitions/include/interface/evpn-mh-uplink.xml.i b/interface-definitions/include/interface/evpn-mh-uplink.xml.i
new file mode 100644
index 0000000000..5f7fe1b7f4
--- /dev/null
+++ b/interface-definitions/include/interface/evpn-mh-uplink.xml.i
@@ -0,0 +1,8 @@
+
+
+
+ Uplink to the VXLAN core
+
+
+
+
diff --git a/interface-definitions/interfaces_bonding.xml.in b/interface-definitions/interfaces_bonding.xml.in
index e6baed590f..cc0327f3dd 100644
--- a/interface-definitions/interfaces_bonding.xml.in
+++ b/interface-definitions/interfaces_bonding.xml.in
@@ -102,12 +102,7 @@
-
-
- Uplink to the VXLAN core
-
-
-
+ #include
diff --git a/interface-definitions/interfaces_ethernet.xml.in b/interface-definitions/interfaces_ethernet.xml.in
index 4e55bac7cf..89f990d411 100644
--- a/interface-definitions/interfaces_ethernet.xml.in
+++ b/interface-definitions/interfaces_ethernet.xml.in
@@ -57,6 +57,14 @@
auto
#include
+
+
+ EVPN Multihoming
+
+
+ #include
+
+
#include
#include
#include
diff --git a/smoketest/scripts/cli/test_interfaces_ethernet.py b/smoketest/scripts/cli/test_interfaces_ethernet.py
index 8f387b23dd..4843a40da1 100755
--- a/smoketest/scripts/cli/test_interfaces_ethernet.py
+++ b/smoketest/scripts/cli/test_interfaces_ethernet.py
@@ -354,5 +354,15 @@ def test_ethtool_flow_control(self):
out = loads(out)
self.assertFalse(out[0]['autonegotiate'])
+ def test_ethtool_evpn_uplink_tarcking(self):
+ for interface in self._interfaces:
+ self.cli_set(self._base_path + [interface, 'evpn', 'uplink'])
+
+ self.cli_commit()
+
+ for interface in self._interfaces:
+ frrconfig = self.getFRRconfig(f'interface {interface}', daemon='zebra')
+ self.assertIn(f' evpn mh uplink', frrconfig)
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/src/conf_mode/interfaces_ethernet.py b/src/conf_mode/interfaces_ethernet.py
index 6da7e6a698..54d0669cb1 100755
--- a/src/conf_mode/interfaces_ethernet.py
+++ b/src/conf_mode/interfaces_ethernet.py
@@ -41,6 +41,7 @@
from vyos.pki import load_certificate
from vyos.pki import wrap_private_key
from vyos.template import render
+from vyos.template import render_to_string
from vyos.utils.process import call
from vyos.utils.dict import dict_search
from vyos.utils.dict import dict_to_paths_values
@@ -48,6 +49,7 @@
from vyos.utils.dict import dict_delete
from vyos.utils.file import write_file
from vyos import ConfigError
+from vyos import frr
from vyos import airbag
airbag.enable()
@@ -389,6 +391,10 @@ def generate(ethernet):
write_file(ca_cert_file_path, '\n'.join(ca_chains))
+ ethernet['frr_zebra_config'] = ''
+ if 'deleted' not in ethernet:
+ ethernet['frr_zebra_config'] = render_to_string('frr/evpn.mh.frr.j2', ethernet)
+
return None
def apply(ethernet):
@@ -407,6 +413,17 @@ def apply(ethernet):
call(f'systemctl {eapol_action} wpa_supplicant-wired@{ifname}')
+ zebra_daemon = 'zebra'
+ # Save original configuration prior to starting any commit actions
+ frr_cfg = frr.FRRConfig()
+
+ # The route-map used for the FIB (zebra) is part of the zebra daemon
+ frr_cfg.load_configuration(zebra_daemon)
+ frr_cfg.modify_section(f'^interface {ifname}', stop_pattern='^exit', remove_stop_mark=True)
+ if 'frr_zebra_config' in ethernet:
+ frr_cfg.add_before(frr.default_add_before, ethernet['frr_zebra_config'])
+ frr_cfg.commit_configuration(zebra_daemon)
+
if __name__ == '__main__':
try:
c = get_config()