FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
encap.c
Go to the documentation of this file.
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,
34 #undef _
35 };
36 
37 typedef enum
38 {
39 #define _(sym,str) L2T_ENCAP_ERROR_##sym,
41 #undef _
44 
45 
46 typedef enum
47 {
52 
53 typedef struct
54 {
59 
61 
62 #define NSTAGES 3
63 
64 static inline void
66 {
69 }
70 
71 static inline void
73 {
74  l2tp_encap_runtime_t *rt = (void *) node->runtime_data;
76 
77  u32 sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_TX];
78  u32 session_index = rt->cached_session_index;
79 
80  if (PREDICT_FALSE (rt->cached_sw_if_index != sw_if_index))
81  {
83  session_index = rt->cached_session_index = hi->dev_instance;
84  rt->cached_sw_if_index = sw_if_index;
85  }
86 
87  /* Remember mapping index, prefetch the mini counter */
88  vnet_buffer (b)->l2t.next_index = L2T_ENCAP_NEXT_IP6_LOOKUP;
89  vnet_buffer (b)->l2t.session_index = session_index;
90 
91  /* $$$$ prefetch counter... */
92 }
93 
94 static inline u32
96 {
97  l2t_main_t *lm = &l2t_main;
99  u32 node_counter_base_index = n->error_heap_index;
101  l2tpv3_header_t *l2tp;
102  u32 session_index;
104  l2t_session_t *s;
105  ip6_header_t *ip6;
106  u16 payload_length;
108 
109  /* Other-than-output pkt? We're done... */
110  if (vnet_buffer (b)->l2t.next_index != L2T_ENCAP_NEXT_IP6_LOOKUP)
111  return vnet_buffer (b)->l2t.next_index;
112 
113  em->counters[node_counter_base_index + L2T_ENCAP_ERROR_NETWORK_TO_USER] +=
114  1;
115 
116  session_index = vnet_buffer (b)->l2t.session_index;
117 
118  counter_index =
119  session_index_to_counter_index (session_index,
121 
122  /* per-mapping byte stats include the ethernet header */
125  counter_index, 1 /* packet_increment */ ,
127 
128  s = pool_elt_at_index (lm->sessions, session_index);
129 
130  vnet_buffer (b)->sw_if_index[VLIB_TX] = s->encap_fib_index;
131 
132  /* Paint on an l2tpv3 hdr */
134  l2tp = vlib_buffer_get_current (b);
135 
136  l2tp->session_id = s->remote_session_id;
137  l2tp->cookie = s->remote_cookie;
139  {
140  l2tp->l2_specific_sublayer = 0;
141  }
142 
143  /* Paint on an ip6 header */
144  vlib_buffer_advance (b, -(sizeof (*ip6)));
146 
147  if (PREDICT_FALSE (!(s->admin_up)))
148  {
149  b->error = node->errors[L2T_ENCAP_ERROR_ADMIN_DOWN];
151  goto done;
152  }
153 
154  ip6->ip_version_traffic_class_and_flow_label =
155  clib_host_to_net_u32 (0x6 << 28);
156 
157  /* calculate ip6 payload length */
158  payload_length = vlib_buffer_length_in_chain (vm, b);
159  payload_length -= sizeof (*ip6);
160 
161  ip6->payload_length = clib_host_to_net_u16 (payload_length);
162  ip6->protocol = IP_PROTOCOL_L2TP;
163  ip6->hop_limit = 0xff;
164  ip6->src_address.as_u64[0] = s->our_address.as_u64[0];
165  ip6->src_address.as_u64[1] = s->our_address.as_u64[1];
166  ip6->dst_address.as_u64[0] = s->client_address.as_u64[0];
167  ip6->dst_address.as_u64[1] = s->client_address.as_u64[1];
168 
169 
170 done:
171  if (PREDICT_FALSE (b->flags & VLIB_BUFFER_IS_TRACED))
172  {
173  l2t_trace_t *t = vlib_add_trace (vm, node, b, sizeof (*t));
174  t->is_user_to_network = 0;
175  t->our_address.as_u64[0] = ip6->src_address.as_u64[0];
176  t->our_address.as_u64[1] = ip6->src_address.as_u64[1];
177  t->client_address.as_u64[0] = ip6->dst_address.as_u64[0];
178  t->client_address.as_u64[1] = ip6->dst_address.as_u64[1];
179  t->session_index = session_index;
180  }
181 
182  return next_index;
183 }
184 
185 #include <vnet/pipeline.h>
186 
190 {
191  return dispatch_pipeline (vm, node, frame);
192 }
193 
194 
195 /* *INDENT-OFF* */
197  .name = "l2tp-encap",
198  .vector_size = sizeof (u32),
199  .format_trace = format_l2t_trace,
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
219 {
221 
223  rt->vnet_main = vnet_get_main ();
224  rt->cached_sw_if_index = (u32) ~ 0;
225  rt->cached_session_index = (u32) ~ 0;
226 }
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  */
vlib_error_main_t
Definition: error.h:61
vlib_node_get_runtime_data
static void * vlib_node_get_runtime_data(vlib_main_t *vm, u32 node_index)
Get node runtime private data by node index.
Definition: node_funcs.h:137
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
vlib_prefetch_buffer_header
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:231
pipeline.h
next_index
nat44_ei_hairpin_src_next_t next_index
Definition: nat44_ei_hairpinning.c:412
l2t_session_t::l2_sublayer_present
u8 l2_sublayer_present
Definition: l2tp.h:45
pool_elt_at_index
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:549
l2t_main_t
Definition: l2tp.h:58
l2t_main_t::sessions
l2t_session_t * sessions
Definition: l2tp.h:61
format_l2t_trace
u8 * format_l2t_trace(u8 *s, va_list *args)
Definition: l2tp.c:30
VLIB_NODE_TYPE_INTERNAL
@ VLIB_NODE_TYPE_INTERNAL
Definition: node.h:72
l2t_trace_t::is_user_to_network
int is_user_to_network
Definition: l2tp.h:90
l2tp_encap_runtime_t::cached_session_index
u32 cached_session_index
Definition: encap.c:55
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
vlib_main_t::error_main
vlib_error_main_t error_main
Definition: main.h:179
u16
unsigned short u16
Definition: types.h:57
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
counter_index
static u32 counter_index(vlib_main_t *vm, vlib_error_t e)
Definition: drop.c:67
stage0
static void stage0(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b)
Definition: encap.c:65
hi
vl_api_ip4_address_t hi
Definition: arp.api:37
vlib_frame_t
Definition: node.h:372
vlib_buffer_length_in_chain
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:433
l2tp_encap_runtime_t::vnet_main
vnet_main_t * vnet_main
Definition: encap.c:57
l2tp_encap_runtime_t
Definition: encap.c:53
ethernet.h
session_index_to_counter_index
static u32 session_index_to_counter_index(u32 session_index, u32 counter_id)
Definition: l2tp.h:108
l2t_encap_error_t
l2t_encap_error_t
Definition: encap.c:37
l2t_session_t::admin_up
u8 admin_up
Definition: l2tp.h:48
l2t_encap_next_t
l2t_encap_next_t
Definition: encap.c:46
CLIB_PREFETCH
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:76
hash.h
vlib_buffer_advance
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:276
vlib_buffer_t::error
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:145
vlib_error_main_t::counters
u64 * counters
Definition: error.h:64
error.h
VLIB_NODE_FN
#define VLIB_NODE_FN(node)
Definition: node.h:202
l2t_session_t::l2tp_hdr_size
u8 l2tp_hdr_size
Definition: l2tp.h:44
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:441
vnet_get_main
vnet_main_t * vnet_get_main(void)
Definition: pnat_test_stubs.h:56
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
vlib_get_thread_index
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:187
ARRAY_LEN
#define ARRAY_LEN(x)
Definition: clib.h:70
L2T_ENCAP_N_NEXT
@ L2T_ENCAP_N_NEXT
Definition: encap.c:50
l2tp_encap_runtime_t::cached_sw_if_index
u32 cached_sw_if_index
Definition: encap.c:56
l2t_trace_t::client_address
ip6_address_t client_address
Definition: l2tp.h:93
vlib_get_node
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:86
l2t_encap_error_strings
static char * l2t_encap_error_strings[]
Definition: encap.c:31
l2t_session_t::client_address
ip6_address_t client_address
Definition: l2tp.h:29
CLIB_CACHE_LINE_BYTES
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:58
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
stage1
static void stage1(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b)
Definition: encap.c:72
last_stage
static u32 last_stage(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b)
Definition: encap.c:95
vnet_hw_interface_t
Definition: interface.h:638
vnet_main_t
Definition: vnet.h:76
SESSION_COUNTER_NETWORK_TO_USER
@ SESSION_COUNTER_NETWORK_TO_USER
Definition: l2tp.h:104
l2t_session_t::remote_cookie
u64 remote_cookie
Definition: l2tp.h:33
l2t_encap_node
vlib_node_registration_t l2t_encap_node
(constructor) VLIB_REGISTER_NODE (l2t_encap_node)
Definition: encap.c:196
ip.h
u32
unsigned int u32
Definition: types.h:88
vnet_get_sup_hw_interface
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
Definition: interface_funcs.h:92
l2t_trace_t::our_address
ip6_address_t our_address
Definition: l2tp.h:92
ip6
vl_api_ip6_address_t ip6
Definition: one.api:424
ip6_header_t
Definition: ip6_packet.h:294
L2T_ENCAP_NEXT_IP6_LOOKUP
@ L2T_ENCAP_NEXT_IP6_LOOKUP
Definition: encap.c:49
foreach_l2t_encap_error
#define foreach_l2t_encap_error
Definition: encap.c:26
l2t_main
l2t_main_t l2t_main
Definition: l2tp.c:26
vlib_main_t
Definition: main.h:102
vlib_node_t
Definition: node.h:247
vlib_add_trace
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:628
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
vlib_buffer_get_current
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
rt
vnet_interface_output_runtime_t * rt
Definition: interface_output.c:419
L2T_ENCAP_NEXT_DROP
@ L2T_ENCAP_NEXT_DROP
Definition: encap.c:48
vlib_buffer_t::data
u8 data[]
Packet data.
Definition: buffer.h:204
l2tp_encap_init
void l2tp_encap_init(vlib_main_t *vm)
Definition: encap.c:218
l2t_session_t
Definition: l2tp.h:25
vlib_node_t::error_heap_index
u32 error_heap_index
Definition: node.h:315
l2t_trace_t
Definition: l2tp.h:88
l2t_main_t::counter_main
vlib_combined_counter_main_t counter_main
Definition: l2tp.h:71
l2tp.h
vnet.h
vlib_node_runtime_t
Definition: node.h:454
sw_if_index
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
l2t_trace_t::session_index
u32 session_index
Definition: l2tp.h:91
VLIB_TX
@ VLIB_TX
Definition: defs.h:47
l2t_session_t::remote_session_id
u32 remote_session_id
Definition: l2tp.h:35
l2t_session_t::encap_fib_index
u32 encap_fib_index
Definition: l2tp.h:42
L2T_ENCAP_N_ERROR
@ L2T_ENCAP_N_ERROR
Definition: encap.c:42
type
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vlib_increment_combined_counter
vlib_increment_combined_counter(ccm, ti, sw_if_index, n_buffers, n_bytes)
l2t_session_t::our_address
ip6_address_t our_address
Definition: l2tp.h:28
vlib_buffer_t::flags
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index,...
Definition: buffer.h:133
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169