Skip to content

T7315: Change CLI fot VPP NAT #25

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 12 additions & 13 deletions interface-definitions/vpp.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -853,18 +853,18 @@
<priority>320</priority>
</properties>
<children>
<leafNode name="inbound-interface">
<leafNode name="inside-interface">
<properties>
<help>Inbound interface of NAT traffic</help>
<help>NAT inside interface</help>
<completionHelp>
<list>any</list>
<script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
</leafNode>
<leafNode name="outbound-interface">
<leafNode name="outside-interface">
<properties>
<help>Outbound interface of NAT traffic</help>
<help>NAT outside interface</help>
<completionHelp>
<list>any</list>
<script>${vyos_completion_dir}/list_interfaces</script>
Expand Down Expand Up @@ -920,7 +920,7 @@
</valueHelp>
</properties>
<children>
<node name="destination">
<node name="external">
<properties>
<help>NAT external parameters</help>
</properties>
Expand Down Expand Up @@ -968,27 +968,25 @@
</properties>
<defaultValue>all</defaultValue>
</leafNode>
<leafNode name="outbound-interface">
<leafNode name="outside-interface">
<properties>
<help>Outbound interface of NAT traffic</help>
<help>NAT outside interface</help>
<completionHelp>
<list>any</list>
<script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
</leafNode>
<leafNode name="inbound-interface">
<leafNode name="inside-interface">
<properties>
<help>Inbound interface of NAT traffic</help>
<help>NAT inside interface</help>
<completionHelp>
<list>any</list>
<script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
</properties>
</leafNode>
<node name="translation">
<node name="local">
<properties>
<help>NAT internal parameters</help>
<help>NAT local parameters</help>
</properties>
<children>
<leafNode name="address">
Expand All @@ -1006,6 +1004,7 @@
#include <include/port-number.xml.i>
</children>
</node>
#include <include/generic-description.xml.i>
</children>
</tagNode>
</children>
Expand Down
32 changes: 6 additions & 26 deletions python/vyos/vpp/nat/nat44.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,31 +151,24 @@ class Nat44Static(Nat44):
def __init__(self):
self.vpp = VPPControl()

def add_inbound_interface(self, interface_in):
def add_inside_interface(self, interface_in):
self.interface_in = interface_in
self.add_nat44_interface_inside()

def delete_inbound_interface(self, interface_in):
def delete_inside_interface(self, interface_in):
self.interface_in = interface_in
self.delete_nat44_interface_inside()

def add_outbound_interface(self, interface_out):
def add_outside_interface(self, interface_out):
self.interface_out = interface_out
self.add_nat44_interface_outside()

def delete_outbound_interface(self, interface_out):
def delete_outside_interface(self, interface_out):
self.interface_out = interface_out
self.delete_nat44_interface_outside()

