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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
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.h>
25 #include <vnet/ip/ip_types_api.h>
27 #include <vpp/app/version.h>
29 #include <vlibapi/api.h>
30 #include <vlibmemory/api.h>
32 /* define message IDs */
33 #include <vnet/format_fns.h>
34 #include <cnat/cnat.api_enum.h>
35 #include <cnat/cnat.api_types.h>
38 * Base message ID fot the plugin
40 static u32 cnat_base_msg_id;
42 #define REPLY_MSG_ID_BASE cnat_base_msg_id
44 #include <vlibapi/api_helper_macros.h>
47 cnat_endpoint_decode (const vl_api_cnat_endpoint_t * in,
48 cnat_endpoint_t * out)
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);
54 if (out->ce_sw_if_index == INDEX_INVALID)
55 ip_address_decode2 (&in->addr, &out->ce_ip);
57 rv = ip_address_family_decode (in->if_af, &out->ce_ip.version);
62 cnat_endpoint_tuple_decode (const vl_api_cnat_endpoint_tuple_t * in,
63 cnat_endpoint_tuple_t * out)
66 rv = cnat_endpoint_decode (&in->src_ep, &out->src_ep);
69 rv = cnat_endpoint_decode (&in->dst_ep, &out->dst_ep);
70 out->ep_flags = in->flags;
75 cnat_endpoint_encode (const cnat_endpoint_t * in,
76 vl_api_cnat_endpoint_t * out)
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);
84 clib_memset ((void *) &in->ce_ip, 0, sizeof (in->ce_ip));
88 vl_api_cnat_translation_update_t_handler (vl_api_cnat_translation_update_t
91 vl_api_cnat_translation_update_reply_t *rmp;
93 cnat_endpoint_tuple_t *paths = NULL, *path;
94 ip_protocol_t ip_proto;
99 cnat_lb_type_t lb_type;
101 rv = ip_proto_decode (mp->translation.ip_proto, &ip_proto);
106 n_paths = clib_net_to_host_u32 (mp->translation.n_paths);
107 vec_validate (paths, n_paths - 1);
109 for (pi = 0; pi < n_paths; pi++)
112 rv = cnat_endpoint_tuple_decode (&mp->translation.paths[pi], path);
117 rv = cnat_endpoint_decode (&mp->translation.vip, &vip);
121 flags = mp->translation.flags;
122 if (!mp->translation.is_real_ip)
123 flags |= CNAT_FLAG_EXCLUSIVE;
125 lb_type = (cnat_lb_type_t) mp->translation.lb_type;
126 id = cnat_translation_update (&vip, ip_proto, paths, flags, lb_type);
131 REPLY_MACRO2 (VL_API_CNAT_TRANSLATION_UPDATE_REPLY,
133 rmp->id = htonl (id);
138 vl_api_cnat_translation_del_t_handler (vl_api_cnat_translation_del_t * mp)
140 vl_api_cnat_translation_del_reply_t *rmp;
143 rv = cnat_translation_delete (ntohl (mp->id));
145 REPLY_MACRO (VL_API_CNAT_TRANSLATION_DEL_REPLY);
148 typedef struct cnat_dump_walk_ctx_t_
150 vl_api_registration_t *rp;
152 } cnat_dump_walk_ctx_t;
155 cnat_translation_send_details (u32 cti, void *args)
157 vl_api_cnat_translation_details_t *mp;
158 cnat_dump_walk_ctx_t *ctx;
160 vl_api_cnat_endpoint_tuple_t *path;
162 cnat_translation_t *ct;
166 ct = cnat_translation_get (cti);
167 n_paths = vec_len (ct->ct_paths);
168 msg_size = sizeof (*mp) + sizeof (mp->translation.paths[0]) * n_paths;
170 mp = vl_msg_api_alloc_zero (msg_size);
171 mp->_vl_msg_id = ntohs (VL_API_CNAT_TRANSLATION_DETAILS + cnat_base_msg_id);
173 /* fill in the message */
174 mp->context = ctx->context;
175 mp->translation.n_paths = clib_host_to_net_u32 (n_paths);
176 mp->translation.id = clib_host_to_net_u32 (cti);
177 cnat_endpoint_encode (&ct->ct_vip, &mp->translation.vip);
178 mp->translation.ip_proto = ip_proto_encode (ct->ct_proto);
179 mp->translation.lb_type = (vl_api_cnat_lb_type_t) ct->lb_type;
181 path = mp->translation.paths;
182 vec_foreach (trk, ct->ct_paths)
184 cnat_endpoint_encode (&trk->ct_ep[VLIB_TX], &path->dst_ep);
185 cnat_endpoint_encode (&trk->ct_ep[VLIB_RX], &path->src_ep);
186 path->flags = trk->ct_flags;
190 vl_api_send_msg (ctx->rp, (u8 *) mp);
192 return (WALK_CONTINUE);
196 vl_api_cnat_translation_dump_t_handler (vl_api_cnat_translation_dump_t * mp)
198 vl_api_registration_t *rp;
200 rp = vl_api_client_index_to_registration (mp->client_index);
204 cnat_dump_walk_ctx_t ctx = {
206 .context = mp->context,
209 cnat_translation_walk (cnat_translation_send_details, &ctx);
213 ip_address2_from_46 (const ip46_address_t * nh,
214 ip_address_family_t af, ip_address_t * ip)
216 ip_addr_46 (ip) = *nh;
217 ip_addr_version (ip) = af;
221 cnat_session_send_details (const cnat_session_t * session, void *args)
223 vl_api_cnat_session_details_t *mp;
224 cnat_dump_walk_ctx_t *ctx;
229 mp = vl_msg_api_alloc_zero (sizeof (*mp));
230 mp->_vl_msg_id = ntohs (VL_API_CNAT_SESSION_DETAILS + cnat_base_msg_id);
232 /* fill in the message */
233 mp->context = ctx->context;
235 ep.ce_sw_if_index = INDEX_INVALID;
236 ep.ce_flags = CNAT_EP_FLAG_RESOLVED;
237 ip_address2_from_46 (&session->value.cs_ip[VLIB_TX], session->key.cs_af,
239 ep.ce_port = clib_host_to_net_u16 (session->value.cs_port[VLIB_TX]);
240 cnat_endpoint_encode (&ep, &mp->session.new);
242 ip_address2_from_46 (&session->key.cs_ip[VLIB_RX], session->key.cs_af,
244 ep.ce_port = clib_host_to_net_u16 (session->key.cs_port[VLIB_RX]);
245 cnat_endpoint_encode (&ep, &mp->session.src);
247 ip_address2_from_46 (&session->key.cs_ip[VLIB_TX], session->key.cs_af,
249 ep.ce_port = clib_host_to_net_u16 (session->key.cs_port[VLIB_TX]);
250 cnat_endpoint_encode (&ep, &mp->session.dst);
252 mp->session.ip_proto = ip_proto_encode (session->key.cs_proto);
253 mp->session.location = session->key.cs_loc;
255 vl_api_send_msg (ctx->rp, (u8 *) mp);
257 return (WALK_CONTINUE);
261 vl_api_cnat_session_dump_t_handler (vl_api_cnat_session_dump_t * mp)
263 vl_api_registration_t *rp;
265 rp = vl_api_client_index_to_registration (mp->client_index);
269 cnat_dump_walk_ctx_t ctx = {
271 .context = mp->context,
274 cnat_session_walk (cnat_session_send_details, &ctx);
278 vl_api_cnat_session_purge_t_handler (vl_api_cnat_session_purge_t * mp)
280 vl_api_cnat_session_purge_reply_t *rmp;
283 cnat_client_throttle_pool_process ();
284 rv = cnat_session_purge ();
285 rv |= cnat_translation_purge ();
287 REPLY_MACRO (VL_API_CNAT_SESSION_PURGE_REPLY);
291 vl_api_cnat_get_snat_addresses_t_handler (vl_api_cnat_get_snat_addresses_t
294 vl_api_cnat_get_snat_addresses_reply_t *rmp;
297 REPLY_MACRO2 (VL_API_CNAT_GET_SNAT_ADDRESSES_REPLY,
299 ip6_address_encode (&ip_addr_v6(&cnat_main.snat_ip6.ce_ip), rmp->snat_ip6);
300 ip4_address_encode (&ip_addr_v4(&cnat_main.snat_ip4.ce_ip), rmp->snat_ip4);
301 rmp->sw_if_index = clib_host_to_net_u32 (cnat_main.snat_ip6.ce_sw_if_index);
306 vl_api_cnat_set_snat_addresses_t_handler (vl_api_cnat_set_snat_addresses_t
309 vl_api_cnat_set_snat_addresses_reply_t *rmp;
310 u32 sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
315 ip4_address_decode (mp->snat_ip4, &ip4);
316 ip6_address_decode (mp->snat_ip6, &ip6);
318 cnat_set_snat (&ip4, &ip6, sw_if_index);
320 REPLY_MACRO (VL_API_CNAT_SET_SNAT_ADDRESSES_REPLY);
324 vl_api_cnat_add_del_snat_prefix_t_handler
325 (vl_api_cnat_add_del_snat_prefix_t * mp)
327 vl_api_cnat_add_del_snat_prefix_reply_t *rmp;
331 ip_prefix_decode2 (&mp->prefix, &pfx);
333 rv = cnat_add_snat_prefix (&pfx);
335 rv = cnat_del_snat_prefix (&pfx);
337 REPLY_MACRO (VL_API_CNAT_ADD_DEL_SNAT_PREFIX_REPLY);
341 vl_api_cnat_set_snat_policy_t_handler (vl_api_cnat_set_snat_policy_t *mp)
343 vl_api_cnat_set_snat_policy_reply_t *rmp;
345 vl_api_cnat_snat_policies_t policy = clib_net_to_host_u32 (mp->policy);
348 case CNAT_SNAT_POLICY_NONE:
349 cnat_set_snat_policy (NULL);
355 REPLY_MACRO (VL_API_CNAT_SET_SNAT_POLICY_REPLY);
357 #include <cnat/cnat.api.c>
359 static clib_error_t *
360 cnat_api_init (vlib_main_t * vm)
362 /* Ask for a correctly-sized block of API message decode slots */
363 cnat_base_msg_id = setup_message_id_table ();
368 VLIB_INIT_FUNCTION (cnat_api_init);
370 VLIB_PLUGIN_REGISTER () = {
371 .version = VPP_BUILD_VER,
372 .description = "CNat Translate",
376 * fd.io coding-style-patch-verification: ON
379 * eval: (c-set-style "gnu")