FD.io VPP  v19.01.2-3-gf61a1a8
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  u16 in_port, snat_det_out_key_t * out)
152 {
153  u32 user_offset;
154  u16 i;
155 
156  user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
157 
158  for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
159  {
160  if (!dm->sessions[i + user_offset].in_port)
161  {
163  (&dm->sessions[i + user_offset].in_port, 0, in_port))
164  {
165  dm->sessions[i + user_offset].out.as_u64 = out->as_u64;
166  dm->sessions[i + user_offset].state = SNAT_SESSION_UNKNOWN;
167  dm->sessions[i + user_offset].expire = 0;
168  clib_atomic_add_fetch (&dm->ses_num, 1);
169  return &dm->sessions[i + user_offset];
170  }
171  }
172  }
173 
174  snat_ipfix_logging_max_entries_per_user (SNAT_DET_SES_PER_USER,
175  in_addr->as_u32);
176  return 0;
177 }
178 
179 always_inline void
181 {
182  if (clib_atomic_bool_cmp_and_swap (&ses->in_port, ses->in_port, 0))
183  {
184  ses->out.as_u64 = 0;
185  clib_atomic_add_fetch (&dm->ses_num, -1);
186  }
187 }
188 
189 #endif /* __included_nat_det_h__ */
190 
191 /*
192  * fd.io coding-style-patch-verification: ON
193  *
194  * Local Variables:
195  * eval: (c-set-style "gnu")
196  * End:
197  */
u16 ext_host_port
Definition: nat.h:85
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:180
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:503
u8 in_plen
Definition: nat.h:277
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:121
unsigned char u8
Definition: types.h:56
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:490
ip4_address_t ext_host_addr
Definition: nat.h:84
#define always_inline
Definition: clib.h:98
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:288
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
u32 sharing_ratio
Definition: nat.h:282
ip4_address_t out_addr
Definition: nat.h:279
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
void snat_ipfix_logging_max_entries_per_user(u32 limit, u32 src_ip)
Generate maximum entries per user exceeded event.
ip4_address_t in_addr
Definition: nat.h:276
#define clib_atomic_bool_cmp_and_swap(addr, old, new)
Definition: atomics.h:38
u16 ports_per_host
Definition: nat.h:284
snat_det_out_key_t out
Definition: nat.h:266
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:903
u32 ses_num
Definition: nat.h:286
static snat_det_session_t * snat_det_ses_create(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 fib_masks[33]
Definition: ip4.h:109