LCOV - code coverage report
Current view: top level - plugins/nsh - nsh_api.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 4 299 1.3 %
Date: 2023-10-26 01:39:38 Functions: 3 15 20.0 %

          Line data    Source code
       1             : /*
       2             :  * nsh_api.c - nsh mapping api
       3             :  *
       4             :  * Copyright (c) 2019 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             : #include <vnet/vnet.h>
      18             : #include <vnet/plugin/plugin.h>
      19             : #include <nsh/nsh.h>
      20             : 
      21             : #include <vlibapi/api.h>
      22             : #include <vlibmemory/api.h>
      23             : #include <vpp/app/version.h>
      24             : #include <vlibapi/api_helper_macros.h>
      25             : 
      26             : #include <plugins/nsh/nsh.api_enum.h>
      27             : #include <plugins/nsh/nsh.api_types.h>
      28             : 
      29             : /**
      30             :  * @brief CLI function for NSH admin up/down
      31             :  *
      32             :  * @param *vnm
      33             :  * @param nsh_hw_if
      34             :  * @param flag
      35             :  *
      36             :  * @return *rc
      37             :  *
      38             :  */
      39             : static clib_error_t *
      40           0 : nsh_interface_admin_up_down (vnet_main_t * vnm, u32 nsh_hw_if, u32 flags)
      41             : {
      42           0 :   if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
      43           0 :     vnet_hw_interface_set_flags (vnm, nsh_hw_if,
      44             :                                  VNET_HW_INTERFACE_FLAG_LINK_UP);
      45             :   else
      46           0 :     vnet_hw_interface_set_flags (vnm, nsh_hw_if, 0);
      47             : 
      48           0 :   return 0;
      49             : }
      50             : 
      51             : /**
      52             :  * @brief Naming for NSH tunnel
      53             :  *
      54             :  * @param *s formatting string
      55             :  * @param *args
      56             :  *
      57             :  * @return *s formatted string
      58             :  *
      59             :  */
      60             : static u8 *
      61           0 : format_nsh_name (u8 * s, va_list * args)
      62             : {
      63           0 :   u32 dev_instance = va_arg (*args, u32);
      64           0 :   return format (s, "nsh_tunnel%d", dev_instance);
      65             : }
      66             : 
      67             : /* *INDENT-OFF* */
      68        5183 : VNET_DEVICE_CLASS (nsh_device_class, static) = {
      69             :   .name = "NSH",
      70             :   .format_device_name = format_nsh_name,
      71             :   .admin_up_down_function = nsh_interface_admin_up_down,
      72             : };
      73             : /* *INDENT-ON* */
      74             : 
      75           0 : static void send_nsh_entry_details
      76             :   (nsh_entry_t * t, vl_api_registration_t * rp, u32 context)
      77             : {
      78             :   vl_api_nsh_entry_details_t *rmp;
      79           0 :   nsh_main_t *nm = &nsh_main;
      80             : 
      81           0 :   rmp = vl_msg_api_alloc (sizeof (*rmp));
      82           0 :   clib_memset (rmp, 0, sizeof (*rmp));
      83             : 
      84           0 :   rmp->_vl_msg_id = ntohs ((VL_API_NSH_ENTRY_DETAILS) + nm->msg_id_base);
      85           0 :   rmp->ver_o_c = t->nsh_base.ver_o_c;
      86           0 :   rmp->ttl = (t->nsh_base.ver_o_c & NSH_TTL_H4_MASK) << 2 |
      87           0 :     (t->nsh_base.length & NSH_TTL_L2_MASK) >> 6;
      88           0 :   rmp->length = t->nsh_base.length & NSH_LEN_MASK;
      89           0 :   rmp->md_type = t->nsh_base.md_type;
      90           0 :   rmp->next_protocol = t->nsh_base.next_protocol;
      91           0 :   rmp->nsp_nsi = htonl (t->nsh_base.nsp_nsi);
      92             : 
      93           0 :   if (t->nsh_base.md_type == 1)
      94             :     {
      95           0 :       rmp->tlv_length = 4;
      96           0 :       rmp->c1 = htonl (t->md.md1_data.c1);
      97           0 :       rmp->c2 = htonl (t->md.md1_data.c2);
      98           0 :       rmp->c3 = htonl (t->md.md1_data.c3);
      99           0 :       rmp->c4 = htonl (t->md.md1_data.c4);
     100             :     }
     101           0 :   else if (t->nsh_base.md_type == 2)
     102             :     {
     103           0 :       rmp->tlv_length = t->tlvs_len;
     104           0 :       clib_memcpy (rmp->tlv, t->tlvs_data, t->tlvs_len);
     105             :     }
     106             : 
     107           0 :   rmp->context = context;
     108             : 
     109           0 :   vl_api_send_msg (rp, (u8 *) rmp);
     110           0 : }
     111             : 
     112           0 : static void send_nsh_map_details
     113             :   (nsh_map_t * t, vl_api_registration_t * rp, u32 context)
     114             : {
     115             :   vl_api_nsh_map_details_t *rmp;
     116           0 :   nsh_main_t *nm = &nsh_main;
     117             : 
     118           0 :   rmp = vl_msg_api_alloc (sizeof (*rmp));
     119           0 :   clib_memset (rmp, 0, sizeof (*rmp));
     120             : 
     121           0 :   rmp->_vl_msg_id = ntohs ((VL_API_NSH_MAP_DETAILS) + nm->msg_id_base);
     122           0 :   rmp->nsp_nsi = htonl (t->nsp_nsi);
     123           0 :   rmp->mapped_nsp_nsi = htonl (t->mapped_nsp_nsi);
     124           0 :   rmp->nsh_action = htonl (t->nsh_action);
     125           0 :   rmp->sw_if_index = htonl (t->sw_if_index);
     126           0 :   rmp->rx_sw_if_index = htonl (t->rx_sw_if_index);
     127           0 :   rmp->next_node = htonl (t->next_node);
     128             : 
     129           0 :   rmp->context = context;
     130             : 
     131           0 :   vl_api_send_msg (rp, (u8 *) rmp);
     132           0 : }
     133             : 
     134             : static void
     135           0 : vl_api_nsh_map_dump_t_handler (vl_api_nsh_map_dump_t * mp)
     136             : {
     137           0 :   nsh_main_t *nm = &nsh_main;
     138             :   nsh_map_t *t;
     139             :   u32 map_index;
     140             :   vl_api_registration_t *rp;
     141             : 
     142           0 :   rp = vl_api_client_index_to_registration (mp->client_index);
     143           0 :   if (rp == 0)
     144           0 :     return;
     145             : 
     146           0 :   map_index = ntohl (mp->map_index);
     147             : 
     148           0 :   if (~0 == map_index)
     149             :     {
     150           0 :       pool_foreach (t, nm->nsh_mappings)
     151             :       {
     152           0 :         send_nsh_map_details (t, rp, mp->context);
     153             :       }
     154             :     }
     155             :   else
     156             :     {
     157           0 :       if (map_index >= vec_len (nm->nsh_mappings))
     158             :         {
     159           0 :           return;
     160             :         }
     161           0 :       t = &nm->nsh_mappings[map_index];
     162           0 :       send_nsh_map_details (t, rp, mp->context);
     163             :     }
     164             : }
     165             : 
     166             : /** API message handler */
     167             : static void
     168           0 : vl_api_nsh_add_del_map_t_handler (vl_api_nsh_add_del_map_t * mp)
     169             : {
     170             :   vl_api_nsh_add_del_map_reply_t *rmp;
     171             :   int rv;
     172           0 :   nsh_add_del_map_args_t _a = { 0 }, *a = &_a;
     173           0 :   u32 map_index = ~0;
     174             : 
     175           0 :   a->is_add = mp->is_add;
     176           0 :   a->map.nsp_nsi = ntohl (mp->nsp_nsi);
     177           0 :   a->map.mapped_nsp_nsi = ntohl (mp->mapped_nsp_nsi);
     178           0 :   a->map.nsh_action = ntohl (mp->nsh_action);
     179           0 :   a->map.sw_if_index = ntohl (mp->sw_if_index);
     180           0 :   a->map.rx_sw_if_index = ntohl (mp->rx_sw_if_index);
     181           0 :   a->map.next_node = ntohl (mp->next_node);
     182             : 
     183           0 :   rv = nsh_add_del_map (a, &map_index);
     184             : 
     185           0 :   if ((a->map.next_node == NSH_NODE_NEXT_ENCAP_VXLAN4)
     186           0 :       | (a->map.next_node == NSH_NODE_NEXT_ENCAP_VXLAN6))
     187             :     {
     188           0 :       rv = nsh_add_del_proxy_session (a);
     189             :     }
     190             : 
     191           0 :   REPLY_MACRO2 (VL_API_NSH_ADD_DEL_MAP_REPLY, (
     192             :                                                 {
     193             :                                                 rmp->map_index =
     194             :                                                 htonl (map_index);
     195             :                                                 }
     196             :                 ));
     197             : }
     198             : 
     199             : int
     200           0 : nsh_header_rewrite (nsh_entry_t * nsh_entry)
     201             : {
     202           0 :   u8 *rw = 0;
     203           0 :   int len = 0;
     204             :   nsh_base_header_t *nsh_base;
     205             :   nsh_md1_data_t *nsh_md1;
     206           0 :   nsh_main_t *nm = &nsh_main;
     207             :   nsh_md2_data_t *opt0;
     208             :   nsh_md2_data_t *limit0;
     209             :   nsh_md2_data_t *nsh_md2;
     210           0 :   nsh_option_map_t _nsh_option, *nsh_option = &_nsh_option;
     211           0 :   u8 old_option_size = 0;
     212           0 :   u8 new_option_size = 0;
     213             : 
     214           0 :   vec_free (nsh_entry->rewrite);
     215           0 :   if (nsh_entry->nsh_base.md_type == 1)
     216             :     {
     217           0 :       len = sizeof (nsh_base_header_t) + sizeof (nsh_md1_data_t);
     218             :     }
     219           0 :   else if (nsh_entry->nsh_base.md_type == 2)
     220             :     {
     221             :       /* set to maxim, maybe dataplane will add more TLVs */
     222           0 :       len = MAX_NSH_HEADER_LEN;
     223             :     }
     224           0 :   vec_validate_aligned (rw, len - 1, CLIB_CACHE_LINE_BYTES);
     225           0 :   clib_memset (rw, 0, len);
     226             : 
     227           0 :   nsh_base = (nsh_base_header_t *) rw;
     228           0 :   nsh_base->ver_o_c = nsh_entry->nsh_base.ver_o_c;
     229           0 :   nsh_base->length = nsh_entry->nsh_base.length;
     230           0 :   nsh_base->md_type = nsh_entry->nsh_base.md_type;
     231           0 :   nsh_base->next_protocol = nsh_entry->nsh_base.next_protocol;
     232           0 :   nsh_base->nsp_nsi = clib_host_to_net_u32 (nsh_entry->nsh_base.nsp_nsi);
     233             : 
     234           0 :   if (nsh_base->md_type == 1)
     235             :     {
     236           0 :       nsh_md1 = (nsh_md1_data_t *) (rw + sizeof (nsh_base_header_t));
     237           0 :       nsh_md1->c1 = clib_host_to_net_u32 (nsh_entry->md.md1_data.c1);
     238           0 :       nsh_md1->c2 = clib_host_to_net_u32 (nsh_entry->md.md1_data.c2);
     239           0 :       nsh_md1->c3 = clib_host_to_net_u32 (nsh_entry->md.md1_data.c3);
     240           0 :       nsh_md1->c4 = clib_host_to_net_u32 (nsh_entry->md.md1_data.c4);
     241           0 :       nsh_entry->rewrite_size = 24;
     242             :     }
     243           0 :   else if (nsh_base->md_type == 2)
     244             :     {
     245           0 :       opt0 = (nsh_md2_data_t *) (nsh_entry->tlvs_data);
     246           0 :       limit0 = (nsh_md2_data_t *) ((u8 *) opt0 + nsh_entry->tlvs_len);
     247             : 
     248           0 :       nsh_md2 = (nsh_md2_data_t *) (rw + sizeof (nsh_base_header_t));
     249           0 :       nsh_entry->rewrite_size = sizeof (nsh_base_header_t);
     250             : 
     251           0 :       while (opt0 < limit0)
     252             :         {
     253           0 :           old_option_size = sizeof (nsh_md2_data_t) + opt0->length;
     254             :           /* round to 4-byte */
     255           0 :           old_option_size = ((old_option_size + 3) >> 2) << 2;
     256             : 
     257           0 :           nsh_option = nsh_md2_lookup_option (opt0->class, opt0->type);
     258           0 :           if (nsh_option == NULL)
     259             :             {
     260           0 :               goto next_tlv_md2;
     261             :             }
     262             : 
     263           0 :           if (nm->add_options[nsh_option->option_id] != NULL)
     264             :             {
     265           0 :               if (0 != nm->add_options[nsh_option->option_id] ((u8 *) nsh_md2,
     266             :                                                                &new_option_size))
     267             :                 {
     268           0 :                   goto next_tlv_md2;
     269             :                 }
     270             : 
     271             :               /* round to 4-byte */
     272           0 :               new_option_size = ((new_option_size + 3) >> 2) << 2;
     273             : 
     274           0 :               nsh_entry->rewrite_size += new_option_size;
     275           0 :               nsh_md2 =
     276           0 :                 (nsh_md2_data_t *) (((u8 *) nsh_md2) + new_option_size);
     277           0 :               opt0 = (nsh_md2_data_t *) (((u8 *) opt0) + old_option_size);
     278             :             }
     279             :           else
     280             :             {
     281           0 :             next_tlv_md2:
     282           0 :               opt0 = (nsh_md2_data_t *) (((u8 *) opt0) + old_option_size);
     283             :             }
     284             : 
     285             :         }
     286             :     }
     287             : 
     288           0 :   nsh_entry->rewrite = rw;
     289           0 :   nsh_base->length = (nsh_base->length & NSH_TTL_L2_MASK) |
     290           0 :     ((nsh_entry->rewrite_size >> 2) & NSH_LEN_MASK);
     291             : 
     292           0 :   return 0;
     293             : }
     294             : 
     295             : extern vnet_hw_interface_class_t nsh_hw_class;
     296             : 
     297             : /**
     298             :  * Action function to add or del an nsh map.
     299             :  * Shared by both CLI and binary API
     300             :  **/
     301             : int
     302           0 : nsh_add_del_map (nsh_add_del_map_args_t * a, u32 * map_indexp)
     303             : {
     304           0 :   nsh_main_t *nm = &nsh_main;
     305           0 :   vnet_main_t *vnm = nm->vnet_main;
     306           0 :   nsh_map_t *map = 0;
     307             :   u32 key, *key_copy;
     308             :   uword *entry;
     309             :   hash_pair_t *hp;
     310           0 :   u32 map_index = ~0;
     311             :   vnet_hw_interface_t *hi;
     312           0 :   u32 nsh_hw_if = ~0;
     313           0 :   u32 nsh_sw_if = ~0;
     314             : 
     315             :   /* net order, so data plane could use nsh header to lookup directly */
     316           0 :   key = clib_host_to_net_u32 (a->map.nsp_nsi);
     317             : 
     318           0 :   entry = hash_get_mem (nm->nsh_mapping_by_key, &key);
     319             : 
     320           0 :   if (a->is_add)
     321             :     {
     322             :       /* adding an entry, must not already exist */
     323           0 :       if (entry)
     324           0 :         return -1;              //TODO API_ERROR_INVALID_VALUE;
     325             : 
     326           0 :       pool_get_aligned (nm->nsh_mappings, map, CLIB_CACHE_LINE_BYTES);
     327           0 :       clib_memset (map, 0, sizeof (*map));
     328             : 
     329             :       /* copy from arg structure */
     330           0 :       map->nsp_nsi = a->map.nsp_nsi;
     331           0 :       map->mapped_nsp_nsi = a->map.mapped_nsp_nsi;
     332           0 :       map->nsh_action = a->map.nsh_action;
     333           0 :       map->sw_if_index = a->map.sw_if_index;
     334           0 :       map->rx_sw_if_index = a->map.rx_sw_if_index;
     335           0 :       map->next_node = a->map.next_node;
     336           0 :       map->adj_index = a->map.adj_index;
     337             : 
     338             : 
     339           0 :       key_copy = clib_mem_alloc (sizeof (*key_copy));
     340           0 :       clib_memcpy (key_copy, &key, sizeof (*key_copy));
     341             : 
     342           0 :       hash_set_mem (nm->nsh_mapping_by_key, key_copy, map - nm->nsh_mappings);
     343           0 :       map_index = map - nm->nsh_mappings;
     344             : 
     345           0 :       if (vec_len (nm->free_nsh_tunnel_hw_if_indices) > 0)
     346             :         {
     347           0 :           nsh_hw_if = nm->free_nsh_tunnel_hw_if_indices
     348           0 :             [vec_len (nm->free_nsh_tunnel_hw_if_indices) - 1];
     349           0 :           vec_dec_len (nm->free_nsh_tunnel_hw_if_indices, 1);
     350             : 
     351           0 :           hi = vnet_get_hw_interface (vnm, nsh_hw_if);
     352           0 :           hi->dev_instance = map_index;
     353           0 :           hi->hw_instance = hi->dev_instance;
     354             :         }
     355             :       else
     356             :         {
     357           0 :           nsh_hw_if = vnet_register_interface
     358             :             (vnm, nsh_device_class.index, map_index, nsh_hw_class.index,
     359             :              map_index);
     360           0 :           hi = vnet_get_hw_interface (vnm, nsh_hw_if);
     361           0 :           hi->output_node_index = nsh_aware_vnf_proxy_node.index;
     362             :         }
     363             : 
     364           0 :       map->nsh_hw_if = nsh_hw_if;
     365           0 :       map->nsh_sw_if = nsh_sw_if = hi->sw_if_index;
     366           0 :       vec_validate_init_empty (nm->tunnel_index_by_sw_if_index, nsh_sw_if,
     367             :                                ~0);
     368           0 :       nm->tunnel_index_by_sw_if_index[nsh_sw_if] = key;
     369             : 
     370           0 :       vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
     371             :                                    VNET_SW_INTERFACE_FLAG_ADMIN_UP);
     372             :     }
     373             :   else
     374             :     {
     375           0 :       if (!entry)
     376           0 :         return -2;              //TODO API_ERROR_NO_SUCH_ENTRY;
     377             : 
     378           0 :       map = pool_elt_at_index (nm->nsh_mappings, entry[0]);
     379             : 
     380           0 :       vnet_sw_interface_set_flags (vnm, map->nsh_sw_if,
     381             :                                    VNET_SW_INTERFACE_FLAG_ADMIN_DOWN);
     382           0 :       vec_add1 (nm->free_nsh_tunnel_hw_if_indices, map->nsh_sw_if);
     383           0 :       nm->tunnel_index_by_sw_if_index[map->nsh_sw_if] = ~0;
     384             : 
     385           0 :       hp = hash_get_pair (nm->nsh_mapping_by_key, &key);
     386           0 :       key_copy = (void *) (hp->key);
     387           0 :       hash_unset_mem (nm->nsh_mapping_by_key, &key);
     388           0 :       clib_mem_free (key_copy);
     389             : 
     390           0 :       pool_put (nm->nsh_mappings, map);
     391             :     }
     392             : 
     393           0 :   if (map_indexp)
     394           0 :     *map_indexp = map_index;
     395             : 
     396           0 :   return 0;
     397             : }
     398             : 
     399             : /**
     400             :  * Action function to add or del an nsh-proxy-session.
     401             :  * Shared by both CLI and binary API
     402             :  **/
     403             : int
     404           0 : nsh_add_del_proxy_session (nsh_add_del_map_args_t * a)
     405             : {
     406           0 :   nsh_main_t *nm = &nsh_main;
     407           0 :   nsh_proxy_session_t *proxy = 0;
     408             :   nsh_proxy_session_by_key_t key, *key_copy;
     409             :   uword *entry;
     410             :   hash_pair_t *hp;
     411           0 :   u32 nsp = 0, nsi = 0;
     412             : 
     413           0 :   clib_memset (&key, 0, sizeof (key));
     414           0 :   key.transport_type = a->map.next_node;
     415           0 :   key.transport_index = a->map.sw_if_index;
     416             : 
     417           0 :   entry = hash_get_mem (nm->nsh_proxy_session_by_key, &key);
     418             : 
     419           0 :   if (a->is_add)
     420             :     {
     421             :       /* adding an entry, must not already exist */
     422           0 :       if (entry)
     423           0 :         return -1;              //TODO API_ERROR_INVALID_VALUE;
     424             : 
     425           0 :       pool_get_aligned (nm->nsh_proxy_sessions, proxy, CLIB_CACHE_LINE_BYTES);
     426           0 :       clib_memset (proxy, 0, sizeof (*proxy));
     427             : 
     428             :       /* Nsi needs to minus 1 within NSH-Proxy */
     429           0 :       nsp = (a->map.nsp_nsi >> NSH_NSP_SHIFT) & NSH_NSP_MASK;
     430           0 :       nsi = a->map.nsp_nsi & NSH_NSI_MASK;
     431           0 :       if (nsi == 0)
     432           0 :         return -1;
     433             : 
     434           0 :       nsi = nsi - 1;
     435             :       /* net order, so could use it to lookup nsh map table directly */
     436           0 :       proxy->nsp_nsi = clib_host_to_net_u32 ((nsp << NSH_NSP_SHIFT) | nsi);
     437             : 
     438           0 :       key_copy = clib_mem_alloc (sizeof (*key_copy));
     439           0 :       clib_memcpy (key_copy, &key, sizeof (*key_copy));
     440             : 
     441           0 :       hash_set_mem (nm->nsh_proxy_session_by_key, key_copy,
     442             :                     proxy - nm->nsh_proxy_sessions);
     443             :     }
     444             :   else
     445             :     {
     446           0 :       if (!entry)
     447           0 :         return -2;              //TODO API_ERROR_NO_SUCH_ENTRY;
     448             : 
     449           0 :       proxy = pool_elt_at_index (nm->nsh_proxy_sessions, entry[0]);
     450           0 :       hp = hash_get_pair (nm->nsh_proxy_session_by_key, &key);
     451           0 :       key_copy = (void *) (hp->key);
     452           0 :       hash_unset_mem (nm->nsh_proxy_session_by_key, &key);
     453           0 :       clib_mem_free (key_copy);
     454             : 
     455           0 :       pool_put (nm->nsh_proxy_sessions, proxy);
     456             :     }
     457             : 
     458           0 :   return 0;
     459             : }
     460             : 
     461             : /**
     462             :  * Action function for adding an NSH entry
     463             :  * nsh_add_del_entry_args_t *a: host order
     464             :  */
     465             : int
     466           0 : nsh_add_del_entry (nsh_add_del_entry_args_t * a, u32 * entry_indexp)
     467             : {
     468           0 :   nsh_main_t *nm = &nsh_main;
     469           0 :   nsh_entry_t *nsh_entry = 0;
     470             :   u32 key, *key_copy;
     471             :   uword *entry_id;
     472             :   hash_pair_t *hp;
     473           0 :   u32 entry_index = ~0;
     474           0 :   u8 tlvs_len = 0;
     475           0 :   u8 *data = 0;
     476             : 
     477             :   /* host order, because nsh map table stores nsp_nsi in host order */
     478           0 :   key = a->nsh_entry.nsh_base.nsp_nsi;
     479             : 
     480           0 :   entry_id = hash_get_mem (nm->nsh_entry_by_key, &key);
     481             : 
     482           0 :   if (a->is_add)
     483             :     {
     484             :       /* adding an entry, must not already exist */
     485           0 :       if (entry_id)
     486           0 :         return -1;              // TODO VNET_API_ERROR_INVALID_VALUE;
     487             : 
     488           0 :       pool_get_aligned (nm->nsh_entries, nsh_entry, CLIB_CACHE_LINE_BYTES);
     489           0 :       clib_memset (nsh_entry, 0, sizeof (*nsh_entry));
     490             : 
     491             :       /* copy from arg structure */
     492             : #define _(x) nsh_entry->nsh_base.x = a->nsh_entry.nsh_base.x;
     493           0 :       foreach_copy_nsh_base_hdr_field;
     494             : #undef _
     495             : 
     496           0 :       if (a->nsh_entry.nsh_base.md_type == 1)
     497             :         {
     498           0 :           nsh_entry->md.md1_data.c1 = a->nsh_entry.md.md1_data.c1;
     499           0 :           nsh_entry->md.md1_data.c2 = a->nsh_entry.md.md1_data.c2;
     500           0 :           nsh_entry->md.md1_data.c3 = a->nsh_entry.md.md1_data.c3;
     501           0 :           nsh_entry->md.md1_data.c4 = a->nsh_entry.md.md1_data.c4;
     502             :         }
     503           0 :       else if (a->nsh_entry.nsh_base.md_type == 2)
     504             :         {
     505           0 :           vec_free (nsh_entry->tlvs_data);
     506           0 :           tlvs_len = a->nsh_entry.tlvs_len;
     507           0 :           vec_validate_aligned (data, tlvs_len - 1, CLIB_CACHE_LINE_BYTES);
     508             : 
     509           0 :           clib_memcpy (data, a->nsh_entry.tlvs_data, tlvs_len);
     510           0 :           nsh_entry->tlvs_data = data;
     511           0 :           nsh_entry->tlvs_len = tlvs_len;
     512           0 :           vec_free (a->nsh_entry.tlvs_data);
     513             :         }
     514             : 
     515           0 :       nsh_header_rewrite (nsh_entry);
     516             : 
     517           0 :       key_copy = clib_mem_alloc (sizeof (*key_copy));
     518           0 :       clib_memcpy (key_copy, &key, sizeof (*key_copy));
     519             : 
     520           0 :       hash_set_mem (nm->nsh_entry_by_key, key_copy,
     521             :                     nsh_entry - nm->nsh_entries);
     522           0 :       entry_index = nsh_entry - nm->nsh_entries;
     523             :     }
     524             :   else
     525             :     {
     526           0 :       if (!entry_id)
     527           0 :         return -2;              //TODO API_ERROR_NO_SUCH_ENTRY;
     528             : 
     529           0 :       nsh_entry = pool_elt_at_index (nm->nsh_entries, entry_id[0]);
     530           0 :       hp = hash_get_pair (nm->nsh_entry_by_key, &key);
     531           0 :       key_copy = (void *) (hp->key);
     532           0 :       hash_unset_mem (nm->nsh_entry_by_key, &key);
     533           0 :       clib_mem_free (key_copy);
     534             : 
     535           0 :       vec_free (nsh_entry->tlvs_data);
     536           0 :       vec_free (nsh_entry->rewrite);
     537           0 :       pool_put (nm->nsh_entries, nsh_entry);
     538             :     }
     539             : 
     540           0 :   if (entry_indexp)
     541           0 :     *entry_indexp = entry_index;
     542             : 
     543           0 :   return 0;
     544             : }
     545             : 
     546             : 
     547             : /** API message handler */
     548           0 : static void vl_api_nsh_add_del_entry_t_handler
     549             :   (vl_api_nsh_add_del_entry_t * mp)
     550             : {
     551             :   vl_api_nsh_add_del_entry_reply_t *rmp;
     552             :   int rv;
     553           0 :   nsh_add_del_entry_args_t _a = { 0 }, *a = &_a;
     554           0 :   u32 entry_index = ~0;
     555           0 :   u8 tlvs_len = 0;
     556           0 :   u8 *data = 0;
     557             : 
     558           0 :   a->is_add = mp->is_add;
     559           0 :   a->nsh_entry.nsh_base.ver_o_c =
     560           0 :     (mp->ver_o_c & 0xF0) | ((mp->ttl & NSH_LEN_MASK) >> 2);
     561           0 :   a->nsh_entry.nsh_base.length =
     562           0 :     (mp->length & NSH_LEN_MASK) | ((mp->ttl & 0x3) << 6);
     563           0 :   a->nsh_entry.nsh_base.md_type = mp->md_type;
     564           0 :   a->nsh_entry.nsh_base.next_protocol = mp->next_protocol;
     565           0 :   a->nsh_entry.nsh_base.nsp_nsi = ntohl (mp->nsp_nsi);
     566           0 :   if (mp->md_type == 1)
     567             :     {
     568           0 :       a->nsh_entry.md.md1_data.c1 = ntohl (mp->c1);
     569           0 :       a->nsh_entry.md.md1_data.c2 = ntohl (mp->c2);
     570           0 :       a->nsh_entry.md.md1_data.c3 = ntohl (mp->c3);
     571           0 :       a->nsh_entry.md.md1_data.c4 = ntohl (mp->c4);
     572             :     }
     573           0 :   else if (mp->md_type == 2)
     574             :     {
     575           0 :       tlvs_len = mp->tlv_length;
     576           0 :       vec_validate_aligned (data, tlvs_len - 1, CLIB_CACHE_LINE_BYTES);
     577             : 
     578           0 :       clib_memcpy (data, mp->tlv, tlvs_len);
     579           0 :       a->nsh_entry.tlvs_data = data;
     580           0 :       a->nsh_entry.tlvs_len = tlvs_len;
     581             :     }
     582             : 
     583           0 :   rv = nsh_add_del_entry (a, &entry_index);
     584             : 
     585           0 :   REPLY_MACRO2 (VL_API_NSH_ADD_DEL_ENTRY_REPLY, (
     586             :                                                   {
     587             :                                                   rmp->entry_index =
     588             :                                                   htonl (entry_index);
     589             :                                                   }
     590             :                 ));
     591             : }
     592             : 
     593             : static void
     594           0 : vl_api_nsh_entry_dump_t_handler (vl_api_nsh_entry_dump_t * mp)
     595             : {
     596           0 :   nsh_main_t *nm = &nsh_main;
     597             :   nsh_entry_t *t;
     598             :   u32 entry_index;
     599             :   vl_api_registration_t *rp;
     600             : 
     601           0 :   rp = vl_api_client_index_to_registration (mp->client_index);
     602           0 :   if (rp == 0)
     603           0 :     return;
     604             : 
     605           0 :   entry_index = ntohl (mp->entry_index);
     606             : 
     607           0 :   if (~0 == entry_index)
     608             :     {
     609           0 :       pool_foreach (t, nm->nsh_entries)
     610             :       {
     611           0 :         send_nsh_entry_details (t, rp, mp->context);
     612             :       }
     613             :     }
     614             :   else
     615             :     {
     616           0 :       if (entry_index >= vec_len (nm->nsh_entries))
     617             :         {
     618           0 :           return;
     619             :         }
     620           0 :       t = &nm->nsh_entries[entry_index];
     621           0 :       send_nsh_entry_details (t, rp, mp->context);
     622             :     }
     623             : }
     624             : 
     625             : #include <nsh/nsh.api.c>
     626             : 
     627             : /* Set up the API message handling tables */
     628             : clib_error_t *
     629         575 : nsh_api_init (vlib_main_t * vm, nsh_main_t * nm)
     630             : {
     631             :   /* Add our API messages to the global name_crc hash table */
     632         575 :   nm->msg_id_base = setup_message_id_table ();
     633             : 
     634         575 :   return 0;
     635             : }
     636             : 
     637             : /*
     638             :  * fd.io coding-style-patch-verification: ON
     639             :  *
     640             :  * Local Variables:
     641             :  * eval: (c-set-style "gnu")
     642             :  * End:
     643             :  */

Generated by: LCOV version 1.14