LCOV - code coverage report
Current view: top level - plugins/nsh - nsh_pop.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 2 124 1.6 %
Date: 2023-10-26 01:39:38 Functions: 6 11 54.5 %

          Line data    Source code
       1             : /*
       2             :  * nsh_pop.c - nsh POP only processing
       3             :  *
       4             :  * Copyright (c) 2017 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 <vnet/gre/packet.h>
      22             : #include <vnet/vxlan-gpe/vxlan_gpe.h>
      23             : #include <vnet/l2/l2_classify.h>
      24             : 
      25             : #include <vlibapi/api.h>
      26             : #include <vlibmemory/api.h>
      27             : 
      28             : extern nsh_option_map_t * nsh_md2_lookup_option (u16 class, u8 type);
      29             : 
      30             : extern u8 * format_nsh_header (u8 * s, va_list * args);
      31             : extern u8 * format_nsh_node_map_trace (u8 * s, va_list * args);
      32             : extern u8 * format_nsh_pop_header (u8 * s, va_list * args);
      33             : extern u8 * format_nsh_pop_node_map_trace (u8 * s, va_list * args);
      34             : 
      35             : static uword
      36           0 : nsh_pop_inline (vlib_main_t * vm,
      37             :                vlib_node_runtime_t * node,
      38             :                vlib_frame_t * from_frame)
      39             : {
      40             :   u32 n_left_from, next_index, *from, *to_next;
      41           0 :   nsh_main_t * nm = &nsh_main;
      42             : 
      43           0 :   from = vlib_frame_vector_args(from_frame);
      44           0 :   n_left_from = from_frame->n_vectors;
      45             : 
      46           0 :   next_index = node->cached_next_index;
      47             : 
      48           0 :   while (n_left_from > 0)
      49             :     {
      50             :       u32 n_left_to_next;
      51             : 
      52           0 :       vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
      53             : 
      54           0 :       while (n_left_from >= 4 && n_left_to_next >= 2)
      55             :         {
      56             :           u32 bi0, bi1;
      57             :           vlib_buffer_t * b0, *b1;
      58           0 :           u32 next0 = NSH_NODE_NEXT_DROP, next1 = NSH_NODE_NEXT_DROP;
      59             :           uword * entry0, *entry1;
      60           0 :           nsh_base_header_t * hdr0 = 0, *hdr1 = 0;
      61           0 :           u32 header_len0 = 0, header_len1 = 0;
      62             :           u32 nsp_nsi0, nsp_nsi1;
      63             :           u32 error0, error1;
      64           0 :           nsh_map_t * map0 = 0, *map1 = 0;
      65             : 
      66             :           /* Prefetch next iteration. */
      67             :           {
      68             :             vlib_buffer_t * p2, *p3;
      69             : 
      70           0 :             p2 = vlib_get_buffer(vm, from[2]);
      71           0 :             p3 = vlib_get_buffer(vm, from[3]);
      72             : 
      73           0 :             vlib_prefetch_buffer_header(p2, LOAD);
      74           0 :             vlib_prefetch_buffer_header(p3, LOAD);
      75             : 
      76           0 :             CLIB_PREFETCH(p2->data, 2*CLIB_CACHE_LINE_BYTES, LOAD);
      77           0 :             CLIB_PREFETCH(p3->data, 2*CLIB_CACHE_LINE_BYTES, LOAD);
      78             :           }
      79             : 
      80           0 :           bi0 = from[0];
      81           0 :           bi1 = from[1];
      82           0 :           to_next[0] = bi0;
      83           0 :           to_next[1] = bi1;
      84           0 :           from += 2;
      85           0 :           to_next += 2;
      86           0 :           n_left_from -= 2;
      87           0 :           n_left_to_next -= 2;
      88             : 
      89           0 :           error0 = 0;
      90           0 :           error1 = 0;
      91             : 
      92           0 :           b0 = vlib_get_buffer(vm, bi0);
      93           0 :           b1 = vlib_get_buffer(vm, bi1);
      94           0 :           hdr0 = vlib_buffer_get_current(b0);
      95           0 :           nsp_nsi0 = hdr0->nsp_nsi;
      96           0 :           header_len0 = hdr0->length * 4;
      97             : 
      98           0 :           hdr1 = vlib_buffer_get_current(b1);
      99           0 :           nsp_nsi1 = hdr1->nsp_nsi;
     100           0 :           header_len1 = hdr1->length * 4;
     101             : 
     102             :           /* Process packet 0 */
     103           0 :           entry0 = hash_get_mem(nm->nsh_mapping_by_key, &nsp_nsi0);
     104           0 :           if (PREDICT_FALSE(entry0 == 0))
     105             :             {
     106           0 :               error0 = NSH_NODE_ERROR_NO_MAPPING;
     107           0 :               goto trace0;
     108             :             }
     109             : 
     110             :           /* Entry should point to a mapping ...*/
     111           0 :           map0 = pool_elt_at_index(nm->nsh_mappings, entry0[0]);
     112             : 
     113             :           /* set up things for next node to transmit ie which node to handle it and where */
     114           0 :           next0 = map0->next_node;
     115             :           //vnet_buffer(b0)->sw_if_index[VLIB_TX] = map0->sw_if_index;
     116             : 
     117           0 :           if(PREDICT_FALSE(map0->nsh_action == NSH_ACTION_POP))
     118             :             {
     119             :               /* Manipulate MD2 */
     120           0 :               if(PREDICT_FALSE(hdr0->md_type == 2))
     121             :                 {
     122           0 :                   if (PREDICT_FALSE(next0 == NSH_NODE_NEXT_DROP))
     123             :                     {
     124           0 :                       error0 = NSH_NODE_ERROR_INVALID_OPTIONS;
     125           0 :                       goto trace0;
     126             :                     }
     127             :                   //vnet_buffer(b0)->sw_if_index[VLIB_RX] = map0->sw_if_index;
     128             :                 }
     129             : 
     130             :               /* Pop NSH header */
     131           0 :               vlib_buffer_advance(b0, (word)header_len0);
     132           0 :               goto trace0;
     133             :             }
     134             : 
     135           0 :           entry0 = hash_get_mem(nm->nsh_entry_by_key, &map0->mapped_nsp_nsi);
     136           0 :           if (PREDICT_FALSE(entry0 == 0))
     137             :             {
     138           0 :               error0 = NSH_NODE_ERROR_NO_ENTRY;
     139           0 :               goto trace0;
     140             :             }
     141             : 
     142           0 :         trace0: b0->error = error0 ? node->errors[error0] : 0;
     143             : 
     144           0 :           if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
     145             :             {
     146           0 :               nsh_input_trace_t *tr = vlib_add_trace(vm, node, b0, sizeof(*tr));
     147           0 :               clib_memcpy_fast ( &(tr->trace_data), hdr0, (hdr0->length*4) );
     148             :             }
     149             : 
     150             :           /* Process packet 1 */
     151           0 :           entry1 = hash_get_mem(nm->nsh_mapping_by_key, &nsp_nsi1);
     152           0 :           if (PREDICT_FALSE(entry1 == 0))
     153             :             {
     154           0 :               error1 = NSH_NODE_ERROR_NO_MAPPING;
     155           0 :               goto trace1;
     156             :             }
     157             : 
     158             :           /* Entry should point to a mapping ...*/
     159           0 :           map1 = pool_elt_at_index(nm->nsh_mappings, entry1[0]);
     160             : 
     161             :           /* set up things for next node to transmit ie which node to handle it and where */
     162           0 :           next1 = map1->next_node;
     163             :           //vnet_buffer(b1)->sw_if_index[VLIB_TX] = map1->sw_if_index;
     164             : 
     165           0 :           if(PREDICT_FALSE(map1->nsh_action == NSH_ACTION_POP))
     166             :             {
     167             :               /* Manipulate MD2 */
     168           0 :               if(PREDICT_FALSE(hdr1->md_type == 2))
     169             :                 {
     170           0 :                   if (PREDICT_FALSE(next1 == NSH_NODE_NEXT_DROP))
     171             :                     {
     172           0 :                       error1 = NSH_NODE_ERROR_INVALID_OPTIONS;
     173           0 :                       goto trace1;
     174             :                     }
     175             :                   //vnet_buffer(b1)->sw_if_index[VLIB_RX] = map1->sw_if_index;
     176             :                 }
     177             : 
     178             :               /* Pop NSH header */
     179           0 :               vlib_buffer_advance(b1, (word)header_len1);
     180           0 :               goto trace1;
     181             :             }
     182             : 
     183           0 :           entry1 = hash_get_mem(nm->nsh_entry_by_key, &map1->mapped_nsp_nsi);
     184           0 :           if (PREDICT_FALSE(entry1 == 0))
     185             :             {
     186           0 :               error1 = NSH_NODE_ERROR_NO_ENTRY;
     187           0 :               goto trace1;
     188             :             }
     189             : 
     190             : 
     191           0 :         trace1: b1->error = error1 ? node->errors[error1] : 0;
     192             : 
     193           0 :           if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
     194             :             {
     195           0 :               nsh_input_trace_t *tr = vlib_add_trace(vm, node, b1, sizeof(*tr));
     196           0 :               clib_memcpy_fast ( &(tr->trace_data), hdr1, (hdr1->length*4) );
     197             :             }
     198             : 
     199           0 :           vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
     200             :                                           n_left_to_next, bi0, bi1, next0, next1);
     201             : 
     202             :         }
     203             : 
     204           0 :       while (n_left_from > 0 && n_left_to_next > 0)
     205             :         {
     206           0 :           u32 bi0 = 0;
     207           0 :           vlib_buffer_t * b0 = NULL;
     208           0 :           u32 next0 = NSH_NODE_NEXT_DROP;
     209             :           uword * entry0;
     210           0 :           nsh_base_header_t * hdr0 = 0;
     211           0 :           u32 header_len0 = 0;
     212             :           u32 nsp_nsi0;
     213             :           u32 error0;
     214           0 :           nsh_map_t * map0 = 0;
     215             : 
     216           0 :           bi0 = from[0];
     217           0 :           to_next[0] = bi0;
     218           0 :           from += 1;
     219           0 :           to_next += 1;
     220           0 :           n_left_from -= 1;
     221           0 :           n_left_to_next -= 1;
     222           0 :           error0 = 0;
     223             : 
     224           0 :           b0 = vlib_get_buffer(vm, bi0);
     225           0 :           hdr0 = vlib_buffer_get_current(b0);
     226             : 
     227           0 :           nsp_nsi0 = hdr0->nsp_nsi;
     228           0 :           header_len0 = hdr0->length * 4;
     229             : 
     230           0 :           entry0 = hash_get_mem(nm->nsh_mapping_by_key, &nsp_nsi0);
     231             : 
     232           0 :           if (PREDICT_FALSE(entry0 == 0))
     233             :             {
     234           0 :               error0 = NSH_NODE_ERROR_NO_MAPPING;
     235           0 :               goto trace00;
     236             :             }
     237             : 
     238             :           /* Entry should point to a mapping ...*/
     239           0 :           map0 = pool_elt_at_index(nm->nsh_mappings, entry0[0]);
     240             : 
     241             : 
     242             :           /* set up things for next node to transmit ie which node to handle it and where */
     243           0 :           next0 = map0->next_node;
     244             :           //vnet_buffer(b0)->sw_if_index[VLIB_TX] = map0->sw_if_index;
     245             : 
     246           0 :           if(PREDICT_FALSE(map0->nsh_action == NSH_ACTION_POP))
     247             :             {
     248             :               /* Manipulate MD2 */
     249           0 :               if(PREDICT_FALSE(hdr0->md_type == 2))
     250             :                 {
     251           0 :                   if (PREDICT_FALSE(next0 == NSH_NODE_NEXT_DROP))
     252             :                     {
     253           0 :                       error0 = NSH_NODE_ERROR_INVALID_OPTIONS;
     254           0 :                       goto trace00;
     255             :                     }
     256             :                   //vnet_buffer(b0)->sw_if_index[VLIB_RX] = map0->sw_if_index;
     257             :                 }
     258             : 
     259             :               /* Pop NSH header */
     260           0 :               vlib_buffer_advance(b0, (word)header_len0);
     261           0 :               goto trace00;
     262             :             }
     263             : 
     264           0 :           entry0 = hash_get_mem(nm->nsh_entry_by_key, &map0->mapped_nsp_nsi);
     265           0 :           if (PREDICT_FALSE(entry0 == 0))
     266             :             {
     267           0 :               error0 = NSH_NODE_ERROR_NO_ENTRY;
     268           0 :               goto trace00;
     269             :             }
     270             : 
     271           0 :           trace00: b0->error = error0 ? node->errors[error0] : 0;
     272             : 
     273           0 :           if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
     274             :             {
     275           0 :               nsh_input_trace_t *tr = vlib_add_trace(vm, node, b0, sizeof(*tr));
     276           0 :               clib_memcpy_fast ( &(tr->trace_data[0]), hdr0, (hdr0->length*4) );
     277             :             }
     278             : 
     279           0 :           vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
     280             :                                           n_left_to_next, bi0, next0);
     281             :         }
     282             : 
     283           0 :       vlib_put_next_frame(vm, node, next_index, n_left_to_next);
     284             : 
     285             :     }
     286             : 
     287           0 :   return from_frame->n_vectors;
     288             : }
     289             : 
     290             : /**
     291             :  * @brief Graph processing dispatch function for NSH Input
     292             :  *
     293             :  * @node nsh_input
     294             :  * @param *vm
     295             :  * @param *node
     296             :  * @param *from_frame
     297             :  *
     298             :  * @return from_frame->n_vectors
     299             :  *
     300             :  */
     301        2300 : VLIB_NODE_FN (nsh_pop_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
     302             :                   vlib_frame_t * from_frame)
     303             : {
     304           0 :   return nsh_pop_inline (vm, node, from_frame);
     305             : }
     306             : 
     307             : static char * nsh_pop_node_error_strings[] = {
     308             : #define _(sym,string) string,
     309             :   foreach_nsh_node_error
     310             : #undef _
     311             : };
     312             : 
     313             : /* register nsh-input node */
     314       51864 : VLIB_REGISTER_NODE (nsh_pop_node) = {
     315             :   .name = "nsh-pop",
     316             :   .vector_size = sizeof (u32),
     317             :   .format_trace = format_nsh_pop_node_map_trace,
     318             :   .format_buffer = format_nsh_pop_header,
     319             :   .type = VLIB_NODE_TYPE_INTERNAL,
     320             : 
     321             :   .n_errors = ARRAY_LEN(nsh_pop_node_error_strings),
     322             :   .error_strings = nsh_pop_node_error_strings,
     323             : 
     324             :   .n_next_nodes = NSH_NODE_N_NEXT,
     325             : 
     326             :   .next_nodes = {
     327             : #define _(s,n) [NSH_NODE_NEXT_##s] = n,
     328             :     foreach_nsh_node_next
     329             : #undef _
     330             :   },
     331             : };
     332             : 

Generated by: LCOV version 1.14