2 * snat_det.h - deterministic NAT definitions
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * @brief deterministic NAT definitions
22 #ifndef __included_nat_det_h__
23 #define __included_nat_det_h__
25 #include <vnet/ip/ip.h>
27 #include <nat/nat_ipfix_logging.h>
30 #define SNAT_DET_SES_PER_USER 1000
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);
37 is_addr_in_net (ip4_address_t * addr, ip4_address_t * net, u8 plen)
39 if (net->as_u32 == (addr->as_u32 & ip4_main.fib_masks[plen]))
44 always_inline snat_det_map_t *
45 snat_det_map_by_user (snat_main_t * sm, ip4_address_t * user_addr)
50 pool_foreach (dm, sm->det_maps,
52 if (is_addr_in_net(user_addr, &dm->in_addr, dm->in_plen))
59 always_inline snat_det_map_t *
60 snat_det_map_by_out (snat_main_t * sm, ip4_address_t * out_addr)
65 pool_foreach (dm, sm->det_maps,
67 if (is_addr_in_net(out_addr, &dm->out_addr, dm->out_plen))
75 snat_det_forward (snat_det_map_t * dm, ip4_address_t * in_addr,
76 ip4_address_t * out_addr, u16 * lo_port)
78 u32 in_offset, out_offset;
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;
84 clib_host_to_net_u32 (clib_net_to_host_u32 (dm->out_addr.as_u32) +
86 *lo_port = 1024 + dm->ports_per_host * (in_offset % dm->sharing_ratio);
90 snat_det_reverse (snat_det_map_t * dm, ip4_address_t * out_addr, u16 out_port,
91 ip4_address_t * in_addr)
93 u32 in_offset1, in_offset2, out_offset;
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;
100 clib_host_to_net_u32 (clib_net_to_host_u32 (dm->in_addr.as_u32) +
101 in_offset1 + in_offset2);
105 snat_det_user_ses_offset (ip4_address_t * addr, u8 plen)
107 return (clib_net_to_host_u32 (addr->as_u32) & pow2_mask (32 - plen)) *
108 SNAT_DET_SES_PER_USER;
111 always_inline snat_det_session_t *
112 snat_det_get_ses_by_out (snat_det_map_t * dm, ip4_address_t * in_addr,
118 user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
119 for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
121 if (dm->sessions[i + user_offset].out.as_u64 == out_key)
122 return &dm->sessions[i + user_offset];
128 always_inline snat_det_session_t *
129 snat_det_find_ses_by_in (snat_det_map_t * dm, ip4_address_t * in_addr,
130 u16 in_port, snat_det_out_key_t out_key)
132 snat_det_session_t *ses;
136 user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
137 for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
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];
149 always_inline snat_det_session_t *
150 snat_det_ses_create (snat_det_map_t * dm, ip4_address_t * in_addr,
151 u16 in_port, snat_det_out_key_t * out)
156 user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
158 for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
160 if (!dm->sessions[i + user_offset].in_port)
162 if (__sync_bool_compare_and_swap
163 (&dm->sessions[i + user_offset].in_port, 0, in_port))
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 __sync_add_and_fetch (&dm->ses_num, 1);
169 return &dm->sessions[i + user_offset];
174 snat_ipfix_logging_max_entries_per_user (in_addr->as_u32);
179 snat_det_ses_close (snat_det_map_t * dm, snat_det_session_t * ses)
181 if (__sync_bool_compare_and_swap (&ses->in_port, ses->in_port, 0))
184 __sync_add_and_fetch (&dm->ses_num, -1);
188 #endif /* __included_nat_det_h__ */
191 * fd.io coding-style-patch-verification: ON
194 * eval: (c-set-style "gnu")