Table of Contents

Description of NAT statistics

NAT statistics can be logged to stat_log and via fdpi_ctrl.
To view queue information, you can dump the NAT profile via fdpi_cli.

Logging statistics to fastdpi_stat.log

This is configured using the dbg_log_mask parameter in /etc/dpi/fastdpi.conf.
A service reload is required for the changes to take effect: service fastdpi reload
Example:
dbg_log_mask=0x2000000

0x40000 - output of NAT initialization details (profiles, public addresses, etc.) to the alert log
0x100000 - output of statistics by blocks of public addresses (if 0x2000000 is set)
0x2000000 - NAT statistics output.

Common for all profiles

[STAT    ][2021/12/22-17:33:17:513859] NAT statistics : itrnsl=0, iprof=2, profile 'cgnat', nttype=0, ref_cnt=1, cidr=94.140.198.84/30
[STAT    ][2021/12/22-17:33:17:513869] NAT statistics : itrnsl=1, iprof=3, profile 'nat1_1', nttype=1, ref_cnt=1, cidr=16.35.121.0/24

    itrnsl  - internal index of the private<-->public proile converter.
    iprof   - internal index of the profile
    profile - profile name
    nttype  - profile type (0 - cgnat, 1 - 1:1)
    ref_cnt - counter of references of converter usage by profiles
    (Profiles can use one set of CIDR, but different number of restrictions per session)
    cidr    - list of profile's public addresses CIDR

CG-NAT Profile

[STAT    ][2021/12/22-17:33:19:252622] NAT statistics : itrnsl=0, iprof=2, profile 'cgnat', nttype=0, ref_cnt=1, cidr=94.140.198.84/30
        k=0, itrnsld=0, cidr=94.140.198.84/30
                total  TCP : 30/20/0/7/17/ 0/0/0 50/20/0/50/0 5516/8/121
                actual TCP : 0/0/0/0/0 0/0/0 0/0/0/0/0 0/0/0
                total  UDP : 13/4/0/13/1/ 0/0/0 17/4/11/17/0 28/1/3
                actual UDP : 0/0/0/0/0 0/0/0 0/0/0/0/0 0/0/0
                total GRE : 0/0

Information on the data converter

        k=0, itrnsld=0, cidr=94.140.198.84/30
    k       - itrnsld number
    itrnsld - internal converter data index - the one serving the CIDR
    cidr    - exact cidr

    total   - total statistics
    actual  - статистика изменеий счетчиков за период вывода статистики (delta_alarm parameter, 15 seconds by default) 

    total  TCP : 30/20/0/7/17 0/0/0 50/20/0/50/0 5516/8/121

Four groups группы:
1 group — operations with public address ports

30/20/0/7/17:

30 - allocation of a new public port 
20 - public port reuse 
0  - errors of allocating a new public port
7  - performs decrement of number of subscriber sessions on flow releasing 
17 - performs decrement of the number of subscriber sessions on public port reuse

2 group — general statistics

0/0/0:

0 - calculated CRC by IP when accessed to allocate a public address. Should be == 0 
0 - excessive number of sessions for subscribers
0 - different public addresses in flow and converters - Should be == 0 

3 group — cache statistics private → public

50/20/0/50/0:

50 - added records to cache
20 - deleted records from cache
0  - found records in cache when new public port is allocated
50 - no public address found for private 
0  - errors of adding to cache

4 group — conversion statistics public → private (inet→subs)

5516/8/121: 

5516 - successful translation public → private
8    - port is not in the allocated range of public ports
121  - translation public → private was not found

For TCP/UDP and total/actual statistics are the same.

For GRE – it is GRE by default (when session is not found in PPTP). Only one such session can be created per public address.

total GRE : 0/0
0 - address used 
0 - number of attempts to create sessions on an already allocated public address

1:1 Profile

[STAT    ][2021/12/22-17:17:28:749622] NAT statistics : itrnsl=1, iprof=3, profile 'nat1_1', nttype=1, ref_cnt=1, cidr=16.35.121.0/24
        k=0, itrnsld=1, cidr=16.35.121.0/24
                total 256/256/0/0/0/0 0/0

Group 2 statistics:
1 group - 256/256/0/0/0/0
2 group - 0/0

Example:
dbg_log_mask=0x2100000

