nat: remove non-error error counters
[vpp.git] / src / plugins / nat / nat_det.h
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
37 is_addr_in_net (ip4_address_t * addr, ip4_address_t * net, u8 plen)
38 {
39   if (net->as_u32 == (addr->as_u32 & ip4_main.fib_masks[plen]))
40     return 1;
41   return 0;
42 }
43
44 always_inline snat_det_map_t *
45 snat_det_map_by_user (snat_main_t * sm, ip4_address_t * user_addr)
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
59 always_inline snat_det_map_t *
60 snat_det_map_by_out (snat_main_t * sm, ip4_address_t * out_addr)
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
75 snat_det_forward (snat_det_map_t * dm, ip4_address_t * in_addr,
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
104 always_inline u32
105 snat_det_user_ses_offset (ip4_address_t * addr, u8 plen)
106 {
107   return (clib_net_to_host_u32 (addr->as_u32) & pow2_mask (32 - plen)) *
108     SNAT_DET_SES_PER_USER;
109 }
110
111 always_inline snat_det_session_t *
112 snat_det_get_ses_by_out (snat_det_map_t * dm, ip4_address_t * in_addr,
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
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)
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
149 always_inline snat_det_session_t *
150 snat_det_ses_create (u32 thread_index, snat_det_map_t * dm,
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         {
163           if (clib_atomic_bool_cmp_and_swap
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
175   snat_ipfix_logging_max_entries_per_user (thread_index,
176                                            SNAT_DET_SES_PER_USER,
177                                            in_addr->as_u32);
178   return 0;
179 }
180
181 always_inline void
182 snat_det_ses_close (snat_det_map_t * dm, snat_det_session_t * ses)
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  */