LCOV - code coverage report
Current view: top level - plugins/lisp/lisp-gpe - lisp_gpe_tunnel.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 61 97 62.9 %
Date: 2023-07-05 22:20:52 Functions: 11 13 84.6 %

          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             :  * @file
      17             :  * @brief Common utility functions for IPv4, IPv6 and L2 LISP-GPE tunnels.
      18             :  *
      19             :  */
      20             : #include <lisp/lisp-gpe/lisp_gpe.h>
      21             : #include <lisp/lisp-gpe/lisp_gpe_tunnel.h>
      22             : #include <lisp/lisp-gpe/lisp_gpe_adjacency.h>
      23             : 
      24             : #include <vnet/fib/fib_table.h>
      25             : 
      26             : /**
      27             :  * @brief Pool of all LISP tunnels
      28             :  */
      29             : static lisp_gpe_tunnel_t *lisp_gpe_tunnel_pool;
      30             : 
      31             : /**
      32             :  * @brief a DB of all tunnels
      33             :  */
      34             : static uword *lisp_gpe_tunnel_db;
      35             : 
      36             : /**
      37             :  * @brief Compute IP-UDP-GPE sub-tunnel encap/rewrite header.
      38             :  *
      39             :  * @param[in]   t       Parent of the sub-tunnel.
      40             :  * @param[in]   st      Sub-tunnel.
      41             :  * @param[in]   lp      Local and remote locators used in the encap header.
      42             :  *
      43             :  * @return 0 on success.
      44             :  */
      45             : u8 *
      46           1 : lisp_gpe_tunnel_build_rewrite (const lisp_gpe_tunnel_t * lgt,
      47             :                                const lisp_gpe_adjacency_t * ladj,
      48             :                                lisp_gpe_next_protocol_e payload_proto)
      49             : {
      50             :   lisp_gpe_header_t *lisp0;
      51           1 :   u8 *rw = 0;
      52             :   int len;
      53           1 :   gpe_encap_mode_t encap_mode = vnet_gpe_get_encap_mode ();
      54             : 
      55           1 :   if (AF_IP4 == ip_addr_version (&lgt->key->lcl))
      56             :     {
      57             :       ip4_udp_lisp_gpe_header_t *h0;
      58             :       ip4_header_t *ip0;
      59             : 
      60           1 :       len = sizeof (*h0);
      61             : 
      62           1 :       vec_validate_aligned (rw, len - 1, CLIB_CACHE_LINE_BYTES);
      63             : 
      64           1 :       h0 = (ip4_udp_lisp_gpe_header_t *) rw;
      65             : 
      66             :       /* Fixed portion of the (outer) ip4 header */
      67           1 :       ip0 = &h0->ip4;
      68           1 :       ip0->ip_version_and_header_length = 0x45;
      69           1 :       ip0->ttl = 254;
      70           1 :       ip0->protocol = IP_PROTOCOL_UDP;
      71             : 
      72             :       /* we fix up the ip4 header length and checksum after-the-fact */
      73           1 :       ip_address_copy_addr (&ip0->src_address, &lgt->key->lcl);
      74           1 :       ip_address_copy_addr (&ip0->dst_address, &lgt->key->rmt);
      75           1 :       ip0->checksum = ip4_header_checksum (ip0);
      76             : 
      77             :       /* UDP header, randomize src port on something, maybe? */
      78           1 :       h0->udp.src_port = clib_host_to_net_u16 (4341);
      79           1 :       h0->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_lisp_gpe);
      80             : 
      81             :       /* LISP-gpe header */
      82           1 :       lisp0 = &h0->lisp;
      83             :     }
      84             :   else
      85             :     {
      86             :       ip6_udp_lisp_gpe_header_t *h0;
      87             :       ip6_header_t *ip0;
      88             : 
      89           0 :       len = sizeof (*h0);
      90             : 
      91           0 :       vec_validate_aligned (rw, len - 1, CLIB_CACHE_LINE_BYTES);
      92             : 
      93           0 :       h0 = (ip6_udp_lisp_gpe_header_t *) rw;
      94             : 
      95             :       /* Fixed portion of the (outer) ip6 header */
      96           0 :       ip0 = &h0->ip6;
      97           0 :       ip0->ip_version_traffic_class_and_flow_label =
      98           0 :         clib_host_to_net_u32 (0x6 << 28);
      99           0 :       ip0->hop_limit = 254;
     100           0 :       ip0->protocol = IP_PROTOCOL_UDP;
     101             : 
     102             :       /* we fix up the ip6 header length after-the-fact */
     103           0 :       ip_address_copy_addr (&ip0->src_address, &lgt->key->lcl);
     104           0 :       ip_address_copy_addr (&ip0->dst_address, &lgt->key->rmt);
     105             : 
     106             :       /* UDP header, randomize src port on something, maybe? */
     107           0 :       h0->udp.src_port = clib_host_to_net_u16 (4341);
     108           0 :       h0->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_lisp_gpe);
     109             : 
     110             :       /* LISP-gpe header */
     111           0 :       lisp0 = &h0->lisp;
     112             :     }
     113             : 
     114           1 :   lisp0->flags = ladj->flags;
     115           1 :   if (GPE_ENCAP_VXLAN == encap_mode)
     116             :     /* unset P flag */
     117           0 :     lisp0->flags &= ~LISP_GPE_FLAGS_P;
     118             : 
     119           1 :   lisp0->ver_res = 0;
     120           1 :   lisp0->res = 0;
     121           1 :   lisp0->next_protocol = payload_proto;
     122           1 :   lisp0->iid = clib_host_to_net_u32 (ladj->vni) >> 8;       /* first 24 bits only */
     123             : 
     124           1 :   return (rw);
     125             : }
     126             : 
     127             : static lisp_gpe_tunnel_t *
     128           1 : lisp_gpe_tunnel_db_find (const lisp_gpe_tunnel_key_t * key)
     129             : {
     130             :   uword *p;
     131             : 
     132           1 :   p = hash_get_mem (lisp_gpe_tunnel_db, (void *) key);
     133             : 
     134           1 :   if (NULL != p)
     135             :     {
     136           0 :       return (pool_elt_at_index (lisp_gpe_tunnel_pool, p[0]));
     137             :     }
     138           1 :   return (NULL);
     139             : }
     140             : 
     141             : lisp_gpe_tunnel_t *
     142           5 : lisp_gpe_tunnel_get_i (index_t lgti)
     143             : {
     144           5 :   return (pool_elt_at_index (lisp_gpe_tunnel_pool, lgti));
     145             : }
     146             : 
     147             : index_t
     148           1 : lisp_gpe_tunnel_find_or_create_and_lock (const locator_pair_t * pair,
     149             :                                          u32 rloc_fib_index)
     150             : {
     151           1 :   lisp_gpe_tunnel_key_t key = {
     152             :     .lcl = pair->lcl_loc,
     153             :     .rmt = pair->rmt_loc,
     154             :     .fib_index = rloc_fib_index,
     155             :   };
     156             :   lisp_gpe_tunnel_t *lgt;
     157             :   fib_prefix_t pfx;
     158             : 
     159           1 :   lgt = lisp_gpe_tunnel_db_find (&key);
     160             : 
     161           1 :   if (NULL == lgt)
     162             :     {
     163           1 :       pool_get (lisp_gpe_tunnel_pool, lgt);
     164           1 :       clib_memset (lgt, 0, sizeof (*lgt));
     165             : 
     166           1 :       lgt->key = clib_mem_alloc (sizeof (*lgt->key));
     167           1 :       clib_memset (lgt->key, 0, sizeof (*lgt->key));
     168             : 
     169           1 :       lgt->key->rmt = pair->rmt_loc;
     170           1 :       lgt->key->lcl = pair->lcl_loc;
     171           1 :       lgt->key->fib_index = rloc_fib_index;
     172             : 
     173             :       /*
     174             :        * source the FIB entry for the RLOC so we can track its forwarding
     175             :        * chain
     176             :        */
     177           1 :       ip_address_to_fib_prefix (&lgt->key->rmt, &pfx);
     178             : 
     179           1 :       lgt->fib_entry_index = fib_table_entry_special_add (rloc_fib_index,
     180             :                                                           &pfx,
     181             :                                                           FIB_SOURCE_RR,
     182             :                                                           FIB_ENTRY_FLAG_NONE);
     183             : 
     184           2 :       hash_set_mem (lisp_gpe_tunnel_db, lgt->key,
     185             :                     (lgt - lisp_gpe_tunnel_pool));
     186             :     }
     187             : 
     188           1 :   lgt->locks++;
     189             : 
     190           1 :   return (lgt - lisp_gpe_tunnel_pool);
     191             : }
     192             : 
     193             : void
     194           1 : lisp_gpe_tunnel_unlock (index_t lgti)
     195             : {
     196             :   lisp_gpe_tunnel_t *lgt;
     197             : 
     198           1 :   lgt = lisp_gpe_tunnel_get_i (lgti);
     199           1 :   lgt->locks--;
     200             : 
     201           1 :   if (0 == lgt->locks)
     202             :     {
     203           2 :       hash_unset_mem (lisp_gpe_tunnel_db, lgt->key);
     204           1 :       clib_mem_free (lgt->key);
     205           1 :       pool_put (lisp_gpe_tunnel_pool, lgt);
     206             :     }
     207           1 : }
     208             : 
     209             : const lisp_gpe_tunnel_t *
     210           4 : lisp_gpe_tunnel_get (index_t lgti)
     211             : {
     212           4 :   return (lisp_gpe_tunnel_get_i (lgti));
     213             : }
     214             : 
     215             : /** Format LISP-GPE tunnel. */
     216             : u8 *
     217           0 : format_lisp_gpe_tunnel (u8 * s, va_list * args)
     218             : {
     219           0 :   lisp_gpe_tunnel_t *lgt = va_arg (*args, lisp_gpe_tunnel_t *);
     220             : 
     221           0 :   s = format (s, "tunnel %d\n", lgt - lisp_gpe_tunnel_pool);
     222           0 :   s = format (s, " fib-index: %d, locks:%d \n",
     223           0 :               lgt->key->fib_index, lgt->locks);
     224           0 :   s = format (s, " lisp ver 0\n");
     225             : 
     226           0 :   s = format (s, " locator-pair:\n");
     227           0 :   s = format (s, "  local: %U remote: %U\n",
     228           0 :               format_ip_address, &lgt->key->lcl,
     229           0 :               format_ip_address, &lgt->key->rmt);
     230           0 :   s = format (s, " RLOC FIB entry: %d\n", lgt->fib_entry_index);
     231             : 
     232           0 :   return s;
     233             : }
     234             : 
     235             : /**
     236             :  * CLI command to show LISP-GPE tunnels.
     237             :  */
     238             : static clib_error_t *
     239           0 : show_lisp_gpe_tunnel_command_fn (vlib_main_t * vm,
     240             :                                  unformat_input_t * input,
     241             :                                  vlib_cli_command_t * cmd)
     242             : {
     243             :   lisp_gpe_tunnel_t *lgt;
     244             :   index_t index;
     245             : 
     246           0 :   if (pool_elts (lisp_gpe_tunnel_pool) == 0)
     247           0 :     vlib_cli_output (vm, "No lisp-gpe tunnels configured...");
     248             : 
     249           0 :   if (unformat (input, "%d", &index))
     250             :     {
     251           0 :       lgt = lisp_gpe_tunnel_get_i (index);
     252           0 :       vlib_cli_output (vm, "%U", format_lisp_gpe_tunnel, lgt);
     253             :     }
     254             :   else
     255             :     {
     256             :       /* *INDENT-OFF* */
     257           0 :       pool_foreach (lgt, lisp_gpe_tunnel_pool)
     258             :        {
     259           0 :         vlib_cli_output (vm, "%U", format_lisp_gpe_tunnel, lgt);
     260             :       }
     261             :       /* *INDENT-ON* */
     262             :     }
     263             : 
     264           0 :   return 0;
     265             : }
     266             : 
     267             : /* *INDENT-OFF* */
     268      116069 : VLIB_CLI_COMMAND (show_lisp_gpe_tunnel_command, static) =
     269             : {
     270             :   .path = "show gpe tunnel",
     271             :   .function = show_lisp_gpe_tunnel_command_fn,
     272             : };
     273             : /* *INDENT-ON* */
     274             : 
     275             : static clib_error_t *
     276         559 : lisp_gpe_tunnel_module_init (vlib_main_t * vm)
     277             : {
     278         559 :   lisp_gpe_tunnel_db = hash_create_mem (0,
     279             :                                         sizeof (lisp_gpe_tunnel_key_t),
     280             :                                         sizeof (uword));
     281             : 
     282         559 :   return (NULL);
     283             : }
     284             : 
     285        3359 : VLIB_INIT_FUNCTION (lisp_gpe_tunnel_module_init);
     286             : 
     287             : /*
     288             :  * fd.io coding-style-patch-verification: ON
     289             :  *
     290             :  * Local Variables:
     291             :  * eval: (c-set-style "gnu")
     292             :  * End:
     293             :  */

Generated by: LCOV version 1.14