FD.io VPP  v21.01.1
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 {
67  vlib_prefetch_buffer_header (b, STORE);
68  CLIB_PREFETCH (b->data, 2 * CLIB_CACHE_LINE_BYTES, STORE);
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 
81  {
83  session_index = rt->cached_session_index = hi->dev_instance;
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;
98  vlib_node_t *n = vlib_get_node (vm, l2t_encap_node.index);
99  u32 node_counter_base_index = n->error_heap_index;
100  vlib_error_main_t *em = &vm->error_main;
101  l2tpv3_header_t *l2tp;
102  u32 session_index;
104  l2t_session_t *s;
105  ip6_header_t *ip6;
106  u16 payload_length;
107  u32 next_index = L2T_ENCAP_NEXT_IP6_LOOKUP;
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)));
145  ip6 = vlib_buffer_get_current (b);
146 
147  if (PREDICT_FALSE (!(s->admin_up)))
148  {
149  b->error = node->errors[L2T_ENCAP_ERROR_ADMIN_DOWN];
150  next_index = L2T_ENCAP_NEXT_DROP;
151  goto done;
152  }
153 
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  */
int is_user_to_network
Definition: l2tp.h:90
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
l2t_encap_next_t
Definition: encap.c:46
u32 error_heap_index
Definition: node.h:325
ip6_address_t client_address
Definition: l2tp.h:93
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 thread_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
Definition: counter.h:239
u8 runtime_data[0]
Function dependent node-runtime data.
Definition: node.h:519
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
static void stage0(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b)
Definition: encap.c:65
ip6_address_t our_address
Definition: l2tp.h:28
static void stage1(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b)
Definition: encap.c:72
void l2tp_encap_init(vlib_main_t *vm)
Definition: encap.c:218
u32 encap_fib_index
Definition: l2tp.h:42
vlib_main_t * vm
Definition: in2out_ed.c:1580
#define VLIB_NODE_FN(node)
Definition: node.h:203
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:470
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:402
u32 cached_session_index
Definition: encap.c:55
ip6_address_t src_address
Definition: ip6_packet.h:310
u64 remote_cookie
Definition: l2tp.h:33
static u32 session_index_to_counter_index(u32 session_index, u32 counter_id)
Definition: l2tp.h:108
#define foreach_l2t_encap_error
Definition: encap.c:26
ip6_address_t client_address
Definition: l2tp.h:29
l2t_main_t l2t_main
Definition: l2tp.c:26
vl_api_ip6_address_t ip6
Definition: one.api:424
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:207
const cJSON *const b
Definition: cJSON.h:255
unsigned int u32
Definition: types.h:88
static u32 last_stage(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b)
Definition: encap.c:95
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:136
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
vlib_error_main_t error_main
Definition: main.h:210
u8 * format_l2t_trace(u8 *s, va_list *args)
Definition: l2tp.c:30
unsigned short u16
Definition: types.h:57
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:233
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:136
#define PREDICT_FALSE(x)
Definition: clib.h:121
vnet_main_t * vnet_main
Definition: encap.c:57
static u32 counter_index(vlib_main_t *vm, vlib_error_t e)
Definition: drop.c:67
ip6_address_t our_address
Definition: l2tp.h:92
u64 * counters
Definition: error.h:62
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:170
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:219
u32 cached_sw_if_index
Definition: encap.c:56
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
u8 data[]
Packet data.
Definition: buffer.h:181
#define ARRAY_LEN(x)
Definition: clib.h:67
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1580
u32 remote_session_id
Definition: l2tp.h:35
l2t_encap_error_t
Definition: encap.c:37
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:252
vl_api_ip4_address_t hi
Definition: arp.api:37
vlib_combined_counter_main_t counter_main
Definition: l2tp.h:71
vlib_node_registration_t l2t_encap_node
(constructor) VLIB_REGISTER_NODE (l2t_encap_node)
Definition: encap.c:196
struct _vlib_node_registration vlib_node_registration_t
u32 ip_version_traffic_class_and_flow_label
Definition: ip6_packet.h:297
Definition: defs.h:47
u16 payload_length
Definition: ip6_packet.h:301
u8 l2tp_hdr_size
Definition: l2tp.h:44
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1581
VLIB buffer representation.
Definition: buffer.h:102
l2t_session_t * sessions
Definition: l2tp.h:61
#define vnet_buffer(b)
Definition: buffer.h:417
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:85
u8 admin_up
Definition: l2tp.h:48
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:634
u8 l2_sublayer_present
Definition: l2tp.h:45
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
static char * l2t_encap_error_strings[]
Definition: encap.c:31
u32 session_index
Definition: l2tp.h:91
ip6_address_t dst_address
Definition: ip6_packet.h:310