LCOV - code coverage report
Current view: top level - plugins/lisp/lisp-gpe - decap.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 15 204 7.4 %
Date: 2023-07-05 22:20:52 Functions: 12 21 57.1 %

          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 L2 LISP-GPE decap code.
      18             :  *
      19             :  */
      20             : #include <vlib/vlib.h>
      21             : #include <lisp/lisp-gpe/lisp_gpe.h>
      22             : 
      23             : typedef struct
      24             : {
      25             :   u32 next_index;
      26             :   u32 tunnel_index;
      27             :   u32 error;
      28             :   lisp_gpe_header_t h;
      29             : } lisp_gpe_rx_trace_t;
      30             : 
      31             : static u8 *
      32           0 : format_lisp_gpe_rx_trace (u8 * s, va_list * args)
      33             : {
      34           0 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
      35           0 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
      36           0 :   lisp_gpe_rx_trace_t *t = va_arg (*args, lisp_gpe_rx_trace_t *);
      37             : 
      38           0 :   if (t->tunnel_index != ~0)
      39             :     {
      40           0 :       s = format (s, "LISP-GPE: tunnel %d next %d error %d", t->tunnel_index,
      41             :                   t->next_index, t->error);
      42             :     }
      43             :   else
      44             :     {
      45           0 :       s = format (s, "LISP-GPE: no tunnel next %d error %d\n", t->next_index,
      46             :                   t->error);
      47             :     }
      48           0 :   s = format (s, "\n  %U", format_lisp_gpe_header_with_length, &t->h,
      49             :               (u32) sizeof (t->h) /* max size */ );
      50           0 :   return s;
      51             : }
      52             : 
      53             : static u32 next_proto_to_next_index[LISP_GPE_NEXT_PROTOS] = {
      54             :   LISP_GPE_INPUT_NEXT_DROP,
      55             :   LISP_GPE_INPUT_NEXT_IP4_INPUT,
      56             :   LISP_GPE_INPUT_NEXT_IP6_INPUT,
      57             :   LISP_GPE_INPUT_NEXT_L2_INPUT,
      58             :   LISP_GPE_INPUT_NEXT_DROP
      59             : };
      60             : 
      61             : always_inline u32
      62           0 : next_protocol_to_next_index (lisp_gpe_header_t * lgh, u8 * next_header)
      63             : {
      64           0 :   lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
      65             : 
      66             :   /* lisp-gpe router */
      67           0 :   if (PREDICT_TRUE ((lgh->flags & LISP_GPE_FLAGS_P)
      68             :                     || GPE_ENCAP_VXLAN == lgm->encap_mode))
      69             :     {
      70           0 :       if (PREDICT_FALSE (lgh->next_protocol >= LISP_GPE_NEXT_PROTOS))
      71           0 :         return LISP_GPE_INPUT_NEXT_DROP;
      72             : 
      73           0 :       return next_proto_to_next_index[lgh->next_protocol];
      74             :     }
      75             :   /* legacy lisp router */
      76           0 :   else if ((lgh->flags & LISP_GPE_FLAGS_P) == 0)
      77             :     {
      78           0 :       ip4_header_t *iph = (ip4_header_t *) next_header;
      79           0 :       if ((iph->ip_version_and_header_length & 0xF0) == 0x40)
      80           0 :         return LISP_GPE_INPUT_NEXT_IP4_INPUT;
      81           0 :       else if ((iph->ip_version_and_header_length & 0xF0) == 0x60)
      82           0 :         return LISP_GPE_INPUT_NEXT_IP6_INPUT;
      83             :       else
      84           0 :         return LISP_GPE_INPUT_NEXT_DROP;
      85             :     }
      86             :   else
      87           0 :     return LISP_GPE_INPUT_NEXT_DROP;
      88             : }
      89             : 
      90             : always_inline tunnel_lookup_t *
      91           0 : next_index_to_iface (lisp_gpe_main_t * lgm, u32 next_index)
      92             : {
      93           0 :   if (LISP_GPE_INPUT_NEXT_IP4_INPUT == next_index
      94           0 :       || LISP_GPE_INPUT_NEXT_IP6_INPUT == next_index)
      95           0 :     return &lgm->l3_ifaces;
      96           0 :   else if (LISP_GPE_INPUT_NEXT_L2_INPUT == next_index)
      97           0 :     return &lgm->l2_ifaces;
      98           0 :   else if (LISP_GPE_INPUT_NEXT_NSH_INPUT == next_index)
      99           0 :     return &lgm->nsh_ifaces;
     100           0 :   clib_warning ("next_index not associated to an interface!");
     101           0 :   return 0;
     102             : }
     103             : 
     104             : static_always_inline void
     105           0 : incr_decap_stats (vnet_main_t * vnm, u32 thread_index, u32 length,
     106             :                   u32 sw_if_index, u32 * last_sw_if_index, u32 * n_packets,
     107             :                   u32 * n_bytes)
     108             : {
     109             :   vnet_interface_main_t *im;
     110             : 
     111           0 :   if (PREDICT_TRUE (sw_if_index == *last_sw_if_index))
     112             :     {
     113           0 :       *n_packets += 1;
     114           0 :       *n_bytes += length;
     115             :     }
     116             :   else
     117             :     {
     118           0 :       if (PREDICT_TRUE (*last_sw_if_index != ~0))
     119             :         {
     120           0 :           im = &vnm->interface_main;
     121             : 
     122           0 :           vlib_increment_combined_counter (im->combined_sw_if_counters +
     123             :                                            VNET_INTERFACE_COUNTER_RX,
     124             :                                            thread_index, *last_sw_if_index,
     125           0 :                                            *n_packets, *n_bytes);
     126             :         }
     127           0 :       *last_sw_if_index = sw_if_index;
     128           0 :       *n_packets = 1;
     129           0 :       *n_bytes = length;
     130             :     }
     131           0 : }
     132             : 
     133             : /**
     134             :  * @brief LISP-GPE decap dispatcher.
     135             :  * @node lisp_gpe_input_inline
     136             :  *
     137             :  * LISP-GPE decap dispatcher.
     138             :  *
     139             :  * Decaps IP-UDP-LISP-GPE header and based on the next protocol and in the
     140             :  * GPE header and the vni decides the next node to forward the packet to.
     141             :  *
     142             :  * @param[in]   vm      vlib_main_t corresponding to current thread.
     143             :  * @param[in]   node    vlib_node_runtime_t data for this node.
     144             :  * @param[in]   frame   vlib_frame_t whose contents should be dispatched.
     145             :  *
     146             :  * @return number of vectors in frame.
     147             :  */
     148             : static uword
     149           0 : lisp_gpe_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
     150             :                        vlib_frame_t * from_frame, u8 is_v4)
     151             : {
     152             :   u32 n_left_from, next_index, *from, *to_next, thread_index;
     153           0 :   u32 n_bytes = 0, n_packets = 0, last_sw_if_index = ~0, drops = 0;
     154           0 :   lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
     155             : 
     156           0 :   thread_index = vm->thread_index;
     157           0 :   from = vlib_frame_vector_args (from_frame);
     158           0 :   n_left_from = from_frame->n_vectors;
     159             : 
     160           0 :   next_index = node->cached_next_index;
     161             : 
     162           0 :   while (n_left_from > 0)
     163             :     {
     164             :       u32 n_left_to_next;
     165             : 
     166           0 :       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
     167             : 
     168           0 :       while (n_left_from >= 4 && n_left_to_next >= 2)
     169             :         {
     170             :           u32 bi0, bi1;
     171             :           vlib_buffer_t *b0, *b1;
     172             :           ip4_udp_lisp_gpe_header_t *iul4_0, *iul4_1;
     173             :           ip6_udp_lisp_gpe_header_t *iul6_0, *iul6_1;
     174             :           lisp_gpe_header_t *lh0, *lh1;
     175             :           u32 next0, next1, error0, error1;
     176             :           uword *si0, *si1;
     177             :           tunnel_lookup_t *tl0, *tl1;
     178             : 
     179             :           /* Prefetch next iteration. */
     180             :           {
     181             :             vlib_buffer_t *p2, *p3;
     182             : 
     183           0 :             p2 = vlib_get_buffer (vm, from[2]);
     184           0 :             p3 = vlib_get_buffer (vm, from[3]);
     185             : 
     186           0 :             vlib_prefetch_buffer_header (p2, LOAD);
     187           0 :             vlib_prefetch_buffer_header (p3, LOAD);
     188             : 
     189           0 :             CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
     190           0 :             CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
     191             :           }
     192             : 
     193           0 :           bi0 = from[0];
     194           0 :           bi1 = from[1];
     195           0 :           to_next[0] = bi0;
     196           0 :           to_next[1] = bi1;
     197           0 :           from += 2;
     198           0 :           to_next += 2;
     199           0 :           n_left_to_next -= 2;
     200           0 :           n_left_from -= 2;
     201             : 
     202           0 :           b0 = vlib_get_buffer (vm, bi0);
     203           0 :           b1 = vlib_get_buffer (vm, bi1);
     204             : 
     205             :           /* udp leaves current_data pointing at the lisp header */
     206           0 :           if (is_v4)
     207             :             {
     208           0 :               vlib_buffer_advance (b0,
     209             :                                    -(word) (sizeof (udp_header_t) +
     210             :                                             sizeof (ip4_header_t)));
     211           0 :               vlib_buffer_advance (b1,
     212             :                                    -(word) (sizeof (udp_header_t) +
     213             :                                             sizeof (ip4_header_t)));
     214             : 
     215           0 :               iul4_0 = vlib_buffer_get_current (b0);
     216           0 :               iul4_1 = vlib_buffer_get_current (b1);
     217             : 
     218             :               /* pop (ip, udp, lisp-gpe) */
     219           0 :               vlib_buffer_advance (b0, sizeof (*iul4_0));
     220           0 :               vlib_buffer_advance (b1, sizeof (*iul4_1));
     221             : 
     222           0 :               lh0 = &iul4_0->lisp;
     223           0 :               lh1 = &iul4_1->lisp;
     224             :             }
     225             :           else
     226             :             {
     227           0 :               vlib_buffer_advance (b0,
     228             :                                    -(word) (sizeof (udp_header_t) +
     229             :                                             sizeof (ip6_header_t)));
     230           0 :               vlib_buffer_advance (b1,
     231             :                                    -(word) (sizeof (udp_header_t) +
     232             :                                             sizeof (ip6_header_t)));
     233             : 
     234           0 :               iul6_0 = vlib_buffer_get_current (b0);
     235           0 :               iul6_1 = vlib_buffer_get_current (b1);
     236             : 
     237             :               /* pop (ip, udp, lisp-gpe) */
     238           0 :               vlib_buffer_advance (b0, sizeof (*iul6_0));
     239           0 :               vlib_buffer_advance (b1, sizeof (*iul6_1));
     240             : 
     241           0 :               lh0 = &iul6_0->lisp;
     242           0 :               lh1 = &iul6_1->lisp;
     243             :             }
     244             : 
     245             :           /* determine next_index from lisp-gpe header */
     246           0 :           next0 = next_protocol_to_next_index (lh0,
     247           0 :                                                vlib_buffer_get_current (b0));
     248           0 :           next1 = next_protocol_to_next_index (lh1,
     249           0 :                                                vlib_buffer_get_current (b1));
     250             : 
     251             :           /* determine if tunnel is l2 or l3 */
     252           0 :           tl0 = next_index_to_iface (lgm, next0);
     253           0 :           tl1 = next_index_to_iface (lgm, next1);
     254             : 
     255             :           /* map iid/vni to lisp-gpe sw_if_index which is used by ipx_input to
     256             :            * decide the rx vrf and the input features to be applied */
     257           0 :           si0 = hash_get (tl0->sw_if_index_by_vni,
     258             :                           clib_net_to_host_u32 (lh0->iid << 8));
     259           0 :           si1 = hash_get (tl1->sw_if_index_by_vni,
     260             :                           clib_net_to_host_u32 (lh1->iid << 8));
     261             : 
     262             : 
     263             :           /* Required to make the l2 tag push / pop code work on l2 subifs */
     264           0 :           vnet_update_l2_len (b0);
     265           0 :           vnet_update_l2_len (b1);
     266             : 
     267           0 :           if (si0)
     268             :             {
     269           0 :               incr_decap_stats (lgm->vnet_main, thread_index,
     270           0 :                                 vlib_buffer_length_in_chain (vm, b0), si0[0],
     271             :                                 &last_sw_if_index, &n_packets, &n_bytes);
     272           0 :               vnet_buffer (b0)->sw_if_index[VLIB_RX] = si0[0];
     273           0 :               error0 = 0;
     274             :             }
     275             :           else
     276             :             {
     277           0 :               next0 = LISP_GPE_INPUT_NEXT_DROP;
     278           0 :               error0 = LISP_GPE_ERROR_NO_TUNNEL;
     279           0 :               drops++;
     280             :             }
     281             : 
     282           0 :           if (si1)
     283             :             {
     284           0 :               incr_decap_stats (lgm->vnet_main, thread_index,
     285           0 :                                 vlib_buffer_length_in_chain (vm, b1), si1[0],
     286             :                                 &last_sw_if_index, &n_packets, &n_bytes);
     287           0 :               vnet_buffer (b1)->sw_if_index[VLIB_RX] = si1[0];
     288           0 :               error1 = 0;
     289             :             }
     290             :           else
     291             :             {
     292           0 :               next1 = LISP_GPE_INPUT_NEXT_DROP;
     293           0 :               error1 = LISP_GPE_ERROR_NO_TUNNEL;
     294           0 :               drops++;
     295             :             }
     296             : 
     297           0 :           b0->error = error0 ? node->errors[error0] : 0;
     298           0 :           b1->error = error1 ? node->errors[error1] : 0;
     299             : 
     300           0 :           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
     301             :             {
     302           0 :               lisp_gpe_rx_trace_t *tr = vlib_add_trace (vm, node, b0,
     303             :                                                         sizeof (*tr));
     304           0 :               tr->next_index = next0;
     305           0 :               tr->error = error0;
     306           0 :               tr->h = lh0[0];
     307             :             }
     308             : 
     309           0 :           if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
     310             :             {
     311           0 :               lisp_gpe_rx_trace_t *tr = vlib_add_trace (vm, node, b1,
     312             :                                                         sizeof (*tr));
     313           0 :               tr->next_index = next1;
     314           0 :               tr->error = error1;
     315           0 :               tr->h = lh1[0];
     316             :             }
     317             : 
     318           0 :           vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
     319             :                                            n_left_to_next, bi0, bi1, next0,
     320             :                                            next1);
     321             :         }
     322             : 
     323           0 :       while (n_left_from > 0 && n_left_to_next > 0)
     324             :         {
     325             :           u32 bi0;
     326             :           vlib_buffer_t *b0;
     327             :           u32 next0;
     328             :           ip4_udp_lisp_gpe_header_t *iul4_0;
     329             :           ip6_udp_lisp_gpe_header_t *iul6_0;
     330             :           lisp_gpe_header_t *lh0;
     331             :           u32 error0;
     332             :           uword *si0;
     333             :           tunnel_lookup_t *tl0;
     334             : 
     335           0 :           bi0 = from[0];
     336           0 :           to_next[0] = bi0;
     337           0 :           from += 1;
     338           0 :           to_next += 1;
     339           0 :           n_left_from -= 1;
     340           0 :           n_left_to_next -= 1;
     341             : 
     342           0 :           b0 = vlib_get_buffer (vm, bi0);
     343             : 
     344             :           /* udp leaves current_data pointing at the lisp header
     345             :            * TODO: there's no difference in processing between v4 and v6
     346             :            * encapsulated packets so the code should be simplified if ip header
     347             :            * info is not going to be used for dp smrs/dpsec */
     348           0 :           if (is_v4)
     349             :             {
     350           0 :               vlib_buffer_advance (b0,
     351             :                                    -(word) (sizeof (udp_header_t) +
     352             :                                             sizeof (ip4_header_t)));
     353             : 
     354           0 :               iul4_0 = vlib_buffer_get_current (b0);
     355             : 
     356             :               /* pop (ip, udp, lisp-gpe) */
     357           0 :               vlib_buffer_advance (b0, sizeof (*iul4_0));
     358             : 
     359           0 :               lh0 = &iul4_0->lisp;
     360             :             }
     361             :           else
     362             :             {
     363           0 :               vlib_buffer_advance (b0,
     364             :                                    -(word) (sizeof (udp_header_t) +
     365             :                                             sizeof (ip6_header_t)));
     366             : 
     367           0 :               iul6_0 = vlib_buffer_get_current (b0);
     368             : 
     369             :               /* pop (ip, udp, lisp-gpe) */
     370           0 :               vlib_buffer_advance (b0, sizeof (*iul6_0));
     371             : 
     372           0 :               lh0 = &iul6_0->lisp;
     373             :             }
     374             : 
     375             :           /* TODO if security is to be implemented, something similar to RPF,
     376             :            * probably we'd like to check that the peer is allowed to send us
     377             :            * packets. For this, we should use the tunnel table OR check that
     378             :            * we have a mapping for the source eid and that the outer source of
     379             :            * the packet is one of its locators */
     380             : 
     381             :           /* determine next_index from lisp-gpe header */
     382           0 :           next0 = next_protocol_to_next_index (lh0,
     383           0 :                                                vlib_buffer_get_current (b0));
     384             : 
     385             :           /* determine if tunnel is l2 or l3 */
     386           0 :           tl0 = next_index_to_iface (lgm, next0);
     387             : 
     388             :           /* map iid/vni to lisp-gpe sw_if_index which is used by ipx_input to
     389             :            * decide the rx vrf and the input features to be applied.
     390             :            * NOTE: vni uses only the first 24 bits */
     391           0 :           si0 = hash_get (tl0->sw_if_index_by_vni,
     392             :                           clib_net_to_host_u32 (lh0->iid << 8));
     393             : 
     394             :           /* Required to make the l2 tag push / pop code work on l2 subifs */
     395           0 :           vnet_update_l2_len (b0);
     396             : 
     397           0 :           if (si0)
     398             :             {
     399           0 :               incr_decap_stats (lgm->vnet_main, thread_index,
     400           0 :                                 vlib_buffer_length_in_chain (vm, b0), si0[0],
     401             :                                 &last_sw_if_index, &n_packets, &n_bytes);
     402           0 :               vnet_buffer (b0)->sw_if_index[VLIB_RX] = si0[0];
     403           0 :               error0 = 0;
     404             :             }
     405             :           else
     406             :             {
     407           0 :               next0 = LISP_GPE_INPUT_NEXT_DROP;
     408           0 :               error0 = LISP_GPE_ERROR_NO_TUNNEL;
     409           0 :               drops++;
     410             :             }
     411             : 
     412             :           /* TODO error handling if security is implemented */
     413           0 :           b0->error = error0 ? node->errors[error0] : 0;
     414             : 
     415           0 :           if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
     416             :             {
     417           0 :               lisp_gpe_rx_trace_t *tr = vlib_add_trace (vm, node, b0,
     418             :                                                         sizeof (*tr));
     419           0 :               tr->next_index = next0;
     420           0 :               tr->error = error0;
     421           0 :               tr->h = lh0[0];
     422             :             }
     423             : 
     424           0 :           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
     425             :                                            n_left_to_next, bi0, next0);
     426             :         }
     427             : 
     428           0 :       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
     429             :     }
     430             : 
     431             :   /* flush iface stats */
     432           0 :   incr_decap_stats (lgm->vnet_main, thread_index, 0, ~0, &last_sw_if_index,
     433             :                     &n_packets, &n_bytes);
     434           0 :   vlib_node_increment_counter (vm, lisp_gpe_ip4_input_node.index,
     435             :                                LISP_GPE_ERROR_NO_TUNNEL, drops);
     436           0 :   return from_frame->n_vectors;
     437             : }
     438             : 
     439             : static uword
     440           0 : lisp_gpe_ip4_input (vlib_main_t * vm, vlib_node_runtime_t * node,
     441             :                     vlib_frame_t * from_frame)
     442             : {
     443           0 :   return lisp_gpe_input_inline (vm, node, from_frame, 1);
     444             : }
     445             : 
     446             : static uword
     447           0 : lisp_gpe_ip6_input (vlib_main_t * vm, vlib_node_runtime_t * node,
     448             :                     vlib_frame_t * from_frame)
     449             : {
     450           0 :   return lisp_gpe_input_inline (vm, node, from_frame, 0);
     451             : }
     452             : 
     453             : static char *lisp_gpe_ip4_input_error_strings[] = {
     454             : #define lisp_gpe_error(n,s) s,
     455             : #include <lisp/lisp-gpe/lisp_gpe_error.def>
     456             : #undef lisp_gpe_error
     457             : };
     458             : 
     459             : /* *INDENT-OFF* */
     460       86264 : VLIB_REGISTER_NODE (lisp_gpe_ip4_input_node) = {
     461             :   .function = lisp_gpe_ip4_input,
     462             :   .name = "lisp-gpe-ip4-input",
     463             :   /* Takes a vector of packets. */
     464             :   .vector_size = sizeof (u32),
     465             :   .n_next_nodes = LISP_GPE_INPUT_N_NEXT,
     466             :   .next_nodes = {
     467             : #define _(s,n) [LISP_GPE_INPUT_NEXT_##s] = n,
     468             :     foreach_lisp_gpe_ip_input_next
     469             : #undef _
     470             :   },
     471             : 
     472             :   .n_errors = ARRAY_LEN (lisp_gpe_ip4_input_error_strings),
     473             :   .error_strings = lisp_gpe_ip4_input_error_strings,
     474             : 
     475             :   .format_buffer = format_lisp_gpe_header_with_length,
     476             :   .format_trace = format_lisp_gpe_rx_trace,
     477             :   // $$$$ .unformat_buffer = unformat_lisp_gpe_header,
     478             : };
     479             : /* *INDENT-ON* */
     480             : 
     481             : /* *INDENT-OFF* */
     482       86264 : VLIB_REGISTER_NODE (lisp_gpe_ip6_input_node) = {
     483             :   .function = lisp_gpe_ip6_input,
     484             :   .name = "lisp-gpe-ip6-input",
     485             :   /* Takes a vector of packets. */
     486             :   .vector_size = sizeof (u32),
     487             :   .n_next_nodes = LISP_GPE_INPUT_N_NEXT,
     488             :   .next_nodes = {
     489             : #define _(s,n) [LISP_GPE_INPUT_NEXT_##s] = n,
     490             :     foreach_lisp_gpe_ip_input_next
     491             : #undef _
     492             :   },
     493             : 
     494             :   .n_errors = ARRAY_LEN (lisp_gpe_ip4_input_error_strings),
     495             :   .error_strings = lisp_gpe_ip4_input_error_strings,
     496             : 
     497             :   .format_buffer = format_lisp_gpe_header_with_length,
     498             :   .format_trace = format_lisp_gpe_rx_trace,
     499             :   // $$$$ .unformat_buffer = unformat_lisp_gpe_header,
     500             : };
     501             : /* *INDENT-ON* */
     502             : 
     503             : /**
     504             :  * Adds arc from lisp-gpe-input to nsh-input if nsh-input is available
     505             :  */
     506             : static void
     507         559 : gpe_add_arc_from_input_to_nsh ()
     508             : {
     509         559 :   lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
     510         559 :   vlib_main_t *vm = lgm->vlib_main;
     511             :   vlib_node_t *nsh_input;
     512             : 
     513             :   /* Arc already exists */
     514         559 :   if (next_proto_to_next_index[LISP_GPE_NEXT_PROTO_NSH]
     515             :       != LISP_GPE_INPUT_NEXT_DROP)
     516           0 :     return;
     517             : 
     518             :   /* Check if nsh-input is available */
     519         559 :   if ((nsh_input = vlib_get_node_by_name (vm, (u8 *) "nsh-input")))
     520             :     {
     521             :       u32 slot4, slot6;
     522           0 :       slot4 = vlib_node_add_next_with_slot (vm, lisp_gpe_ip4_input_node.index,
     523           0 :                                             nsh_input->index,
     524             :                                             LISP_GPE_NEXT_PROTO_NSH);
     525           0 :       slot6 = vlib_node_add_next_with_slot (vm, lisp_gpe_ip6_input_node.index,
     526           0 :                                             nsh_input->index,
     527             :                                             LISP_GPE_NEXT_PROTO_NSH);
     528           0 :       ASSERT (slot4 == slot6 && slot4 == LISP_GPE_INPUT_NEXT_NSH_INPUT);
     529             : 
     530           0 :       next_proto_to_next_index[LISP_GPE_NEXT_PROTO_NSH] = slot4;
     531             :     }
     532             : }
     533             : 
     534             : /** GPE decap init function. */
     535             : clib_error_t *
     536         559 : gpe_decap_init (vlib_main_t * vm)
     537             : {
     538         559 :   clib_error_t *error = 0;
     539             : 
     540         559 :   if ((error = vlib_call_init_function (vm, lisp_gpe_init)))
     541           0 :     return error;
     542             : 
     543         559 :   gpe_add_arc_from_input_to_nsh ();
     544         559 :   return 0;
     545             : }
     546             : 
     547             : static uword
     548           0 : lisp_gpe_nsh_placeholder_input (vlib_main_t * vm, vlib_node_runtime_t * node,
     549             :                                 vlib_frame_t * from_frame)
     550             : {
     551           0 :   vlib_node_increment_counter (vm, node->node_index, 0, 1);
     552           0 :   return from_frame->n_vectors;
     553             : }
     554             : 
     555             : static char *lisp_gpe_nsh_placeholder_error_strings[] = {
     556             :   "lisp gpe placeholder nsh decap",
     557             : };
     558             : 
     559             : /* *INDENT-OFF* */
     560       86264 : VLIB_REGISTER_NODE (lisp_gpe_nsh_placeholder_input_node) = {
     561             :   .function = lisp_gpe_nsh_placeholder_input,
     562             :   .name = "lisp-gpe-nsh-placeholder-input",
     563             :   .vector_size = sizeof (u32),
     564             :   .type = VLIB_NODE_TYPE_INTERNAL,
     565             :   .n_next_nodes = 1,
     566             : 
     567             :   .n_errors = 1,
     568             :   .error_strings = lisp_gpe_nsh_placeholder_error_strings,
     569             : 
     570             :   .next_nodes = {
     571             :       [0] = "error-drop",
     572             :   },
     573             : };
     574             : /* *INDENT-ON* */
     575             : 
     576             : static clib_error_t *
     577           0 : lisp_add_placeholder_nsh_node_command_fn (vlib_main_t * vm,
     578             :                                           unformat_input_t * input,
     579             :                                           vlib_cli_command_t * cmd)
     580             : {
     581           0 :   lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
     582           0 :   vlib_node_add_next (lgm->vlib_main, lisp_gpe_ip4_input_node.index,
     583           0 :                       lisp_gpe_nsh_placeholder_input_node.index);
     584           0 :   next_proto_to_next_index[LISP_GPE_NEXT_PROTO_NSH] =
     585             :     LISP_GPE_INPUT_NEXT_NSH_INPUT;
     586           0 :   return 0;
     587             : }
     588             : 
     589             : /* *INDENT-OFF* */
     590      116069 : VLIB_CLI_COMMAND (lisp_add_placeholder_nsh_node_command, static) = {
     591             :   .path = "test one nsh add-placeholder-decap-node",
     592             :   .function = lisp_add_placeholder_nsh_node_command_fn,
     593             : };
     594             : /* *INDENT-ON* */
     595             : 
     596        4479 : VLIB_INIT_FUNCTION (gpe_decap_init);
     597             : 
     598             : /*
     599             :  * fd.io coding-style-patch-verification: ON
     600             :  *
     601             :  * Local Variables:
     602             :  * eval: (c-set-style "gnu")
     603             :  * End:
     604             :  */

Generated by: LCOV version 1.14