misc: remove GNU Indent directives
[vpp.git] / src / plugins / nat / dslite / dslite.c
1 /*
2  * Copyright (c) 2017 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 #include <vnet/plugin/plugin.h>
16 #include <nat/dslite/dslite.h>
17 #include <nat/dslite/dslite_dpo.h>
18 #include <vnet/fib/fib_table.h>
19 #include <vpp/app/version.h>
20
21 dslite_main_t dslite_main;
22 fib_source_t nat_fib_src_hi;
23
24 clib_error_t *dslite_api_hookup (vlib_main_t * vm);
25
26 void
27 add_del_dslite_pool_addr_cb (ip4_address_t addr, u8 is_add, void *opaque);
28
29 static clib_error_t *
30 dslite_init (vlib_main_t * vm)
31 {
32   dslite_main_t *dm = &dslite_main;
33   vlib_thread_registration_t *tr;
34   vlib_thread_main_t *tm = vlib_get_thread_main ();
35   uword *p;
36   vlib_node_t *node;
37
38   node = vlib_get_node_by_name (vm, (u8 *) "dslite-in2out");
39   dm->dslite_in2out_node_index = node->index;
40
41   node = vlib_get_node_by_name (vm, (u8 *) "dslite-in2out-slowpath");
42   dm->dslite_in2out_slowpath_node_index = node->index;
43
44   node = vlib_get_node_by_name (vm, (u8 *) "dslite-out2in");
45   dm->dslite_out2in_node_index = node->index;
46
47   dm->first_worker_index = 0;
48   dm->num_workers = 0;
49
50   // init nat address pool
51   dm->pool.add_del_pool_addr_cb = add_del_dslite_pool_addr_cb;
52   dm->pool.alloc_addr_and_port_cb = nat_alloc_ip4_addr_and_port_cb_default;
53
54   p = hash_get_mem (tm->thread_registrations_by_name, "workers");
55   if (p)
56     {
57       tr = (vlib_thread_registration_t *) p[0];
58       if (tr)
59         {
60           dm->num_workers = tr->count;
61           dm->first_worker_index = tr->first_index;
62         }
63     }
64
65   if (dm->num_workers)
66     dm->port_per_thread = (0xffff - 1024) / dm->num_workers;
67   else
68     dm->port_per_thread = 0xffff - 1024;
69
70   vec_validate (dm->per_thread_data, tm->n_vlib_mains - 1);
71
72   dm->is_ce = 0;
73   dm->is_enabled = 0;
74
75   /* Init counters */
76   dm->total_b4s.name = "total-b4s";
77   dm->total_b4s.stat_segment_name = "/dslite/total-b4s";
78   vlib_validate_simple_counter (&dm->total_b4s, 0);
79   vlib_zero_simple_counter (&dm->total_b4s, 0);
80   dm->total_sessions.name = "total-sessions";
81   dm->total_sessions.stat_segment_name = "/dslite/total-sessions";
82   vlib_validate_simple_counter (&dm->total_sessions, 0);
83   vlib_zero_simple_counter (&dm->total_sessions, 0);
84
85   dslite_dpo_module_init ();
86
87   nat_fib_src_hi = fib_source_allocate ("dslite-hi",
88                                         FIB_SOURCE_PRIORITY_HI,
89                                         FIB_SOURCE_BH_SIMPLE);
90
91   return dslite_api_hookup (vm);
92 }
93
94 static void
95 dslite_init_datastructures (void)
96 {
97   dslite_main_t *dm = &dslite_main;
98   dslite_per_thread_data_t *td;
99   u32 translation_buckets = 1024;
100   u32 translation_memory_size = 128 << 20;
101   u32 b4_buckets = 128;
102   u32 b4_memory_size = 64 << 20;
103
104   vec_foreach (td, dm->per_thread_data)
105     {
106       clib_bihash_init_24_8 (&td->in2out, "dslite in2out", translation_buckets,
107                              translation_memory_size);
108
109       clib_bihash_init_8_8 (&td->out2in, "dslite out2in", translation_buckets,
110                             translation_memory_size);
111
112       clib_bihash_init_16_8 (&td->b4_hash, "dslite b4s", b4_buckets, b4_memory_size);
113     }
114   dm->is_enabled = 1;
115 }
116
117 void
118 dslite_set_ce (dslite_main_t * dm, u8 set)
119 {
120   dm->is_ce = (set != 0);
121 }
122
123 static clib_error_t *
124 dslite_config (vlib_main_t * vm, unformat_input_t * input)
125 {
126   dslite_main_t *dm = &dslite_main;
127
128   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
129     {
130       if (unformat (input, "ce"))
131         dslite_set_ce (dm, 1);
132     }
133   return 0;
134 }
135
136 VLIB_CONFIG_FUNCTION (dslite_config, "dslite");
137
138 int
139 dslite_set_aftr_ip6_addr (dslite_main_t * dm, ip6_address_t * addr)
140 {
141   dpo_id_t dpo = DPO_INVALID;
142
143   if (!dm->is_enabled)
144     dslite_init_datastructures ();
145
146   if (dm->is_ce)
147     {
148       dslite_ce_dpo_create (DPO_PROTO_IP4, 0, &dpo);
149       fib_prefix_t pfx = {
150         .fp_proto = FIB_PROTOCOL_IP4,
151         .fp_len = 0,
152         .fp_addr.ip4.as_u32 = 0,
153       };
154       fib_table_entry_special_dpo_add (0, &pfx, nat_fib_src_hi,
155                                        FIB_ENTRY_FLAG_EXCLUSIVE, &dpo);
156     }
157   else
158     {
159       dslite_dpo_create (DPO_PROTO_IP6, 0, &dpo);
160       fib_prefix_t pfx = {
161         .fp_proto = FIB_PROTOCOL_IP6,
162         .fp_len = 128,
163         .fp_addr.ip6.as_u64[0] = addr->as_u64[0],
164         .fp_addr.ip6.as_u64[1] = addr->as_u64[1],
165       };
166       fib_table_entry_special_dpo_add (0, &pfx, nat_fib_src_hi,
167                                        FIB_ENTRY_FLAG_EXCLUSIVE, &dpo);
168     }
169
170   dpo_reset (&dpo);
171
172   dm->aftr_ip6_addr.as_u64[0] = addr->as_u64[0];
173   dm->aftr_ip6_addr.as_u64[1] = addr->as_u64[1];
174   return 0;
175 }
176
177 int
178 dslite_set_aftr_ip4_addr (dslite_main_t * dm, ip4_address_t * addr)
179 {
180   dm->aftr_ip4_addr.as_u32 = addr->as_u32;
181   return 0;
182 }
183
184 int
185 dslite_set_b4_ip6_addr (dslite_main_t * dm, ip6_address_t * addr)
186 {
187   if (!dm->is_enabled)
188     dslite_init_datastructures ();
189
190   if (dm->is_ce)
191     {
192       dpo_id_t dpo = DPO_INVALID;
193
194       dslite_ce_dpo_create (DPO_PROTO_IP6, 0, &dpo);
195       fib_prefix_t pfx = {
196         .fp_proto = FIB_PROTOCOL_IP6,
197         .fp_len = 128,
198         .fp_addr.ip6.as_u64[0] = addr->as_u64[0],
199         .fp_addr.ip6.as_u64[1] = addr->as_u64[1],
200       };
201       fib_table_entry_special_dpo_add (0, &pfx, nat_fib_src_hi,
202                                        FIB_ENTRY_FLAG_EXCLUSIVE, &dpo);
203
204       dpo_reset (&dpo);
205
206       dm->b4_ip6_addr.as_u64[0] = addr->as_u64[0];
207       dm->b4_ip6_addr.as_u64[1] = addr->as_u64[1];
208     }
209   else
210     {
211       return VNET_API_ERROR_FEATURE_DISABLED;
212     }
213
214   return 0;
215 }
216
217 int
218 dslite_set_b4_ip4_addr (dslite_main_t * dm, ip4_address_t * addr)
219 {
220   if (dm->is_ce)
221     {
222       dm->b4_ip4_addr.as_u32 = addr->as_u32;
223     }
224   else
225     {
226       return VNET_API_ERROR_FEATURE_DISABLED;
227     }
228
229   return 0;
230 }
231
232 void
233 add_del_dslite_pool_addr_cb (ip4_address_t addr, u8 is_add, void *opaque)
234 {
235   dpo_id_t dpo_v4 = DPO_INVALID;
236   fib_prefix_t pfx = {
237     .fp_proto = FIB_PROTOCOL_IP4,
238     .fp_len = 32,
239     .fp_addr.ip4.as_u32 = addr.as_u32,
240   };
241
242   if (is_add)
243     {
244       dslite_dpo_create (DPO_PROTO_IP4, 0, &dpo_v4);
245       fib_table_entry_special_dpo_add (0, &pfx, nat_fib_src_hi,
246                                        FIB_ENTRY_FLAG_EXCLUSIVE, &dpo_v4);
247       dpo_reset (&dpo_v4);
248     }
249   else
250     {
251       fib_table_entry_special_remove (0, &pfx, nat_fib_src_hi);
252     }
253 }
254
255 u8 *
256 format_dslite_trace (u8 * s, va_list * args)
257 {
258   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
259   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
260   dslite_trace_t *t = va_arg (*args, dslite_trace_t *);
261
262   s =
263     format (s, "next index %d, session %d", t->next_index, t->session_index);
264
265   return s;
266 }
267
268 u8 *
269 format_dslite_ce_trace (u8 * s, va_list * args)
270 {
271   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
272   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
273   dslite_ce_trace_t *t = va_arg (*args, dslite_ce_trace_t *);
274
275   s = format (s, "next index %d", t->next_index);
276
277   return s;
278 }
279
280 VLIB_INIT_FUNCTION (dslite_init);
281
282 VLIB_PLUGIN_REGISTER () =
283 {
284   .version = VPP_BUILD_VER,
285   .description = "Dual-Stack Lite",
286 };
287
288 /*
289  * fd.io coding-style-patch-verification: ON
290  *
291  * Local Variables:
292  * eval: (c-set-style "gnu")
293  * End:
294  */