LCOV - code coverage report
Current view: top level - plugins/gre - node.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 233 242 96.3 %
Date: 2023-07-05 22:20:52 Functions: 23 29 79.3 %

          Line data    Source code
       1             : /*
       2             :  * node.c: gre packet processing
       3             :  *
       4             :  * Copyright (c) 2012 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 <vlib/vlib.h>
      19             : #include <vnet/pg/pg.h>
      20             : #include <gre/gre.h>
      21             : #include <vnet/mpls/mpls.h>
      22             : #include <vppinfra/sparse_vec.h>
      23             : 
      24             : #define foreach_gre_input_next                                                \
      25             :   _ (PUNT, "error-punt")                                                      \
      26             :   _ (DROP, "error-drop")                                                      \
      27             :   _ (ETHERNET_INPUT, "ethernet-input")                                        \
      28             :   _ (IP4_INPUT, "ip4-input")                                                  \
      29             :   _ (IP6_INPUT, "ip6-input")                                                  \
      30             :   _ (MPLS_INPUT, "mpls-input")
      31             : 
      32             : typedef enum
      33             : {
      34             : #define _(s, n) GRE_INPUT_NEXT_##s,
      35             :   foreach_gre_input_next
      36             : #undef _
      37             :     GRE_INPUT_N_NEXT,
      38             : } gre_input_next_t;
      39             : 
      40             : typedef struct
      41             : {
      42             :   u32 tunnel_id;
      43             :   u32 length;
      44             :   ip46_address_t src;
      45             :   ip46_address_t dst;
      46             : } gre_rx_trace_t;
      47             : 
      48             : extern u8 *format_gre_rx_trace (u8 *s, va_list *args);
      49             : 
      50             : #ifndef CLIB_MARCH_VARIANT
      51             : u8 *
      52        3840 : format_gre_rx_trace (u8 *s, va_list *args)
      53             : {
      54        3840 :   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
      55        3840 :   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
      56        3840 :   gre_rx_trace_t *t = va_arg (*args, gre_rx_trace_t *);
      57             : 
      58        3840 :   s = format (s, "GRE: tunnel %d len %d src %U dst %U", t->tunnel_id,
      59        3840 :               clib_net_to_host_u16 (t->length), format_ip46_address, &t->src,
      60             :               IP46_TYPE_ANY, format_ip46_address, &t->dst, IP46_TYPE_ANY);
      61        3840 :   return s;
      62             : }
      63             : #endif /* CLIB_MARCH_VARIANT */
      64             : 
      65             : typedef struct
      66             : {
      67             :   /* Sparse vector mapping gre protocol in network byte order
      68             :      to next index. */
      69             :   u16 *next_by_protocol;
      70             : } gre_input_runtime_t;
      71             : 
      72             : always_inline void
      73       12613 : gre_trace (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b,
      74             :            u32 tun_sw_if_index, const ip6_header_t *ip6,
      75             :            const ip4_header_t *ip4, int is_ipv6)
      76             : {
      77       12613 :   gre_rx_trace_t *tr = vlib_add_trace (vm, node, b, sizeof (*tr));
      78       12613 :   tr->tunnel_id = tun_sw_if_index;
      79       12613 :   if (is_ipv6)
      80             :     {
      81        3617 :       tr->length = ip6->payload_length;
      82        3617 :       tr->src.ip6.as_u64[0] = ip6->src_address.as_u64[0];
      83        3617 :       tr->src.ip6.as_u64[1] = ip6->src_address.as_u64[1];
      84        3617 :       tr->dst.ip6.as_u64[0] = ip6->dst_address.as_u64[0];
      85        3617 :       tr->dst.ip6.as_u64[1] = ip6->dst_address.as_u64[1];
      86             :     }
      87             :   else
      88             :     {
      89        8996 :       tr->length = ip4->length;
      90        8996 :       tr->src.as_u64[0] = tr->src.as_u64[1] = 0;
      91        8996 :       tr->dst.as_u64[0] = tr->dst.as_u64[1] = 0;
      92        8996 :       tr->src.ip4.as_u32 = ip4->src_address.as_u32;
      93        8996 :       tr->dst.ip4.as_u32 = ip4->dst_address.as_u32;
      94             :     }
      95       12613 : }
      96             : 
      97             : always_inline void
      98        1696 : gre_tunnel_get (const gre_main_t *gm, vlib_node_runtime_t *node,
      99             :                 vlib_buffer_t *b, u16 *next, const gre_tunnel_key_t *key,
     100             :                 gre_tunnel_key_t *cached_key, u32 *tun_sw_if_index,
     101             :                 u32 *cached_tun_sw_if_index, int is_ipv6)
     102             : {
     103             :   const uword *p;
     104        1743 :   p = is_ipv6 ? hash_get_mem (gm->tunnel_by_key6, &key->gtk_v6) :
     105        3298 :                       hash_get_mem (gm->tunnel_by_key4, &key->gtk_v4);
     106        1696 :   if (PREDICT_FALSE (!p))
     107             :     {
     108        1544 :       *next = GRE_INPUT_NEXT_DROP;
     109        1544 :       b->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL];
     110        1544 :       *tun_sw_if_index = ~0;
     111             :     }
     112             :   else
     113             :     {
     114             :       const gre_tunnel_t *tun;
     115         152 :       tun = pool_elt_at_index (gm->tunnels, *p);
     116         152 :       *cached_tun_sw_if_index = *tun_sw_if_index = tun->sw_if_index;
     117         152 :       if (is_ipv6)
     118          47 :         cached_key->gtk_v6 = key->gtk_v6;
     119             :       else
     120         105 :         cached_key->gtk_v4 = key->gtk_v4;
     121             :     }
     122        1696 : }
     123             : 
     124             : always_inline uword
     125         115 : gre_input (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame,
     126             :            const int is_ipv6)
     127             : {
     128         115 :   gre_main_t *gm = &gre_main;
     129             :   u32 *from, n_left_from;
     130         115 :   vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
     131         115 :   u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
     132         115 :   u16 cached_protocol = ~0;
     133         115 :   u32 cached_next_index = SPARSE_VEC_INVALID_INDEX;
     134         115 :   u32 cached_tun_sw_if_index = ~0;
     135             :   gre_tunnel_key_t cached_key;
     136             : 
     137         115 :   from = vlib_frame_vector_args (frame);
     138         115 :   n_left_from = frame->n_vectors;
     139         115 :   vlib_get_buffers (vm, from, bufs, n_left_from);
     140             : 
     141         115 :   if (is_ipv6)
     142          30 :     clib_memset (&cached_key.gtk_v6, 0xff, sizeof (cached_key.gtk_v6));
     143             :   else
     144          85 :     clib_memset (&cached_key.gtk_v4, 0xff, sizeof (cached_key.gtk_v4));
     145             : 
     146        6390 :   while (n_left_from >= 2)
     147             :     {
     148             :       const ip6_header_t *ip6[2];
     149             :       const ip4_header_t *ip4[2];
     150             :       const gre_header_t *gre[2];
     151             :       u32 nidx[2];
     152             :       next_info_t ni[2];
     153             :       u8 type[2];
     154             :       u16 version[2];
     155             :       u32 len[2];
     156             :       gre_tunnel_key_t key[2];
     157             :       u8 matched[2];
     158             :       u32 tun_sw_if_index[2];
     159             : 
     160        6275 :       if (PREDICT_TRUE (n_left_from >= 6))
     161             :         {
     162        6161 :           vlib_prefetch_buffer_data (b[2], LOAD);
     163        6161 :           vlib_prefetch_buffer_data (b[3], LOAD);
     164        6161 :           vlib_prefetch_buffer_header (b[4], STORE);
     165        6161 :           vlib_prefetch_buffer_header (b[5], STORE);
     166             :         }
     167             : 
     168        6275 :       if (is_ipv6)
     169             :         {
     170             :           /* ip6_local hands us the ip header, not the gre header */
     171        1802 :           ip6[0] = vlib_buffer_get_current (b[0]);
     172        1802 :           ip6[1] = vlib_buffer_get_current (b[1]);
     173        1802 :           gre[0] = (void *) (ip6[0] + 1);
     174        1802 :           gre[1] = (void *) (ip6[1] + 1);
     175        1802 :           vlib_buffer_advance (b[0], sizeof (*ip6[0]) + sizeof (*gre[0]));
     176        1802 :           vlib_buffer_advance (b[1], sizeof (*ip6[0]) + sizeof (*gre[0]));
     177             :         }
     178             :       else
     179             :         {
     180             :           /* ip4_local hands us the ip header, not the gre header */
     181        4473 :           ip4[0] = vlib_buffer_get_current (b[0]);
     182        4473 :           ip4[1] = vlib_buffer_get_current (b[1]);
     183        4473 :           gre[0] = (void *) (ip4[0] + 1);
     184        4473 :           gre[1] = (void *) (ip4[1] + 1);
     185        4473 :           vlib_buffer_advance (b[0], sizeof (*ip4[0]) + sizeof (*gre[0]));
     186        4473 :           vlib_buffer_advance (b[1], sizeof (*ip4[0]) + sizeof (*gre[0]));
     187             :         }
     188             : 
     189        6275 :       if (PREDICT_TRUE (cached_protocol == gre[0]->protocol))
     190             :         {
     191        6218 :           nidx[0] = cached_next_index;
     192             :         }
     193             :       else
     194             :         {
     195          57 :           cached_next_index = nidx[0] =
     196          57 :             sparse_vec_index (gm->next_by_protocol, gre[0]->protocol);
     197          57 :           cached_protocol = gre[0]->protocol;
     198             :         }
     199        6275 :       if (PREDICT_TRUE (cached_protocol == gre[1]->protocol))
     200             :         {
     201        6275 :           nidx[1] = cached_next_index;
     202             :         }
     203             :       else
     204             :         {
     205           0 :           cached_next_index = nidx[1] =
     206           0 :             sparse_vec_index (gm->next_by_protocol, gre[1]->protocol);
     207           0 :           cached_protocol = gre[1]->protocol;
     208             :         }
     209             : 
     210        6275 :       ni[0] = vec_elt (gm->next_by_protocol, nidx[0]);
     211        6275 :       ni[1] = vec_elt (gm->next_by_protocol, nidx[1]);
     212        6275 :       next[0] = ni[0].next_index;
     213        6275 :       next[1] = ni[1].next_index;
     214        6275 :       type[0] = ni[0].tunnel_type;
     215        6275 :       type[1] = ni[1].tunnel_type;
     216             : 
     217        6275 :       b[0]->error = nidx[0] == SPARSE_VEC_INVALID_INDEX ?
     218           0 :                             node->errors[GRE_ERROR_UNKNOWN_PROTOCOL] :
     219        6275 :                             node->errors[GRE_ERROR_NONE];
     220        6275 :       b[1]->error = nidx[1] == SPARSE_VEC_INVALID_INDEX ?
     221           0 :                             node->errors[GRE_ERROR_UNKNOWN_PROTOCOL] :
     222        6275 :                             node->errors[GRE_ERROR_NONE];
     223             : 
     224        6275 :       version[0] = clib_net_to_host_u16 (gre[0]->flags_and_version);
     225        6275 :       version[1] = clib_net_to_host_u16 (gre[1]->flags_and_version);
     226        6275 :       version[0] &= GRE_VERSION_MASK;
     227        6275 :       version[1] &= GRE_VERSION_MASK;
     228             : 
     229       18825 :       b[0]->error =
     230        6275 :         version[0] ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION] : b[0]->error;
     231        6275 :       next[0] = version[0] ? GRE_INPUT_NEXT_DROP : next[0];
     232       18825 :       b[1]->error =
     233        6275 :         version[1] ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION] : b[1]->error;
     234        6275 :       next[1] = version[1] ? GRE_INPUT_NEXT_DROP : next[1];
     235             : 
     236        6275 :       len[0] = vlib_buffer_length_in_chain (vm, b[0]);
     237        6275 :       len[1] = vlib_buffer_length_in_chain (vm, b[1]);
     238             : 
     239             :       /* always search for P2P types in the DP */
     240        6275 :       if (is_ipv6)
     241             :         {
     242        1802 :           gre_mk_key6 (&ip6[0]->dst_address, &ip6[0]->src_address,
     243        1802 :                        vnet_buffer (b[0])->ip.fib_index, type[0],
     244             :                        TUNNEL_MODE_P2P, 0, &key[0].gtk_v6);
     245        1802 :           gre_mk_key6 (&ip6[1]->dst_address, &ip6[1]->src_address,
     246        1802 :                        vnet_buffer (b[1])->ip.fib_index, type[1],
     247             :                        TUNNEL_MODE_P2P, 0, &key[1].gtk_v6);
     248        1802 :           matched[0] = gre_match_key6 (&cached_key.gtk_v6, &key[0].gtk_v6);
     249        1802 :           matched[1] = gre_match_key6 (&cached_key.gtk_v6, &key[1].gtk_v6);
     250             :         }
     251             :       else
     252             :         {
     253        4473 :           gre_mk_key4 (ip4[0]->dst_address, ip4[0]->src_address,
     254        4473 :                        vnet_buffer (b[0])->ip.fib_index, type[0],
     255             :                        TUNNEL_MODE_P2P, 0, &key[0].gtk_v4);
     256        4473 :           gre_mk_key4 (ip4[1]->dst_address, ip4[1]->src_address,
     257        4473 :                        vnet_buffer (b[1])->ip.fib_index, type[1],
     258             :                        TUNNEL_MODE_P2P, 0, &key[1].gtk_v4);
     259        4473 :           matched[0] = gre_match_key4 (&cached_key.gtk_v4, &key[0].gtk_v4);
     260        4473 :           matched[1] = gre_match_key4 (&cached_key.gtk_v4, &key[1].gtk_v4);
     261             :         }
     262             : 
     263        6275 :       tun_sw_if_index[0] = cached_tun_sw_if_index;
     264        6275 :       tun_sw_if_index[1] = cached_tun_sw_if_index;
     265        6275 :       if (PREDICT_FALSE (!matched[0]))
     266         819 :         gre_tunnel_get (gm, node, b[0], &next[0], &key[0], &cached_key,
     267             :                         &tun_sw_if_index[0], &cached_tun_sw_if_index, is_ipv6);
     268        6275 :       if (PREDICT_FALSE (!matched[1]))
     269         819 :         gre_tunnel_get (gm, node, b[1], &next[1], &key[1], &cached_key,
     270             :                         &tun_sw_if_index[1], &cached_tun_sw_if_index, is_ipv6);
     271             : 
     272        6275 :       if (PREDICT_TRUE (next[0] > GRE_INPUT_NEXT_DROP))
     273             :         {
     274        5507 :           vlib_increment_combined_counter (
     275        5507 :             &gm->vnet_main->interface_main
     276             :                .combined_sw_if_counters[VNET_INTERFACE_COUNTER_RX],
     277             :             vm->thread_index, tun_sw_if_index[0], 1 /* packets */,
     278        5507 :             len[0] /* bytes */);
     279        5507 :           vnet_buffer (b[0])->sw_if_index[VLIB_RX] = tun_sw_if_index[0];
     280             :         }
     281        6275 :       if (PREDICT_TRUE (next[1] > GRE_INPUT_NEXT_DROP))
     282             :         {
     283        5507 :           vlib_increment_combined_counter (
     284        5507 :             &gm->vnet_main->interface_main
     285             :                .combined_sw_if_counters[VNET_INTERFACE_COUNTER_RX],
     286             :             vm->thread_index, tun_sw_if_index[1], 1 /* packets */,
     287        5507 :             len[1] /* bytes */);
     288        5507 :           vnet_buffer (b[1])->sw_if_index[VLIB_RX] = tun_sw_if_index[1];
     289             :         }
     290             : 
     291        6275 :       vnet_buffer (b[0])->sw_if_index[VLIB_TX] = (u32) ~0;
     292        6275 :       vnet_buffer (b[1])->sw_if_index[VLIB_TX] = (u32) ~0;
     293             : 
     294        6275 :       if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
     295        6275 :         gre_trace (vm, node, b[0], tun_sw_if_index[0], ip6[0], ip4[0],
     296             :                    is_ipv6);
     297        6275 :       if (PREDICT_FALSE (b[1]->flags & VLIB_BUFFER_IS_TRACED))
     298        6275 :         gre_trace (vm, node, b[1], tun_sw_if_index[1], ip6[1], ip4[1],
     299             :                    is_ipv6);
     300             : 
     301        6275 :       b += 2;
     302        6275 :       next += 2;
     303        6275 :       n_left_from -= 2;
     304             :     }
     305             : 
     306         178 :   while (n_left_from >= 1)
     307             :     {
     308             :       const ip6_header_t *ip6[1];
     309             :       const ip4_header_t *ip4[1];
     310             :       const gre_header_t *gre[1];
     311             :       u32 nidx[1];
     312             :       next_info_t ni[1];
     313             :       u8 type[1];
     314             :       u16 version[1];
     315             :       u32 len[1];
     316             :       gre_tunnel_key_t key[1];
     317             :       u8 matched[1];
     318             :       u32 tun_sw_if_index[1];
     319             : 
     320          63 :       if (PREDICT_TRUE (n_left_from >= 3))
     321             :         {
     322           0 :           vlib_prefetch_buffer_data (b[1], LOAD);
     323           0 :           vlib_prefetch_buffer_header (b[2], STORE);
     324             :         }
     325             : 
     326          63 :       if (is_ipv6)
     327             :         {
     328             :           /* ip6_local hands us the ip header, not the gre header */
     329          13 :           ip6[0] = vlib_buffer_get_current (b[0]);
     330          13 :           gre[0] = (void *) (ip6[0] + 1);
     331          13 :           vlib_buffer_advance (b[0], sizeof (*ip6[0]) + sizeof (*gre[0]));
     332             :         }
     333             :       else
     334             :         {
     335             :           /* ip4_local hands us the ip header, not the gre header */
     336          50 :           ip4[0] = vlib_buffer_get_current (b[0]);
     337          50 :           gre[0] = (void *) (ip4[0] + 1);
     338          50 :           vlib_buffer_advance (b[0], sizeof (*ip4[0]) + sizeof (*gre[0]));
     339             :         }
     340             : 
     341          63 :       if (PREDICT_TRUE (cached_protocol == gre[0]->protocol))
     342             :         {
     343           5 :           nidx[0] = cached_next_index;
     344             :         }
     345             :       else
     346             :         {
     347          58 :           cached_next_index = nidx[0] =
     348          58 :             sparse_vec_index (gm->next_by_protocol, gre[0]->protocol);
     349          58 :           cached_protocol = gre[0]->protocol;
     350             :         }
     351             : 
     352          63 :       ni[0] = vec_elt (gm->next_by_protocol, nidx[0]);
     353          63 :       next[0] = ni[0].next_index;
     354          63 :       type[0] = ni[0].tunnel_type;
     355             : 
     356          63 :       b[0]->error = nidx[0] == SPARSE_VEC_INVALID_INDEX ?
     357           1 :                             node->errors[GRE_ERROR_UNKNOWN_PROTOCOL] :
     358          62 :                             node->errors[GRE_ERROR_NONE];
     359             : 
     360          63 :       version[0] = clib_net_to_host_u16 (gre[0]->flags_and_version);
     361          63 :       version[0] &= GRE_VERSION_MASK;
     362             : 
     363         189 :       b[0]->error =
     364          63 :         version[0] ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION] : b[0]->error;
     365          63 :       next[0] = version[0] ? GRE_INPUT_NEXT_DROP : next[0];
     366             : 
     367          63 :       len[0] = vlib_buffer_length_in_chain (vm, b[0]);
     368             : 
     369          63 :       if (is_ipv6)
     370             :         {
     371          13 :           gre_mk_key6 (&ip6[0]->dst_address, &ip6[0]->src_address,
     372          13 :                        vnet_buffer (b[0])->ip.fib_index, type[0],
     373             :                        TUNNEL_MODE_P2P, 0, &key[0].gtk_v6);
     374          13 :           matched[0] = gre_match_key6 (&cached_key.gtk_v6, &key[0].gtk_v6);
     375             :         }
     376             :       else
     377             :         {
     378          50 :           gre_mk_key4 (ip4[0]->dst_address, ip4[0]->src_address,
     379          50 :                        vnet_buffer (b[0])->ip.fib_index, type[0],
     380             :                        TUNNEL_MODE_P2P, 0, &key[0].gtk_v4);
     381          50 :           matched[0] = gre_match_key4 (&cached_key.gtk_v4, &key[0].gtk_v4);
     382             :         }
     383             : 
     384          63 :       tun_sw_if_index[0] = cached_tun_sw_if_index;
     385          63 :       if (PREDICT_FALSE (!matched[0]))
     386          58 :         gre_tunnel_get (gm, node, b[0], &next[0], &key[0], &cached_key,
     387             :                         &tun_sw_if_index[0], &cached_tun_sw_if_index, is_ipv6);
     388             : 
     389          63 :       if (PREDICT_TRUE (next[0] > GRE_INPUT_NEXT_DROP))
     390             :         {
     391          55 :           vlib_increment_combined_counter (
     392          55 :             &gm->vnet_main->interface_main
     393             :                .combined_sw_if_counters[VNET_INTERFACE_COUNTER_RX],
     394             :             vm->thread_index, tun_sw_if_index[0], 1 /* packets */,
     395          55 :             len[0] /* bytes */);
     396          55 :           vnet_buffer (b[0])->sw_if_index[VLIB_RX] = tun_sw_if_index[0];
     397             :         }
     398             : 
     399          63 :       vnet_buffer (b[0])->sw_if_index[VLIB_TX] = (u32) ~0;
     400             : 
     401          63 :       if (PREDICT_FALSE (b[0]->flags & VLIB_BUFFER_IS_TRACED))
     402          63 :         gre_trace (vm, node, b[0], tun_sw_if_index[0], ip6[0], ip4[0],
     403             :                    is_ipv6);
     404             : 
     405          63 :       b += 1;
     406          63 :       next += 1;
     407          63 :       n_left_from -= 1;
     408             :     }
     409             : 
     410         115 :   vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
     411             : 
     412         115 :   vlib_node_increment_counter (
     413             :     vm, is_ipv6 ? gre6_input_node.index : gre4_input_node.index,
     414             :     GRE_ERROR_PKTS_DECAP, n_left_from);
     415             : 
     416         115 :   return frame->n_vectors;
     417             : }
     418             : 
     419        2321 : VLIB_NODE_FN (gre4_input_node)
     420             : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
     421             : {
     422          85 :   return gre_input (vm, node, from_frame, /* is_ip6 */ 0);
     423             : }
     424             : 
     425        2266 : VLIB_NODE_FN (gre6_input_node)
     426             : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
     427             : {
     428          30 :   return gre_input (vm, node, from_frame, /* is_ip6 */ 1);
     429             : }
     430             : 
     431             : static char *gre_error_strings[] = {
     432             : #define gre_error(n, s) s,
     433             : #include "error.def"
     434             : #undef gre_error
     435             : };
     436             : 
     437             : /* *INDENT-OFF* */
     438      133880 : VLIB_REGISTER_NODE (gre4_input_node) = {
     439             :   .name = "gre4-input",
     440             :   /* Takes a vector of packets. */
     441             :   .vector_size = sizeof (u32),
     442             : 
     443             :   .n_errors = GRE_N_ERROR,
     444             :   .error_strings = gre_error_strings,
     445             : 
     446             :   .n_next_nodes = GRE_INPUT_N_NEXT,
     447             :   .next_nodes = {
     448             : #define _(s, n) [GRE_INPUT_NEXT_##s] = n,
     449             :     foreach_gre_input_next
     450             : #undef _
     451             :   },
     452             : 
     453             :   .format_buffer = format_gre_header_with_length,
     454             :   .format_trace = format_gre_rx_trace,
     455             :   .unformat_buffer = unformat_gre_header,
     456             : };
     457             : 
     458      133880 : VLIB_REGISTER_NODE (gre6_input_node) = {
     459             :   .name = "gre6-input",
     460             :   /* Takes a vector of packets. */
     461             :   .vector_size = sizeof (u32),
     462             : 
     463             :   .runtime_data_bytes = sizeof (gre_input_runtime_t),
     464             : 
     465             :   .n_errors = GRE_N_ERROR,
     466             :   .error_strings = gre_error_strings,
     467             : 
     468             :   .n_next_nodes = GRE_INPUT_N_NEXT,
     469             :   .next_nodes = {
     470             : #define _(s, n) [GRE_INPUT_NEXT_##s] = n,
     471             :     foreach_gre_input_next
     472             : #undef _
     473             :   },
     474             : 
     475             :   .format_buffer = format_gre_header_with_length,
     476             :   .format_trace = format_gre_rx_trace,
     477             :   .unformat_buffer = unformat_gre_header,
     478             : };
     479             : /* *INDENT-ON* */
     480             : 
     481             : #ifndef CLIB_MARCH_VARIANT
     482             : void
     483        2236 : gre_register_input_protocol (vlib_main_t *vm, gre_protocol_t protocol,
     484             :                              u32 node_index, gre_tunnel_type_t tunnel_type)
     485             : {
     486        2236 :   gre_main_t *em = &gre_main;
     487             :   gre_protocol_info_t *pi;
     488             :   next_info_t *n;
     489             :   u32 i;
     490             : 
     491             :   {
     492        2236 :     clib_error_t *error = vlib_call_init_function (vm, gre_input_init);
     493        2236 :     if (error)
     494           0 :       clib_error_report (error);
     495             :   }
     496             : 
     497        2236 :   pi = gre_get_protocol_info (em, protocol);
     498        2236 :   pi->node_index = node_index;
     499        2236 :   pi->tunnel_type = tunnel_type;
     500        2236 :   pi->next_index = vlib_node_add_next (vm, gre4_input_node.index, node_index);
     501        2236 :   i = vlib_node_add_next (vm, gre6_input_node.index, node_index);
     502        2236 :   ASSERT (i == pi->next_index);
     503             : 
     504             :   /* Setup gre protocol -> next index sparse vector mapping. */
     505        2236 :   n = sparse_vec_validate (em->next_by_protocol,
     506             :                            clib_host_to_net_u16 (protocol));
     507        2236 :   n->next_index = pi->next_index;
     508        2236 :   n->tunnel_type = tunnel_type;
     509        2236 : }
     510             : 
     511             : static void
     512        1118 : gre_setup_node (vlib_main_t *vm, u32 node_index)
     513             : {
     514        1118 :   vlib_node_t *n = vlib_get_node (vm, node_index);
     515        1118 :   pg_node_t *pn = pg_get_node (node_index);
     516             : 
     517        1118 :   n->format_buffer = format_gre_header_with_length;
     518        1118 :   n->unformat_buffer = unformat_gre_header;
     519        1118 :   pn->unformat_edit = unformat_pg_gre_header;
     520        1118 : }
     521             : 
     522             : static clib_error_t *
     523         559 : gre_input_init (vlib_main_t *vm)
     524             : {
     525         559 :   gre_main_t *gm = &gre_main;
     526             :   vlib_node_t *ethernet_input, *ip4_input, *ip6_input, *mpls_unicast_input;
     527             : 
     528             :   {
     529             :     clib_error_t *error;
     530         559 :     error = vlib_call_init_function (vm, gre_init);
     531         559 :     if (error)
     532           0 :       clib_error_report (error);
     533             :   }
     534             : 
     535         559 :   gre_setup_node (vm, gre4_input_node.index);
     536         559 :   gre_setup_node (vm, gre6_input_node.index);
     537             : 
     538         559 :   gm->next_by_protocol =
     539         559 :     sparse_vec_new (/* elt bytes */ sizeof (gm->next_by_protocol[0]),
     540             :                     /* bits in index */ BITS (((gre_header_t *) 0)->protocol));
     541             : 
     542             :   /* These could be moved to the supported protocol input node defn's */
     543         559 :   ethernet_input = vlib_get_node_by_name (vm, (u8 *) "ethernet-input");
     544         559 :   ASSERT (ethernet_input);
     545         559 :   ip4_input = vlib_get_node_by_name (vm, (u8 *) "ip4-input");
     546         559 :   ASSERT (ip4_input);
     547         559 :   ip6_input = vlib_get_node_by_name (vm, (u8 *) "ip6-input");
     548         559 :   ASSERT (ip6_input);
     549         559 :   mpls_unicast_input = vlib_get_node_by_name (vm, (u8 *) "mpls-input");
     550         559 :   ASSERT (mpls_unicast_input);
     551             : 
     552         559 :   gre_register_input_protocol (vm, GRE_PROTOCOL_teb, ethernet_input->index,
     553             :                                GRE_TUNNEL_TYPE_TEB);
     554             : 
     555         559 :   gre_register_input_protocol (vm, GRE_PROTOCOL_ip4, ip4_input->index,
     556             :                                GRE_TUNNEL_TYPE_L3);
     557             : 
     558         559 :   gre_register_input_protocol (vm, GRE_PROTOCOL_ip6, ip6_input->index,
     559             :                                GRE_TUNNEL_TYPE_L3);
     560             : 
     561         559 :   gre_register_input_protocol (vm, GRE_PROTOCOL_mpls_unicast,
     562             :                                mpls_unicast_input->index, GRE_TUNNEL_TYPE_L3);
     563             : 
     564         559 :   return 0;
     565             : }
     566             : 
     567        1119 : VLIB_INIT_FUNCTION (gre_input_init);
     568             : 
     569             : #endif /* CLIB_MARCH_VARIANT */
     570             : /*
     571             :  * fd.io coding-style-patch-verification: ON
     572             :  *
     573             :  * Local Variables:
     574             :  * eval: (c-set-style "gnu")
     575             :  * End:
     576             :  */

Generated by: LCOV version 1.14