Output of public addresses statistics

[STAT    ][2021/12/22-21:14:48:385991] NAT statistics : itrnsl=0, iprof=2, profile 'cgnat', nttype=0, ref_cnt=1, cidr=94.140.198.84/30
        k=0, itrnsld=0, cidr=94.140.198.84/30
                total  TCP : 26/4/0/4/2/ 0/0/0 30/4/0/30/0 3045/1/36
                actual TCP : 0/0/0/0/0 0/0/0 0/0/0/0/0 0/0/0
                        TCP whiteblck ip_mask=0x0, nwhaddr=2
                                whip=94.140.198.84 : sb=64, lsb=64, nb=1008, whpa=64512, whpb=0, whpf=64512, awhb=4, fwhb=1004, puwhb=0.40%
                                        thr=0, ublock=1, uport=0
                                        thr=1, ublock=1, uport=0
                                        thr=2, ublock=1, uport=0
                                        thr=3, ublock=1, uport=0
                                whip=94.140.198.86 : sb=64, lsb=64, nb=1008, whpa=64512, whpb=26, whpf=64486, awhb=4, fwhb=1004, puwhb=0.40%
                                        thr=0, ublock=1, uport=0
                                        thr=1, ublock=1, uport=0
                                        thr=2, ublock=1, uport=13
                                        thr=3, ublock=1, uport=13
TCP whiteblck ip_mask=0x0, nwhaddr=2 :

    ip_mask - addresses mask
    nwhaddr - the number of public addresses that are under the mask
whip=94.140.198.84 : sb=64 ( 64 ), nb=1008, whpa=64512, whpb=0, whpf=64512, awhb=4, fwhb=1004, puwhb=0.40%

    whip=94.140.198.84 - public address
    sb=64       - port block size
    lsb=64      - size of the last block
    nb=1008     - number of port blocks
    whpa=64512  - total ports
    whpb=0      - ports occupied
    whpf=64512  - free ports
    awhb=4      - blocks issued
    fwhb=1004   - free blocks
    puwhb=0.40% - percentage of blocks occupied

Added in version 12.1.0

whp_salfs 	- how many ports are in the 'short' queue
whp_lalfs 	- how many ports are in the 'long' queue
whp_ruse  	- how many ports can be reused
whp_ruse_salfs 	- how many ports can be reused from the 'short' queue
whp_ruse_lalfs 	- how many ports can be reused from the 'long' queue
whp_dthr 	- how many ports were created in one worker thread but used in another thread
whp_dthr_salfs  - how many ports were created in one worker thread but used in another from the 'short' queue
whp_dthr_lalfs  - how many ports were created in one worker thread but used in another from the 'long' queue

Within the public address you can see the distribution of captured ports/blocks by worker threads

thr=0, ublock=1, uport=0
thr=0 - worker thread number
ublock=1 - public ports blocks used 
uport=0 - public ports used
thr_salfs 	- how many ports are in the 'short' queue
thr_lalfs 	- how many ports are in the 'long' queue
thr_ruse 	- how many ports can be reused
thr_ruse_salfs 	- how many ports can be reused from the 'short' queue
thr_ruse_lalfs 	- how many ports can be reused from the 'long' queue
thr_dthr 	- how many ports were created in one worker thread but used in another thread
thr_dthr_salfs	- how many ports were created in one worker thread but used in another from the 'short' queue
thr_dthr_lalfs	- how many ports were created in one worker thread but used in another from 'long' queue

The output format is the same.

fdpi_ctrl list status --service 11 --ip 192.168.4.20
Autodetected fastdpi params : dev='em1', port=29001
connecting 94.140.198.68:29001 ...

================================
192.168.4.20    crcip=0xd649d853        nttype=0        profile='cgnat' itrnsl=0 itrnsld=0       whiteip=94.140.198.86   sess_tcp=127     active_sess_tcp=0       sess_udp=108     active_sess_udp=1       indmtd=4

Output:

192.168.4.20		- private IP
crcip=0xd649d853	- CRC of the private IP
nttype=0        	- NAT type: 0 - cgnat, 1 - 1:1
profile='cgnat' 	- profile name
itrnsl=0 		- internal index of the converter private<-->public profile.
itrnsld=0       	- internal converter data index 
whiteip=94.140.198.86 	- public address
sess_tcp=127    	- number of TCP sessions
active_sess_tcp=0	- Number of active NAT translations for TCP
sess_udp=108   		- number of UDP sessions
active_sess_udp=1	- Number of active NAT translations for UDP
indmtd=4              	- internal index of subscriber data (subscriber metadata)

