LCOV - code coverage report
Current view: top level - plugins/cnat - cnat_api.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 124 155 80.0 %
Date: 2023-10-26 01:39:38 Functions: 17 19 89.5 %

          Line data    Source code
       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          74 : cnat_endpoint_decode (const vl_api_cnat_endpoint_t * in,
      48             :                       cnat_endpoint_t * out)
      49             : {
      50          74 :   int rv = 0;
      51          74 :   out->ce_port = clib_net_to_host_u16 (in->port);
      52          74 :   out->ce_sw_if_index = clib_net_to_host_u32 (in->sw_if_index);
      53          74 :   out->ce_flags = 0;
      54          74 :   if (out->ce_sw_if_index == INDEX_INVALID)
      55          64 :     ip_address_decode2 (&in->addr, &out->ce_ip);
      56             :   else
      57          10 :     rv = ip_address_family_decode (in->if_af, &out->ce_ip.version);
      58          74 :   return rv;
      59             : }
      60             : 
      61             : static int
      62          26 : cnat_endpoint_tuple_decode (const vl_api_cnat_endpoint_tuple_t * in,
      63             :                             cnat_endpoint_tuple_t * out)
      64             : {
      65          26 :   int rv = 0;
      66          26 :   rv = cnat_endpoint_decode (&in->src_ep, &out->src_ep);
      67          26 :   if (rv)
      68           0 :     return rv;
      69          26 :   rv = cnat_endpoint_decode (&in->dst_ep, &out->dst_ep);
      70          26 :   out->ep_flags = in->flags;
      71          26 :   return rv;
      72             : }
      73             : 
      74             : static void
      75          20 : cnat_endpoint_encode (const cnat_endpoint_t * in,
      76             :                       vl_api_cnat_endpoint_t * out)
      77             : {
      78          20 :   out->port = clib_net_to_host_u16 (in->ce_port);
      79          20 :   out->sw_if_index = clib_net_to_host_u32 (in->ce_sw_if_index);
      80          20 :   out->if_af = ip_address_family_encode (in->ce_ip.version);
      81          20 :   if (in->ce_flags & CNAT_EP_FLAG_RESOLVED)
      82          20 :     ip_address_encode2 (&in->ce_ip, &out->addr);
      83             :   else
      84           0 :     clib_memset (&out->addr, 0, sizeof (out->addr));
      85          20 : }
      86             : 
      87             : static void
      88          22 : 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          22 :   cnat_endpoint_tuple_t *paths = NULL, *path;
      94             :   ip_protocol_t ip_proto;
      95          22 :   u32 id = ~0;
      96             :   u8 flags;
      97          22 :   int rv = 0;
      98             :   u32 pi, n_paths;
      99             :   cnat_lb_type_t lb_type;
     100          22 :   flow_hash_config_t flow_hash_config = 0;
     101             : 
     102          22 :   rv = ip_proto_decode (mp->translation.ip_proto, &ip_proto);
     103             : 
     104          22 :   if (rv)
     105           0 :     goto done;
     106             : 
     107          22 :   n_paths = clib_net_to_host_u32 (mp->translation.n_paths);
     108          22 :   vec_validate (paths, n_paths - 1);
     109             : 
     110          48 :   for (pi = 0; pi < n_paths; pi++)
     111             :     {
     112          26 :       path = &paths[pi];
     113          26 :       rv = cnat_endpoint_tuple_decode (&mp->translation.paths[pi], path);
     114          26 :       if (rv)
     115           0 :         goto done;
     116             :     }
     117             : 
     118          22 :   rv = cnat_endpoint_decode (&mp->translation.vip, &vip);
     119          22 :   if (rv)
     120           0 :     goto done;
     121             : 
     122          22 :   flags = mp->translation.flags;
     123          22 :   if (!mp->translation.is_real_ip)
     124          22 :     flags |= CNAT_FLAG_EXCLUSIVE;
     125             : 
     126          22 :   lb_type = (cnat_lb_type_t) mp->translation.lb_type;
     127          22 :   flow_hash_config = (flow_hash_config_t) clib_net_to_host_u32 (
     128          22 :     mp->translation.flow_hash_config);
     129          22 :   id = cnat_translation_update (&vip, ip_proto, paths, flags, lb_type,
     130             :                                 flow_hash_config);
     131             : 
     132          22 :   vec_free (paths);
     133             : 
     134          22 : done:
     135          22 :   REPLY_MACRO2 (VL_API_CNAT_TRANSLATION_UPDATE_REPLY,
     136             :   ({
     137             :     rmp->id = htonl (id);
     138             :   }));
     139             : }
     140             : 
     141             : static void
     142          14 : 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          14 :   rv = cnat_translation_delete (ntohl (mp->id));
     148             : 
     149          14 :   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           4 : 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           4 :   ctx = args;
     170           4 :   ct = cnat_translation_get (cti);
     171           4 :   n_paths = vec_len (ct->ct_paths);
     172           4 :   msg_size = sizeof (*mp) + sizeof (mp->translation.paths[0]) * n_paths;
     173             : 
     174           4 :   mp = vl_msg_api_alloc_zero (msg_size);
     175           4 :   mp->_vl_msg_id = ntohs (VL_API_CNAT_TRANSLATION_DETAILS + cnat_base_msg_id);
     176             : 
     177             :   /* fill in the message */
     178           4 :   mp->context = ctx->context;
     179           4 :   mp->translation.n_paths = clib_host_to_net_u32 (n_paths);
     180           4 :   mp->translation.id = clib_host_to_net_u32 (cti);
     181           4 :   cnat_endpoint_encode (&ct->ct_vip, &mp->translation.vip);
     182           4 :   mp->translation.ip_proto = ip_proto_encode (ct->ct_proto);
     183           4 :   mp->translation.lb_type = (vl_api_cnat_lb_type_t) ct->lb_type;
     184             : 
     185           4 :   path = mp->translation.paths;
     186          12 :   vec_foreach (trk, ct->ct_paths)
     187             :   {
     188           8 :     cnat_endpoint_encode (&trk->ct_ep[VLIB_TX], &path->dst_ep);
     189           8 :     cnat_endpoint_encode (&trk->ct_ep[VLIB_RX], &path->src_ep);
     190           8 :     path->flags = trk->ct_flags;
     191           8 :     path++;
     192             :   }
     193             : 
     194           4 :   vl_api_send_msg (ctx->rp, (u8 *) mp);
     195             : 
     196           4 :   return (WALK_CONTINUE);
     197             : }
     198             : 
     199             : static void
     200          20 : vl_api_cnat_translation_dump_t_handler (vl_api_cnat_translation_dump_t * mp)
     201             : {
     202             :   vl_api_registration_t *rp;
     203             : 
     204          20 :   rp = vl_api_client_index_to_registration (mp->client_index);
     205          20 :   if (rp == 0)
     206           0 :     return;
     207             : 
     208          20 :   cnat_dump_walk_ctx_t ctx = {
     209             :     .rp = rp,
     210          20 :     .context = mp->context,
     211             :   };
     212             : 
     213          20 :   cnat_translation_walk (cnat_translation_send_details, &ctx);
     214             : }
     215             : 
     216             : static void
     217           0 : ip_address2_from_46 (const ip46_address_t * nh,
     218             :                      ip_address_family_t af, ip_address_t * ip)
     219             : {
     220           0 :   ip_addr_46 (ip) = *nh;
     221           0 :   ip_addr_version (ip) = af;
     222           0 : }
     223             : 
     224             : static walk_rc_t
     225           0 : 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           0 :   ctx = args;
     232             : 
     233           0 :   mp = vl_msg_api_alloc_zero (sizeof (*mp));
     234           0 :   mp->_vl_msg_id = ntohs (VL_API_CNAT_SESSION_DETAILS + cnat_base_msg_id);
     235             : 
     236             :   /* fill in the message */
     237           0 :   mp->context = ctx->context;
     238             : 
     239           0 :   ep.ce_sw_if_index = INDEX_INVALID;
     240           0 :   ep.ce_flags = CNAT_EP_FLAG_RESOLVED;
     241           0 :   ip_address2_from_46 (&session->value.cs_ip[VLIB_TX], session->key.cs_af,
     242             :                        &ep.ce_ip);
     243           0 :   ep.ce_port = clib_host_to_net_u16 (session->value.cs_port[VLIB_TX]);
     244           0 :   cnat_endpoint_encode (&ep, &mp->session.new);
     245             : 
     246           0 :   ip_address2_from_46 (&session->key.cs_ip[VLIB_RX], session->key.cs_af,
     247             :                        &ep.ce_ip);
     248           0 :   ep.ce_port = clib_host_to_net_u16 (session->key.cs_port[VLIB_RX]);
     249           0 :   cnat_endpoint_encode (&ep, &mp->session.src);
     250             : 
     251           0 :   ip_address2_from_46 (&session->key.cs_ip[VLIB_TX], session->key.cs_af,
     252             :                        &ep.ce_ip);
     253           0 :   ep.ce_port = clib_host_to_net_u16 (session->key.cs_port[VLIB_TX]);
     254           0 :   cnat_endpoint_encode (&ep, &mp->session.dst);
     255             : 
     256           0 :   mp->session.ip_proto = ip_proto_encode (session->key.cs_proto);
     257           0 :   mp->session.location = session->key.cs_loc;
     258             : 
     259           0 :   vl_api_send_msg (ctx->rp, (u8 *) mp);
     260             : 
     261           0 :   return (WALK_CONTINUE);
     262             : }
     263             : 
     264             : static void
     265           7 : vl_api_cnat_session_dump_t_handler (vl_api_cnat_session_dump_t * mp)
     266             : {
     267             :   vl_api_registration_t *rp;
     268             : 
     269           7 :   rp = vl_api_client_index_to_registration (mp->client_index);
     270           7 :   if (rp == 0)
     271           0 :     return;
     272             : 
     273           7 :   cnat_dump_walk_ctx_t ctx = {
     274             :     .rp = rp,
     275           7 :     .context = mp->context,
     276             :   };
     277             : 
     278           7 :   cnat_session_walk (cnat_session_send_details, &ctx);
     279             : }
     280             : 
     281             : static void
     282          15 : 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          15 :   cnat_client_throttle_pool_process ();
     288          15 :   rv = cnat_session_purge ();
     289          15 :   rv |= cnat_translation_purge ();
     290             : 
     291          15 :   REPLY_MACRO (VL_API_CNAT_SESSION_PURGE_REPLY);
     292             : }
     293             : 
     294             : static void
     295           2 : 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           2 :   cnat_snat_policy_main_t *cpm = &cnat_snat_policy_main;
     300           2 :   int rv = 0;
     301             : 
     302           2 :   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           6 : 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           6 :   u32 sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
     316             :   ip4_address_t ip4;
     317             :   ip6_address_t ip6;
     318           6 :   int rv = 0;
     319             : 
     320           6 :   ip4_address_decode (mp->snat_ip4, &ip4);
     321           6 :   ip6_address_decode (mp->snat_ip6, &ip6);
     322             : 
     323           6 :   cnat_set_snat (&ip4, &ip6, sw_if_index);
     324             : 
     325           6 :   REPLY_MACRO (VL_API_CNAT_SET_SNAT_ADDRESSES_REPLY);
     326             : }
     327             : 
     328             : static void
     329           4 : 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           4 :   int rv = 0;
     333           4 :   cnat_snat_policy_type_t policy = (cnat_snat_policy_type_t) mp->policy;
     334             : 
     335           4 :   rv = cnat_set_snat_policy (policy);
     336             : 
     337           4 :   REPLY_MACRO (VL_API_CNAT_SET_SNAT_POLICY_REPLY);
     338             : }
     339             : 
     340             : static void
     341           8 : 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           8 :   ip_prefix_decode2 (&mp->prefix, &pfx);
     349           8 :   if (mp->is_add)
     350           4 :     rv = cnat_snat_policy_add_pfx (&pfx);
     351             :   else
     352           4 :     rv = cnat_snat_policy_del_pfx (&pfx);
     353             : 
     354           8 :   REPLY_MACRO (VL_API_CNAT_SNAT_POLICY_ADD_DEL_EXCLUDE_PFX_REPLY);
     355             : }
     356             : 
     357             : static void
     358          24 : 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          24 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     363          24 :   int rv = 0;
     364             : 
     365          24 :   VALIDATE_SW_IF_INDEX (mp);
     366             : 
     367          24 :   cnat_snat_interface_map_type_t table =
     368          24 :     (cnat_snat_interface_map_type_t) mp->table;
     369             : 
     370          24 :   rv = cnat_snat_policy_add_del_if (sw_if_index, mp->is_add, table);
     371             : 
     372          24 :   BAD_SW_IF_INDEX_LABEL;
     373             : 
     374          24 :   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         575 : cnat_api_init (vlib_main_t * vm)
     381             : {
     382             :   /* Ask for a correctly-sized block of API message decode slots */
     383         575 :   cnat_base_msg_id = setup_message_id_table ();
     384             : 
     385         575 :   return 0;
     386             : }
     387             : 
     388        1151 : 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             :  */

Generated by: LCOV version 1.14