summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2026-10-19 20:42:41 +0200
committerGitHub <noreply@github.com>2026-10-19 20:42:41 +0200
commitcd6a243f62cd3af7a54f95bb126fdf599975154a (patch)
treea12089c6ac4b5fc22766a060cf5c9bc49e3a9f58 /python
parentc10ad3232e25a06ce24b36e1196eb856fde7d503 (diff)
parenta0ea6ec9012350d6bda47d86f9f6f7b928acd0d0 (diff)
downloadvyos-1x-cd6a243f62cd3af7a54f95bb126fdf599975154a.tar.gz
vyos-1x-cd6a243f62cd3af7a54f95bb126fdf599975154a.zip
Merge pull request #5574 from c-po/nat-fixes
nat: T9475: commit failures and weight issue in load-balancing, translation issues for port-ranges
Diffstat (limited to 'python')
-rw-r--r--python/vyos/nat.py23
1 files changed, 18 insertions, 5 deletions
diff --git a/python/vyos/nat.py b/python/vyos/nat.py
index 0a252bbd8..9eeb62db6 100644
--- a/python/vyos/nat.py
+++ b/python/vyos/nat.py
@@ -92,6 +92,10 @@ def parse_nat_rule(rule_conf, rule_id, nat_type, ipv6=False):
else:
translation_output.append(f'{ip_prefix} prefix to {ip_prefix} {translation_prefix}addr map {{ {map_addr} : {addr} }}')
ignore_type_addr = True
+ elif port:
+ # nft has no "prefix to <net>:<port>" syntax, a catch-all
+ # map key keeps the 1:1 prefix mapping plus the port range
+ translation_output.append(f'{ip_prefix} prefix to {ip_prefix} {translation_prefix}addr map {{ 0.0.0.0/0 : {addr} . {port} }}')
else:
translation_output.append(f'prefix to {addr}')
else:
@@ -120,26 +124,33 @@ def parse_nat_rule(rule_conf, rule_id, nat_type, ipv6=False):
else:
translation_str = " ".join(translation_output)
- if options:
- translation_str += f' {",".join(options)}'
+ options_str = f' {",".join(options)}' if options else ''
if not ipv6 and 'backend' in rule_conf['load_balance']:
hash_input_items = []
current_prob = 0
nat_map = []
+ # the port has to be part of every map value, nft rejects a port
+ # or options between "to" and the hash expression
+ translation_str = f'{nat_type[:1]}nat {ip_prefix} to' if port else f'{nat_type[:1]}nat to'
+ backend_suffix = f' . {port}' if port else ''
+
for trans_addr, addr in rule_conf['load_balance']['backend'].items():
item_prob = int(addr['weight'])
upper_limit = current_prob + item_prob - 1
hash_val = str(current_prob) + '-' + str(upper_limit)
- element = hash_val + " : " + trans_addr
+ element = hash_val + " : " + trans_addr + backend_suffix
nat_map.append(element)
current_prob = current_prob + item_prob
elements = ' , '.join(nat_map)
+ # weights are relative - a modulus other than their sum leaves hash
+ # values without a backend
+ modulus = current_prob
if 'hash' in rule_conf['load_balance'] and 'random' in rule_conf['load_balance']['hash']:
- translation_str += ' numgen random mod 100 map ' + '{ ' + f'{elements}' + ' }'
+ translation_str += f' numgen random mod {modulus} map ' + '{ ' + f'{elements}' + ' }'
else:
for input_param in rule_conf['load_balance']['hash']:
if input_param == 'source-address':
@@ -154,7 +165,9 @@ def parse_nat_rule(rule_conf, rule_id, nat_type, ipv6=False):
param = f'{prot} dport'
hash_input_items.append(param)
hash_input = ' . '.join(hash_input_items)
- translation_str += f' jhash ' + f'{hash_input}' + ' mod 100 map ' + '{ ' + f'{elements}' + ' }'
+ translation_str += f' jhash ' + f'{hash_input}' + f' mod {modulus} map ' + '{ ' + f'{elements}' + ' }'
+
+ translation_str += options_str
for target in ['source', 'destination']:
if target not in rule_conf: