LCOV - code coverage report
Current view: top level - plugins/l2tp - encap.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 8 72 11.1 %
Date: 2023-07-05 22:20:52 Functions: 7 14 50.0 %

          Line data    Source code
       1             : /*
       2             :  * encap.c : L2TPv3 tunnel encapsulation
       3             :  *
       4             :  * Copyright (c) 2013 Cisco and/or its affiliates.
       5             :  * Licensed under the Apache License, Version 2.0 (the "License");
       6             :  * you may not use this file except in compliance with the License.
       7             :  * You may obtain a copy of the License at:
       8             :  *
       9             :  *     http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  * Unless required by applicable law or agreed to in writing, software
      12             :  * distributed under the License is distributed on an "AS IS" BASIS,
      13             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  * See the License for the specific language governing permissions and
      15             :  * limitations under the License.
      16             :  */
      17             : 
      18             : #include <vppinfra/error.h>
      19             : #include <vppinfra/hash.h>
      20             : #include <vnet/vnet.h>
      21             : #include <vnet/ip/ip.h>
      22             : #include <vnet/ethernet/ethernet.h>
      23             : #include <l2tp/l2tp.h>
      24             : 
      25             : /* Statistics (not really errors) */
      26             : #define foreach_l2t_encap_error                                 \
      27             : _(NETWORK_TO_USER, "L2TP L2 network to user (ip6) pkts")      \
      28             : _(LOOKUP_FAIL_TO_L3, "L2TP L2 session lookup failed pkts")      \
      29             : _(ADMIN_DOWN, "L2TP tunnel is down")
      30             : 
      31             : static char *l2t_encap_error_strings[] = {
      32             : #define _(sym,string) string,
      33             :   foreach_l2t_encap_error
      34             : #undef _
      35             : };
      36             : 
      37             : typedef enum
      38             : {
      39             : #define _(sym,str) L2T_ENCAP_ERROR_##sym,
      40             :   foreach_l2t_encap_error
      41             : #undef _
      42             :     L2T_ENCAP_N_ERROR,
      43             : } l2t_encap_error_t;
      44             : 
      45             : 
      46             : typedef enum
      47             : {
      48             :   L2T_ENCAP_NEXT_DROP,
      49             :   L2T_ENCAP_NEXT_IP6_LOOKUP,
      50             :   L2T_ENCAP_N_NEXT,
      51             : } l2t_encap_next_t;
      52             : 
      53             : typedef struct
      54             : {
      55             :   u32 cached_session_index;
      56             :   u32 cached_sw_if_index;
      57             :   vnet_main_t *vnet_main;
      58             : } l2tp_encap_runtime_t;
      59             : 
      60             : extern vlib_node_registration_t l2t_encap_node;
      61             : 
      62             : #define NSTAGES 3
      63             : 
      64             : static inline void
      65           0 : stage0 (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_buffer_t * b)
      66             : {
      67           0 :   vlib_prefetch_buffer_header (b, STORE);
      68           0 :   CLIB_PREFETCH (b->data, 2 * CLIB_CACHE_LINE_BYTES, STORE);
      69           0 : }
      70             : 
      71             : static inline void
      72           0 : stage1 (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_buffer_t * b)
      73             : {
      74           0 :   l2tp_encap_runtime_t *rt = (void *) node->runtime_data;
      75             :   vnet_hw_interface_t *hi;
      76             : 
      77           0 :   u32 sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_TX];
      78           0 :   u32 session_index = rt->cached_session_index;
      79             : 
      80           0 :   if (PREDICT_FALSE (rt->cached_sw_if_index != sw_if_index))
      81             :     {
      82           0 :       hi = vnet_get_sup_hw_interface (rt->vnet_main, sw_if_index);
      83           0 :       session_index = rt->cached_session_index = hi->dev_instance;
      84           0 :       rt->cached_sw_if_index = sw_if_index;
      85             :     }
      86             : 
      87             :   /* Remember mapping index, prefetch the mini counter */
      88           0 :   vnet_buffer (b)->l2t.next_index = L2T_ENCAP_NEXT_IP6_LOOKUP;
      89           0 :   vnet_buffer (b)->l2t.session_index = session_index;
      90             : 
      91             :   /* $$$$ prefetch counter... */
      92           0 : }
      93             : 
      94             : static inline u32
      95           0 : last_stage (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_buffer_t * b)
      96             : {
      97           0 :   l2t_main_t *lm = &l2t_main;
      98           0 :   vlib_node_t *n = vlib_get_node (vm, l2t_encap_node.index);
      99           0 :   u32 node_counter_base_index = n->error_heap_index;
     100           0 :   vlib_error_main_t *em = &vm->error_main;
     101             :   l2tpv3_header_t *l2tp;
     102             :   u32 session_index;
     103             :   u32 counter_index;
     104             :   l2t_session_t *s;
     105             :   ip6_header_t *ip6;
     106             :   u16 payload_length;
     107           0 :   u32 next_index = L2T_ENCAP_NEXT_IP6_LOOKUP;
     108             : 
     109             :   /* Other-than-output pkt? We're done... */
     110           0 :   if (vnet_buffer (b)->l2t.next_index != L2T_ENCAP_NEXT_IP6_LOOKUP)
     111           0 :     return vnet_buffer (b)->l2t.next_index;
     112             : 
     113           0 :   em->counters[node_counter_base_index + L2T_ENCAP_ERROR_NETWORK_TO_USER] +=
     114             :     1;
     115             : 
     116           0 :   session_index = vnet_buffer (b)->l2t.session_index;
     117             : 
     118             :   counter_index =
     119           0 :     session_index_to_counter_index (session_index,
     120             :                                     SESSION_COUNTER_NETWORK_TO_USER);
     121             : 
     122             :   /* per-mapping byte stats include the ethernet header */
     123           0 :   vlib_increment_combined_counter (&lm->counter_main,
     124           0 :                                    vlib_get_thread_index (),
     125             :                                    counter_index, 1 /* packet_increment */ ,
     126             :                                    vlib_buffer_length_in_chain (vm, b));
     127             : 
     128           0 :   s = pool_elt_at_index (lm->sessions, session_index);
     129             : 
     130           0 :   vnet_buffer (b)->sw_if_index[VLIB_TX] = s->encap_fib_index;
     131             : 
     132             :   /* Paint on an l2tpv3 hdr */
     133           0 :   vlib_buffer_advance (b, -(s->l2tp_hdr_size));
     134           0 :   l2tp = vlib_buffer_get_current (b);
     135             : 
     136           0 :   l2tp->session_id = s->remote_session_id;
     137           0 :   l2tp->cookie = s->remote_cookie;
     138           0 :   if (PREDICT_FALSE (s->l2_sublayer_present))
     139             :     {
     140           0 :       l2tp->l2_specific_sublayer = 0;
     141             :     }
     142             : 
     143             :   /* Paint on an ip6 header */
     144           0 :   vlib_buffer_advance (b, -(sizeof (*ip6)));
     145           0 :   ip6 = vlib_buffer_get_current (b);
     146             : 
     147           0 :   if (PREDICT_FALSE (!(s->admin_up)))
     148             :     {
     149           0 :       b->error = node->errors[L2T_ENCAP_ERROR_ADMIN_DOWN];
     150           0 :       next_index = L2T_ENCAP_NEXT_DROP;
     151           0 :       goto done;
     152             :     }
     153             : 
     154           0 :   ip6->ip_version_traffic_class_and_flow_label =
     155           0 :     clib_host_to_net_u32 (0x6 << 28);
     156             : 
     157             :   /* calculate ip6 payload length */
     158           0 :   payload_length = vlib_buffer_length_in_chain (vm, b);
     159           0 :   payload_length -= sizeof (*ip6);
     160             : 
     161           0 :   ip6->payload_length = clib_host_to_net_u16 (payload_length);
     162           0 :   ip6->protocol = IP_PROTOCOL_L2TP;
     163           0 :   ip6->hop_limit = 0xff;
     164           0 :   ip6->src_address.as_u64[0] = s->our_address.as_u64[0];
     165           0 :   ip6->src_address.as_u64[1] = s->our_address.as_u64[1];
     166           0 :   ip6->dst_address.as_u64[0] = s->client_address.as_u64[0];
     167           0 :   ip6->dst_address.as_u64[1] = s->client_address.as_u64[1];
     168             : 
     169             : 
     170           0 : done:
     171           0 :   if (PREDICT_FALSE (b->flags & VLIB_BUFFER_IS_TRACED))
     172             :     {
     173           0 :       l2t_trace_t *t = vlib_add_trace (vm, node, b, sizeof (*t));
     174           0 :       t->is_user_to_network = 0;
     175           0 :       t->our_address.as_u64[0] = ip6->src_address.as_u64[0];
     176           0 :       t->our_address.as_u64[1] = ip6->src_address.as_u64[1];
     177           0 :       t->client_address.as_u64[0] = ip6->dst_address.as_u64[0];
     178           0 :       t->client_address.as_u64[1] = ip6->dst_address.as_u64[1];
     179           0 :       t->session_index = session_index;
     180             :     }
     181             : 
     182           0 :   return next_index;
     183             : }
     184             : 
     185             : #include <vnet/pipeline.h>
     186             : 
     187        2236 : VLIB_NODE_FN (l2t_encap_node) (vlib_main_t * vm,
     188             :                                vlib_node_runtime_t * node,
     189             :                                vlib_frame_t * frame)
     190             : {
     191           0 :   return dispatch_pipeline (vm, node, frame);
     192             : }
     193             : 
     194             : 
     195             : /* *INDENT-OFF* */
     196      109240 : VLIB_REGISTER_NODE (l2t_encap_node) = {
     197             :   .name = "l2tp-encap",
     198             :   .vector_size = sizeof (u32),
     199             :   .format_trace = format_l2t_trace,
     200             :   .type = VLIB_NODE_TYPE_INTERNAL,
     201             :   .runtime_data_bytes = sizeof (l2tp_encap_runtime_t),
     202             : 
     203             :   .n_errors = ARRAY_LEN(l2t_encap_error_strings),
     204             :   .error_strings = l2t_encap_error_strings,
     205             : 
     206             :   .n_next_nodes = L2T_ENCAP_N_NEXT,
     207             : 
     208             :   /*  add dispositions here */
     209             :   .next_nodes = {
     210             :     [L2T_ENCAP_NEXT_IP6_LOOKUP] = "ip6-lookup",
     211             :     [L2T_ENCAP_NEXT_DROP] = "error-drop",
     212             :   },
     213             : };
     214             : /* *INDENT-ON* */
     215             : 
     216             : #ifndef CLIB_MARCH_VARIANT
     217             : void
     218         613 : l2tp_encap_init (vlib_main_t * vm)
     219             : {
     220             :   l2tp_encap_runtime_t *rt;
     221             : 
     222         613 :   rt = vlib_node_get_runtime_data (vm, l2t_encap_node.index);
     223         613 :   rt->vnet_main = vnet_get_main ();
     224         613 :   rt->cached_sw_if_index = (u32) ~ 0;
     225         613 :   rt->cached_session_index = (u32) ~ 0;
     226         613 : }
     227             : #endif /* CLIB_MARCH_VARIANT */
     228             : 
     229             : /*
     230             :  * fd.io coding-style-patch-verification: ON
     231             :  *
     232             :  * Local Variables:
     233             :  * eval: (c-set-style "gnu")
     234             :  * End:
     235             :  */

Generated by: LCOV version 1.14