hs-test: more debug output in http3 test
[vpp.git] / src / plugins / cnat / cnat_api.c
1 /*
2  * Copyright (c) 2016 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 #include <stddef.h>
17
18 #include <vnet/vnet.h>
19 #include <vnet/plugin/plugin.h>
20 #include <cnat/cnat_translation.h>
21 #include <cnat/cnat_session.h>
22 #include <cnat/cnat_client.h>
23 #include <cnat/cnat_snat_policy.h>
24
25 #include <vnet/ip/ip_types_api.h>
26
27 #include <vpp/app/version.h>
28
29 #include <vlibapi/api.h>
30 #include <vlibmemory/api.h>
31
32 /* define message IDs */
33 #include <vnet/format_fns.h>
34 #include <cnat/cnat.api_enum.h>
35 #include <cnat/cnat.api_types.h>
36
37 /**
38  * Base message ID fot the plugin
39  */
40 static u32 cnat_base_msg_id;
41
42 #define REPLY_MSG_ID_BASE cnat_base_msg_id
43
44 #include <vlibapi/api_helper_macros.h>
45
46 static int
47 cnat_endpoint_decode (const vl_api_cnat_endpoint_t * in,
48                       cnat_endpoint_t * out)
49 {
50   int rv = 0;
51   out->ce_port = clib_net_to_host_u16 (in->port);
52   out->ce_sw_if_index = clib_net_to_host_u32 (in->sw_if_index);
53   out->ce_flags = 0;
54   if (out->ce_sw_if_index == INDEX_INVALID)
55     ip_address_decode2 (&in->addr, &out->ce_ip);
56   else
57     rv = ip_address_family_decode (in->if_af, &out->ce_ip.version);
58   return rv;
59 }
60
61 static int
62 cnat_endpoint_tuple_decode (const vl_api_cnat_endpoint_tuple_t * in,
63                             cnat_endpoint_tuple_t * out)
64 {
65   int rv = 0;
66   rv = cnat_endpoint_decode (&in->src_ep, &out->src_ep);
67   if (rv)
68     return rv;
69   rv = cnat_endpoint_decode (&in->dst_ep, &out->dst_ep);
70   out->ep_flags = in->flags;
71   return rv;
72 }
73
74 static void
75 cnat_endpoint_encode (const cnat_endpoint_t * in,
76                       vl_api_cnat_endpoint_t * out)
77 {
78   out->port = clib_net_to_host_u16 (in->ce_port);
79   out->sw_if_index = clib_net_to_host_u32 (in->ce_sw_if_index);
80   out->if_af = ip_address_family_encode (in->ce_ip.version);
81   if (in->ce_flags & CNAT_EP_FLAG_RESOLVED)
82     ip_address_encode2 (&in->ce_ip, &out->addr);
83   else
84     clib_memset (&out->addr, 0, sizeof (out->addr));
85 }
86
87 static void
88 vl_api_cnat_translation_update_t_handler (vl_api_cnat_translation_update_t
89                                           * mp)
90 {
91   vl_api_cnat_translation_update_reply_t *rmp;
92   cnat_endpoint_t vip;
93   cnat_endpoint_tuple_t *paths = NULL, *path;
94   ip_protocol_t ip_proto;
95   u32 id = ~0;
96   u8 flags;
97   int rv = 0;
98   u32 pi, n_paths;
99   cnat_lb_type_t lb_type;
100   flow_hash_config_t flow_hash_config = 0;
101
102   rv = ip_proto_decode (mp->translation.ip_proto, &ip_proto);
103
104   if (rv)
105     goto done;
106
107   n_paths = clib_net_to_host_u32 (mp->translation.n_paths);
108   vec_validate (paths, n_paths - 1);
109
110   for (pi = 0; pi < n_paths; pi++)
111     {
112       path = &paths[pi];
113       rv = cnat_endpoint_tuple_decode (&mp->translation.paths[pi], path);
114       if (rv)
115         goto done;
116     }
117
118   rv = cnat_endpoint_decode (&mp->translation.vip, &vip);
119   if (rv)
120     goto done;
121
122   flags = mp->translation.flags;
123   if (!mp->translation.is_real_ip)
124     flags |= CNAT_FLAG_EXCLUSIVE;
125
126   lb_type = (cnat_lb_type_t) mp->translation.lb_type;
127   flow_hash_config = (flow_hash_config_t) clib_net_to_host_u32 (
128     mp->translation.flow_hash_config);
129   id = cnat_translation_update (&vip, ip_proto, paths, flags, lb_type,
130                                 flow_hash_config);
131
132   vec_free (paths);
133
134 done:
135   REPLY_MACRO2 (VL_API_CNAT_TRANSLATION_UPDATE_REPLY,
136   ({
137     rmp->id = htonl (id);
138   }));
139 }
140
141 static void
142 vl_api_cnat_translation_del_t_handler (vl_api_cnat_translation_del_t * mp)
143 {
144   vl_api_cnat_translation_del_reply_t *rmp;
145   int rv;
146
147   rv = cnat_translation_delete (ntohl (mp->id));
148
149   REPLY_MACRO (VL_API_CNAT_TRANSLATION_DEL_REPLY);
150 }
151
152 typedef struct cnat_dump_walk_ctx_t_
153 {
154   vl_api_registration_t *rp;
155   u32 context;
156 } cnat_dump_walk_ctx_t;
157
158 static walk_rc_t
159 cnat_translation_send_details (u32 cti, void *args)
160 {
161   vl_api_cnat_translation_details_t *mp;
162   cnat_dump_walk_ctx_t *ctx;
163   cnat_ep_trk_t *trk;
164   vl_api_cnat_endpoint_tuple_t *path;
165   size_t msg_size;
166   cnat_translation_t *ct;
167   u32 n_paths;
168
169   ctx = args;
170   ct = cnat_translation_get (cti);
171   n_paths = vec_len (ct->ct_paths);
172   msg_size = sizeof (*mp) + sizeof (mp->translation.paths[0]) * n_paths;
173
174   mp = vl_msg_api_alloc_zero (msg_size);
175   mp->_vl_msg_id = ntohs (VL_API_CNAT_TRANSLATION_DETAILS + cnat_base_msg_id);
176
177   /* fill in the message */
178   mp->context = ctx->context;
179   mp->translation.n_paths = clib_host_to_net_u32 (n_paths);
180   mp->translation.id = clib_host_to_net_u32 (cti);
181   cnat_endpoint_encode (&ct->ct_vip, &mp->translation.vip);
182   mp->translation.ip_proto = ip_proto_encode (ct->ct_proto);
183   mp->translation.lb_type = (vl_api_cnat_lb_type_t) ct->lb_type;
184
185   path = mp->translation.paths;
186   vec_foreach (trk, ct->ct_paths)
187   {
188     cnat_endpoint_encode (&trk->ct_ep[VLIB_TX], &path->dst_ep);
189     cnat_endpoint_encode (&trk->ct_ep[VLIB_RX], &path->src_ep);
190     path->flags = trk->ct_flags;
191     path++;
192   }
193
194   vl_api_send_msg (ctx->rp, (u8 *) mp);
195
196   return (WALK_CONTINUE);
197 }
198
199 static void
200 vl_api_cnat_translation_dump_t_handler (vl_api_cnat_translation_dump_t * mp)
201 {
202   vl_api_registration_t *rp;
203
204   rp = vl_api_client_index_to_registration (mp->client_index);
205   if (rp == 0)
206     return;
207
208   cnat_dump_walk_ctx_t ctx = {
209     .rp = rp,
210     .context = mp->context,
211   };
212
213   cnat_translation_walk (cnat_translation_send_details, &ctx);
214 }
215
216 static void
217 ip_address2_from_46 (const ip46_address_t * nh,
218                      ip_address_family_t af, ip_address_t * ip)
219 {
220   ip_addr_46 (ip) = *nh;
221   ip_addr_version (ip) = af;
222 }
223
224 static walk_rc_t
225 cnat_session_send_details (const cnat_session_t * session, void *args)
226 {
227   vl_api_cnat_session_details_t *mp;
228   cnat_dump_walk_ctx_t *ctx;
229   cnat_endpoint_t ep;
230
231   ctx = args;
232
233   mp = vl_msg_api_alloc_zero (sizeof (*mp));
234   mp->_vl_msg_id = ntohs (VL_API_CNAT_SESSION_DETAILS + cnat_base_msg_id);
235
236   /* fill in the message */
237   mp->context = ctx->context;
238
239   ep.ce_sw_if_index = INDEX_INVALID;
240   ep.ce_flags = CNAT_EP_FLAG_RESOLVED;
241   ip_address2_from_46 (&session->value.cs_ip[VLIB_TX], session->key.cs_af,
242                        &ep.ce_ip);
243   ep.ce_port = clib_host_to_net_u16 (session->value.cs_port[VLIB_TX]);
244   cnat_endpoint_encode (&ep, &mp->session.new);
245
246   ip_address2_from_46 (&session->key.cs_ip[VLIB_RX], session->key.cs_af,
247                        &ep.ce_ip);
248   ep.ce_port = clib_host_to_net_u16 (session->key.cs_port[VLIB_RX]);
249   cnat_endpoint_encode (&ep, &mp->session.src);
250
251   ip_address2_from_46 (&session->key.cs_ip[VLIB_TX], session->key.cs_af,
252                        &ep.ce_ip);
253   ep.ce_port = clib_host_to_net_u16 (session->key.cs_port[VLIB_TX]);
254   cnat_endpoint_encode (&ep, &mp->session.dst);
255
256   mp->session.ip_proto = ip_proto_encode (session->key.cs_proto);
257   mp->session.location = session->key.cs_loc;
258
259   vl_api_send_msg (ctx->rp, (u8 *) mp);
260
261   return (WALK_CONTINUE);
262 }
263
264 static void
265 vl_api_cnat_session_dump_t_handler (vl_api_cnat_session_dump_t * mp)
266 {
267   vl_api_registration_t *rp;
268
269   rp = vl_api_client_index_to_registration (mp->client_index);
270   if (rp == 0)
271     return;
272
273   cnat_dump_walk_ctx_t ctx = {
274     .rp = rp,
275     .context = mp->context,
276   };
277
278   cnat_session_walk (cnat_session_send_details, &ctx);
279 }
280
281 static void
282 vl_api_cnat_session_purge_t_handler (vl_api_cnat_session_purge_t * mp)
283 {
284   vl_api_cnat_session_purge_reply_t *rmp;
285   int rv;
286
287   cnat_client_throttle_pool_process ();
288   rv = cnat_session_purge ();
289   rv |= cnat_translation_purge ();
290
291   REPLY_MACRO (VL_API_CNAT_SESSION_PURGE_REPLY);
292 }
293
294 static void
295 vl_api_cnat_get_snat_addresses_t_handler (vl_api_cnat_get_snat_addresses_t
296                                           * mp)
297 {
298   vl_api_cnat_get_snat_addresses_reply_t *rmp;
299   cnat_snat_policy_main_t *cpm = &cnat_snat_policy_main;
300   int rv = 0;
301
302   REPLY_MACRO2 (
303     VL_API_CNAT_GET_SNAT_ADDRESSES_REPLY, ({
304       ip6_address_encode (&ip_addr_v6 (&cpm->snat_ip6.ce_ip), rmp->snat_ip6);
305       ip4_address_encode (&ip_addr_v4 (&cpm->snat_ip4.ce_ip), rmp->snat_ip4);
306       rmp->sw_if_index = clib_host_to_net_u32 (cpm->snat_ip6.ce_sw_if_index);
307     }));
308 }
309
310 static void
311 vl_api_cnat_set_snat_addresses_t_handler (vl_api_cnat_set_snat_addresses_t
312                                           * mp)
313 {
314   vl_api_cnat_set_snat_addresses_reply_t *rmp;
315   u32 sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
316   ip4_address_t ip4;
317   ip6_address_t ip6;
318   int rv = 0;
319
320   ip4_address_decode (mp->snat_ip4, &ip4);
321   ip6_address_decode (mp->snat_ip6, &ip6);
322
323   cnat_set_snat (&ip4, &ip6, sw_if_index);
324
325   REPLY_MACRO (VL_API_CNAT_SET_SNAT_ADDRESSES_REPLY);
326 }
327
328 static void
329 vl_api_cnat_set_snat_policy_t_handler (vl_api_cnat_set_snat_policy_t *mp)
330 {
331   vl_api_cnat_set_snat_policy_reply_t *rmp;
332   int rv = 0;
333   cnat_snat_policy_type_t policy = (cnat_snat_policy_type_t) mp->policy;
334
335   rv = cnat_set_snat_policy (policy);
336
337   REPLY_MACRO (VL_API_CNAT_SET_SNAT_POLICY_REPLY);
338 }
339
340 static void
341 vl_api_cnat_snat_policy_add_del_exclude_pfx_t_handler (
342   vl_api_cnat_snat_policy_add_del_exclude_pfx_t *mp)
343 {
344   vl_api_cnat_snat_policy_add_del_exclude_pfx_reply_t *rmp;
345   ip_prefix_t pfx;
346   int rv;
347
348   ip_prefix_decode2 (&mp->prefix, &pfx);
349   if (mp->is_add)
350     rv = cnat_snat_policy_add_pfx (&pfx);
351   else
352     rv = cnat_snat_policy_del_pfx (&pfx);
353
354   REPLY_MACRO (VL_API_CNAT_SNAT_POLICY_ADD_DEL_EXCLUDE_PFX_REPLY);
355 }
356
357 static void
358 vl_api_cnat_snat_policy_add_del_if_t_handler (
359   vl_api_cnat_snat_policy_add_del_if_t *mp)
360 {
361   vl_api_cnat_snat_policy_add_del_if_reply_t *rmp;
362   u32 sw_if_index = ntohl (mp->sw_if_index);
363   int rv = 0;
364
365   VALIDATE_SW_IF_INDEX (mp);
366
367   cnat_snat_interface_map_type_t table =
368     (cnat_snat_interface_map_type_t) mp->table;
369
370   rv = cnat_snat_policy_add_del_if (sw_if_index, mp->is_add, table);
371
372   BAD_SW_IF_INDEX_LABEL;
373
374   REPLY_MACRO (VL_API_CNAT_SNAT_POLICY_ADD_DEL_IF_REPLY);
375 }
376
377 #include <cnat/cnat.api.c>
378
379 static clib_error_t *
380 cnat_api_init (vlib_main_t * vm)
381 {
382   /* Ask for a correctly-sized block of API message decode slots */
383   cnat_base_msg_id = setup_message_id_table ();
384
385   return 0;
386 }
387
388 VLIB_INIT_FUNCTION (cnat_api_init);
389
390 VLIB_PLUGIN_REGISTER () = {
391     .version = VPP_BUILD_VER,
392     .description = "CNat Translate",
393 };
394
395 /*
396  * fd.io coding-style-patch-verification: ON
397  *
398  * Local Variables:
399  * eval: (c-set-style "gnu")
400  * End:
401  */