Line data Source code
1 : /*
2 : * Copyright (c) 2020 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 :
16 : #ifndef __included_nat44_ei_inlines_h__
17 : #define __included_nat44_ei_inlines_h__
18 :
19 : #include <vppinfra/clib.h>
20 :
21 : #include <nat/nat44-ei/nat44_ei.h>
22 : #include <nat/nat44-ei/nat44_ei_ha.h>
23 : #include <nat/lib/nat_proto.h>
24 :
25 : always_inline u64
26 116022 : calc_nat_key (ip4_address_t addr, u16 port, u32 fib_index, u8 proto)
27 : {
28 116022 : ASSERT (fib_index <= (1 << 14) - 1);
29 116022 : ASSERT (proto <= (1 << 3) - 1);
30 232044 : return (u64) addr.as_u32 << 32 | (u64) port << 16 | fib_index << 3 |
31 116022 : (proto & 0x7);
32 : }
33 :
34 : always_inline void
35 20963 : split_nat_key (u64 key, ip4_address_t *addr, u16 *port, u32 *fib_index,
36 : nat_protocol_t *proto)
37 : {
38 20963 : if (addr)
39 : {
40 20963 : addr->as_u32 = key >> 32;
41 : }
42 20963 : if (port)
43 : {
44 20963 : *port = (key >> 16) & (u16) ~0;
45 : }
46 20963 : if (fib_index)
47 : {
48 20963 : *fib_index = key >> 3 & ((1 << 13) - 1);
49 : }
50 20963 : if (proto)
51 : {
52 20963 : *proto = key & 0x7;
53 : }
54 20963 : }
55 :
56 : always_inline void
57 116022 : init_nat_k (clib_bihash_kv_8_8_t *kv, ip4_address_t addr, u16 port,
58 : u32 fib_index, nat_protocol_t proto)
59 : {
60 116022 : kv->key = calc_nat_key (addr, port, fib_index, proto);
61 116022 : kv->value = ~0ULL;
62 116022 : }
63 :
64 : always_inline void
65 77 : init_nat_kv (clib_bihash_kv_8_8_t *kv, ip4_address_t addr, u16 port,
66 : u32 fib_index, nat_protocol_t proto, u32 thread_index,
67 : u32 session_index)
68 : {
69 77 : init_nat_k (kv, addr, port, fib_index, proto);
70 77 : kv->value = (u64) thread_index << 32 | session_index;
71 77 : }
72 :
73 : always_inline void
74 10484 : init_nat_i2o_k (clib_bihash_kv_8_8_t *kv, nat44_ei_session_t *s)
75 : {
76 10484 : return init_nat_k (kv, s->in2out.addr, s->in2out.port, s->in2out.fib_index,
77 : s->nat_proto);
78 : }
79 :
80 : always_inline void
81 10487 : init_nat_i2o_kv (clib_bihash_kv_8_8_t *kv, nat44_ei_session_t *s,
82 : u32 thread_index, u32 session_index)
83 : {
84 10487 : init_nat_k (kv, s->in2out.addr, s->in2out.port, s->in2out.fib_index,
85 : s->nat_proto);
86 10487 : kv->value = (u64) thread_index << 32 | session_index;
87 10487 : }
88 :
89 : always_inline void
90 10484 : init_nat_o2i_k (clib_bihash_kv_8_8_t *kv, nat44_ei_session_t *s)
91 : {
92 10484 : return init_nat_k (kv, s->out2in.addr, s->out2in.port, s->out2in.fib_index,
93 : s->nat_proto);
94 : }
95 :
96 : always_inline void
97 10487 : init_nat_o2i_kv (clib_bihash_kv_8_8_t *kv, nat44_ei_session_t *s,
98 : u32 thread_index, u32 session_index)
99 : {
100 10487 : init_nat_k (kv, s->out2in.addr, s->out2in.port, s->out2in.fib_index,
101 : s->nat_proto);
102 10487 : kv->value = (u64) thread_index << 32 | session_index;
103 10487 : }
104 :
105 : always_inline u32
106 20972 : nat_value_get_thread_index (clib_bihash_kv_8_8_t *value)
107 : {
108 20972 : return value->value >> 32;
109 : }
110 :
111 : always_inline u32
112 21155 : nat_value_get_session_index (clib_bihash_kv_8_8_t *value)
113 : {
114 21155 : return value->value & ~(u32) 0;
115 : }
116 :
117 : always_inline u8
118 10451 : nat44_ei_is_interface_addr (ip4_main_t *im, vlib_node_runtime_t *node,
119 : u32 sw_if_index0, u32 ip4_addr)
120 : {
121 10451 : nat44_ei_runtime_t *rt = (nat44_ei_runtime_t *) node->runtime_data;
122 : u8 ip4_addr_exists;
123 :
124 10451 : if (PREDICT_FALSE (rt->cached_sw_if_index != sw_if_index0))
125 : {
126 20 : ip_lookup_main_t *lm = &im->lookup_main;
127 : ip_interface_address_t *ia;
128 : ip4_address_t *a;
129 :
130 20 : rt->cached_sw_if_index = ~0;
131 20 : hash_free (rt->cached_presence_by_ip4_address);
132 :
133 38 : foreach_ip_interface_address (
134 : lm, ia, sw_if_index0, 1 /* honor unnumbered */, ({
135 : a = ip_interface_address_get_address (lm, ia);
136 : hash_set (rt->cached_presence_by_ip4_address, a->as_u32, 1);
137 : rt->cached_sw_if_index = sw_if_index0;
138 : }));
139 :
140 20 : if (rt->cached_sw_if_index == ~0)
141 3 : return 0;
142 : }
143 :
144 10448 : ip4_addr_exists = !!hash_get (rt->cached_presence_by_ip4_address, ip4_addr);
145 10448 : if (PREDICT_FALSE (ip4_addr_exists))
146 1 : return 1;
147 : else
148 10447 : return 0;
149 : }
150 :
151 : /** \brief Per-user LRU list maintenance */
152 : always_inline void
153 10674 : nat44_ei_session_update_lru (nat44_ei_main_t *nm, nat44_ei_session_t *s,
154 : u32 thread_index)
155 : {
156 : /* don't update too often - timeout is in magnitude of seconds anyway */
157 10674 : if (s->last_heard > s->last_lru_update + 1)
158 : {
159 10488 : clib_dlist_remove (nm->per_thread_data[thread_index].list_pool,
160 : s->per_user_index);
161 10488 : clib_dlist_addtail (nm->per_thread_data[thread_index].list_pool,
162 : s->per_user_list_head_index, s->per_user_index);
163 10488 : s->last_lru_update = s->last_heard;
164 : }
165 10674 : }
166 :
167 : always_inline void
168 10487 : nat44_ei_user_session_increment (nat44_ei_main_t *nm, nat44_ei_user_t *u,
169 : u8 is_static)
170 : {
171 10487 : if (u->nsessions + u->nstaticsessions < nm->max_translations_per_user)
172 : {
173 10487 : if (is_static)
174 49 : u->nstaticsessions++;
175 : else
176 10438 : u->nsessions++;
177 : }
178 10487 : }
179 :
180 : always_inline void
181 10484 : nat44_ei_delete_user_with_no_session (nat44_ei_main_t *nm, nat44_ei_user_t *u,
182 : u32 thread_index)
183 : {
184 : clib_bihash_kv_8_8_t kv;
185 : nat44_ei_user_key_t u_key;
186 10484 : nat44_ei_main_per_thread_data_t *tnm =
187 10484 : vec_elt_at_index (nm->per_thread_data, thread_index);
188 :
189 10484 : if (u->nstaticsessions == 0 && u->nsessions == 0)
190 : {
191 10395 : u_key.addr.as_u32 = u->addr.as_u32;
192 10395 : u_key.fib_index = u->fib_index;
193 10395 : kv.key = u_key.as_u64;
194 10395 : pool_put_index (tnm->list_pool, u->sessions_per_user_list_head_index);
195 10395 : pool_put (tnm->users, u);
196 10395 : clib_bihash_add_del_8_8 (&tnm->user_hash, &kv, 0);
197 10395 : vlib_set_simple_counter (&nm->total_users, thread_index, 0,
198 10395 : pool_elts (tnm->users));
199 : }
200 10484 : }
201 :
202 : static_always_inline u8
203 10493 : nat44_ei_maximum_sessions_exceeded (nat44_ei_main_t *nm, u32 thread_index)
204 : {
205 10493 : if (pool_elts (nm->per_thread_data[thread_index].sessions) >=
206 10493 : nm->max_translations_per_thread)
207 1 : return 1;
208 10492 : return 0;
209 : }
210 :
211 : always_inline void
212 10674 : nat44_ei_session_update_counters (nat44_ei_session_t *s, f64 now, uword bytes,
213 : u32 thread_index)
214 : {
215 10674 : s->last_heard = now;
216 10674 : s->total_pkts++;
217 10674 : s->total_bytes += bytes;
218 10674 : nat_ha_sref (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
219 10674 : s->ext_host_port, s->nat_proto, s->out2in.fib_index,
220 : s->total_pkts, s->total_bytes, thread_index,
221 : &s->ha_last_refreshed, now);
222 10674 : }
223 :
224 : static_always_inline u32
225 49 : nat_session_get_timeout (nat_timeouts_t *timeouts, nat_protocol_t proto,
226 : u8 state)
227 : {
228 49 : switch (proto)
229 : {
230 0 : case NAT_PROTOCOL_ICMP:
231 0 : return timeouts->icmp;
232 0 : case NAT_PROTOCOL_UDP:
233 0 : return timeouts->udp;
234 49 : case NAT_PROTOCOL_TCP:
235 : {
236 49 : if (state)
237 0 : return timeouts->tcp.transitory;
238 : else
239 49 : return timeouts->tcp.established;
240 : }
241 0 : default:
242 0 : return timeouts->udp;
243 : }
244 : return 0;
245 : }
246 :
247 : #endif /* __included_nat44_ei_inlines_h__ */
248 :
249 : /*
250 : * fd.io coding-style-patch-verification: ON
251 : *
252 : * Local Variables:
253 : * eval: (c-set-style "gnu")
254 : * End:
255 : */
|