LCOV - code coverage report
Current view: top level - plugins/nsh - nsh.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 77 120 64.2 %
Date: 2023-10-26 01:39:38 Functions: 6 10 60.0 %

          Line data    Source code
       1             : /*
       2             :  * nsh.c - nsh mapping
       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 <vnet/vnet.h>
      19             : #include <vnet/plugin/plugin.h>
      20             : #include <nsh/nsh.h>
      21             : #include <gre/gre.h>
      22             : #include <vxlan/vxlan.h>
      23             : #include <vnet/vxlan-gpe/vxlan_gpe.h>
      24             : #include <vnet/l2/l2_classify.h>
      25             : #include <vnet/adj/adj.h>
      26             : #include <vpp/app/version.h>
      27             : 
      28             : nsh_main_t nsh_main;
      29             : 
      30             : /* Uses network order's class and type to register */
      31             : int
      32         575 : nsh_md2_register_option (u16 class,
      33             :                          u8 type,
      34             :                          u8 option_size,
      35             :                          int add_options (u8 * opt,
      36             :                                           u8 * opt_size),
      37             :                          int options (vlib_buffer_t * b,
      38             :                                       nsh_tlv_header_t * opt),
      39             :                          int swap_options (vlib_buffer_t * b,
      40             :                                            nsh_tlv_header_t * old_opt,
      41             :                                            nsh_tlv_header_t * new_opt),
      42             :                          int pop_options (vlib_buffer_t * b,
      43             :                                           nsh_tlv_header_t * opt),
      44             :                          u8 * trace (u8 * s, nsh_tlv_header_t * opt))
      45             : {
      46         575 :   nsh_main_t *nm = &nsh_main;
      47             :   nsh_option_map_by_key_t key, *key_copy;
      48             :   uword *p;
      49             :   nsh_option_map_t *nsh_option;
      50             : 
      51         575 :   key.class = class;
      52         575 :   key.type = type;
      53         575 :   key.pad = 0;
      54             : 
      55         575 :   p = hash_get_mem (nm->nsh_option_map_by_key, &key);
      56             :   /* Already registered */
      57         575 :   if (p != 0)
      58             :     {
      59           0 :       return (-1);
      60             :     }
      61             : 
      62         575 :   pool_get_aligned (nm->nsh_option_mappings, nsh_option,
      63             :                     CLIB_CACHE_LINE_BYTES);
      64         575 :   clib_memset (nsh_option, 0, sizeof (*nsh_option));
      65         575 :   nsh_option->option_id = nsh_option - nm->nsh_option_mappings;
      66             : 
      67         575 :   key_copy = clib_mem_alloc (sizeof (*key_copy));
      68         575 :   clib_memcpy (key_copy, &key, sizeof (*key_copy));
      69        1150 :   hash_set_mem (nm->nsh_option_map_by_key, key_copy,
      70             :                 nsh_option - nm->nsh_option_mappings);
      71             : 
      72         575 :   if (option_size > (MAX_NSH_OPTION_LEN + sizeof (nsh_tlv_header_t)))
      73             :     {
      74           0 :       return (-1);
      75             :     }
      76         575 :   nm->options_size[nsh_option->option_id] = option_size;
      77         575 :   nm->add_options[nsh_option->option_id] = add_options;
      78         575 :   nm->options[nsh_option->option_id] = options;
      79         575 :   nm->swap_options[nsh_option->option_id] = swap_options;
      80         575 :   nm->pop_options[nsh_option->option_id] = pop_options;
      81         575 :   nm->trace[nsh_option->option_id] = trace;
      82             : 
      83         575 :   return (0);
      84             : }
      85             : 
      86             : /* Uses network order's class and type to lookup */
      87             : nsh_option_map_t *
      88           0 : nsh_md2_lookup_option (u16 class, u8 type)
      89             : {
      90           0 :   nsh_main_t *nm = &nsh_main;
      91             :   nsh_option_map_by_key_t key;
      92             :   uword *p;
      93             : 
      94           0 :   key.class = class;
      95           0 :   key.type = type;
      96           0 :   key.pad = 0;
      97             : 
      98           0 :   p = hash_get_mem (nm->nsh_option_map_by_key, &key);
      99             :   /* not registered */
     100           0 :   if (p == 0)
     101             :     {
     102           0 :       return NULL;
     103             :     }
     104             : 
     105           0 :   return pool_elt_at_index (nm->nsh_option_mappings, p[0]);
     106             : 
     107             : }
     108             : 
     109             : /* Uses network order's class and type to unregister */
     110             : int
     111           0 : nsh_md2_unregister_option (u16 class,
     112             :                            u8 type,
     113             :                            int options (vlib_buffer_t * b,
     114             :                                         nsh_tlv_header_t * opt),
     115             :                            u8 * trace (u8 * s, nsh_tlv_header_t * opt))
     116             : {
     117           0 :   nsh_main_t *nm = &nsh_main;
     118             :   nsh_option_map_by_key_t key, *key_copy;
     119             :   uword *p;
     120             :   hash_pair_t *hp;
     121             :   nsh_option_map_t *nsh_option;
     122             : 
     123           0 :   key.class = class;
     124           0 :   key.type = type;
     125           0 :   key.pad = 0;
     126             : 
     127           0 :   p = hash_get_mem (nm->nsh_option_map_by_key, &key);
     128             :   /* not registered */
     129           0 :   if (p == 0)
     130             :     {
     131           0 :       return (-1);
     132             :     }
     133             : 
     134           0 :   nsh_option = pool_elt_at_index (nm->nsh_option_mappings, p[0]);
     135           0 :   nm->options[nsh_option->option_id] = NULL;
     136           0 :   nm->add_options[nsh_option->option_id] = NULL;
     137           0 :   nm->pop_options[nsh_option->option_id] = NULL;
     138           0 :   nm->trace[nsh_option->option_id] = NULL;
     139             : 
     140           0 :   hp = hash_get_pair (nm->nsh_option_map_by_key, &key);
     141           0 :   key_copy = (void *) (hp->key);
     142           0 :   hash_unset_mem (nm->nsh_option_map_by_key, &key_copy);
     143           0 :   clib_mem_free (key_copy);
     144             : 
     145           0 :   pool_put (nm->nsh_option_mappings, nsh_option);
     146             : 
     147           0 :   return (0);
     148             : }
     149             : 
     150             : /**
     151             :  * @brief Formatting function for tracing VXLAN GPE with length
     152             :  *
     153             :  * @param *s
     154             :  * @param *args
     155             :  *
     156             :  * @return *s
     157             :  *
     158             :  */
     159             : static u8 *
     160           0 : format_nsh_tunnel_with_length (u8 * s, va_list * args)
     161             : {
     162           0 :   u32 dev_instance = va_arg (*args, u32);
     163           0 :   s = format (s, "unimplemented dev %u", dev_instance);
     164           0 :   return s;
     165             : }
     166             : 
     167             : /* *INDENT-OFF* */
     168        2879 : VNET_HW_INTERFACE_CLASS (nsh_hw_class) = {
     169             :   .name = "NSH",
     170             :   .format_header = format_nsh_tunnel_with_length,
     171             :   .build_rewrite = default_build_rewrite,
     172             :   .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
     173             : };
     174             : /* *INDENT-ON* */
     175             : 
     176             : void
     177           0 : nsh_md2_set_next_ioam_export_override (uword next)
     178             : {
     179           0 :   nsh_main_t *hm = &nsh_main;
     180           0 :   hm->decap_v4_next_override = next;
     181           0 :   return;
     182             : }
     183             : 
     184             : clib_error_t *
     185         575 : nsh_init (vlib_main_t * vm)
     186             : {
     187             :   vlib_node_t *node, *gre4_input, *gre6_input;
     188         575 :   nsh_main_t *nm = &nsh_main;
     189         575 :   clib_error_t *error = 0;
     190             :   uword next_node;
     191             :   vlib_node_registration_t *vxlan4_input, *vxlan6_input;
     192             : 
     193             :   /* Init the main structures from VPP */
     194         575 :   nm->vlib_main = vm;
     195         575 :   nm->vnet_main = vnet_get_main ();
     196             : 
     197             :   /* Various state maintenance mappings */
     198         575 :   nm->nsh_mapping_by_key = hash_create_mem (0, sizeof (u32), sizeof (uword));
     199             : 
     200             :   nm->nsh_mapping_by_mapped_key
     201         575 :     = hash_create_mem (0, sizeof (u32), sizeof (uword));
     202             : 
     203         575 :   nm->nsh_entry_by_key = hash_create_mem (0, sizeof (u32), sizeof (uword));
     204             : 
     205             :   nm->nsh_proxy_session_by_key
     206         575 :     =
     207         575 :     hash_create_mem (0, sizeof (nsh_proxy_session_by_key_t), sizeof (uword));
     208             : 
     209             :   nm->nsh_option_map_by_key
     210         575 :     = hash_create_mem (0, sizeof (nsh_option_map_by_key_t), sizeof (uword));
     211             : 
     212         575 :   error = nsh_api_init (vm, nm);
     213         575 :   if (error)
     214           0 :     return error;
     215             : 
     216         575 :   node = vlib_get_node_by_name (vm, (u8 *) "nsh-input");
     217         575 :   nm->nsh_input_node_index = node->index;
     218             : 
     219         575 :   node = vlib_get_node_by_name (vm, (u8 *) "nsh-proxy");
     220         575 :   nm->nsh_proxy_node_index = node->index;
     221             : 
     222         575 :   node = vlib_get_node_by_name (vm, (u8 *) "nsh-classifier");
     223         575 :   nm->nsh_classifier_node_index = node->index;
     224             : 
     225             :   /* Add dispositions to nodes that feed nsh-input */
     226             :   //alagalah - validate we don't really need to use the node value
     227             :   next_node =
     228         575 :     vlib_node_add_next (vm, vxlan4_gpe_input_node.index,
     229         575 :                         nm->nsh_input_node_index);
     230         575 :   vlib_node_add_next (vm, vxlan4_gpe_input_node.index,
     231         575 :                       nm->nsh_proxy_node_index);
     232         575 :   vlib_node_add_next (vm, vxlan4_gpe_input_node.index,
     233         575 :                       nsh_aware_vnf_proxy_node.index);
     234         575 :   vxlan_gpe_register_decap_protocol (VXLAN_GPE_PROTOCOL_NSH, next_node);
     235             : 
     236         575 :   vlib_node_add_next (vm, vxlan6_gpe_input_node.index,
     237         575 :                       nm->nsh_input_node_index);
     238         575 :   vlib_node_add_next (vm, vxlan6_gpe_input_node.index,
     239         575 :                       nm->nsh_proxy_node_index);
     240         575 :   vlib_node_add_next (vm, vxlan6_gpe_input_node.index,
     241         575 :                       nsh_aware_vnf_proxy_node.index);
     242             : 
     243         575 :   gre4_input = vlib_get_node_by_name (vm, (u8 *) "gre4-input");
     244         575 :   gre6_input = vlib_get_node_by_name (vm, (u8 *) "gre6-input");
     245         575 :   if (gre4_input == 0 || gre6_input == 0)
     246             :     {
     247           0 :       error = clib_error_return (0, "gre_plugin.so is not loaded");
     248           0 :       return error;
     249             :     }
     250         575 :   vlib_node_add_next (vm, gre4_input->index, nm->nsh_input_node_index);
     251         575 :   vlib_node_add_next (vm, gre4_input->index, nm->nsh_proxy_node_index);
     252         575 :   vlib_node_add_next (vm, gre4_input->index, nsh_aware_vnf_proxy_node.index);
     253         575 :   vlib_node_add_next (vm, gre6_input->index, nm->nsh_input_node_index);
     254         575 :   vlib_node_add_next (vm, gre6_input->index, nm->nsh_proxy_node_index);
     255         575 :   vlib_node_add_next (vm, gre6_input->index, nsh_aware_vnf_proxy_node.index);
     256             : 
     257             :   /* Add NSH-Proxy support */
     258             :   vxlan4_input =
     259         575 :     vlib_get_plugin_symbol ("vxlan_plugin.so", "vxlan4_input_node");
     260             :   vxlan6_input =
     261         575 :     vlib_get_plugin_symbol ("vxlan_plugin.so", "vxlan6_input_node");
     262         575 :   if (vxlan4_input == 0 || vxlan6_input == 0)
     263             :     {
     264           0 :       error = clib_error_return (0, "vxlan_plugin.so is not loaded");
     265           0 :       return error;
     266             :     }
     267         575 :   vlib_node_add_next (vm, vxlan4_input->index, nm->nsh_proxy_node_index);
     268         575 :   vlib_node_add_next (vm, vxlan6_input->index, nm->nsh_proxy_node_index);
     269             : 
     270             :   /* Add NSH-Classifier support */
     271         575 :   vlib_node_add_next (vm, ip4_classify_node.index,
     272         575 :                       nm->nsh_classifier_node_index);
     273         575 :   vlib_node_add_next (vm, ip6_classify_node.index,
     274         575 :                       nm->nsh_classifier_node_index);
     275         575 :   vlib_node_add_next (vm, l2_input_classify_node.index,
     276         575 :                       nm->nsh_classifier_node_index);
     277             : 
     278             :   /* Add Ethernet+NSH support */
     279         575 :   ethernet_register_input_type (vm, ETHERNET_TYPE_NSH,
     280             :                                 nm->nsh_input_node_index);
     281             : 
     282         575 :   return error;
     283             : }
     284             : 
     285        1151 : VLIB_INIT_FUNCTION (nsh_init);
     286             : 
     287             : /* *INDENT-OFF* */
     288             : VLIB_PLUGIN_REGISTER () = {
     289             :     .version = VPP_BUILD_VER,
     290             :     .description = "Network Service Header (NSH)",
     291             : };
     292             : /* *INDENT-ON* */
     293             : 
     294             : /*
     295             :  * fd.io coding-style-patch-verification: ON
     296             :  *
     297             :  * Local Variables:
     298             :  * eval: (c-set-style "gnu")
     299             :  * End:
     300             :  */

Generated by: LCOV version 1.14