fdpi_ctrl list status --service 11 --ip 192.168.4.20 --outformat=json
fdpi_ctrl list status --service 11 --ip 192.168.4.20 --outformat=json  | jq .

fdpi_ctrl list all status --service 11
fdpi_ctrl list all status --service 11 --outformat=json

The format is the same.

List of NAT Translations

Tracking translation lifetime. Displays a list of all NAT translations for the specified internal IP address.
The status of a translation is determined by the time of its last use and the lifetime parameter specified in the cluster options. If <lifetime> (in seconds) is specified, its value is used as the translation’s lifetime.

Command format:

fdpi_cli nat show <internal_ip> [<lifetime>]

Sample output:

fdpi_cli nat show 172.16.120.35
nat_type   protocol internal ip     internal port dest ip         dest port  external ip     external port active
CGNAT      TCP      172.16.120.35   33186         0.0.0.0         0          172.16.120.4    1031          false
CGNAT      TCP      172.16.120.35   52896         17.108.151.45   80         172.16.120.4    1024          false
CGNAT      TCP      172.16.120.35   38762         0.0.0.0         0          172.16.120.4    1033          false
CGNAT      TCP      172.16.120.35   40548         103.108.151.45  80         172.16.120.4    1038          false
CGNAT      TCP      172.16.120.35   36466         17.108.151.45   443        172.16.120.4    1036          false
CGNAT      TCP      172.16.120.35   37848         0.0.0.0         0          172.16.120.4    1026          false

Legend:

nat_type     	- NAT type (0 - CGNAT, 1 - 1:1 NAT),
protocol     	- Layer 4 protocol (0 - TCP, 1 - UDP),
internal_ip     - private IP,
internal_port	- internal port,
dest_ip     	- destination IP,
dest_port     	- destination port,
external_ip     - external IP,
external_port   - external port,
active         	- translation activity flag (true if active)

Key to command to view NAT profile statistics via fdpi_ctrl

Command:

fdpi_ctrl list status --service 11 --profile.name cgnat

Output:

nttype=0        profile='test_nat_cgnat'        itrnsl=0        nitrnsld=1
        itrnsld=0       cidr=94.140.198.84/30
                proto=TCP       ip_mask=0x0     nwhaddr=2
                        proto=TCP       ip_mask=0x0     whip=94.140.198.84      sb=64   lsb=64  nb=1008 whpa=64512      whpb=0  whpf=64512      awhb=4  fwhb=1004       puwhb=0.40%     whp_salfs=0     whp_lalfs=0     whp_ruse=0      whp_ruse_salfs=0        whp_ruse_lalfs=0        whp_dthr=0      whp_dthr_salfs=0        whp_dthr_lalfs=0
                                nthr=0  ublock=1        uport=0 thr_salfs=0     thr_lalfs=0     thr_ruse=0      thr_ruse_salfs=0        thr_ruse_lalfs=0        thr_dthr=0      thr_dthr_salfs=0        thr_dthr_lalfs=0
                                nthr=1  ublock=1        uport=0 thr_salfs=0     thr_lalfs=0     thr_ruse=0      thr_ruse_salfs=0        thr_ruse_lalfs=0        thr_dthr=0      thr_dthr_salfs=0        thr_dthr_lalfs=0

Key:

nttype         - profile type (0 - cgnat, 1 - 1:1)
profile        - profile name
itrnsl         - internal index of private<-->public profile converter
nitrnsld       - number of profile converter data (number of CIDR)
itrnsld        - internal converter data index - the one serving the CIDR
cidr           - exact CIDR
proto          - TCP/UDP
ip_mask        - addresses mask
nwhaddr        - the number of public addresses which fall under the mask or CRC (depends on rx_dispatcher parameter)
whip           - public address
sb             - size of the block of ports to be allocated
lsb            - size of the last block
nb             - number of prot blocks
whpa           - ports in total
whpb           - ports occupied
whpf           - free ports
awhb           - blocks issued
fwhb           - free blocks
puwhb          - percentage of blocks occupied
whp_salfs      - is in the 'short' queue
whp_lalfs      - in the 'long' queue
whp_ruse       - can be used
whp_ruse_salfs - can be used in 'short' queue
whp_ruse_lalfs - can be used in 'long' queue
whp_dthr       - number of elements ithr_owner != ithr by queue
whp_dthr_salfs - number of elements ithr_owner != ithr by 'short' queue
whp_dthr_lalfs - number of elements ithr_owner != ithr by 'long' queue
rx_dispatcher parameter description at the link

