VPP/NAT

From fd.io
< VPP
Revision as of 04:19, 10 October 2017 by Matfabia (Talk | contribs)

Jump to: navigation, search

Contents

VPP NAT implementation

Introduction

The VPP NAT is an implementation of NAT44 and NAT64. It is a plugin and is meant to replace the VCGN component. The target use case is a general IPv4 CPE NAT, a CGN and to act as a NAT44 in a Openstack deployment.

It is intended to be pluggable, in the sense that it should be possible to plug the NAT44 function together with the MAP-E IPv4 to IPv6 translator to create a MAP-E CE, likewise one can plug the NAT44 together with MAP-T to create a MAP-T CE or 464XLAT.

NAT44 features are tracked as they are developed in the following VPP-441 and NAT64 VPP-707.

Requirements

  • Scale to millions of bindings
  • Performance goal of 10Mpps/core.
  • Configurable address and port selection algorithm.
  • User quotas for sessions.
  • Thread safe
  • Efficient port utilisation. Endpoint independent for applications requiring it, address and port filtering otherwise
  • No ALGs
  • Configurable IP address pooling behavour
  • Plugable with MAP-E/T to create MAP-E/T CE, 464XLAT
  • Stateful NAT64
  • Support for NAT on a stick (single inside / outside interface)

Work list

Task Owner Planned Release Status Description
1:1 NAT Matus 0 Committed VPP-339
1:1 NAT with ports Matus 0 Committed VPP-339
1:1 NAT with disabled dynamic translation Matus 0 Committed VPP-339 add "static mapping only [connection tracking]" to snat startup config.
VRF awareness Matus 0 Committed VPP-339 One tenant == One VRF. One VRF == multiple interfaces / multiple subnets, add vrf to static mapping API/CLI.
1:1 NAT delete and dump API Matus 0 Committed VPP-339
SNAT: Delete and dump addresses Matus 0 Committed VPP-453
Multiple inside interface - Multiple subnets Matus 0 DONE VPP-447 Multiple inside interfaces for the same "tenant" with non-overlapping address space.
Inside overlapping interfaces Matus 0 Committed VPP-446 Tenants on separate interfaces, separate VRFs with overlapping address space.
Thread safe Matus 0 Committed VPP-443 All traffic corresponding to a specific session to be handled by a CPU core.
SNAT: Dump API for in and out interfaces Matus 0 Committed VPP-459
SNAT: Address range overlapping Matus 0 Committed VPP-478
API (Java and Python) 0 Done HONEYCOMB-135 SNAT - Honeycomb
SNAT: make test Matus DONE
Hairpinning Matus 1 DONE VPP-444 Hosts communicating behind the same NAT using the external representation of their address. hairpinning
Logging Matus 17.04 DONE VPP-445 Netflow - IPFix
CGN: Deterministic NAT Matus 17.04 DONE VPP-623
Port allocation per protocol Matus 17.04 DONE CGN VPP-622
SNAT: static mappings for dhcp addressed interfaces Matus 17.04 DONE home gateway VPP-590
SNAT: Add outside addresses to FIB Matus 17.04 DONE FDS VPP-613
SNAT: Add setting of tenant VRF id for NAT pool addresses Juraj 17.04 DONE Openstack VPP-641
SNAT: Performance Matus WIP 10Mpps/core. Linear scaling with number of cores. VPP-832
Scale 10 million sessions.
Input ACL support before NAT
Multiple outside interfaces
ICMP error packet translation Juraj 17.04 DONE VPP-629
MAP-E CE
DS-lite
NAT64 Matus 17.07 DONE VPP-699, some stuff done details here
IP fragmentation Matus 17.10 IN REVIEW VPP-890
PCP No plan.
SNAT: Fallback to 3-tuple key for non TCP/UDP sessions Matus 17.10 DONE VPP-884
Syslog: Log sessions Matus 17.10
One armed SNAT Matus 17.10
TCP MSS clamping  ?
Fragmentation of Outgoing Packets  ? RFC4787 section 10
in2out translation as an output feature on the outside interface Matus 17.10 DONE fix for VPP-903, hairpinning
Destination NAT44 with load-balancing Matus 17.10 DONE VPP-954
Rename snat plugin Matus 17.10 DONE VPP-955
Twice NAT44 Matus VPP-969

NAT44

old API (will be deprecated after 17.10)

add NAT44 external address range:

define snat_add_address_range {
 u32 client_index;
 u32 context;
 u32 vrf_id;
 u8 is_ip4;
 u8 first_ip_address[16];
 u8 last_ip_address[16];
 u8 is_add;
};

dump NAT44 external addresses:

define snat_address_dump {
 u32 client_index;
 u32 context;
};
define snat_address_details {
 u32 context;
 u8 is_ip4;
 u8 ip_address[16];
};

enable/disable NAT44 feature on the interface:

define snat_interface_add_del_feature {
 u32 client_index;
 u32 context;
 u8 is_add;
 u8 is_inside;
 u32 sw_if_index;
};

