VPP/NAT
Contents
- 1 VPP NAT implementation
- 1.1 Introduction
- 1.2 Requirements
- 1.3 Work list
- 1.4 API
- 1.5 CLI
- 1.5.1 Enable S-NAT feature example
- 1.5.2 NAPT - add pool address example
- 1.5.3 NAPT - add pool address for specific tenant
- 1.5.4 1:1 NAT example
- 1.5.5 1:1 NAT with ports example
- 1.5.6 Set S-NAT workers example
- 1.5.7 Enable S-NAT IPFIX logging example
- 1.5.8 Add S-NAT pool address from specific (DHCP addressed) interfce example
- 1.5.9 1:1 NAT for DHCP addressed interface example
- 1.6 Startup config
- 1.7 NAT IPFIX logging
- 1.8 CGN - deterministic NAT
- 1.9 Stateful NAT64
- 1.10 YANG model
- 1.11 References
VPP NAT implementation
Introduction
The VPP SNAT is an implementation of NAT44. 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.
Features are tracked as they are developed in the following VPP-441.
Until code is upstreamed it is developed on gitub.
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 | 1 | |||
DS-lite | ||||
NAT64 | Matus | 17.07 | WIP | VPP-699, some stuff done details here |
IP fragmentation | ||||
PCP | No plan. | |||
SNAT: Fallback to 3-tuple key for non TCP/UDP sessions | Matus | VPP-884 |
API
add S-NAT plugin 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 S-NAT plugin 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 S-NAT 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 S-NAT 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 S-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 S-NAT plugin workers:
define snat_set_workers { u32 client_index; u32 context; u64 worker_mask; };
dump S-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 S-NAT 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 S-NAT 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 S-NAT IPFIX logging:
define snat_ipfix_enable_disable { u32 client_index; u32 context; u32 domain_id; u16 src_port; u8 enable; };
dump S-NAT 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 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; };
CLI
set interface snat in <intfc> out <intfc> [del] snat add addresses <ip4-range-start> [- <ip4-range-end>] [tenant-vrf <vrf-id>] [del] snat add static mapping tcp|udp|icmp local <ip4-addr> [<port>] external (<ip4-addr>|<intfc>) [<port>] [vrf <table-id>] [del] set snat workers <workers-list> snat ipfix logging [domain <domain-id>] [src-port <port>] [disable] snat add interface address <interface> [del] show snat [detail|verbose]
Enable S-NAT feature example
To enable NAT feature with local network interface GigabitEthernet0/8/0 and external network interface GigabitEthernet0/a/0 use:
vpp# set interface snat in GigabitEthernet0/8/0 out GigabitEthernet0/a/0
NAPT - add pool address example
To add NAT pool address use:
vpp# snat add address 172.16.1.3 vpp# snat add address 172.16.2.2 - 172.16.2.24
NAPT - add pool address for specific tenant
To add NAT pool address for specific tenent (identified by VRF id) use:
vpp# snat add address 172.16.1.3 tenant-vrf 10 vpp# snat 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# snat add static mapping local 10.0.0.3 external 4.4.4.4
1:1 NAT with ports example
If not runnig "static mapping only" S-NAT plugin mode first use:
vpp# snat 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# snat add static mapping tcp local 10.0.0.3 6303 external 4.4.4.4 3606
Set S-NAT workers example
To set S-NAT workers (2 or more workers available, by default S-NAT use all available worker threads) use:
vpp# set snat workers 0-1
Enable S-NAT IPFIX logging example
To set IPFIX exporter use:
vpp# set ipfix exporter collector 10.10.10.3 src 10.10.10.1
To enable SNAT IPFIX logging use:
vpp# snat ipfix logging
Add S-NAT pool address from specific (DHCP addressed) interfce example
To add S-NAT pool address from specific interfce use:
vpp# snat add interface address GigabitEthernet0/8/0
1:1 NAT for DHCP addressed interface example
To add static mapping for DHCP addressed interface use:
vpp# snat add static mapping tcp local 10.0.0.3 6303 external GigabitEthernet0/a/0 3606
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
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 S-NAT plugin deterministic mode add following to statrup config:
snat { deterministic }
To verify S-NAT plugin mode use:
vpp# show snat SNAT mode: deterministic mapping
CLI
Supported CLI commands:
set interface snat in <intfc> out <intfc> [del] snat deterministic add in <addr>/<plen> out <addr>/<plen> [del] snat deterministic forward <addr> snat deterministic reverse <addr>:<port> set snat deterministic timeout [udp <sec> | tcp-established <sec> | tcp-transitory <sec> | icmp <sec> | reset] snat 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 snat 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# snat deterministic add in 10.0.0.0/18 out 1.1.1.1/30
To show deterministic mapping information use:
vpp# show snat detail SNAT 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# snat 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# snat deterministic reverse 1.1.1.1:1276 10.0.16.16
To set values of timeouts use:
vpp# set snat deterministic timeout udp 120 tcp-established 7500 tcp-transitory 250 icmp 90
To reset default values of timeouts use:
vpp# set snat deterministic timeout reset
To close session using outside address and port and external endpoint address and port use:
vpp# snat 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# snat deterministic close session in 3.3.3.3:3487 2.2.2.2:2387
API
Add/delete S-NAT deterministic 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 S-NAT deterministic 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; };
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 | |
IPFix | |
unsolicited inbound SYN packet | |
address-dependent filtering | |
fragmented packets translation |
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 tcp|udp|icmp set nat64 timeouts udp <sec> icmp <sec> tcp-trans <sec> tcp-est <sec> tcp-incoming-syn <sec> | reset show nat64 tiemouts show nat64 session table tcp|udp|icmp 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# at64 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 timeoutes 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 timeoutes to default values use:
vpp# set nat64 timeouts reset
To show NAT64 session timeoutes use:
vpp# show nat64 tiemouts NAT64 session timeouts: UDP 300sec ICMP 60sec TCP transitory 240sec TCP established 7440sec TCP incoming SYN 6sec
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 (not supported yet):
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 (not supported yet):
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)
References
- RFC2663 - NAT terminology and considerations
- RFC4787 - NAT requirements for UDP
- RFC5382 - NAT requirements for TCP
- RFC5508 - NAT requirements for ICMP
- RFC6146 - Stateful NAT64: Network Address and Protocol Translation from IPv6 Clients to IPv4 Servers
- RFC6888 - CGN requirements - qualify and plan dev sequence:
- RFC7422 - Deterministic address mapping
- RFC7269 - NAT64 Deployment Options and Experience
- draft-ietf-behave-ipfix-nat-logging - IPFIX Information Elements for logging NAT Events