def add_nat44_static_mapping(
self,
iface_out,
local_ip,
external_ip,
local_port,
external_port,
protocol,
use_iface,
self, local_ip, external_ip, local_port, external_port, protocol
):
"""Add NAT44 static mapping"""
self.vpp.api.nat44_add_del_static_mapping_v2(
Expand All @@ -185,21 +178,11 @@ def add_nat44_static_mapping(
local_port=local_port,
external_port=external_port,
flags=0x08 if not (protocol or local_port) else 0x00,
external_sw_if_index=(
self.vpp.get_sw_if_index(iface_out) if use_iface else 0xFFFFFFFF
),
is_add=True,
)

def delete_nat44_static_mapping(
self,
iface_out,
local_ip,
external_ip,
local_port,
external_port,
protocol,
use_iface,
self, local_ip, external_ip, local_port, external_port, protocol
):
"""Delete NAT44 static mapping"""
self.vpp.api.nat44_add_del_static_mapping_v2(
Expand All @@ -209,8 +192,5 @@ def delete_nat44_static_mapping(
local_port=local_port,
external_port=external_port,
flags=0x08 if not (protocol or local_port) else 0x00,
external_sw_if_index=(
self.vpp.get_sw_if_index(iface_out) if use_iface else 0xFFFFFFFF
),
is_add=False,
)
10 changes: 5 additions & 5 deletions src/conf_mode/vpp_nat_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def verify(config):
if 'remove' in config:
return None

required_keys = {'inbound_interface', 'outbound_interface'}
required_keys = {'inside_interface', 'outside_interface'}
if not all(key in config for key in required_keys):
missing_keys = required_keys - set(config.keys())
raise ConfigError(
Expand All @@ -83,8 +83,8 @@ def apply(config):
# Delete NAT source
if 'effective' in config:
remove_config = config.get('effective')
interface_in = remove_config.get('inbound_interface')
interface_out = remove_config.get('outbound_interface')
interface_in = remove_config.get('inside_interface')
interface_out = remove_config.get('outside_interface')
translation_address = remove_config.get('translation', {}).get('address')

n = Nat44(interface_in, interface_out, translation_address)
Expand All @@ -96,8 +96,8 @@ def apply(config):
return None

# Add NAT44
interface_in = config.get('inbound_interface')
interface_out = config.get('outbound_interface')
interface_in = config.get('inside_interface')
interface_out = config.get('outside_interface')
translation_address = config.get('translation', {}).get('address')

n = Nat44(interface_in, interface_out, translation_address)
Expand Down
63 changes: 27 additions & 36 deletions src/conf_mode/vpp_nat_static.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,12 @@ def get_config(config=None) -> dict:
expand_nodes=Diff.DELETE | Diff.ADD,
)

if 'inbound_interface' in tmp:
new, old = diff.get_value_diff(base_rule + ['inbound-interface'])
if 'inside_interface' in tmp:
new, old = diff.get_value_diff(base_rule + ['inside-interface'])
in_iface_add.append(new) if new else None
in_iface_del.append(old) if old else None
if 'outbound_interface' in tmp:
new, old = diff.get_value_diff(base_rule + ['outbound-interface'])
if 'outside_interface' in tmp:
new, old = diff.get_value_diff(base_rule + ['outside-interface'])
out_iface_add.append(new) if new else None
out_iface_del.append(old) if old else None

Expand Down Expand Up @@ -120,21 +120,24 @@ def verify(config):
if 'remove' in config:
return None

required_keys = {'inbound_interface', 'outbound_interface'}
required_keys = {'inside_interface', 'outside_interface'}
for rule, rule_config in config['rule'].items():
missing_keys = required_keys - rule_config.keys()
if missing_keys:
raise ConfigError(
f"Required options are missing: {', '.join(missing_keys).replace('_', '-')} in rule {rule}"
)

if not rule_config.get('translation', {}).get('address'):
raise ConfigError(f'Translation requires address in rule {rule}')
if not rule_config.get('local', {}).get('address'):
raise ConfigError(f'Local settings require address in rule {rule}')

has_dest_port = 'port' in rule_config.get('destination', {})
has_trans_port = 'port' in rule_config.get('translation', {})
if not rule_config.get('external', {}).get('address'):
raise ConfigError(f'External settings require address in rule {rule}')

if not has_trans_port == has_dest_port:
has_local_port = 'port' in rule_config.get('local', {})
has_external_port = 'port' in rule_config.get('external', {})

if not has_external_port == has_local_port:
raise ConfigError(
'Source and destination ports must either both be specified, or neither must be specified'
)
Expand All @@ -147,28 +150,22 @@ def generate(config):
def apply(config):
n = Nat44Static()

# Delete inbound interfaces
# Delete inside interfaces
for interface in config['in_iface_del']:
n.delete_inbound_interface(interface)
# Delete outbound interfaces
n.delete_inside_interface(interface)
# Delete outside interfaces
for interface in config['out_iface_del']:
n.delete_outbound_interface(interface)
n.delete_outside_interface(interface)
# Delete NAT static mapping rules
for rule in config['changed_rules']:
if rule in config.get('effective', {}).get('rule', {}):
rule_config = config['effective']['rule'][rule]
n.delete_nat44_static_mapping(
iface_out=rule_config.get('outbound_interface'),
local_ip=rule_config.get('translation').get('address'),
external_ip=rule_config.get('destination', {}).get('address', ''),
local_port=int(rule_config.get('translation', {}).get('port', 0)),
external_port=int(rule_config.get('destination', {}).get('port', 0)),
local_ip=rule_config.get('local').get('address'),
external_ip=rule_config.get('external', {}).get('address', ''),
local_port=int(rule_config.get('local', {}).get('port', 0)),
external_port=int(rule_config.get('external', {}).get('port', 0)),
protocol=protocol_map[rule_config.get('protocol', 'all')],
use_iface=(
True
if not rule_config.get('destination', {}).get('address')
else False
),
)

if 'remove' in config:
Expand All @@ -177,24 +174,18 @@ def apply(config):
# Add NAT44 static mapping rules
n.enable_nat44_ed()
for interface in config['in_iface_add']:
n.add_inbound_interface(interface)
n.add_inside_interface(interface)
for interface in config['out_iface_add']:
n.add_outbound_interface(interface)
n.add_outside_interface(interface)
for rule in config['changed_rules']:
if rule in config.get('rule', {}):
rule_config = config['rule'][rule]
n.add_nat44_static_mapping(
iface_out=rule_config.get('outbound_interface'),
local_ip=rule_config.get('translation').get('address'),
external_ip=rule_config.get('destination', {}).get('address', ''),
local_port=int(rule_config.get('translation', {}).get('port', 0)),
external_port=int(rule_config.get('destination', {}).get('port', 0)),
local_ip=rule_config.get('local').get('address'),
external_ip=rule_config.get('external', {}).get('address', ''),
local_port=int(rule_config.get('local', {}).get('port', 0)),
external_port=int(rule_config.get('external', {}).get('port', 0)),
protocol=protocol_map[rule_config.get('protocol', 'all')],
use_iface=(
True
if not rule_config.get('destination', {}).get('address')
else False
),
)


Expand Down
27 changes: 11 additions & 16 deletions src/op_mode/show_vpp_nat44.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,27 +116,22 @@ def _get_raw_output_static_rules(vpp_api):
return rules_list


def _get_formatted_output_rules(vpp, rules_list):
def _get_formatted_output_rules(rules_list):
data_entries = []
for rule in rules_list:
dest_address = rule.get('external_ip_address')
dest_port = rule.get('external_port') or ''
trans_address = rule.get('local_ip_address')
trans_port = rule.get('local_port') or ''
external_address = rule.get('external_ip_address')
external_port = rule.get('external_port') or ''
local_address = rule.get('local_ip_address')
local_port = rule.get('local_port') or ''
protocol = protocol_map[rule.get('protocol', 0)]
dest_sh_if_index = rule.get('external_sw_if_index')

vpp_if_name = vpp.get_interface_name(dest_sh_if_index)
if vpp_if_name:
dest_address = vpp_if_name

values = [dest_address, dest_port, trans_address, trans_port, protocol]
values = [external_address, external_port, local_address, local_port, protocol]
data_entries.append(values)
headers = [
'Des_address/interface',
'Dest_port',
'Trans_address',
'Trans_port',
'External address',
'External port',
'Local address',
'Local port',
'Protocol',
]
out = sorted(data_entries, key=lambda x: x[2])
Expand Down Expand Up @@ -170,7 +165,7 @@ def show_static(raw: bool):
return rules_list

else:
return _get_formatted_output_rules(vpp, rules_list)
return _get_formatted_output_rules(rules_list)


if __name__ == '__main__':
Expand Down