dump interfaces with NAT44 feature:

define snat_interface_dump {
 u32 client_index;
 u32 context;
};
define snat_interface_details {
 u32 context;
 u8 is_inside;
 u32 sw_if_index;
};

add/del 1:1 NAT:

define snat_add_static_mapping {
 u32 client_index;
 u32 context;
 u8 is_add;
 u8 is_ip4;
 u8 addr_only;
 u8 local_ip_address[16];
 u8 external_ip_address[16];
 u8 protocol;
 u16 local_port;
 u16 external_port;
 u32 external_sw_if_index;
 u32 vrf_id;
};

dump 1:1 NAT:

define snat_static_mapping_dump {
 u32 client_index;
 u32 context;
};
define snat_static_mapping_details {
 u32 context;
 u8 is_ip4;
 u8 addr_only;
 u8 local_ip_address[16];
 u8 external_ip_address[16];
 u8 protocol;
 u16 local_port;
 u16 external_port;
 u32 vrf_id;
};

show NAT plugin config:

define snat_show_config {
 u32 client_index;
 u32 context;
};
define snat_show_config_reply {
 u32 context;
 i32 retval;
 u8 static_mapping_only;
 u8 static_mapping_connection_tracking;
 u32 translation_buckets;
 u32 translation_memory_size;
 u32 user_buckets;
 u32 user_memory_size;
 u32 max_translations_per_user;
 u32 outside_vrf_id;
 u32 inside_vrf_id;
};

set NAT plugin workers:

define snat_set_workers {
 u32 client_index;
 u32 context;
 u64 worker_mask;
};

dump NAT plugin workers:

define snat_worker_dump {
 u32 client_index;
 u32 context;
};
define snat_worker_details {
 u32 context;
 u32 worker_index;
 u32 lcore_id;
 u8 name[64];
};

add/del NAT44 pool address from specific interfce:

define snat_add_del_interface_addr {
 u32 client_index;
 u32 context;
 u8 is_add;
 u8 is_inside;
 u32 sw_if_index;
};

dump NAT44 pool addresses interfaces:

define snat_interface_addr_dump {
 u32 client_index;
 u32 context;
};
define snat_interface_addr_details {
 u32 context;
 u32 sw_if_index;
};

enable/disable NAT IPFIX logging:

define snat_ipfix_enable_disable {
 u32 client_index;
 u32 context;
 u32 domain_id;
 u16 src_port;
 u8 enable;
};

dump NAT44 users:

define snat_user_dump {
 u32 client_index;
 u32 context;
};
define snat_user_details {
 u32 context;
 u32 vrf_id;
 u8 is_ip4;
 u8 ip_address[16];
 u32 nsessions;
 u32 nstaticsessions;
};

dump NAT44 user's sessions:

define snat_user_session_dump {
 u32 client_index;
 u32 context;
 u8 ip_address[16];
 u32 vrf_id;
};
define snat_user_session_details {
 u32 context;
 u8 is_ip4;
 u8 outside_ip_address[16];
 u16 outside_port;
 u8 inside_ip_address[16];
 u16 inside_port;
 u16 protocol;
 u8 is_static;
 u64 last_heard;
 u64 total_bytes;
 u32 total_pkts;
};

enable/disbale NAT44 as an interface output feature (postrouting in2out translation):

define snat_interface_add_del_output_feature {
 u32 client_index;
 u32 context;
 u8 is_add;
 u8 is_inside;
 u32 sw_if_index;
};

dump interfaces with NAT44 output feature:

define snat_interface_output_feature_dump {
 u32 client_index;
 u32 context;
};
define snat_interface_output_feature_details {
 u32 context;
 u8 is_inside;
 u32 sw_if_index;
};

API (new after renaming)

show NAT plugin startup config:

define nat_show_config {
 u32 client_index;
 u32 context;
};
define nat_show_config_reply {
 u32 context;
 i32 retval;
 u8 static_mapping_only;
 u8 static_mapping_connection_tracking;
 u8 deterministic;
 u32 translation_buckets;
 u32 translation_memory_size;
 u32 user_buckets;
 u32 user_memory_size;
 u32 max_translations_per_user;
 u32 outside_vrf_id;
 u32 inside_vrf_id;
};

set NAT plugin workers:

define nat_set_workers {
 u32 client_index;
 u32 context;
 u64 worker_mask;
};

dump NAT plugin workers:

define nat_worker_dump {
 u32 client_index;
 u32 context;
};
define nat_worker_details {
 u32 context;
 u32 worker_index;
 u32 lcore_id;
 u8 name[64];
};

enable/disable NAT IPFIX logging:

define nat_ipfix_enable_disable {
 u32 client_index;
 u32 context;
 u32 domain_id;
 u16 src_port;
 u8 enable;
};

add/delete NAT44 external address range:

define nat44_add_del_address_range {
 u32 client_index;
 u32 context;
 u8 first_ip_address[4];
 u8 last_ip_address[4];
 u32 vrf_id;
 u8 is_add;
};

