LCOV - code coverage report
Current view: top level - plugins/l2tp - l2tp.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 98 329 29.8 %
Date: 2023-07-05 22:20:52 Functions: 31 42 73.8 %

          Line data    Source code
       1             : /*
       2             :  * l2tp.c : L2TPv3 tunnel support
       3             :  *
       4             :  * Copyright (c) 2013 Cisco and/or its affiliates.
       5             :  * Licensed under the Apache License, Version 2.0 (the "License");
       6             :  * you may not use this file except in compliance with the License.
       7             :  * You may obtain a copy of the License at:
       8             :  *
       9             :  *     http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  * Unless required by applicable law or agreed to in writing, software
      12             :  * distributed under the License is distributed on an "AS IS" BASIS,
      13             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  * See the License for the specific language governing permissions and
      15             :  * limitations under the License.
      16             :  */
      17             : 
      18             : #include <vppinfra/error.h>
      19             : #include <vppinfra/hash.h>
      20             : #include <vnet/vnet.h>
      21             : #include <vnet/ip/ip.h>
      22             : #include <vnet/l2/l2_input.h>
      23             : #include <vnet/ethernet/ethernet.h>
      24             : #include <l2tp/l2tp.h>
      25             : 
      26             : l2t_main_t l2t_main;
      27             : 
      28             : /* packet trace format function */
      29             : u8 *
      30           1 : format_l2t_trace (u8 * s, va_list * args)
      31             : {
      32           1 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
      33           1 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
      34           1 :   l2t_trace_t *t = va_arg (*args, l2t_trace_t *);
      35             : 
      36           1 :   if (t->is_user_to_network)
      37           1 :     s = format (s, "L2T: %U (client) -> %U (our) session %d",
      38             :                 format_ip6_address, &t->client_address,
      39             :                 format_ip6_address, &t->our_address, t->session_index);
      40             :   else
      41           0 :     s = format (s, "L2T: %U (our) -> %U (client) session %d)",
      42             :                 format_ip6_address, &t->our_address,
      43             :                 format_ip6_address, &t->client_address, t->session_index);
      44           1 :   return s;
      45             : }
      46             : 
      47             : u8 *
      48           0 : format_l2t_session (u8 * s, va_list * args)
      49             : {
      50           0 :   l2t_session_t *session = va_arg (*args, l2t_session_t *);
      51           0 :   l2t_main_t *lm = &l2t_main;
      52             :   u32 counter_index;
      53             :   vlib_counter_t v;
      54             : 
      55           0 :   s = format (s, "[%d] %U (our) %U (client) %U (sw_if_index %d)\n",
      56           0 :               session - lm->sessions,
      57             :               format_ip6_address, &session->our_address,
      58             :               format_ip6_address, &session->client_address,
      59             :               format_vnet_sw_interface_name, lm->vnet_main,
      60             :               vnet_get_sw_interface (lm->vnet_main, session->sw_if_index),
      61             :               session->sw_if_index);
      62             : 
      63           0 :   s = format (s, "   local cookies %016llx %016llx remote cookie %016llx\n",
      64             :               clib_net_to_host_u64 (session->local_cookie[0]),
      65             :               clib_net_to_host_u64 (session->local_cookie[1]),
      66             :               clib_net_to_host_u64 (session->remote_cookie));
      67             : 
      68           0 :   s = format (s, "   local session-id %d remote session-id %d\n",
      69             :               clib_net_to_host_u32 (session->local_session_id),
      70             :               clib_net_to_host_u32 (session->remote_session_id));
      71             : 
      72           0 :   s = format (s, "   l2 specific sublayer %s\n",
      73           0 :               session->l2_sublayer_present ? "preset" : "absent");
      74             : 
      75             :   counter_index =
      76           0 :     session_index_to_counter_index (session - lm->sessions,
      77             :                                     SESSION_COUNTER_USER_TO_NETWORK);
      78             : 
      79           0 :   vlib_get_combined_counter (&lm->counter_main, counter_index, &v);
      80           0 :   if (v.packets != 0)
      81           0 :     s = format (s, "   user-to-net: %llu pkts %llu bytes\n",
      82             :                 v.packets, v.bytes);
      83             : 
      84           0 :   vlib_get_combined_counter (&lm->counter_main, counter_index + 1, &v);
      85             : 
      86           0 :   if (v.packets != 0)
      87           0 :     s = format (s, "   net-to-user: %llu pkts %llu bytes\n",
      88             :                 v.packets, v.bytes);
      89           0 :   return s;
      90             : }
      91             : 
      92             : static clib_error_t *
      93           0 : show_l2tp_command_fn (vlib_main_t * vm,
      94             :                       unformat_input_t * input, vlib_cli_command_t * cmd)
      95             : {
      96             :   l2t_session_t *session;
      97           0 :   l2t_main_t *lm = &l2t_main;
      98           0 :   char *keystr = 0;
      99           0 :   int verbose = 0;
     100             : 
     101           0 :   if (unformat (input, "verbose") || unformat (input, "v"))
     102           0 :     verbose = 1;
     103             : 
     104           0 :   if (pool_elts (lm->sessions) == 0)
     105           0 :     vlib_cli_output (vm, "No l2tp sessions...");
     106             :   else
     107           0 :     vlib_cli_output (vm, "%u l2tp sessions...", pool_elts (lm->sessions));
     108             : 
     109           0 :   if (verbose)
     110             :     {
     111           0 :       switch (lm->lookup_type)
     112             :         {
     113           0 :         case L2T_LOOKUP_SRC_ADDRESS:
     114           0 :           keystr = "src address";
     115           0 :           break;
     116             : 
     117           0 :         case L2T_LOOKUP_DST_ADDRESS:
     118           0 :           keystr = "dst address";
     119           0 :           break;
     120             : 
     121           0 :         case L2T_LOOKUP_SESSION_ID:
     122           0 :           keystr = "session id";
     123           0 :           break;
     124             : 
     125           0 :         default:
     126           0 :           keystr = "BOGUS!";
     127           0 :           break;
     128             :         }
     129             : 
     130           0 :       vlib_cli_output (vm, "L2tp session lookup on %s", keystr);
     131             : 
     132             :       /* *INDENT-OFF* */
     133           0 :       pool_foreach (session, lm->sessions)
     134             :        {
     135           0 :         vlib_cli_output (vm, "%U", format_l2t_session, session);
     136             :       }
     137             :       /* *INDENT-ON* */
     138             :     }
     139             : 
     140           0 :   return 0;
     141             : }
     142             : 
     143             : /* *INDENT-OFF* */
     144      172087 : VLIB_CLI_COMMAND (show_session_detail_command, static) = {
     145             :   .path = "show l2tpv3",
     146             :   .short_help = "show l2tpv3 [verbose]",
     147             :   .function = show_l2tp_command_fn,
     148             : };
     149             : /* *INDENT-ON* */
     150             : 
     151             : static clib_error_t *
     152           0 : test_counters_command_fn (vlib_main_t * vm,
     153             :                           unformat_input_t * input, vlib_cli_command_t * cmd)
     154             : {
     155             :   l2t_session_t *session;
     156           0 :   l2t_main_t *lm = &l2t_main;
     157             :   u32 session_index;
     158             :   u32 counter_index;
     159           0 :   u32 nincr = 0;
     160           0 :   u32 thread_index = vm->thread_index;
     161             : 
     162             :   /* *INDENT-OFF* */
     163           0 :   pool_foreach (session, lm->sessions)
     164             :    {
     165           0 :     session_index = session - lm->sessions;
     166             :     counter_index =
     167           0 :       session_index_to_counter_index (session_index,
     168             :                                       SESSION_COUNTER_USER_TO_NETWORK);
     169           0 :     vlib_increment_combined_counter (&lm->counter_main,
     170             :                                      thread_index,
     171             :                                      counter_index,
     172             :                                      1/*pkt*/, 1111 /*bytes*/);
     173           0 :     vlib_increment_combined_counter (&lm->counter_main,
     174             :                                      thread_index,
     175             :                                      counter_index+1,
     176             :                                      1/*pkt*/, 2222 /*bytes*/);
     177           0 :     nincr++;
     178             : 
     179             :   }
     180             :   /* *INDENT-ON* */
     181           0 :   vlib_cli_output (vm, "Incremented %d active counters\n", nincr);
     182             : 
     183           0 :   return 0;
     184             : }
     185             : 
     186             : /* *INDENT-OFF* */
     187      172087 : VLIB_CLI_COMMAND (test_counters_command, static) = {
     188             :     .path = "test lt2p counters",
     189             :     .short_help = "increment all active counters",
     190             :     .function = test_counters_command_fn,
     191             : };
     192             : /* *INDENT-ON* */
     193             : 
     194             : static clib_error_t *
     195           0 : clear_counters_command_fn (vlib_main_t * vm,
     196             :                            unformat_input_t * input, vlib_cli_command_t * cmd)
     197             : {
     198             :   l2t_session_t *session;
     199           0 :   l2t_main_t *lm = &l2t_main;
     200             :   u32 session_index;
     201             :   u32 counter_index;
     202           0 :   u32 nincr = 0;
     203             : 
     204             :   /* *INDENT-OFF* */
     205           0 :   pool_foreach (session, lm->sessions)
     206             :    {
     207           0 :     session_index = session - lm->sessions;
     208             :     counter_index =
     209           0 :       session_index_to_counter_index (session_index,
     210             :                                       SESSION_COUNTER_USER_TO_NETWORK);
     211           0 :     vlib_zero_combined_counter (&lm->counter_main, counter_index);
     212           0 :     vlib_zero_combined_counter (&lm->counter_main, counter_index+1);
     213           0 :     nincr++;
     214             :   }
     215             :   /* *INDENT-ON* */
     216           0 :   vlib_cli_output (vm, "Cleared %d active counters\n", nincr);
     217             : 
     218           0 :   return 0;
     219             : }
     220             : 
     221             : /* *INDENT-OFF* */
     222      172087 : VLIB_CLI_COMMAND (clear_counters_command, static) = {
     223             :   .path = "clear l2tp counters",
     224             :   .short_help = "clear all active counters",
     225             :   .function = clear_counters_command_fn,
     226             : };
     227             : /* *INDENT-ON* */
     228             : 
     229             : static u8 *
     230           2 : format_l2tpv3_name (u8 * s, va_list * args)
     231             : {
     232           2 :   l2t_main_t *lm = &l2t_main;
     233           2 :   u32 i = va_arg (*args, u32);
     234           2 :   u32 show_dev_instance = ~0;
     235             : 
     236           2 :   if (i < vec_len (lm->dev_inst_by_real))
     237           0 :     show_dev_instance = lm->dev_inst_by_real[i];
     238             : 
     239           2 :   if (show_dev_instance != ~0)
     240           0 :     i = show_dev_instance;
     241             : 
     242           2 :   return format (s, "l2tpv3_tunnel%d", i);
     243             : }
     244             : 
     245             : static int
     246           0 : l2tpv3_name_renumber (vnet_hw_interface_t * hi, u32 new_dev_instance)
     247             : {
     248           0 :   l2t_main_t *lm = &l2t_main;
     249             : 
     250           0 :   vec_validate_init_empty (lm->dev_inst_by_real, hi->dev_instance, ~0);
     251             : 
     252           0 :   lm->dev_inst_by_real[hi->dev_instance] = new_dev_instance;
     253             : 
     254           0 :   return 0;
     255             : }
     256             : 
     257             : /* *INDENT-OFF* */
     258        7279 : VNET_DEVICE_CLASS (l2tpv3_device_class,static) = {
     259             :   .name = "L2TPv3",
     260             :   .format_device_name = format_l2tpv3_name,
     261             :   .name_renumber = l2tpv3_name_renumber,
     262             : };
     263             : /* *INDENT-ON* */
     264             : 
     265             : static u8 *
     266           0 : format_l2tp_header_with_length (u8 * s, va_list * args)
     267             : {
     268           0 :   u32 dev_instance = va_arg (*args, u32);
     269           0 :   s = format (s, "unimplemented dev %u", dev_instance);
     270           0 :   return s;
     271             : }
     272             : 
     273             : /* *INDENT-OFF* */
     274        3919 : VNET_HW_INTERFACE_CLASS (l2tpv3_hw_class) = {
     275             :   .name = "L2TPV3",
     276             :   .format_header = format_l2tp_header_with_length,
     277             :   .build_rewrite = default_build_rewrite,
     278             :   .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
     279             : };
     280             : /* *INDENT-ON* */
     281             : 
     282             : int
     283           1 : create_l2tpv3_ipv6_tunnel (l2t_main_t * lm,
     284             :                            ip6_address_t * client_address,
     285             :                            ip6_address_t * our_address,
     286             :                            u32 local_session_id,
     287             :                            u32 remote_session_id,
     288             :                            u64 local_cookie,
     289             :                            u64 remote_cookie,
     290             :                            int l2_sublayer_present,
     291             :                            u32 encap_fib_index, u32 * sw_if_index)
     292             : {
     293           1 :   l2t_session_t *s = 0;
     294           1 :   vnet_main_t *vnm = lm->vnet_main;
     295             :   vnet_hw_interface_t *hi;
     296           1 :   uword *p = (uword *) ~ 0;
     297             :   u32 hw_if_index;
     298             :   l2tpv3_header_t l2tp_hdr;
     299             :   ip6_address_t *dst_address_copy, *src_address_copy;
     300             :   u32 counter_index;
     301             : 
     302           1 :   remote_session_id = clib_host_to_net_u32 (remote_session_id);
     303           1 :   local_session_id = clib_host_to_net_u32 (local_session_id);
     304             : 
     305           1 :   switch (lm->lookup_type)
     306             :     {
     307           0 :     case L2T_LOOKUP_SRC_ADDRESS:
     308           0 :       p = hash_get_mem (lm->session_by_src_address, client_address);
     309           0 :       break;
     310             : 
     311           1 :     case L2T_LOOKUP_DST_ADDRESS:
     312           1 :       p = hash_get_mem (lm->session_by_dst_address, our_address);
     313           1 :       break;
     314             : 
     315           0 :     case L2T_LOOKUP_SESSION_ID:
     316           0 :       p = hash_get (lm->session_by_session_id, local_session_id);
     317           0 :       break;
     318             : 
     319           0 :     default:
     320           0 :       ASSERT (0);
     321             :     }
     322             : 
     323             :   /* adding a session: session must not already exist */
     324           1 :   if (p)
     325           0 :     return VNET_API_ERROR_INVALID_VALUE;
     326             : 
     327           1 :   pool_get (lm->sessions, s);
     328           1 :   clib_memset (s, 0, sizeof (*s));
     329           1 :   clib_memcpy (&s->our_address, our_address, sizeof (s->our_address));
     330           1 :   clib_memcpy (&s->client_address, client_address,
     331             :                sizeof (s->client_address));
     332           1 :   s->local_cookie[0] = clib_host_to_net_u64 (local_cookie);
     333           1 :   s->remote_cookie = clib_host_to_net_u64 (remote_cookie);
     334           1 :   s->local_session_id = local_session_id;
     335           1 :   s->remote_session_id = remote_session_id;
     336           1 :   s->l2_sublayer_present = l2_sublayer_present;
     337             :   /* precompute l2tp header size */
     338           1 :   s->l2tp_hdr_size = l2_sublayer_present ?
     339             :     sizeof (l2tpv3_header_t) :
     340             :     sizeof (l2tpv3_header_t) - sizeof (l2tp_hdr.l2_specific_sublayer);
     341           1 :   s->admin_up = 0;
     342           1 :   s->encap_fib_index = encap_fib_index;
     343             : 
     344             :   /* Setup hash table entries */
     345           1 :   switch (lm->lookup_type)
     346             :     {
     347           0 :     case L2T_LOOKUP_SRC_ADDRESS:
     348           0 :       src_address_copy = clib_mem_alloc (sizeof (*src_address_copy));
     349           0 :       clib_memcpy (src_address_copy, client_address,
     350             :                    sizeof (*src_address_copy));
     351           0 :       hash_set_mem (lm->session_by_src_address, src_address_copy,
     352             :                     s - lm->sessions);
     353           0 :       break;
     354           1 :     case L2T_LOOKUP_DST_ADDRESS:
     355           1 :       dst_address_copy = clib_mem_alloc (sizeof (*dst_address_copy));
     356           1 :       clib_memcpy (dst_address_copy, our_address, sizeof (*dst_address_copy));
     357           2 :       hash_set_mem (lm->session_by_dst_address, dst_address_copy,
     358             :                     s - lm->sessions);
     359           1 :       break;
     360           0 :     case L2T_LOOKUP_SESSION_ID:
     361           0 :       hash_set (lm->session_by_session_id, local_session_id,
     362             :                 s - lm->sessions);
     363           0 :       break;
     364             : 
     365           0 :     default:
     366           0 :       ASSERT (0);
     367             :     }
     368             : 
     369             :   /* validate counters */
     370             :   counter_index =
     371           1 :     session_index_to_counter_index (s - lm->sessions,
     372             :                                     SESSION_COUNTER_USER_TO_NETWORK);
     373           1 :   vlib_validate_combined_counter (&lm->counter_main, counter_index);
     374           1 :   vlib_validate_combined_counter (&lm->counter_main, counter_index + 1);
     375             : 
     376           1 :   if (vec_len (lm->free_l2tpv3_tunnel_hw_if_indices) > 0)
     377             :     {
     378           0 :       hw_if_index = lm->free_l2tpv3_tunnel_hw_if_indices
     379           0 :         [vec_len (lm->free_l2tpv3_tunnel_hw_if_indices) - 1];
     380           0 :       vec_dec_len (lm->free_l2tpv3_tunnel_hw_if_indices, 1);
     381             : 
     382           0 :       hi = vnet_get_hw_interface (vnm, hw_if_index);
     383           0 :       hi->dev_instance = s - lm->sessions;
     384           0 :       hi->hw_instance = hi->dev_instance;
     385             :     }
     386             :   else
     387             :     {
     388           1 :       hw_if_index = vnet_register_interface
     389           1 :         (vnm, l2tpv3_device_class.index, s - lm->sessions,
     390           1 :          l2tpv3_hw_class.index, s - lm->sessions);
     391           1 :       hi = vnet_get_hw_interface (vnm, hw_if_index);
     392           1 :       hi->output_node_index = l2t_encap_node.index;
     393             :       /* $$$$ initialize custom dispositions, if needed */
     394             :     }
     395             : 
     396           1 :   s->hw_if_index = hw_if_index;
     397           1 :   s->sw_if_index = hi->sw_if_index;
     398             : 
     399           1 :   if (sw_if_index)
     400           1 :     *sw_if_index = hi->sw_if_index;
     401             : 
     402           1 :   if (!lm->proto_registered)
     403             :     {
     404           1 :       ip6_register_protocol (IP_PROTOCOL_L2TP, l2t_decap_local_node.index);
     405           1 :       lm->proto_registered = true;
     406             :     }
     407             : 
     408           1 :   return 0;
     409             : }
     410             : 
     411             : static clib_error_t *
     412           0 : create_l2tpv3_tunnel_command_fn (vlib_main_t * vm,
     413             :                                  unformat_input_t * input,
     414             :                                  vlib_cli_command_t * cmd)
     415             : {
     416             :   ip6_address_t client_address, our_address;
     417           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     418           0 :   l2t_main_t *lm = &l2t_main;
     419           0 :   u64 local_cookie = (u64) ~ 0, remote_cookie = (u64) ~ 0;
     420           0 :   u32 local_session_id = 1, remote_session_id = 1;
     421           0 :   int our_address_set = 0, client_address_set = 0;
     422           0 :   int l2_sublayer_present = 0;
     423             :   int rv;
     424             :   u32 sw_if_index;
     425           0 :   u32 encap_fib_id = ~0;
     426           0 :   u32 encap_fib_index = ~0;
     427           0 :   clib_error_t *error = NULL;
     428             : 
     429             :   /* Get a line of input. */
     430           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     431           0 :     return 0;
     432             : 
     433           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     434             :     {
     435           0 :       if (unformat (line_input, "client %U",
     436             :                     unformat_ip6_address, &client_address))
     437           0 :         client_address_set = 1;
     438           0 :       else if (unformat (line_input, "our %U",
     439             :                          unformat_ip6_address, &our_address))
     440           0 :         our_address_set = 1;
     441           0 :       else if (unformat (line_input, "local-cookie %llx", &local_cookie))
     442             :         ;
     443           0 :       else if (unformat (line_input, "remote-cookie %llx", &remote_cookie))
     444             :         ;
     445           0 :       else if (unformat (line_input, "local-session-id %d",
     446             :                          &local_session_id))
     447             :         ;
     448           0 :       else if (unformat (line_input, "remote-session-id %d",
     449             :                          &remote_session_id))
     450             :         ;
     451           0 :       else if (unformat (line_input, "fib-id %d", &encap_fib_id))
     452             :         ;
     453           0 :       else if (unformat (line_input, "l2-sublayer-present"))
     454           0 :         l2_sublayer_present = 1;
     455             :       else
     456             :         {
     457           0 :           error = clib_error_return (0, "parse error: '%U'",
     458             :                                      format_unformat_error, line_input);
     459           0 :           goto done;
     460             :         }
     461             :     }
     462             : 
     463           0 :   if (encap_fib_id != ~0)
     464             :     {
     465             :       uword *p;
     466           0 :       ip6_main_t *im = &ip6_main;
     467           0 :       if (!(p = hash_get (im->fib_index_by_table_id, encap_fib_id)))
     468             :         {
     469           0 :           error = clib_error_return (0, "No fib with id %d", encap_fib_id);
     470           0 :           goto done;
     471             :         }
     472           0 :       encap_fib_index = p[0];
     473             :     }
     474             :   else
     475             :     {
     476           0 :       encap_fib_index = ~0;
     477             :     }
     478             : 
     479           0 :   if (our_address_set == 0)
     480             :     {
     481           0 :       error = clib_error_return (0, "our address not specified");
     482           0 :       goto done;
     483             :     }
     484           0 :   if (client_address_set == 0)
     485             :     {
     486           0 :       error = clib_error_return (0, "client address not specified");
     487           0 :       goto done;
     488             :     }
     489             : 
     490           0 :   rv = create_l2tpv3_ipv6_tunnel (lm, &client_address, &our_address,
     491             :                                   local_session_id, remote_session_id,
     492             :                                   local_cookie, remote_cookie,
     493             :                                   l2_sublayer_present,
     494             :                                   encap_fib_index, &sw_if_index);
     495           0 :   switch (rv)
     496             :     {
     497           0 :     case 0:
     498           0 :       vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name,
     499             :                        vnet_get_main (), sw_if_index);
     500           0 :       break;
     501           0 :     case VNET_API_ERROR_INVALID_VALUE:
     502           0 :       error = clib_error_return (0, "session already exists...");
     503           0 :       goto done;
     504             : 
     505           0 :     case VNET_API_ERROR_NO_SUCH_ENTRY:
     506           0 :       error = clib_error_return (0, "session does not exist...");
     507           0 :       goto done;
     508             : 
     509           0 :     default:
     510           0 :       error = clib_error_return (0, "l2tp_session_add_del returned %d", rv);
     511           0 :       goto done;
     512             :     }
     513             : 
     514           0 : done:
     515           0 :   unformat_free (line_input);
     516             : 
     517           0 :   return error;
     518             : }
     519             : 
     520             : /* *INDENT-OFF* */
     521      172087 : VLIB_CLI_COMMAND (create_l2tpv3_tunnel_command, static) =
     522             : {
     523             :   .path = "create l2tpv3 tunnel",
     524             :   .short_help =
     525             :   "create l2tpv3 tunnel client <ip6> our <ip6> local-cookie <hex> remote-cookie <hex> local-session <dec> remote-session <dec>",
     526             :   .function = create_l2tpv3_tunnel_command_fn,
     527             : };
     528             : /* *INDENT-ON* */
     529             : 
     530             : int
     531           0 : l2tpv3_set_tunnel_cookies (l2t_main_t * lm,
     532             :                            u32 sw_if_index,
     533             :                            u64 new_local_cookie, u64 new_remote_cookie)
     534             : {
     535             :   l2t_session_t *s;
     536             :   vnet_hw_interface_t *hi;
     537           0 :   vnet_main_t *vnm = vnet_get_main ();
     538           0 :   hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
     539             : 
     540           0 :   if (pool_is_free_index (lm->sessions, hi->dev_instance))
     541           0 :     return VNET_API_ERROR_INVALID_VALUE;
     542             : 
     543           0 :   s = pool_elt_at_index (lm->sessions, hi->dev_instance);
     544             : 
     545           0 :   s->local_cookie[1] = s->local_cookie[0];
     546           0 :   s->local_cookie[0] = clib_host_to_net_u64 (new_local_cookie);
     547           0 :   s->remote_cookie = clib_host_to_net_u64 (new_remote_cookie);
     548             : 
     549           0 :   return 0;
     550             : }
     551             : 
     552             : 
     553             : static clib_error_t *
     554           0 : set_l2tp_tunnel_cookie_command_fn (vlib_main_t * vm,
     555             :                                    unformat_input_t * input,
     556             :                                    vlib_cli_command_t * cmd)
     557             : {
     558           0 :   l2t_main_t *lm = &l2t_main;
     559           0 :   vnet_main_t *vnm = vnet_get_main ();
     560           0 :   u32 sw_if_index = ~0;
     561           0 :   u64 local_cookie = (u64) ~ 0, remote_cookie = (u64) ~ 0;
     562             : 
     563             :   int rv;
     564             : 
     565           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     566             :     {
     567           0 :       if (unformat (input, "%U", unformat_vnet_sw_interface, vnm,
     568             :                     &sw_if_index))
     569             :         ;
     570           0 :       else if (unformat (input, "local %llx", &local_cookie))
     571             :         ;
     572           0 :       else if (unformat (input, "remote %llx", &remote_cookie))
     573             :         ;
     574             :       else
     575           0 :         break;
     576             :     }
     577           0 :   if (sw_if_index == ~0)
     578           0 :     return clib_error_return (0, "unknown interface");
     579           0 :   if (local_cookie == ~0)
     580           0 :     return clib_error_return (0, "local cookie required");
     581           0 :   if (remote_cookie == ~0)
     582           0 :     return clib_error_return (0, "remote cookie required");
     583             : 
     584           0 :   rv = l2tpv3_set_tunnel_cookies (lm, sw_if_index,
     585             :                                   local_cookie, remote_cookie);
     586             : 
     587           0 :   switch (rv)
     588             :     {
     589           0 :     case 0:
     590           0 :       break;
     591             : 
     592           0 :     case VNET_API_ERROR_INVALID_SW_IF_INDEX:
     593           0 :       return clib_error_return (0, "invalid interface");
     594             : 
     595           0 :     default:
     596           0 :       return clib_error_return (0, "l2tp_session_set_cookies returned %d",
     597             :                                 rv);
     598             :     }
     599             : 
     600           0 :   return 0;
     601             : }
     602             : 
     603             : /* *INDENT-OFF* */
     604      172087 : VLIB_CLI_COMMAND (set_l2tp_tunnel_cookie_command, static) =
     605             : {
     606             :   .path = "set l2tpv3 tunnel cookie",
     607             :   .short_help =
     608             :   "set l2tpv3 tunnel cookie <intfc> local <hex> remote <hex>",
     609             :   .function = set_l2tp_tunnel_cookie_command_fn,
     610             : };
     611             : /* *INDENT-ON* */
     612             : 
     613             : int
     614           0 : l2tpv3_interface_enable_disable (vnet_main_t * vnm,
     615             :                                  u32 sw_if_index, int enable_disable)
     616             : {
     617             : 
     618           0 :   if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
     619           0 :     return VNET_API_ERROR_INVALID_SW_IF_INDEX;
     620             : 
     621           0 :   vnet_feature_enable_disable ("ip6-unicast", "l2tp-decap", sw_if_index,
     622             :                                enable_disable, 0, 0);
     623           0 :   return 0;
     624             : }
     625             : 
     626             : /* Enable/disable L2TPv3 intercept on IP6 forwarding path */
     627             : static clib_error_t *
     628           0 : set_ip6_l2tpv3 (vlib_main_t * vm,
     629             :                 unformat_input_t * input, vlib_cli_command_t * cmd)
     630             : {
     631           0 :   u32 sw_if_index = ~0;
     632           0 :   int is_add = 1;
     633             :   int rv;
     634           0 :   vnet_main_t *vnm = vnet_get_main ();
     635             : 
     636           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     637             :     {
     638           0 :       if (unformat (input, "%U", unformat_vnet_sw_interface, vnm,
     639             :                     &sw_if_index))
     640             :         ;
     641           0 :       else if (unformat (input, "del"))
     642           0 :         is_add = 0;
     643             :       else
     644           0 :         break;
     645             :     }
     646             : 
     647           0 :   if (sw_if_index == ~0)
     648           0 :     return clib_error_return (0, "interface required");
     649             : 
     650           0 :   rv = l2tpv3_interface_enable_disable (vnm, sw_if_index, is_add);
     651             : 
     652           0 :   switch (rv)
     653             :     {
     654           0 :     case 0:
     655           0 :       break;
     656             : 
     657           0 :     case VNET_API_ERROR_INVALID_SW_IF_INDEX:
     658           0 :       return clib_error_return (0, "invalid interface");
     659             : 
     660           0 :     default:
     661           0 :       return clib_error_return (0,
     662             :                                 "l2tp_interface_enable_disable returned %d",
     663             :                                 rv);
     664             :     }
     665           0 :   return 0;
     666             : }
     667             : 
     668             : /* *INDENT-OFF* */
     669      172087 : VLIB_CLI_COMMAND (set_interface_ip6_l2tpv3, static) =
     670             : {
     671             :   .path = "set interface ip6 l2tpv3",
     672             :   .function = set_ip6_l2tpv3,
     673             :   .short_help = "set interface ip6 l2tpv3 <intfc> [del]",
     674             : };
     675             : /* *INDENT-ON* */
     676             : 
     677             : static clib_error_t *
     678         559 : l2tp_config (vlib_main_t * vm, unformat_input_t * input)
     679             : {
     680         559 :   l2t_main_t *lm = &l2t_main;
     681             : 
     682         559 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     683             :     {
     684           0 :       if (unformat (input, "lookup-v6-src"))
     685           0 :         lm->lookup_type = L2T_LOOKUP_SRC_ADDRESS;
     686           0 :       else if (unformat (input, "lookup-v6-dst"))
     687           0 :         lm->lookup_type = L2T_LOOKUP_DST_ADDRESS;
     688           0 :       else if (unformat (input, "lookup-session-id"))
     689           0 :         lm->lookup_type = L2T_LOOKUP_SESSION_ID;
     690             :       else
     691           0 :         return clib_error_return (0, "unknown input `%U'",
     692             :                                   format_unformat_error, input);
     693             :     }
     694         559 :   return 0;
     695             : }
     696             : 
     697        2826 : VLIB_CONFIG_FUNCTION (l2tp_config, "l2tp");
     698             : 
     699             : 
     700             : clib_error_t *
     701       13268 : l2tp_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
     702             : {
     703       13268 :   l2t_main_t *lm = &l2t_main;
     704       13268 :   vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
     705       13268 :   if (hi->hw_class_index != l2tpv3_hw_class.index)
     706       13268 :     return 0;
     707             : 
     708           0 :   u32 session_index = hi->dev_instance;
     709           0 :   l2t_session_t *s = pool_elt_at_index (lm->sessions, session_index);
     710           0 :   s->admin_up = ! !(flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP);
     711           0 :   return 0;
     712             : }
     713             : 
     714        2241 : VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (l2tp_sw_interface_up_down);
     715             : 
     716             : clib_error_t *
     717         559 : l2tp_init (vlib_main_t * vm)
     718             : {
     719         559 :   l2t_main_t *lm = &l2t_main;
     720         559 :   ip_main_t *im = &ip_main;
     721             :   ip_protocol_info_t *pi;
     722             : 
     723         559 :   lm->vnet_main = vnet_get_main ();
     724         559 :   lm->vlib_main = vm;
     725         559 :   lm->lookup_type = L2T_LOOKUP_DST_ADDRESS;
     726             : 
     727         559 :   lm->session_by_src_address = hash_create_mem
     728             :     (0, sizeof (ip6_address_t) /* key bytes */ ,
     729             :      sizeof (u32) /* value bytes */ );
     730         559 :   lm->session_by_dst_address = hash_create_mem
     731             :     (0, sizeof (ip6_address_t) /* key bytes */ ,
     732             :      sizeof (u32) /* value bytes */ );
     733         559 :   lm->session_by_session_id = hash_create (0, sizeof (uword));
     734             : 
     735         559 :   pi = ip_get_protocol_info (im, IP_PROTOCOL_L2TP);
     736         559 :   pi->unformat_pg_edit = unformat_pg_l2tp_header;
     737             : 
     738         559 :   lm->proto_registered = false;
     739             : 
     740             :   /* insure these nodes are included in build */
     741         559 :   l2tp_encap_init (vm);
     742             : 
     743         559 :   return 0;
     744             : }
     745             : 
     746        1119 : VLIB_INIT_FUNCTION (l2tp_init);
     747             : 
     748             : clib_error_t *
     749          54 : l2tp_worker_init (vlib_main_t * vm)
     750             : {
     751          54 :   l2tp_encap_init (vm);
     752             : 
     753          54 :   return 0;
     754             : }
     755             : 
     756        1119 : VLIB_WORKER_INIT_FUNCTION (l2tp_worker_init);
     757             : 
     758             : /*
     759             :  * fd.io coding-style-patch-verification: ON
     760             :  *
     761             :  * Local Variables:
     762             :  * eval: (c-set-style "gnu")
     763             :  * End:
     764             :  */

Generated by: LCOV version 1.14