FD.io VPP  v17.04-9-g99c0734
Vector Packet Processing
snat_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_snat_det_h__
23 #define __included_snat_det_h__
24 
25 #include <vnet/ip/ip.h>
26 #include <snat/snat.h>
27 
28 
29 #define SNAT_DET_SES_PER_USER 1000
30 
31 
32 int snat_det_add_map (snat_main_t * sm, ip4_address_t * in_addr, u8 in_plen,
33  ip4_address_t * out_addr, u8 out_plen, int is_add);
34 
35 always_inline int
37 {
38  if (net->as_u32 == (addr->as_u32 & ip4_main.fib_masks[plen]))
39  return 1;
40  return 0;
41 }
42 
45 {
46  snat_det_map_t *dm;
47 
48  /* *INDENT-OFF* */
49  pool_foreach (dm, sm->det_maps,
50  ({
51  if (is_addr_in_net(user_addr, &dm->in_addr, dm->in_plen))
52  return dm;
53  }));
54  /* *INDENT-ON* */
55  return 0;
56 }
57 
60 {
61  snat_det_map_t *dm;
62 
63  /* *INDENT-OFF* */
64  pool_foreach (dm, sm->det_maps,
65  ({
66  if (is_addr_in_net(out_addr, &dm->out_addr, dm->out_plen))
67  return dm;
68  }));
69  /* *INDENT-ON* */
70  return 0;
71 }
72 
73 always_inline void
75  ip4_address_t * out_addr, u16 * lo_port)
76 {
77  u32 in_offset, out_offset;
78 
79  in_offset = clib_net_to_host_u32 (in_addr->as_u32) -
80  clib_net_to_host_u32 (dm->in_addr.as_u32);
81  out_offset = in_offset / dm->sharing_ratio;
82  out_addr->as_u32 =
83  clib_host_to_net_u32 (clib_net_to_host_u32 (dm->out_addr.as_u32) +
84  out_offset);
85  *lo_port = 1024 + dm->ports_per_host * (in_offset % dm->sharing_ratio);
86 }
87 
88 always_inline void
89 snat_det_reverse (snat_det_map_t * dm, ip4_address_t * out_addr, u16 out_port,
90  ip4_address_t * in_addr)
91 {
92  u32 in_offset1, in_offset2, out_offset;
93 
94  out_offset = clib_net_to_host_u32 (out_addr->as_u32) -
95  clib_net_to_host_u32 (dm->out_addr.as_u32);
96  in_offset1 = out_offset * dm->sharing_ratio;
97  in_offset2 = (out_port - 1024) / dm->ports_per_host;
98  in_addr->as_u32 =
99  clib_host_to_net_u32 (clib_net_to_host_u32 (dm->in_addr.as_u32) +
100  in_offset1 + in_offset2);
101 }
102 
105 {
106  return (clib_net_to_host_u32 (addr->as_u32) & pow2_mask (32 - plen)) *
108 }
109 
112  u64 out_key)
113 {
114  u32 user_offset;
115  u16 i;
116 
117  user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
118  for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
119  {
120  if (dm->sessions[i + user_offset].out.as_u64 == out_key)
121  return &dm->sessions[i + user_offset];
122  }
123 
124  return 0;
125 }
126 
129  ip4_address_t * in_addr, u16 in_port)
130 {
131  u32 user_offset;
132  u16 i;
133 
134  user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
135  for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
136  {
137  if (dm->sessions[i + user_offset].in_port == in_port)
138  return &dm->sessions[i + user_offset];
139  }
140 
141  return 0;
142 }
143 
146  u16 in_port, snat_det_out_key_t * out)
147 {
148  u32 user_offset;
149  u16 i;
150 
151  user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
152 
153  for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
154  {
155  if (!dm->sessions[i + user_offset].in_port)
156  {
157  if (__sync_bool_compare_and_swap
158  (&dm->sessions[i + user_offset].in_port, 0, in_port))
159  {
160  dm->sessions[i + user_offset].out.as_u64 = out->as_u64;
161  dm->sessions[i + user_offset].state = SNAT_SESSION_UNKNOWN;
162  dm->sessions[i + user_offset].expire = 0;
163  __sync_add_and_fetch (&dm->ses_num, 1);
164  return &dm->sessions[i + user_offset];
165  }
166  }
167  }
168 
169  return 0;
170 }
171 
172 always_inline void
174 {
175  if (__sync_bool_compare_and_swap (&ses->in_port, ses->in_port, 0))
176  {
177  ses->out.as_u64 = 0;
178  __sync_add_and_fetch (&dm->ses_num, -1);
179  }
180 }
181 
182 #endif /* __included_snat_det_h__ */
183 
184 /*
185  * fd.io coding-style-patch-verification: ON
186  *
187  * Local Variables:
188  * eval: (c-set-style "gnu")
189  * End:
190  */
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
static snat_det_session_t * snat_det_find_ses_by_in(snat_det_map_t *dm, ip4_address_t *in_addr, u16 in_port)
Definition: snat_det.h:128
static void snat_det_reverse(snat_det_map_t *dm, ip4_address_t *out_addr, u16 out_port, ip4_address_t *in_addr)
Definition: snat_det.h:89
static snat_det_map_t * snat_det_map_by_out(snat_main_t *sm, ip4_address_t *out_addr)
Definition: snat_det.h:59
static void snat_det_forward(snat_det_map_t *dm, ip4_address_t *in_addr, ip4_address_t *out_addr, u16 *lo_port)
Definition: snat_det.h:74
u8 in_plen
Definition: snat.h:172
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
#define always_inline
Definition: clib.h:84
static uword pow2_mask(uword x)
Definition: clib.h:257
unsigned long u64
Definition: types.h:89
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: snat_det.c:40
snat_det_session_t * sessions
Definition: snat.h:179
#define SNAT_DET_SES_PER_USER
Definition: snat_det.h:29
u32 sharing_ratio
Definition: snat.h:175
ip4_address_t out_addr
Definition: snat.h:173
unsigned int u32
Definition: types.h:88
static u32 snat_det_user_ses_offset(ip4_address_t *addr, u8 plen)
Definition: snat_det.h:104
ip4_address_t in_addr
Definition: snat.h:171
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: snat_det.h:111
static int is_addr_in_net(ip4_address_t *addr, ip4_address_t *net, u8 plen)
Definition: snat_det.h:36
unsigned short u16
Definition: types.h:57
unsigned char u8
Definition: types.h:56
static snat_det_map_t * snat_det_map_by_user(snat_main_t *sm, ip4_address_t *user_addr)
Definition: snat_det.h:44
u16 ports_per_host
Definition: snat.h:176
snat_det_out_key_t out
Definition: snat.h:165
static void snat_det_ses_close(snat_det_map_t *dm, snat_det_session_t *ses)
Definition: snat_det.h:173
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1117
u32 ses_num
Definition: snat.h:177
vhost_vring_addr_t addr
Definition: vhost-user.h:84
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: snat_det.h:145
u32 fib_masks[33]
Definition: ip4.h:117