dump NAT44 external addresses:

define nat44_address_dump {
 u32 client_index;
 u32 context;
};
define nat44_address_details {
 u32 context;
 u8 ip_address[4];
 u32 vrf_id;
};

enable/disable NAT44 feature on the interface:

define nat44_interface_add_del_feature {
 u32 client_index;
 u32 context;
 u8 is_add;
 u8 is_inside;
 u32 sw_if_index;
};

dump interfaces with NAT44 feature:

define nat44_interface_dump {
 u32 client_index;
 u32 context;
};
define nat44_interface_details {
 u32 context;
 u8 is_inside;
 u32 sw_if_index;
};

add/delete 1:1 NAT:

define nat44_add_del_static_mapping {
 u32 client_index;
 u32 context;
 u8 is_add;
 u8 addr_only;
 u8 local_ip_address[4];
 u8 external_ip_address[4];
 u8 protocol;
 u16 local_port;
 u16 external_port;
 u32 external_sw_if_index;
 u32 vrf_id;
};

dump 1:1 NAT:

define nat44_static_mapping_dump {
 u32 client_index;
 u32 context;
};
define nat44_static_mapping_details {
 u32 context;
 u8 addr_only;
 u8 local_ip_address[4];
 u8 external_ip_address[4];
 u8 protocol;
 u16 local_port;
 u16 external_port;
 u32 external_sw_if_index;
 u32 vrf_id;
};

add/delete NAT44 pool address from specific interface:

define nat44_add_del_interface_addr {
 u32 client_index;
 u32 context;
 u8 is_add;
 u8 is_inside;
 u32 sw_if_index;
};

dump NAT44 pool addresses interfaces:

define nat44_interface_addr_dump {
 u32 client_index;
 u32 context;
};
define nat44_interface_addr_details {
 u32 context;
 u32 sw_if_index;
};

dump NAT44 users:

nat44_user_dump {
 u32 client_index;
 u32 context;
};
define nat44_user_details {
 u32 context;
 u32 vrf_id;
 u8 ip_address[4];
 u32 nsessions;
 u32 nstaticsessions;
};

dump NAT44 user's sessions:

define nat44_user_session_dump {
 u32 client_index;
 u32 context;
 u8 ip_address[4];
 u32 vrf_id;
};
define nat44_user_session_details {
 u32 context;
 u8 outside_ip_address[4];
 u16 outside_port;
 u8 inside_ip_address[4];
 u16 inside_port;
 u16 protocol;
 u8 is_static;
 u64 last_heard;
 u64 total_bytes;
 u32 total_pkts;
};

enable/disbale NAT44 as an interface output feature (postrouting in2out translation):

define nat44_interface_add_del_output_feature {
 u32 client_index;
 u32 context;
 u8 is_add;
 u8 is_inside;
 u32 sw_if_index;
};

dump interfaces with NAT44 output feature:

define nat44_interface_output_feature_dump {
 u32 client_index;
 u32 context;
};
define nat44_interface_output_feature_details {
 u32 context;
 u8 is_inside;
 u32 sw_if_index;
};

Add/delete NAT44 static mapping with load balancing:

typeonly define nat44_lb_addr_port {
 u8 addr[4];
 u16 port;
 u8 probability;
};
define nat44_add_del_lb_static_mapping {
 u32 client_index;
 u32 context;
 u8 is_add;
 u8 external_addr[4];
 u16 external_port;
 u8 protocol;
 u32 vrf_id;
 u8 local_num;
 vl_api_nat44_lb_addr_port_t locals[local_num];
};

Dump NAT44 static mapping with load balancing:

define nat44_lb_static_mapping_dump {
 u32 client_index;
 u32 context;
}; 
define nat44_lb_static_mapping_details {
 u32 context;
 u8 external_addr[4];
 u16 external_port;
 u8 protocol;
 u32 vrf_id;
 u8 local_num;
 vl_api_nat44_lb_addr_port_t locals[local_num];
};

CLI

set interface nat44 in <intfc> out <intfc> [output-feature] [del]
nat44 add address <ip4-range-start> [- <ip4-range-end>] [tenant-vrf <vrf-id>] [del]
nat44 add static mapping tcp|udp|icmp local <ip4-addr> [<port>] external (<ip4-addr>|<intfc>) [<port>] [vrf <table-id>] [del]
nat44 add load-balancing static mapping protocol tcp|udp external <addr>:<port> local <addr>:<port> probability <n> [vrf <table-id>] [del]
set nat workers <workers-list>
nat ipfix logging [domain <domain-id>] [src-port <port>] [disable]
nat44 add interface address <interface> [del]
show nat44 [detail|verbose]

Enable NAT44 feature example

To enable NAT44 feature with local network interface GigabitEthernet0/8/0 use:

vpp# set interface nat44 in GigabitEthernet0/8/0

To enable NAT44 feature with external network interface GigabitEthernet0/a/0 use:

vpp# set interface nat44 out GigabitEthernet0/a/0

