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_snat_det_h__
23 #define __included_snat_det_h__
25 #include <vnet/ip/ip.h>
26 #include <snat/snat.h>
29 #define SNAT_DET_SES_PER_USER 1000
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);
36 is_addr_in_net (ip4_address_t * addr, ip4_address_t * net, u8 plen)
38 if (net->as_u32 == (addr->as_u32 & ip4_main.fib_masks[plen]))
43 always_inline snat_det_map_t *
44 snat_det_map_by_user (snat_main_t * sm, ip4_address_t * user_addr)
49 pool_foreach (dm, sm->det_maps,
51 if (is_addr_in_net(user_addr, &dm->in_addr, dm->in_plen))
58 always_inline snat_det_map_t *
59 snat_det_map_by_out (snat_main_t * sm, ip4_address_t * out_addr)
64 pool_foreach (dm, sm->det_maps,
66 if (is_addr_in_net(out_addr, &dm->out_addr, dm->out_plen))
74 snat_det_forward (snat_det_map_t * dm, ip4_address_t * in_addr,
75 ip4_address_t * out_addr, u16 * lo_port)
77 u32 in_offset, out_offset;
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;
83 clib_host_to_net_u32 (clib_net_to_host_u32 (dm->out_addr.as_u32) +
85 *lo_port = 1024 + dm->ports_per_host * (in_offset % dm->sharing_ratio);
89 snat_det_reverse (snat_det_map_t * dm, ip4_address_t * out_addr, u16 out_port,
90 ip4_address_t * in_addr)
92 u32 in_offset1, in_offset2, out_offset;
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;
99 clib_host_to_net_u32 (clib_net_to_host_u32 (dm->in_addr.as_u32) +
100 in_offset1 + in_offset2);
104 snat_det_user_ses_offset (ip4_address_t * addr, u8 plen)
106 return (clib_net_to_host_u32 (addr->as_u32) & pow2_mask (32 - plen)) *
107 SNAT_DET_SES_PER_USER;
110 always_inline snat_det_session_t *
111 snat_det_get_ses_by_out (snat_det_map_t * dm, ip4_address_t * in_addr,
117 user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
118 for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
120 if (dm->sessions[i + user_offset].out.as_u64 == out_key)
121 return &dm->sessions[i + user_offset];
127 always_inline snat_det_session_t *
128 snat_det_find_ses_by_in (snat_det_map_t * dm,
129 ip4_address_t * in_addr, u16 in_port)
134 user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
135 for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
137 if (dm->sessions[i + user_offset].in_port == in_port)
138 return &dm->sessions[i + user_offset];
144 always_inline snat_det_session_t *
145 snat_det_ses_create (snat_det_map_t * dm, ip4_address_t * in_addr,
146 u16 in_port, snat_det_out_key_t * out)
151 user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
153 for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
155 if (!dm->sessions[i + user_offset].in_port)
157 if (__sync_bool_compare_and_swap
158 (&dm->sessions[i + user_offset].in_port, 0, in_port))
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];
173 snat_det_ses_close (snat_det_map_t * dm, snat_det_session_t * ses)
175 if (__sync_bool_compare_and_swap (&ses->in_port, ses->in_port, 0))
178 __sync_add_and_fetch (&dm->ses_num, -1);
182 #endif /* __included_snat_det_h__ */
185 * fd.io coding-style-patch-verification: ON
188 * eval: (c-set-style "gnu")