Skip to content

Commit 83be29d

Browse files
committed
T7950: VPP: Unexpected None interface in CGNAT when ethernet subinterface is removed from vif
Do not allow to delete subinterface if it is in use in VPP features
1 parent c284938 commit 83be29d

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

src/conf_mode/interfaces_ethernet.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1616

1717
import os
18+
import re
1819

1920
from sys import exit
2021

@@ -171,6 +172,13 @@ def get_config(config=None):
171172

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

175+
ethernet['vpp'] = conf.get_config_dict(
176+
['vpp'],
177+
key_mangling=('-', '_'),
178+
get_first_key=True,
179+
no_tag_node_value_mangle=True,
180+
)
181+
174182
return ethernet
175183

176184
def verify_speed_duplex(ethernet: dict, ethtool: Ethtool):
@@ -301,8 +309,51 @@ def verify_flowtable(ethernet: dict):
301309
if vifcname in ethernet['flowtable_interfaces']:
302310
raise ConfigError(f'Cannot delete interface "{vifcname}", still referenced on a flowtable')
303311

312+
def verify_vpp_remove_vif(ethernet: dict):
313+
"""Ensure that VIF interfaces being removed are not used by VPP features"""
314+
possible_vpp_paths = [
315+
# Known paths that already use VLAN interfaces
316+
r'nat.cgnat.interface.inside',
317+
r'nat.cgnat.interface.outside',
318+
r'nat44.interface.inside',
319+
r'nat44.interface.outside',
320+
# Potential paths for VLAN interfaces
321+
r'nat44.address_pool.translation.interface',
322+
r'nat44.address_pool.twice_nat.interface',
323+
r'nat44.exclude.rule.(\d)+.external_interface',
324+
r'interfaces.bonding.bond(\d)+.member.interface',
325+
r'interfaces.bridge.br(\d)+.member.interface',
326+
r'interfaces.xconnect.xcon(\d)+.member.interface',
327+
r'acl.ip.interface',
328+
r'acl.macip.interface',
329+
]
330+
ifname = ethernet['ifname']
331+
vpp_flat = dict_to_paths_values(ethernet.get('vpp', {}))
332+
333+
for vif_group in ['vif_remove', 'vif_s_remove']:
334+
for vif_id in ethernet.get(vif_group, []):
335+
vif_name = f'{ifname}.{vif_id}'
336+
337+
# Find all VPP paths that reference this VIF
338+
matching_paths = [
339+
key
340+
for pattern in possible_vpp_paths
341+
for key, value in vpp_flat.items()
342+
if re.fullmatch(pattern, key)
343+
and (
344+
value == vif_name or (isinstance(value, list) and vif_name in value)
345+
)
346+
]
347+
348+
if matching_paths:
349+
raise ConfigError(
350+
f'Cannot delete interface "{vif_name}", it is still in use by '
351+
f'"vpp {matching_paths[0].replace(".", " ")}"'
352+
)
353+
304354
def verify(ethernet):
305355
verify_flowtable(ethernet)
356+
verify_vpp_remove_vif(ethernet)
306357

307358
if 'deleted' in ethernet:
308359
return None

0 commit comments

Comments
 (0)