Enable NAT44 as an interface output feature (postrouting in2out translation) example

To enable NAT44 as an interface output feature with local network interface GigabitEthernet0/8/0 and external network interface GigabitEthernet0/a/0 use:

vpp# set interface nat44 in GigabitEthernet0/8/0 out GigabitEthernet0/a/0 output-feature

NAT44 add pool address example

To add NAT44 pool address use:

vpp# nat44 add address 172.16.1.3
vpp# nat44 add address 172.16.2.2 - 172.16.2.24

NAT44 add pool address for specific tenant

To add NAT44 pool address for specific tenant (identified by VRF id) use:

vpp# nat44 add address 172.16.1.3 tenant-vrf 10
vpp# nat44 add address 172.16.2.2 - 172.16.2.24 tenant-vrf 20

1:1 NAT example

To create static mapping between local address 10.0.0.3 and external address 4.4.4.4 use:

vpp# nat44 add static mapping local 10.0.0.3 external 4.4.4.4

1:1 NAT with ports example

If not running "static mapping only" NAT plugin mode first use:

vpp# nat44 add address 4.4.4.4

To create static mapping between local host address 10.0.0.3 port 6303 and external address 4.4.4.4 port 3606 for TCP protocol use:

vpp# nat44 add static mapping tcp local 10.0.0.3 6303 external 4.4.4.4 3606

Set NAT plugin workers example

To set NAT plugin workers (2 or more workers available, by default NAT plugin use all available worker threads) use:

vpp# set nat workers 0-1

Enable NAT plugin IPFIX logging example

To set IPFIX exporter use:

vpp# set ipfix exporter collector 10.10.10.3 src 10.10.10.1

To enable NAT plugin IPFIX logging use:

vpp# nat ipfix logging

Add NAT44 pool address from specific (DHCP addressed) interface example

To add NAT44 pool address from specific interface use:

vpp# nat44 add interface address GigabitEthernet0/8/0

1:1 NAT for DHCP addressed interface example

To add static mapping for DHCP addressed interface use:

vpp# nat44 add static mapping tcp local 10.0.0.3 6303 external GigabitEthernet0/a/0 3606

Service load balancing using NAT44

Users that access the local service from external network will access the service using a single IP address and TCP/UDP port number, however NAT plugin is used to load share traffic to multiple servers based on the probability distribution you give it.

First add external address to NAT44 pool:

vpp# nat44 add address 1.2.3.4

To add static mapping with load balancing for service with external IP address 1.2.3.4 and TCP port 80 and mapped to 2 local servers 10.100.10.10:8080 and 10.100.10.20:8080 with probability 80% resp. 20% use:

vpp# nat44 add load-balancing static mapping protocol tcp external 1.2.3.4:80 local 10.100.10.10:8080 probability 80 local 10.100.10.20:8080 probability 20

Startup config

translation hash buckets <n> - default 1024
translation hash memory <n> - default 128<<20
user hash buckets <n> - default 128
user hash memory <n> - default 64<<20
max translations per user <n> - default 100
outside VRF id <table-id> - default 0
inside VRF id <table-id> - default 0
static mapping only [connection tracking] - default dynamic traslations enabled
deterministic - deterministic NAT/CGN

NAT44 packet path

in2out (receive non-translated packet)

VPP graph node path for NAT44 in2out

Node nat44-in2out-worker-hadoff

Determine corresponding worker index

  • Key – source address, Rx fib index
  • Hash table (bihash_8_8) worker_by_in
  • Round-robin worker assignment

Distribute packet to the worker

  • If worker index is same as current worker index get to nat44-in2out node
  • Else do handoff
Node nat44-in2out

Determine corresponding session

  • Key – source address, source port, L4 protocol, Rx fib index
  • Hash table (bihash_8_8) in2out
  • If session not exists next node = nat44-in2out-slowpath

Perform source address and port translation

  • Next node = ip4-lookup
  • Hairpinning (destination address is NAT pool address)
  • Update session counters
  • Update LRU per user session list
Node nat44-in2out-slow-path

Create new session Determine corresponding user

  • Key – source address, L4 protocol, Rx fib index
  • Hash table (bihash_8_8) user_hash
  • If not exist create new

Check number of sessions for corresponding user

  • If over quota recycle the last recently used (per user session list)

Create session

  • Use static mapping (1:1 NAT) or select address and port from NAT pool
  • Per thread pool of sessions
  • Create per user translation list element (dlist)
  • Create session lookup hash entry (in2out, out2in)

Perform source address and port translation

  • Next node = ip4-lookup
  • Hairpinning (destination address is NAT pool address)
  • Update session counters
  • Update LRU per user session list

out2in (receive translated packe)

VPP graph node path for NAT44 out2in

Node nat44-out2in-worker-hadoff

Determine corresponding worker index

  • Key – destination address, destination port, Rx fib index
  • Hash table (bihash_8_8) worker_by_out
  • Round-robin worker assignment

Distribute packet to the worker

  • If worker index is same as current worker index get to nat44-out2in node
  • Else do handoff
