VPP/SNAT

From fd.io
< VPP
Jump to: navigation, search

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 WIP 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
Performance 10Mpps/core. Linear scaling with number of cores.
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
IP fragmentation
PCP No plan.

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

NAT Session Refresh:

  • NAT Outbound refresh behavior
  • UDP idle-timeout 5 minutes
  • TCP established connection idle-timeout 2 hours 4 minutes
  • TCP transitory connection idle-timeout 4 minutes
  • TCP session close detection

TODO:

  • ICMP support
  • configurable idle-timeouts
  • IPFIX logging
  • manual session close
  • administratively turn off translation for specific destination addresses and/or ports
  • additional port range assignment algorithms

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>

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

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;
};

YANG model

References