Key to command to view the dump NAT profile statistics

Command:

fdpi_cli nat dump whaddr queue test_nat_cgnat

Output:

profile='test_nat_cgnat' itrnsl=0
        cidr='94.140.198.84/30' itrnsld=0
                whip=94.140.198.86
                        proto=TCP
                                entryp :
                                        ithr=0, ihead=0, itail=0
                                        ithr=1, ihead=0, itail=0
                                        ithr=2, ihead=133, itail=265
                                        ithr=3, ihead=193, itail=327
                                data :
                                        sind=129, inext=257, iprev=258, whport=1152, graddr=192.168.4.20:60637 tml='2023/03/06 16:28:09, -00:00:10.657 (7472516905147512 ticks)', lifetime=120, canreuse=0, ialf=1, imtd=516, iown=2, ilst=2, subproto=0, decr_sess=0, ind_gcache_slice=1, igcache=40
                                        sind=130, inext=151, iprev=148, whport=1153, graddr=192.168.4.20:52553 tml='2023/03/06 16:27:50, -00:00:29.455 (7472459405058624 ticks)', lifetime=30, canreuse=0, ialf=0, imtd=516, iown=2, ilst=2, subproto=0, decr_sess=0, ind_gcache_slice=1, igcache=1

Key:

profile        - profile name
itrnsl         - internal index of the private<-->public profile converter

cidr           - exact CIDR
itrnsld        - internal converter data index - the one serving the CIDR

whip           - public address
proto          - TCP/UDP

The implementation of the used ports queue for public addresses uses a single array - let's call it WHP, of size 0xffff. It is used to build a list of used ports for the worker thread. Index 0 is used as a stub (empty).

Thread queues cannot be output as a list, because records in the queue are moved in the process, which may cause the output to loop. Therefore, the WHP array is output 'as is' for occupied entries.

entryp : sets entry points to the list of public ports of the worker thread
	ithr   - worker thread number
	ihead  - top of the list
	itail  - the last element of the list
data : WHP white port array data (only occupied entries are output)

	sind		 - record index
	inext            - next record index
	iprev            - previous record index
	
	whport           - public port
	graddr           - private address, which the public address is assigned to
	tml              - time of the last record access 
	lifetime         - timeout, time in seconds, the record lifetime (depends on the parameters for short/long queue)
	canreuse         - sign that the record can be used again
	ialf             - number of the processing queue :
							en_nalfs_shrt = 0,  # queue with a short lifetime
							en_nalfs_long = 1,  # long queue
	indmtd           - internal index of the subscriber's data (subscriber's metadata)
	iown             - owner thread which has created the record
	ilst             - number of the thread which has last accessed the record
	subproto         - the protocol the record was allocated for from UDP
						typedef enum en_nat_borrw_udp: u_int8_t
						{
							ennatborwu_ORG     = 0, # UDP/TCP
							ennatborwu_DFLTGRE = 1, # общий GRE 
							ennatborwu_MAX     = 2, # ICMP
						} en_nat_borrw_udp_t;
					   
	decr_sess        - a mark that the port usage counter on the private address has decremented
	ind_gcache_slice - index of the 'private --> public' transcoding cache-slice
	igcache          - index in the corresponding cache-slice recoding 'private --> public' 

Monitoring Free/Busy Ports on Whitelisted Addresses

Proactive monitoring helps avoid issues with a shortage of free ports and the resulting inability to create new sessions, by allocating additional blocks of whitelisted addresses or reducing port allocation limits when resources in the current pool are exhausted.

Free ports on a white address = whpf (unallocated) + whp_ruse (ready for reuse)
Busy ports on a white address = whpb (allocated) - whp_ruse (ready for reuse)