Node nat44-out2in

Determine corresponding session

  • Key – source address, source port, L4 protocol, Rx fib index
  • Hash table (bihash_8_8) out2in
  • If session not exists try to match static mapping (1:1 NAT) otherwise next node = error-drop

Perform source address and port translation

  • Next node = ip4-lookup
  • Update session counters
  • Update LRU per user session list

Data structures

snat_main_t
/* Session lookup hash tables */
clib_bihash_8_8_t out2in;
clib_bihash_8_8_t in2out;
/* User lookup hash table */
clib_bihash_8_8_t user_hash;
/* Worker index lookup hash tables */
clib_bihash_8_8_t worker_by_in;
clib_bihash_8_8_t worker_by_out;
/* Static mappings (1:1 NAT) lookup hash tables */
clib_bihash_8_8_t static_mapping_by_local;
clib_bihash_8_8_t static_mapping_by_external;
/* Per thread data */
snat_main_per_thread_data_t * per_thread_data;
snat_main_per_thread_data_t
/* User pool */
snat_user_t * users;
/* Session pool */
snat_session_t * sessions;
/* Pool of double-linked list elements (per user session list) */
dlist_elt_t * list_pool;
snat_user_t
ip4_address_t addr;
u32 fib_index;
u32 sessions_per_user_list_head_index;
u32 nsessions;
u32 nstaticsessions;
snat_session_t
snat_session_key_t out2in;
snat_session_key_t in2out;
u32 flags;
u32 per_user_index;
u32 per_user_list_head_index;
f64 last_heard;
u64 total_bytes;
u32 total_pkts;
u32 outside_address_index;
ip4_address_t ext_host_addr;
snat_session_key_t
ip4_address_t addr;
u16 port;
u16 protocol:3, fib_index:13;
snat_user_key_t
ip4_address_t addr;
u32 fib_index;

NAT IPFIX logging

Supported NAT events:

Event Name Value
NAT Addresses exhausted 3
NAT44 Session create 4
NAT44 Session delete 5

Address Exhausted event template:

Field Name Size (bits)
observationTimeMilliseconds 64
natEvent 8
natPoolId 32

NAT44 Session delete/create template:

Field Name Size (bits)
observationTimeMilliseconds 64
natEvent 8
sourceIPv4Address 32
postNATSourceIPv4Address 32
protocolIdentifier 8
sourceTransportPort 16
postNAPTSourceTransportPort 16
ingressVRFID 32

CGN - deterministic NAT

Inside user is statically mapped to a set of outside ports with the purpose of enabling deterministic NAT to reduce logging and to achieve high scale/high performance in CGN deployments. Support endpoint dependent mapping to deal with overloading of the outside ports. Prealocate 1000 session slots for each inside user. Use sequential port range assignment algorithm (the first block goes to address 1, the second block to address 2, etc.)

Supported protocols:

  • TCP
  • UDP
  • ICMP

NAT Session Refresh:

  • NAT Outbound refresh behavior
  • default UDP idle-timeout 5 minutes
  • default TCP established connection idle-timeout 2 hours 4 minutes
  • default TCP transitory connection idle-timeout 4 minutes
  • default ICMP idle-timeout 60 seconds
  • TCP session close detection
  • configurable idle-timeouts

TODO:

  • additional port range assignment algorithms

