Skip to content

Commit 5de0ae8

Browse files
committed
T7731: Static ARP entries are missing after an interface status change
1 parent 21d509d commit 5de0ae8

File tree

13 files changed

+202
-5
lines changed

13 files changed

+202
-5
lines changed

data/config-mode-dependencies/vyos-1x.json

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,40 @@
88
"group_resync": ["system_conntrack", "nat", "policy_route", "load-balancing_wan"]
99
},
1010
"interfaces_bonding": {
11-
"ethernet": ["interfaces_ethernet"]
11+
"ethernet": ["interfaces_ethernet"],
12+
"static_arp": ["protocols_static_arp"]
1213
},
1314
"interfaces_bridge": {
1415
"vxlan": ["interfaces_vxlan"],
15-
"wlan": ["interfaces_wireless"]
16+
"wlan": ["interfaces_wireless"],
17+
"static_arp": ["protocols_static_arp"]
18+
},
19+
"interfaces_ethernet": {
20+
"static_arp": ["protocols_static_arp"]
21+
},
22+
"interfaces_geneve": {
23+
"static_arp": ["protocols_static_arp"]
24+
},
25+
"interfaces_l2tpv3": {
26+
"static_arp": ["protocols_static_arp"]
27+
},
28+
"interfaces_macsec": {
29+
"static_arp": ["protocols_static_arp"]
30+
},
31+
"interfaces_pseudo_ethernet": {
32+
"static_arp": ["protocols_static_arp"]
33+
},
34+
"interfaces_virtual_ethernet": {
35+
"static_arp": ["protocols_static_arp"]
36+
},
37+
"interfaces_vxlan": {
38+
"static_arp": ["protocols_static_arp"]
39+
},
40+
"interfaces_wireless": {
41+
"static_arp": ["protocols_static_arp"]
42+
},
43+
"interfaces_wwan": {
44+
"static_arp": ["protocols_static_arp"]
1645
},
1746
"interfaces_wireguard": {
1847
"vxlan": ["interfaces_vxlan"]

smoketest/scripts/cli/test_vpp.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,6 +1595,29 @@ def test_20_kernel_options_hugepages(self):
15951595
self.assertIn(f' hugepagesz={hp_size_1g} hugepages={hp_count_1g}', tmp)
15961596
self.assertIn(f' hugepagesz={hp_size_2m} hugepages={hp_count_2m}', tmp)
15971597

1598+
def test_21_static_arp(self):
1599+
host = '192.0.2.10'
1600+
mac = '00:01:02:03:04:0a'
1601+
1602+
self.cli_set(['interfaces', 'ethernet', interface, 'address', '192.0.2.1/24'])
1603+
self.cli_set(
1604+
['protocols', 'static', 'arp', 'interface', interface, 'address', host, 'mac', mac]
1605+
)
1606+
self.cli_commit()
1607+
1608+
# Change VPP configuration
1609+
self.cli_set(base_path + ['settings', 'unix', 'poll-sleep-usec', '50'])
1610+
1611+
# Ensure arp entry is not disappeared
1612+
_, neighbors = rc_cmd('sudo ip neighbor')
1613+
self.assertIn(f'{host} dev {interface} lladdr {mac}', neighbors)
1614+
1615+
# Check VPP IP neighbors
1616+
_, vpp_neighbors = rc_cmd('sudo vppctl show ip neighbors')
1617+
self.assertRegex(vpp_neighbors, rf'{host}\s+S\s+{mac}\s+{interface}')
1618+
1619+
self.cli_delete(['protocols'])
1620+
15981621

15991622
if __name__ == '__main__':
16001623
unittest.main(verbosity=2, failfast=VyOSUnitTestSHIM.TestCase.debug_on())

src/conf_mode/interfaces_bonding.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,19 @@ def get_config(config=None):
175175
tmp = has_vrf_configured(conf, interface)
176176
if tmp: bond['member']['interface'][interface].update({'has_vrf' : ''})
177177

178+
# Protocols static arp dependency
179+
static_arp = conf.get_config_dict(
180+
['protocols', 'static', 'arp', 'interface'],
181+
key_mangling=('-', '_'),
182+
get_first_key=True,
183+
)
184+
if any(
185+
key == ifname or key.startswith(f"{ifname}.")
186+
for key in static_arp.keys()
187+
):
188+
set_dependents('static_arp', conf)
189+
bond['static_arp'] = {}
190+
178191
return bond
179192

180193

@@ -279,7 +292,7 @@ def apply(bond):
279292
else:
280293
b.update(bond)
281294

282-
if dict_search('member.interface_remove', bond):
295+
if dict_search('member.interface_remove', bond) or 'static_arp' in bond:
283296
try:
284297
call_dependents()
285298
except ConfigError:

src/conf_mode/interfaces_bridge.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,19 @@ def get_config(config=None):
124124
if len(bridge['member']) == 0:
125125
del bridge['member']
126126

127+
# Protocols static arp dependency
128+
static_arp = conf.get_config_dict(
129+
['protocols', 'static', 'arp', 'interface'],
130+
key_mangling=('-', '_'),
131+
get_first_key=True,
132+
)
133+
if any(
134+
key == ifname or key.startswith(f"{ifname}.")
135+
for key in static_arp.keys()
136+
):
137+
set_dependents('static_arp', conf)
138+
bridge['static_arp'] = {}
139+
127140
return bridge
128141

129142
def verify(bridge):
@@ -220,6 +233,9 @@ def apply(bridge):
220233
except ConfigError:
221234
raise ConfigError(f'Error updating member interface {interface} configuration after changing bridge!')
222235

236+
if 'static_arp' in bridge:
237+
call_dependents()
238+
223239
return None
224240

225241
if __name__ == '__main__':

src/conf_mode/interfaces_ethernet.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
from vyos.base import Warning
2222
from vyos.config import Config
23+
from vyos.configdep import set_dependents, call_dependents
2324
from vyos.configdict import get_interface_dict
2425
from vyos.configdict import is_node_changed
2526
from vyos.configdict import get_flowtable_interfaces
@@ -171,6 +172,18 @@ def get_config(config=None):
171172

172173
ethernet['flowtable_interfaces'] = get_flowtable_interfaces(conf)
173174

175+
# Protocols static arp dependency
176+
static_arp = conf.get_config_dict(
177+
['protocols', 'static', 'arp', 'interface'],
178+
key_mangling=('-', '_'),
179+
get_first_key=True,
180+
)
181+
if any(
182+
key == ifname or key.startswith(f"{ifname}.")
183+
for key in static_arp.keys()
184+
):
185+
set_dependents('static_arp', conf)
186+
174187
return ethernet
175188

176189
def verify_speed_duplex(ethernet: dict, ethtool: Ethtool):
@@ -368,6 +381,7 @@ def apply(ethernet):
368381
e.remove()
369382
else:
370383
e.update(ethernet)
384+
call_dependents()
371385
return None
372386

373387
if __name__ == '__main__':

src/conf_mode/interfaces_geneve.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from sys import exit
1818

1919
from vyos.config import Config
20+
from vyos.configdep import set_dependents, call_dependents
2021
from vyos.configdict import get_interface_dict
2122
from vyos.configdict import is_node_changed
2223
from vyos.configverify import verify_address
@@ -51,6 +52,15 @@ def get_config(config=None):
5152
if is_node_changed(conf, base + [ifname, cli_option]):
5253
geneve.update({'rebuild_required': {}})
5354

55+
# Protocols static arp dependency
56+
static_arp = conf.get_config_dict(
57+
['protocols', 'static', 'arp', 'interface'],
58+
key_mangling=('-', '_'),
59+
get_first_key=True,
60+
)
61+
if ifname in static_arp.keys():
62+
set_dependents('static_arp', conf)
63+
5464
return geneve
5565

5666
def verify(geneve):
@@ -90,6 +100,8 @@ def apply(geneve):
90100
g = GeneveIf(**geneve)
91101
g.update(geneve)
92102

103+
call_dependents()
104+
93105
return None
94106

95107

src/conf_mode/interfaces_l2tpv3.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from sys import exit
1818

1919
from vyos.config import Config
20+
from vyos.configdep import set_dependents, call_dependents
2021
from vyos.configdict import get_interface_dict
2122
from vyos.configdict import leaf_node_changed
2223
from vyos.configverify import verify_address
@@ -56,6 +57,15 @@ def get_config(config=None):
5657
tmp = leaf_node_changed(conf, base + [ifname, 'session-id'])
5758
l2tpv3.update({'session_id': tmp[0]})
5859

60+
# Protocols static arp dependency
61+
static_arp = conf.get_config_dict(
62+
['protocols', 'static', 'arp', 'interface'],
63+
key_mangling=('-', '_'),
64+
get_first_key=True,
65+
)
66+
if ifname in static_arp.keys():
67+
set_dependents('static_arp', conf)
68+
5969
return l2tpv3
6070

6171
def verify(l2tpv3):
@@ -100,6 +110,8 @@ def apply(l2tpv3):
100110
l = L2TPv3If(**l2tpv3)
101111
l.update(l2tpv3)
102112

113+
call_dependents()
114+
103115
return None
104116

105117
if __name__ == '__main__':

src/conf_mode/interfaces_macsec.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from sys import exit
2020

2121
from vyos.config import Config
22+
from vyos.configdep import set_dependents, call_dependents
2223
from vyos.configdict import get_interface_dict
2324
from vyos.configdict import is_node_changed
2425
from vyos.configdict import is_source_interface
@@ -78,6 +79,15 @@ def get_config(config=None):
7879
tmp = is_source_interface(conf, macsec['source_interface'], ['macsec', 'pseudo-ethernet'])
7980
if tmp and tmp != ifname: macsec.update({'is_source_interface' : tmp})
8081

82+
# Protocols static arp dependency
83+
static_arp = conf.get_config_dict(
84+
['protocols', 'static', 'arp', 'interface'],
85+
key_mangling=('-', '_'),
86+
get_first_key=True,
87+
)
88+
if ifname in static_arp.keys():
89+
set_dependents('static_arp', conf)
90+
8191
return macsec
8292

8393

@@ -193,6 +203,8 @@ def apply(macsec):
193203
if not is_systemd_service_running(systemd_service) or 'shutdown_required' in macsec:
194204
call(f'systemctl reload-or-restart {systemd_service}')
195205

206+
call_dependents()
207+
196208
return None
197209

198210

src/conf_mode/interfaces_pseudo-ethernet.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
from sys import exit
1818

1919
from vyos.config import Config
20+
from vyos.configdep import set_dependents, call_dependents
2021
from vyos.configdict import get_interface_dict
21-
from vyos.configdict import is_node_changed
2222
from vyos.configdict import is_source_interface
2323
from vyos.configdict import is_node_changed
2424
from vyos.configverify import verify_vrf
@@ -61,6 +61,18 @@ def get_config(config=None):
6161
tmp = is_source_interface(conf, peth['source_interface'], ['macsec'])
6262
if tmp and tmp != ifname: peth.update({'is_source_interface' : tmp})
6363

64+
# Protocols static arp dependency
65+
static_arp = conf.get_config_dict(
66+
['protocols', 'static', 'arp', 'interface'],
67+
key_mangling=('-', '_'),
68+
get_first_key=True,
69+
)
70+
if any(
71+
key == ifname or key.startswith(f"{ifname}.")
72+
for key in static_arp.keys()
73+
):
74+
set_dependents('static_arp', conf)
75+
6476
return peth
6577

6678
def verify(peth):
@@ -95,6 +107,8 @@ def apply(peth):
95107
p = MACVLANIf(**peth)
96108
p.update(peth)
97109

110+
call_dependents()
111+
98112
return None
99113

100114
if __name__ == '__main__':

src/conf_mode/interfaces_virtual-ethernet.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from vyos import ConfigError
2020
from vyos import airbag
2121
from vyos.config import Config
22+
from vyos.configdep import set_dependents, call_dependents
2223
from vyos.configdict import get_interface_dict
2324
from vyos.configverify import verify_address
2425
from vyos.configverify import verify_bridge_delete
@@ -47,6 +48,18 @@ def get_config(config=None):
4748
veth['other_interfaces'] = conf.get_config_dict(base, key_mangling=('-', '_'),
4849
get_first_key=True, no_tag_node_value_mangle=True)
4950

51+
# Protocols static arp dependency
52+
static_arp = conf.get_config_dict(
53+
['protocols', 'static', 'arp', 'interface'],
54+
key_mangling=('-', '_'),
55+
get_first_key=True,
56+
)
57+
if any(
58+
key == ifname or key.startswith(f"{ifname}.")
59+
for key in static_arp.keys()
60+
):
61+
set_dependents('static_arp', conf)
62+
5063
return veth
5164

5265

@@ -101,6 +114,8 @@ def apply(veth):
101114
p = VethIf(**veth)
102115
p.update(veth)
103116

117+
call_dependents()
118+
104119
return None
105120

106121

0 commit comments

Comments
 (0)