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)
50 ip_address_decode2 (&in->addr, &out->ce_ip);
51 out->ce_port = clib_net_to_host_u16 (in->port);
55 cnat_endpoint_tuple_decode (const vl_api_cnat_endpoint_tuple_t * in,
56 cnat_endpoint_tuple_t * out)
58 cnat_endpoint_decode (&in->src_ep, &out->src_ep);
59 cnat_endpoint_decode (&in->dst_ep, &out->dst_ep);
63 cnat_endpoint_encode (const cnat_endpoint_t * in,
64 vl_api_cnat_endpoint_t * out)
66 ip_address_encode2 (&in->ce_ip, &out->addr);
67 out->port = clib_net_to_host_u16 (in->ce_port);
71 vl_api_cnat_translation_update_t_handler (vl_api_cnat_translation_update_t
74 vl_api_cnat_translation_update_reply_t *rmp;
76 cnat_endpoint_tuple_t *paths = NULL, *path;
77 ip_protocol_t ip_proto;
83 rv = ip_proto_decode (mp->translation.ip_proto, &ip_proto);
88 vec_validate (paths, mp->translation.n_paths - 1);
90 for (pi = 0; pi < mp->translation.n_paths; pi++)
93 cnat_endpoint_tuple_decode (&mp->translation.paths[pi], path);
95 cnat_endpoint_decode (&mp->translation.vip, &vip);
97 flags = mp->translation.flags;
98 if (!mp->translation.is_real_ip)
99 flags |= CNAT_FLAG_EXCLUSIVE;
100 id = cnat_translation_update (&vip, ip_proto, paths, flags);
106 REPLY_MACRO2 (VL_API_CNAT_TRANSLATION_UPDATE_REPLY,
108 rmp->id = htonl (id);
114 vl_api_cnat_translation_del_t_handler (vl_api_cnat_translation_del_t * mp)
116 vl_api_cnat_translation_del_reply_t *rmp;
119 rv = cnat_translation_delete (ntohl (mp->id));
121 REPLY_MACRO (VL_API_CNAT_TRANSLATION_DEL_REPLY);
124 typedef struct cnat_dump_walk_ctx_t_
126 vl_api_registration_t *rp;
128 } cnat_dump_walk_ctx_t;
131 cnat_translation_send_details (u32 cti, void *args)
133 vl_api_cnat_translation_details_t *mp;
134 cnat_dump_walk_ctx_t *ctx;
136 vl_api_cnat_endpoint_tuple_t *path;
138 cnat_translation_t *ct;
142 ct = cnat_translation_get (cti);
143 n_paths = vec_len (ct->ct_paths);
144 msg_size = sizeof (*mp) + sizeof (mp->translation.paths[0]) * n_paths;
146 mp = vl_msg_api_alloc_zero (msg_size);
147 mp->_vl_msg_id = ntohs (VL_API_CNAT_TRANSLATION_DETAILS + cnat_base_msg_id);
149 /* fill in the message */
150 mp->context = ctx->context;
151 mp->translation.n_paths = n_paths;
152 mp->translation.id = htonl (cti);
153 cnat_endpoint_encode (&ct->ct_vip, &mp->translation.vip);
154 mp->translation.ip_proto = ip_proto_encode (ct->ct_proto);
156 path = mp->translation.paths;
157 vec_foreach (trk, ct->ct_paths)
159 cnat_endpoint_encode (&trk->ct_ep[VLIB_TX], &path->dst_ep);
160 cnat_endpoint_encode (&trk->ct_ep[VLIB_RX], &path->src_ep);
164 vl_api_send_msg (ctx->rp, (u8 *) mp);
166 return (WALK_CONTINUE);
170 vl_api_cnat_translation_dump_t_handler (vl_api_cnat_translation_dump_t * mp)
172 vl_api_registration_t *rp;
174 rp = vl_api_client_index_to_registration (mp->client_index);
178 cnat_dump_walk_ctx_t ctx = {
180 .context = mp->context,
183 cnat_translation_walk (cnat_translation_send_details, &ctx);
187 ip_address2_from_46 (const ip46_address_t * nh,
188 ip_address_family_t af, ip_address_t * ip)
190 ip_addr_46 (ip) = *nh;
191 ip_addr_version (ip) = af;
195 cnat_session_send_details (const cnat_session_t * session, void *args)
197 vl_api_cnat_session_details_t *mp;
198 cnat_dump_walk_ctx_t *ctx;
203 mp = vl_msg_api_alloc_zero (sizeof (*mp));
204 mp->_vl_msg_id = ntohs (VL_API_CNAT_SESSION_DETAILS + cnat_base_msg_id);
206 /* fill in the message */
207 mp->context = ctx->context;
209 ip_address2_from_46 (&session->value.cs_ip[VLIB_TX], session->key.cs_af,
211 ep.ce_port = clib_host_to_net_u16 (session->value.cs_port[VLIB_TX]);
212 cnat_endpoint_encode (&ep, &mp->session.new);
214 ip_address2_from_46 (&session->key.cs_ip[VLIB_RX], session->key.cs_af,
216 ep.ce_port = clib_host_to_net_u16 (session->key.cs_port[VLIB_RX]);
217 cnat_endpoint_encode (&ep, &mp->session.src);
219 ip_address2_from_46 (&session->key.cs_ip[VLIB_TX], session->key.cs_af,
221 ep.ce_port = clib_host_to_net_u16 (session->key.cs_port[VLIB_TX]);
222 cnat_endpoint_encode (&ep, &mp->session.dst);
224 mp->session.ip_proto = ip_proto_encode (session->key.cs_proto);
226 vl_api_send_msg (ctx->rp, (u8 *) mp);
228 return (WALK_CONTINUE);
232 vl_api_cnat_session_dump_t_handler (vl_api_cnat_session_dump_t * mp)
234 vl_api_registration_t *rp;
236 rp = vl_api_client_index_to_registration (mp->client_index);
240 cnat_dump_walk_ctx_t ctx = {
242 .context = mp->context,
245 cnat_session_walk (cnat_session_send_details, &ctx);
249 vl_api_cnat_session_purge_t_handler (vl_api_cnat_session_purge_t * mp)
251 vl_api_cnat_session_purge_reply_t *rmp;
254 cnat_client_throttle_pool_process ();
255 rv = cnat_session_purge ();
256 rv |= cnat_translation_purge ();
258 REPLY_MACRO (VL_API_CNAT_SESSION_PURGE_REPLY);
262 vl_api_cnat_set_snat_addresses_t_handler (vl_api_cnat_set_snat_addresses_t
265 vl_api_cnat_set_snat_addresses_reply_t *rmp;
268 ip4_address_decode (mp->snat_ip4, &cnat_main.snat_ip4);
269 ip6_address_decode (mp->snat_ip6, &cnat_main.snat_ip6);
271 REPLY_MACRO (VL_API_CNAT_SET_SNAT_ADDRESSES_REPLY);
275 vl_api_cnat_add_del_snat_prefix_t_handler
276 (vl_api_cnat_add_del_snat_prefix_t * mp)
278 vl_api_cnat_add_del_snat_prefix_reply_t *rmp;
282 ip_prefix_decode2 (&mp->prefix, &pfx);
284 rv = cnat_add_snat_prefix (&pfx);
286 rv = cnat_del_snat_prefix (&pfx);
288 REPLY_MACRO (VL_API_CNAT_ADD_DEL_SNAT_PREFIX_REPLY);
291 #include <cnat/cnat.api.c>
293 static clib_error_t *
294 cnat_api_init (vlib_main_t * vm)
296 /* Ask for a correctly-sized block of API message decode slots */
297 cnat_base_msg_id = setup_message_id_table ();
302 VLIB_INIT_FUNCTION (cnat_api_init);
305 VLIB_PLUGIN_REGISTER () = {
306 .version = VPP_BUILD_VER,
307 .description = "CNat Translate",
312 * fd.io coding-style-patch-verification: ON
315 * eval: (c-set-style "gnu")