Supported IPFIX NAT events:

  • Quota exceeded - Maximum entries per user exceeded (NAT Event Type = 13, NAT Quota Exceeded Event Type = 3

IPFIX templates

Maximum entries per user exceeded:

Field Name Size (bits)
observationTimeMilliseconds 64
natEvent 8
natQuotaExceededEvent 32
sourceIPv4Address 32

Startup config

To enable NAT plugin deterministic mode add following to statrup config:

nat { deterministic }

To verify NAT plugin mode use:

vpp# show nat44
NAT plugin mode: deterministic mapping

CLI

Supported CLI commands:

set interface nat44 in <intfc> out <intfc> [del]
nat44 deterministic add in <addr>/<plen> out <addr>/<plen> [del]
nat44 deterministic forward <addr>
nat44 deterministic reverse <addr>:<port>
set nat44 deterministic timeout [udp <sec> | tcp-established <sec> | tcp-transitory <sec> | icmp <sec> | reset]
nat44 deterministic close session out|in <addr>:<port> <ext_endp_addr>:<ext_endp_port>

Example configuration

To enable NAT feature (local network interface GigabitEthernet0/8/0 and external network interface GigabitEthernet0/a/0) use:

vpp# set int nat44 in GigabitEthernet0/8/0 out GigabitEthernet0/a/0

To create deterministic mapping between inside network 10.0.0.0/18 and outside address range 1.1.1.0/30 use:

vpp# nat44 deterministic add in 10.0.0.0/18 out 1.1.1.1/30

To show deterministic mapping information use:

vpp# show nat44 detail
NAT plugin mode: deterministic mapping
GigabitEthernet0/8/0 in
GigabitEthernet0/a/0 out
1 deterministic mappings
in 10.0.0.0/18 out 1.1.1.0/30
 outside address sharing ratio: 4096
 number of ports per inside host: 15
 sessions number: 0

To obtain outside address and port range of the inside host 10.0.0.2 use:

vpp# nat44 deterministic forward 10.0.0.2
1.1.1.0:<1054-1068>

To obtain inside host address from outside address 1.1.1.1 and port 1276 use:

vpp# nat44 deterministic reverse 1.1.1.1:1276
10.0.16.16

To set values of timeouts use:

vpp# set nat44 deterministic timeout udp 120 tcp-established 7500 tcp-transitory 250 icmp 90

To reset default values of timeouts use:

vpp# set nat44 deterministic timeout reset

To close session using outside address and port and external endpoint address and port use:

vpp# nat44 deterministic close session out 1.1.1.1:1276 2.2.2.2:2387

To close session using inside address and port and external endpoint address and port use:

vpp# nat44 deterministic close session in 3.3.3.3:3487 2.2.2.2:2387

old API (will be deprecated after 17.10)

Add/delete deterministic NAT mapping:

define snat_add_det_map {
 u32 client_index;
 u32 context;
 u8 is_add;
 u8 is_ip4;
 u8 addr_only;
 u8 in_addr[16];
 u8 in_plen;
 u8 out_addr[16];
 u8 out_plen;
};

Get outside address and port range from inside address:

define snat_det_forward {
 u32 client_index;
 u32 context;
 u8 is_ip4;
 u8 in_addr[16];
};
define snat_det_forward_reply {
 u32 context;
 i32 retval;
 u16 out_port_lo;
 u16 out_port_hi;
 u8 is_ip4;
 u8 out_addr[16];
};

Get inside address from outside address and port:

define snat_det_reverse {
 u32 client_index;
 u32 context;
 u16 out_port;
 u8 is_ip4;
 u8 out_addr[16];
};
define snat_det_reverse_reply {
 u32 context;
 i32 retval;
 u8 is_ip4;
 u8 in_addr[16];
};

Dump deterministic NAT mappings:

define snat_det_map_dump {
 u32 client_index;
 u32 context;
};
define snat_det_map_details {
 u32 context;
 u8 is_ip4;
 u8 in_addr[16];
 u8 in_plen;
 u8 out_addr[16];
 u8 out_plen;
 u32 sharing_ratio;
 u16 ports_per_host;
 u32 ses_num;
};

Set values of timeouts for deterministic NAT (in seconds, 0 = default value):

define snat_det_set_timeouts {
 u32 client_index;
 u32 context;
 u32 udp;
 u32 tcp_established;
 u32 tcp_transitory;
 u32 icmp;
};

Get values of timeouts for deterministic NAT (in seconds):

define snat_det_get_timeouts {
 u32 client_index;
 u32 context;
};
define snat_det_get_timeouts_reply {
 u32 context;
 i32 retval;
 u32 udp;
 u32 tcp_established;
 u32 tcp_transitory;
 u32 icmp;
};

Close deterministic NAT using outside address and port:

define snat_det_close_session_out {
 u32 client_index;
 u32 context;
 u8 is_ip4;
 u8 out_addr[16];
 u16 out_port;
 u8 ext_addr[16];
 u16 ext_port;
};

Close deterministic NAT using inside address and port:

define snat_det_close_session_in {
 u32 client_index;
 u32 context;
 u8 is_ip4;
 u8 in_addr[16];
 u16 in_port;
 u8 ext_addr[16];
 u16 ext_port;
};

Dump deterministic NAT sessions:

define snat_det_session_dump {
 u32 client_index;
 u32 context;
 u8 is_ip4;
 u8 user_addr[16];
};
define snat_det_session_details {
 u32 client_index;
 u32 context;
 u8 is_ip4;
 u16 in_port;
 u8 ext_addr[16];
 u16 ext_port;
 u16 out_port;
 u8 state;
 u32 expire;
};

API (new after renaming)

Add/delete deterministic NAT mapping:

define nat_det_add_del_map {
 u32 client_index;
 u32 context;
 u8 is_add;
 u8 is_nat44;
 u8 addr_only;
 u8 in_addr[16];
 u8 in_plen;
 u8 out_addr[4];
 u8 out_plen;
};

Get outside address and port range from inside address:

define nat_det_forward {
 u32 client_index;
 u32 context;
 u8 is_nat44;
 u8 in_addr[16];
};
define nat_det_forward_reply {
 u32 context;
 i32 retval;
 u16 out_port_lo;
 u16 out_port_hi;
 u8 out_addr[4];
};

Get inside address from outside address and port:

define nat_det_reverse {
 u32 client_index;
 u32 context;
 u16 out_port;
 u8 out_addr[4];
};
define nat_det_reverse_reply {
 u32 context;
 i32 retval;
 u8 is_nat44;
 u8 in_addr[16];
};

Dump deterministic NAT mappings:

define nat_det_map_dump {
 u32 client_index;
 u32 context;
};
define nat_det_map_details {
 u32 context;
 u8 is_nat44;
 u8 in_addr[16];
 u8 in_plen;
 u8 out_addr[4];
 u8 out_plen;
 u32 sharing_ratio;
 u16 ports_per_host;
 u32 ses_num;
};

Set values of timeouts for deterministic NAT (in seconds, 0 = default value):

define nat_det_set_timeouts {
 u32 client_index;
 u32 context;
 u32 udp;
 u32 tcp_established;
 u32 tcp_transitory;
 u32 icmp;
};

Get values of timeouts for deterministic NAT (in seconds):

define nat_det_get_timeouts {
 u32 client_index;
 u32 context;
};
define nat_det_get_timeouts_reply {
 u32 context;
 i32 retval;
 u32 udp;
 u32 tcp_established;
 u32 tcp_transitory;
 u32 icmp;
};

Close deterministic NAT using outside address and port:

define nat_det_close_session_out {
 u32 client_index;
 u32 context;
 u8 out_addr[4];
 u16 out_port;
 u8 ext_addr[4];
 u16 ext_port;
};

Close deterministic NAT using inside address and port:

define nat_det_close_session_in {
 u32 client_index;
 u32 context;
 u8 is_nat44;
 u8 in_addr[16];
 u16 in_port;
 u8 ext_addr[16];
 u16 ext_port;
};

Dump deterministic NAT sessions:

define nat_det_session_dump {
 u32 client_index;
 u32 context;
 u8 is_nat44;
 u8 user_addr[16];
};
define nat_det_session_details {
 u32 client_index;
 u32 context;
 u16 in_port;
 u8 ext_addr[4];
 u16 ext_port;
 u16 out_port;
 u8 state;
 u32 expire;
};

Memory requirements

Deterministic NAT prealocate vector with 1000 session slots (one session 15B) for each host from inside network range. Heap size is configured via heapsize parameter. For large inside network you need to compile VPP with 64bit vector (-DCLIB_VEC64).

Stateful NAT64

VPP stateful NAT64 implementation support TCP,UDP and ICMP translation (fragmented packets are not currently supported). WARNING: Multi thread is not supported yet!

TODO list

Task Status
hairpinning DONE (17.07)
custom prefix DONE (17.07)
documentation DONE (17.07)
multi thread VPP-891 (17.10)
IPFix
unsolicited inbound SYN packet
address-dependent filtering
fragmented packets translation VPP-890 (17.10)

CLI

Supported CLI commands:

nat64 add pool address <ip4-range-start> [- <ip4-range-end>] [tenant-vrf <vrf-id>] [del]
show nat64 pool
set interface nat64 in|out <intfc> [del]
show nat64 interfaces
nat64 add static bib <ip6-addr> <port> <ip4-addr> <port> tcp|udp|icmp [vfr <table-id>] [del]
show nat64 bib all|tcp|udp|icmp|unknown
set nat64 timeouts udp <sec> icmp <sec> tcp-trans <sec> tcp-est <sec> tcp-incoming-syn <sec> | reset
show nat64 timeouts
show nat64 session table all|tcp|udp|icmp|unknown
nat64 add prefix <ip6-prefix>/<plen> [tenant-vrf <vrf-id>] [del]
show nat64 prefix

Example configuration

To enable NAT64 feature with local (IPv6) network interface GigabitEthernet0/8/0 and external (IPv4) network interface GigabitEthernet0/a/0 use:

vpp# set interface nat64 in GigabitEthernet0/8/0 out GigabitEthernet0/a/0

To show interfaces with NAT64 feature use:

vpp# show nat64 interfaces
NAT64 interfaces:
 GigabitEthernet0/8/0 in
 GigabitEthernet0/a/0 out

To add NAT64 pool address use:

vpp# nat64 add pool address 10.1.1.3
vpp# nat64 add pool address 10.1.1.2 - 10.1.1.5

To add NAT64 pool address for specific tenant use:

vpp# nat64 add pool address 10.1.1.10 tenant-vrf 10

To show NAT64 pool addresses use:

vpp# show nat64 pool
NAT64 pool:
 10.0.0.3

To add NAT64 static BIB entry use:

vpp# nat64 add static bib 2001:db8:85a3::8a2e:370:7334 1234 10.1.1.3 5678 tcp
vpp# nat64 add static bib 2001:db8:85a3::8a2e:370:7333 1234 10.1.1.3 5679 udp vrf 10

To show NAT64 BIBs use:

vpp# show nat64 bib tcp
NAT64 tcp BIB:
 fd01:1::2 6303 10.0.0.3 62303 tcp vrf 0 dynamic 1 sessions
vpp# show nat64 bib udp
NAT64 udp BIB:
 fd01:1::2 6304 10.0.0.3 10546 udp vrf 0 dynamic 1 sessions
vpp# show nat64 bib icmp
NAT64 icmp BIB:
 fd01:1::2 6305 10.0.0.3 63209 icmp vrf 0 dynamic 1 sessions
 fd01:1::2 1234 10.0.0.3 21300 icmp vrf 0 dynamic 1 sessions

To show NAT64 session tables use:

vpp# show nat64 session table tcp
NAT64 tcp session table:
 fd01:1::2 6303 64:ff9b::ac10:202 20 10.0.0.3 62303 172.16.2.2 20 tcp vrf 0
vpp# show nat64 session table udp
NAT64 udp session table:
 fd01:1::2 6304 64:ff9b::ac10:202 20 10.0.0.3 10546 172.16.2.2 20 udp vrf 0
vpp# show nat64 session table icmp
NAT64 icmp session table:
 fd01:1::2 64:ff9b::ac10:202 6305 10.0.0.3 172.16.2.2 63209 icmp vrf 0

To set NAT64 session timeouts use (in seconds):

vpp# set nat64 timeouts udp 200 icmp 30 tcp-trans 250 tcp-est 7450 tcp-incoming-syn 10

To reset NAT64 session timeouts to default values use:

vpp# set nat64 timeouts reset

To show NAT64 session timeouts use:

vpp# show nat64 timeouts
NAT64 session timeouts:
 UDP 300sec
 ICMP 60sec
 TCP transitory 240sec
 TCP established 7440sec
 TCP incoming SYN 6sec

To set NAT64 global prefix use:

vpp# nat64 add prefix 2001:db8::/32

To set NAT64 prefix for specific tenant use:

vpp# nat64 add prefix 2001:db8:122:300::/56 tenant-vrf 10

To show NAT64 prefix use:

vpp# show nat64 prefix
NAT64 prefix:
 2001:db8::/32 tenant-vrf 0
 2001:db8:122:300::/56 tenant-vrf 10

API

Add/delete address range to NAT64 pool:

define nat64_add_del_pool_addr_range {
 u32 client_index;
 u32 context;
 u8 start_addr[4];
 u8 end_addr[4];
 u32 vrf_id;
 u8 is_add;
};

Dump NAT64 pool addresses:

define nat64_pool_addr_dump {
 u32 client_index;
 u32 context;
};
define nat64_pool_addr_details {
 u32 context;
 u8 address[4];
 u32 vrf_id;
};

Enable/disable NAT64 feature on the interface:

define nat64_add_del_interface {
 u32 client_index;
 u32 context;
 u32 sw_if_index;
 u8 is_inside;
 u8 is_add;
};

Dump interfaces with NAT64 feature:

define nat64_interface_dump {
 u32 client_index;
 u32 context;
};
define nat64_interface_details {
 u32 context;
 u8 is_inside;
 u32 sw_if_index;
};

Add/delete NAT64 static BIB entry:

define nat64_add_del_static_bib {
 u32 client_index;
 u32 context;
 u8 i_addr[16];
 u8 o_addr[4];
 u16 i_port;
 u16 o_port;
 u32 vrf_id;
 u8 proto;
 u8 is_add;
};

Dump NAT64 BIB:

define nat64_bib_dump {
 u32 client_index;
 u32 context;
 u8 proto;
};
define nat64_bib_details {
 u32 context;
 u8 i_addr[16];
 u8 o_addr[4];
 u16 i_port;
 u16 o_port;
 u32 vrf_id;
 u8 proto;
 u8 is_static;
 u32 ses_num;
};

Set values of timeouts for NAT64 (in seconds, 0 = default):

define nat64_set_timeouts {
 u32 client_index;
 u32 context;
 u32 udp;
 u32 icmp;
 u32 tcp_trans;
 u32 tcp_est;
 u32 tcp_incoming_syn;
};

Get values of timeouts for NAT64 (in seconds):

define nat64_get_timeouts {
 u32 client_index;
 u32 context;
};
define nat64_get_timeouts_reply {
 u32 context;
 i32 retval;
 u32 udp;
 u32 icmp;
 u32 tcp_trans;
 u32 tcp_est;
 u32 tcp_incoming_syn;
};

Dump NAT64 session table:

define nat64_st_dump {
 u32 client_index;
 u32 context;
 u8 proto;
};
define nat64_st_details {
 u32 context;
 u8 il_addr[16];
 u8 ol_addr[4];
 u16 il_port;
 u16 ol_port;
 u8 ir_addr[16];
 u8 or_addr[4];
 u16 r_port;
 u32 vrf_id;
 u8 proto;
};

Add/del NAT64 prefix:

define nat64_add_del_prefix {
 u32 client_index;
 u32 context;
 u8 prefix[16];
 u8 prefix_len;
 u32 vrf_id;
 u8 is_add;
};

Dump NAT64 prefix:

define nat64_prefix_dump {
 u32 client_index;
 u32 context;
};
define nat64_prefix_details {
 u32 context;
 u8 prefix[16];
 u8 prefix_len;
 u32 vrf_id;
};

YANG model

YANG Data Model for NAT (draft)

A YANG Data Model for NAT and NPT (draft)

References