LCOV - code coverage report
Current view: top level - plugins/nat/dslite - dslite.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 118 121 97.5 %
Date: 2023-07-05 22:20:52 Functions: 15 15 100.0 %

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

Generated by: LCOV version 1.14