FD.io VPP  v20.01-48-g3e0dafb74
Vector Packet Processing
nat_det.h
Go to the documentation of this file.
1 /*
2  * snat_det.h - deterministic NAT definitions
3  *
4  * Copyright (c) 2017 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 /**
18  * @file
19  * @brief deterministic NAT definitions
20  */
21 
22 #ifndef __included_nat_det_h__
23 #define __included_nat_det_h__
24 
25 #include <vnet/ip/ip.h>
26 #include <nat/nat.h>
27 #include <nat/nat_ipfix_logging.h>
28 
29 
30 #define SNAT_DET_SES_PER_USER 1000
31 
32 
33 int snat_det_add_map (snat_main_t * sm, ip4_address_t * in_addr, u8 in_plen,
34  ip4_address_t * out_addr, u8 out_plen, int is_add);
35 
36 always_inline int
38 {
39  if (net->as_u32 == (addr->as_u32 & ip4_main.fib_masks[plen]))
40  return 1;
41  return 0;
42 }
43 
46 {
47  snat_det_map_t *dm;
48 
49  /* *INDENT-OFF* */
50  pool_foreach (dm, sm->det_maps,
51  ({
52  if (is_addr_in_net(user_addr, &dm->in_addr, dm->in_plen))
53  return dm;
54  }));
55  /* *INDENT-ON* */
56  return 0;
57 }
58 
61 {
62  snat_det_map_t *dm;
63 
64  /* *INDENT-OFF* */
65  pool_foreach (dm, sm->det_maps,
66  ({
67  if (is_addr_in_net(out_addr, &dm->out_addr, dm->out_plen))
68  return dm;
69  }));
70  /* *INDENT-ON* */
71  return 0;
72 }
73 
74 always_inline void
76  ip4_address_t * out_addr, u16 * lo_port)
77 {
78  u32 in_offset, out_offset;
79 
80  in_offset = clib_net_to_host_u32 (in_addr->as_u32) -
81  clib_net_to_host_u32 (dm->in_addr.as_u32);
82  out_offset = in_offset / dm->sharing_ratio;
83  out_addr->as_u32 =
84  clib_host_to_net_u32 (clib_net_to_host_u32 (dm->out_addr.as_u32) +
85  out_offset);
86  *lo_port = 1024 + dm->ports_per_host * (in_offset % dm->sharing_ratio);
87 }
88 
89 always_inline void
90 snat_det_reverse (snat_det_map_t * dm, ip4_address_t * out_addr, u16 out_port,
91  ip4_address_t * in_addr)
92 {
93  u32 in_offset1, in_offset2, out_offset;
94 
95  out_offset = clib_net_to_host_u32 (out_addr->as_u32) -
96  clib_net_to_host_u32 (dm->out_addr.as_u32);
97  in_offset1 = out_offset * dm->sharing_ratio;
98  in_offset2 = (out_port - 1024) / dm->ports_per_host;
99  in_addr->as_u32 =
100  clib_host_to_net_u32 (clib_net_to_host_u32 (dm->in_addr.as_u32) +
101  in_offset1 + in_offset2);
102 }
103 
106 {
107  return (clib_net_to_host_u32 (addr->as_u32) & pow2_mask (32 - plen)) *
109 }
110 
113  u64 out_key)
114 {
115  u32 user_offset;
116  u16 i;
117 
118  user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
119  for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
120  {
121  if (dm->sessions[i + user_offset].out.as_u64 == out_key)
122  return &dm->sessions[i + user_offset];
123  }
124 
125  return 0;
126 }
127 
130  u16 in_port, snat_det_out_key_t out_key)
131 {
132  snat_det_session_t *ses;
133  u32 user_offset;
134  u16 i;
135 
136  user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
137  for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
138  {
139  ses = &dm->sessions[i + user_offset];
140  if (ses->in_port == in_port &&
141  ses->out.ext_host_addr.as_u32 == out_key.ext_host_addr.as_u32 &&
142  ses->out.ext_host_port == out_key.ext_host_port)
143  return &dm->sessions[i + user_offset];
144  }
145 
146  return 0;
147 }
148 
151  ip4_address_t * in_addr, u16 in_port,
152  snat_det_out_key_t * out)
153 {
154  u32 user_offset;
155  u16 i;
156 
157  user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
158 
159  for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
160  {
161  if (!dm->sessions[i + user_offset].in_port)
162  {
164  (&dm->sessions[i + user_offset].in_port, 0, in_port))
165  {
166  dm->sessions[i + user_offset].out.as_u64 = out->as_u64;
167  dm->sessions[i + user_offset].state = SNAT_SESSION_UNKNOWN;
168  dm->sessions[i + user_offset].expire = 0;
169  clib_atomic_add_fetch (&dm->ses_num, 1);
170  return &dm->sessions[i + user_offset];
171  }
172  }
173  }
174 
176  SNAT_DET_SES_PER_USER,
177  in_addr->as_u32);
178  return 0;
179 }
180 
181 always_inline void
183 {
184  if (clib_atomic_bool_cmp_and_swap (&ses->in_port, ses->in_port, 0))
185  {
186  ses->out.as_u64 = 0;
187  clib_atomic_add_fetch (&dm->ses_num, -1);
188  }
189 }
190 
191 #endif /* __included_nat_det_h__ */
192 
193 /*
194  * fd.io coding-style-patch-verification: ON
195  *
196  * Local Variables:
197  * eval: (c-set-style "gnu")
198  * End:
199  */
void snat_ipfix_logging_max_entries_per_user(u32 thread_index, u32 limit, u32 src_ip)
Generate maximum entries per user exceeded event.
u16 ext_host_port
Definition: nat.h:123
int snat_det_add_map(snat_main_t *sm, ip4_address_t *in_addr, u8 in_plen, ip4_address_t *out_addr, u8 out_plen, int is_add)
Add/delete deterministic NAT mapping.
Definition: nat_det.c:40
#define clib_atomic_add_fetch(a, b)
Definition: atomics.h:30
unsigned long u64
Definition: types.h:89
static void snat_det_ses_close(snat_det_map_t *dm, snat_det_session_t *ses)
Definition: nat_det.h:182
int i
static snat_det_session_t * snat_det_find_ses_by_in(snat_det_map_t *dm, ip4_address_t *in_addr, u16 in_port, snat_det_out_key_t out_key)
Definition: nat_det.h:129
static void snat_det_forward(snat_det_map_t *dm, ip4_address_t *in_addr, ip4_address_t *out_addr, u16 *lo_port)
Definition: nat_det.h:75
snat_det_map_t * det_maps
Definition: nat.h:653
u8 in_plen
Definition: nat.h:390
static void snat_det_reverse(snat_det_map_t *dm, ip4_address_t *out_addr, u16 out_port, ip4_address_t *in_addr)
Definition: nat_det.h:90
vhost_vring_addr_t addr
Definition: vhost_user.h:147
unsigned char u8
Definition: types.h:56
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:498
ip4_address_t ext_host_addr
Definition: nat.h:122
static uword pow2_mask(uword x)
Definition: clib.h:220
#define SNAT_DET_SES_PER_USER
Definition: nat_det.h:30
unsigned int u32
Definition: types.h:88
static u32 snat_det_user_ses_offset(ip4_address_t *addr, u8 plen)
Definition: nat_det.h:105
snat_det_session_t * sessions
Definition: nat.h:401
static snat_det_map_t * snat_det_map_by_out(snat_main_t *sm, ip4_address_t *out_addr)
Definition: nat_det.h:60
unsigned short u16
Definition: types.h:57
#define always_inline
Definition: ipsec.h:28
static snat_det_session_t * snat_det_ses_create(u32 thread_index, snat_det_map_t *dm, ip4_address_t *in_addr, u16 in_port, snat_det_out_key_t *out)
Definition: nat_det.h:150
u32 sharing_ratio
Definition: nat.h:395
ip4_address_t out_addr
Definition: nat.h:392
static int is_addr_in_net(ip4_address_t *addr, ip4_address_t *net, u8 plen)
Definition: nat_det.h:37
static snat_det_map_t * snat_det_map_by_user(snat_main_t *sm, ip4_address_t *user_addr)
Definition: nat_det.h:45
ip4_address_t in_addr
Definition: nat.h:389
#define clib_atomic_bool_cmp_and_swap(addr, old, new)
Definition: atomics.h:38
u16 ports_per_host
Definition: nat.h:397
snat_det_out_key_t out
Definition: nat.h:379
static snat_det_session_t * snat_det_get_ses_by_out(snat_det_map_t *dm, ip4_address_t *in_addr, u64 out_key)
Definition: nat_det.h:112
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1079
u32 ses_num
Definition: nat.h:399
u32 fib_masks[33]
Definition: ip4.h:118