blob: 637d4a740c8eb23fc8f1941c7b71af34b9f95361 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
Florin Corase127a7e2016-02-18 22:20:01 +01002 * Copyright (c) 2016 Cisco and/or its affiliates.
Ed Warnickecb9cada2015-12-08 15:45:58 -07003 * 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 */
Florin Corasff0bf132016-09-05 19:30:35 +020015/**
16 * @file
17 * @brief L2 LISP-GPE decap code.
18 *
19 */
Ed Warnickecb9cada2015-12-08 15:45:58 -070020#include <vlib/vlib.h>
21#include <vnet/pg/pg.h>
22#include <vnet/lisp-gpe/lisp_gpe.h>
23
Florin Corase127a7e2016-02-18 22:20:01 +010024typedef struct
25{
Ed Warnickecb9cada2015-12-08 15:45:58 -070026 u32 next_index;
27 u32 tunnel_index;
28 u32 error;
29 lisp_gpe_header_t h;
30} lisp_gpe_rx_trace_t;
31
Florin Corase127a7e2016-02-18 22:20:01 +010032static u8 *
33format_lisp_gpe_rx_trace (u8 * s, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -070034{
35 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
36 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
Florin Coras220beac2016-08-16 23:04:00 +020037 lisp_gpe_rx_trace_t *t = va_arg (*args, lisp_gpe_rx_trace_t *);
Ed Warnickecb9cada2015-12-08 15:45:58 -070038
39 if (t->tunnel_index != ~0)
40 {
Florin Corase127a7e2016-02-18 22:20:01 +010041 s = format (s, "LISP-GPE: tunnel %d next %d error %d", t->tunnel_index,
Florin Coras220beac2016-08-16 23:04:00 +020042 t->next_index, t->error);
Ed Warnickecb9cada2015-12-08 15:45:58 -070043 }
44 else
45 {
Florin Corase127a7e2016-02-18 22:20:01 +010046 s = format (s, "LISP-GPE: no tunnel next %d error %d\n", t->next_index,
Florin Coras220beac2016-08-16 23:04:00 +020047 t->error);
Ed Warnickecb9cada2015-12-08 15:45:58 -070048 }
Florin Corase127a7e2016-02-18 22:20:01 +010049 s = format (s, "\n %U", format_lisp_gpe_header_with_length, &t->h,
Florin Coras220beac2016-08-16 23:04:00 +020050 (u32) sizeof (t->h) /* max size */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -070051 return s;
52}
53
Florin Coras220beac2016-08-16 23:04:00 +020054static u32 next_proto_to_next_index[LISP_GPE_NEXT_PROTOS] = {
55 LISP_GPE_INPUT_NEXT_DROP,
56 LISP_GPE_INPUT_NEXT_IP4_INPUT,
57 LISP_GPE_INPUT_NEXT_IP6_INPUT,
58 LISP_GPE_INPUT_NEXT_L2_INPUT,
59 LISP_GPE_INPUT_NEXT_DROP
Florin Corase127a7e2016-02-18 22:20:01 +010060};
61
Florin Coras1a1adc72016-07-22 01:45:30 +020062always_inline u32
Florin Corase127a7e2016-02-18 22:20:01 +010063next_protocol_to_next_index (lisp_gpe_header_t * lgh, u8 * next_header)
64{
Florin Corasc7e91e42016-05-02 18:26:26 +020065 /* lisp-gpe router */
Florin Coras220beac2016-08-16 23:04:00 +020066 if (PREDICT_TRUE ((lgh->flags & LISP_GPE_FLAGS_P)
67 && lgh->next_protocol < LISP_GPE_NEXT_PROTOS))
Florin Corasc7e91e42016-05-02 18:26:26 +020068 return next_proto_to_next_index[lgh->next_protocol];
Florin Coras1a1adc72016-07-22 01:45:30 +020069 /* legacy lisp router */
Florin Corasc7e91e42016-05-02 18:26:26 +020070 else if ((lgh->flags & LISP_GPE_FLAGS_P) == 0)
Florin Corase127a7e2016-02-18 22:20:01 +010071 {
Florin Coras220beac2016-08-16 23:04:00 +020072 ip4_header_t *iph = (ip4_header_t *) next_header;
Florin Corase127a7e2016-02-18 22:20:01 +010073 if ((iph->ip_version_and_header_length & 0xF0) == 0x40)
Florin Coras220beac2016-08-16 23:04:00 +020074 return LISP_GPE_INPUT_NEXT_IP4_INPUT;
Florin Corase127a7e2016-02-18 22:20:01 +010075 else if ((iph->ip_version_and_header_length & 0xF0) == 0x60)
Florin Coras220beac2016-08-16 23:04:00 +020076 return LISP_GPE_INPUT_NEXT_IP6_INPUT;
Florin Corase127a7e2016-02-18 22:20:01 +010077 else
Florin Coras220beac2016-08-16 23:04:00 +020078 return LISP_GPE_INPUT_NEXT_DROP;
Florin Corase127a7e2016-02-18 22:20:01 +010079 }
Florin Corase127a7e2016-02-18 22:20:01 +010080 else
81 return LISP_GPE_INPUT_NEXT_DROP;
82}
83
Florin Coras1a1adc72016-07-22 01:45:30 +020084always_inline tunnel_lookup_t *
85next_index_to_iface (lisp_gpe_main_t * lgm, u32 next_index)
86{
87 if (LISP_GPE_INPUT_NEXT_IP4_INPUT == next_index
88 || LISP_GPE_INPUT_NEXT_IP6_INPUT == next_index)
89 return &lgm->l3_ifaces;
90 else if (LISP_GPE_INPUT_NEXT_L2_INPUT == next_index)
91 return &lgm->l2_ifaces;
Florin Coras220beac2016-08-16 23:04:00 +020092 clib_warning ("next_index not associated to an interface!");
Florin Coras1a1adc72016-07-22 01:45:30 +020093 return 0;
94}
95
Florin Coras0f6b7962016-06-21 22:32:47 +020096static_always_inline void
Florin Coras220beac2016-08-16 23:04:00 +020097incr_decap_stats (vnet_main_t * vnm, u32 cpu_index, u32 length,
98 u32 sw_if_index, u32 * last_sw_if_index, u32 * n_packets,
99 u32 * n_bytes)
Florin Coras0f6b7962016-06-21 22:32:47 +0200100{
Florin Coras220beac2016-08-16 23:04:00 +0200101 vnet_interface_main_t *im;
Florin Coras0f6b7962016-06-21 22:32:47 +0200102
Florin Coras220beac2016-08-16 23:04:00 +0200103 if (PREDICT_TRUE (sw_if_index == *last_sw_if_index))
Florin Coras0f6b7962016-06-21 22:32:47 +0200104 {
105 *n_packets += 1;
106 *n_bytes += length;
107 }
108 else
109 {
Florin Coras220beac2016-08-16 23:04:00 +0200110 if (PREDICT_TRUE (*last_sw_if_index != ~0))
111 {
112 im = &vnm->interface_main;
Florin Coras0f6b7962016-06-21 22:32:47 +0200113
Florin Coras220beac2016-08-16 23:04:00 +0200114 vlib_increment_combined_counter (im->combined_sw_if_counters +
115 VNET_INTERFACE_COUNTER_RX,
116 cpu_index, *last_sw_if_index,
117 *n_packets, *n_bytes);
118 }
Florin Coras0f6b7962016-06-21 22:32:47 +0200119 *last_sw_if_index = sw_if_index;
120 *n_packets = 1;
121 *n_bytes = length;
122 }
123}
124
Florin Corasff0bf132016-09-05 19:30:35 +0200125/**
126 * @brief LISP-GPE decap dispatcher.
127 * @node lisp_gpe_input_inline
128 *
129 * LISP-GPE decap dispatcher.
130 *
131 * Decaps IP-UDP-LISP-GPE header and based on the next protocol and in the
132 * GPE header and the vni decides the next node to forward the packet to.
133 *
134 * @param[in] vm vlib_main_t corresponding to current thread.
135 * @param[in] node vlib_node_runtime_t data for this node.
136 * @param[in] frame vlib_frame_t whose contents should be dispatched.
137 *
138 * @return number of vectors in frame.
139 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700140static uword
Florin Coras02655bd2016-04-26 00:17:24 +0200141lisp_gpe_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
Florin Coras220beac2016-08-16 23:04:00 +0200142 vlib_frame_t * from_frame, u8 is_v4)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700143{
Florin Coras220beac2016-08-16 23:04:00 +0200144 u32 n_left_from, next_index, *from, *to_next, cpu_index;
Florin Coras0f6b7962016-06-21 22:32:47 +0200145 u32 n_bytes = 0, n_packets = 0, last_sw_if_index = ~0, drops = 0;
Florin Coras220beac2016-08-16 23:04:00 +0200146 lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700147
Florin Coras220beac2016-08-16 23:04:00 +0200148 cpu_index = os_get_cpu_number ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700149 from = vlib_frame_vector_args (from_frame);
150 n_left_from = from_frame->n_vectors;
151
152 next_index = node->cached_next_index;
153
154 while (n_left_from > 0)
155 {
156 u32 n_left_to_next;
157
Florin Coras220beac2016-08-16 23:04:00 +0200158 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700159
Ed Warnickecb9cada2015-12-08 15:45:58 -0700160 while (n_left_from >= 4 && n_left_to_next >= 2)
Florin Coras220beac2016-08-16 23:04:00 +0200161 {
162 u32 bi0, bi1;
163 vlib_buffer_t *b0, *b1;
164 ip4_udp_lisp_gpe_header_t *iul4_0, *iul4_1;
165 ip6_udp_lisp_gpe_header_t *iul6_0, *iul6_1;
166 lisp_gpe_header_t *lh0, *lh1;
167 u32 next0, next1, error0, error1;
168 uword *si0, *si1;
169 tunnel_lookup_t *tl0, *tl1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700170
Florin Coras220beac2016-08-16 23:04:00 +0200171 /* Prefetch next iteration. */
172 {
173 vlib_buffer_t *p2, *p3;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700174
Florin Coras220beac2016-08-16 23:04:00 +0200175 p2 = vlib_get_buffer (vm, from[2]);
176 p3 = vlib_get_buffer (vm, from[3]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700177
Florin Coras220beac2016-08-16 23:04:00 +0200178 vlib_prefetch_buffer_header (p2, LOAD);
179 vlib_prefetch_buffer_header (p3, LOAD);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700180
Florin Coras220beac2016-08-16 23:04:00 +0200181 CLIB_PREFETCH (p2->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
182 CLIB_PREFETCH (p3->data, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
183 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700184
Florin Coras220beac2016-08-16 23:04:00 +0200185 bi0 = from[0];
186 bi1 = from[1];
187 to_next[0] = bi0;
188 to_next[1] = bi1;
189 from += 2;
190 to_next += 2;
191 n_left_to_next -= 2;
192 n_left_from -= 2;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700193
Florin Coras220beac2016-08-16 23:04:00 +0200194 b0 = vlib_get_buffer (vm, bi0);
195 b1 = vlib_get_buffer (vm, bi1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700196
Florin Coras220beac2016-08-16 23:04:00 +0200197 /* udp leaves current_data pointing at the lisp header */
198 if (is_v4)
199 {
200 vlib_buffer_advance (b0,
201 -(word) (sizeof (udp_header_t) +
202 sizeof (ip4_header_t)));
203 vlib_buffer_advance (b1,
204 -(word) (sizeof (udp_header_t) +
205 sizeof (ip4_header_t)));
Florin Corase127a7e2016-02-18 22:20:01 +0100206
Florin Coras220beac2016-08-16 23:04:00 +0200207 iul4_0 = vlib_buffer_get_current (b0);
208 iul4_1 = vlib_buffer_get_current (b1);
Florin Corase127a7e2016-02-18 22:20:01 +0100209
Florin Coras220beac2016-08-16 23:04:00 +0200210 /* pop (ip, udp, lisp-gpe) */
211 vlib_buffer_advance (b0, sizeof (*iul4_0));
212 vlib_buffer_advance (b1, sizeof (*iul4_1));
Florin Coras02655bd2016-04-26 00:17:24 +0200213
Florin Coras220beac2016-08-16 23:04:00 +0200214 lh0 = &iul4_0->lisp;
215 lh1 = &iul4_1->lisp;
216 }
217 else
218 {
219 vlib_buffer_advance (b0,
220 -(word) (sizeof (udp_header_t) +
221 sizeof (ip6_header_t)));
222 vlib_buffer_advance (b1,
223 -(word) (sizeof (udp_header_t) +
224 sizeof (ip6_header_t)));
Florin Coras02655bd2016-04-26 00:17:24 +0200225
Florin Coras220beac2016-08-16 23:04:00 +0200226 iul6_0 = vlib_buffer_get_current (b0);
227 iul6_1 = vlib_buffer_get_current (b1);
Florin Coras02655bd2016-04-26 00:17:24 +0200228
Florin Coras220beac2016-08-16 23:04:00 +0200229 /* pop (ip, udp, lisp-gpe) */
230 vlib_buffer_advance (b0, sizeof (*iul6_0));
231 vlib_buffer_advance (b1, sizeof (*iul6_1));
Florin Coras02655bd2016-04-26 00:17:24 +0200232
Florin Coras220beac2016-08-16 23:04:00 +0200233 lh0 = &iul6_0->lisp;
234 lh1 = &iul6_1->lisp;
235 }
Florin Corase127a7e2016-02-18 22:20:01 +0100236
Florin Coras220beac2016-08-16 23:04:00 +0200237 /* determine next_index from lisp-gpe header */
238 next0 = next_protocol_to_next_index (lh0,
239 vlib_buffer_get_current (b0));
240 next1 = next_protocol_to_next_index (lh1,
241 vlib_buffer_get_current (b1));
Florin Corase127a7e2016-02-18 22:20:01 +0100242
Florin Coras220beac2016-08-16 23:04:00 +0200243 /* determine if tunnel is l2 or l3 */
244 tl0 = next_index_to_iface (lgm, next0);
245 tl1 = next_index_to_iface (lgm, next1);
Florin Corase127a7e2016-02-18 22:20:01 +0100246
Florin Coras220beac2016-08-16 23:04:00 +0200247 /* map iid/vni to lisp-gpe sw_if_index which is used by ipx_input to
248 * decide the rx vrf and the input features to be applied */
249 si0 = hash_get (tl0->sw_if_index_by_vni,
250 clib_net_to_host_u32 (lh0->iid));
251 si1 = hash_get (tl1->sw_if_index_by_vni,
252 clib_net_to_host_u32 (lh1->iid));
Florin Corase127a7e2016-02-18 22:20:01 +0100253
Florin Coras1a1adc72016-07-22 01:45:30 +0200254
Florin Coras220beac2016-08-16 23:04:00 +0200255 /* Required to make the l2 tag push / pop code work on l2 subifs */
256 vnet_update_l2_len (b0);
257 vnet_update_l2_len (b1);
Florin Coras1a1adc72016-07-22 01:45:30 +0200258
Florin Coras220beac2016-08-16 23:04:00 +0200259 if (si0)
260 {
261 incr_decap_stats (lgm->vnet_main, cpu_index,
262 vlib_buffer_length_in_chain (vm, b0), si0[0],
263 &last_sw_if_index, &n_packets, &n_bytes);
264 vnet_buffer (b0)->sw_if_index[VLIB_RX] = si0[0];
265 error0 = 0;
266 }
267 else
268 {
269 next0 = LISP_GPE_INPUT_NEXT_DROP;
270 error0 = LISP_GPE_ERROR_NO_TUNNEL;
271 drops++;
272 }
Florin Corase127a7e2016-02-18 22:20:01 +0100273
Florin Coras220beac2016-08-16 23:04:00 +0200274 if (si1)
275 {
276 incr_decap_stats (lgm->vnet_main, cpu_index,
277 vlib_buffer_length_in_chain (vm, b1), si1[0],
278 &last_sw_if_index, &n_packets, &n_bytes);
279 vnet_buffer (b1)->sw_if_index[VLIB_RX] = si1[0];
280 error1 = 0;
281 }
282 else
283 {
284 next1 = LISP_GPE_INPUT_NEXT_DROP;
285 error1 = LISP_GPE_ERROR_NO_TUNNEL;
286 drops++;
287 }
Florin Coras577c3552016-04-21 00:45:40 +0200288
Florin Coras220beac2016-08-16 23:04:00 +0200289 b0->error = error0 ? node->errors[error0] : 0;
290 b1->error = error1 ? node->errors[error1] : 0;
Florin Corase127a7e2016-02-18 22:20:01 +0100291
Florin Coras220beac2016-08-16 23:04:00 +0200292 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
293 {
294 lisp_gpe_rx_trace_t *tr = vlib_add_trace (vm, node, b0,
295 sizeof (*tr));
296 tr->next_index = next0;
297 tr->error = error0;
298 tr->h = lh0[0];
299 }
Florin Corase127a7e2016-02-18 22:20:01 +0100300
Florin Coras220beac2016-08-16 23:04:00 +0200301 if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
302 {
303 lisp_gpe_rx_trace_t *tr = vlib_add_trace (vm, node, b1,
304 sizeof (*tr));
305 tr->next_index = next1;
306 tr->error = error1;
307 tr->h = lh1[0];
308 }
Florin Corase127a7e2016-02-18 22:20:01 +0100309
Florin Coras220beac2016-08-16 23:04:00 +0200310 vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
311 n_left_to_next, bi0, bi1, next0,
312 next1);
313 }
314
Florin Corase127a7e2016-02-18 22:20:01 +0100315 while (n_left_from > 0 && n_left_to_next > 0)
Florin Coras220beac2016-08-16 23:04:00 +0200316 {
317 u32 bi0;
318 vlib_buffer_t *b0;
319 u32 next0;
320 ip4_udp_lisp_gpe_header_t *iul4_0;
321 ip6_udp_lisp_gpe_header_t *iul6_0;
322 lisp_gpe_header_t *lh0;
323 u32 error0;
324 uword *si0;
325 tunnel_lookup_t *tl0;
Florin Corase127a7e2016-02-18 22:20:01 +0100326
Florin Coras220beac2016-08-16 23:04:00 +0200327 bi0 = from[0];
328 to_next[0] = bi0;
329 from += 1;
330 to_next += 1;
331 n_left_from -= 1;
332 n_left_to_next -= 1;
Florin Corase127a7e2016-02-18 22:20:01 +0100333
Florin Coras220beac2016-08-16 23:04:00 +0200334 b0 = vlib_get_buffer (vm, bi0);
Florin Corase127a7e2016-02-18 22:20:01 +0100335
Florin Coras220beac2016-08-16 23:04:00 +0200336 /* udp leaves current_data pointing at the lisp header
337 * TODO: there's no difference in processing between v4 and v6
338 * encapsulated packets so the code should be simplified if ip header
339 * info is not going to be used for dp smrs/dpsec */
340 if (is_v4)
341 {
342 vlib_buffer_advance (b0,
343 -(word) (sizeof (udp_header_t) +
344 sizeof (ip4_header_t)));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700345
Florin Coras220beac2016-08-16 23:04:00 +0200346 iul4_0 = vlib_buffer_get_current (b0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700347
Florin Coras220beac2016-08-16 23:04:00 +0200348 /* pop (ip, udp, lisp-gpe) */
349 vlib_buffer_advance (b0, sizeof (*iul4_0));
Florin Coras02655bd2016-04-26 00:17:24 +0200350
Florin Coras220beac2016-08-16 23:04:00 +0200351 lh0 = &iul4_0->lisp;
352 }
353 else
354 {
355 vlib_buffer_advance (b0,
356 -(word) (sizeof (udp_header_t) +
357 sizeof (ip6_header_t)));
Florin Coras02655bd2016-04-26 00:17:24 +0200358
Florin Coras220beac2016-08-16 23:04:00 +0200359 iul6_0 = vlib_buffer_get_current (b0);
Florin Coras02655bd2016-04-26 00:17:24 +0200360
Florin Coras220beac2016-08-16 23:04:00 +0200361 /* pop (ip, udp, lisp-gpe) */
362 vlib_buffer_advance (b0, sizeof (*iul6_0));
Florin Coras02655bd2016-04-26 00:17:24 +0200363
Florin Coras220beac2016-08-16 23:04:00 +0200364 lh0 = &iul6_0->lisp;
365 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700366
Florin Coras220beac2016-08-16 23:04:00 +0200367 /* TODO if security is to be implemented, something similar to RPF,
368 * probably we'd like to check that the peer is allowed to send us
369 * packets. For this, we should use the tunnel table OR check that
370 * we have a mapping for the source eid and that the outer source of
371 * the packet is one of its locators */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700372
Florin Coras220beac2016-08-16 23:04:00 +0200373 /* determine next_index from lisp-gpe header */
374 next0 = next_protocol_to_next_index (lh0,
375 vlib_buffer_get_current (b0));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700376
Florin Coras220beac2016-08-16 23:04:00 +0200377 /* determine if tunnel is l2 or l3 */
378 tl0 = next_index_to_iface (lgm, next0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700379
Florin Coras220beac2016-08-16 23:04:00 +0200380 /* map iid/vni to lisp-gpe sw_if_index which is used by ipx_input to
Florin Corasf1950192016-10-25 16:47:52 +0200381 * decide the rx vrf and the input features to be applied.
382 * NOTE: vni uses only the first 24 bits */
Florin Coras220beac2016-08-16 23:04:00 +0200383 si0 = hash_get (tl0->sw_if_index_by_vni,
Florin Corasf1950192016-10-25 16:47:52 +0200384 clib_net_to_host_u32 (lh0->iid << 8));
Florin Coras577c3552016-04-21 00:45:40 +0200385
Florin Coras220beac2016-08-16 23:04:00 +0200386 /* Required to make the l2 tag push / pop code work on l2 subifs */
387 vnet_update_l2_len (b0);
Florin Coras1a1adc72016-07-22 01:45:30 +0200388
Florin Coras220beac2016-08-16 23:04:00 +0200389 if (si0)
390 {
391 incr_decap_stats (lgm->vnet_main, cpu_index,
392 vlib_buffer_length_in_chain (vm, b0), si0[0],
393 &last_sw_if_index, &n_packets, &n_bytes);
394 vnet_buffer (b0)->sw_if_index[VLIB_RX] = si0[0];
395 error0 = 0;
396 }
397 else
398 {
399 next0 = LISP_GPE_INPUT_NEXT_DROP;
400 error0 = LISP_GPE_ERROR_NO_TUNNEL;
401 drops++;
402 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700403
Florin Coras220beac2016-08-16 23:04:00 +0200404 /* TODO error handling if security is implemented */
405 b0->error = error0 ? node->errors[error0] : 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700406
Florin Coras220beac2016-08-16 23:04:00 +0200407 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
408 {
409 lisp_gpe_rx_trace_t *tr = vlib_add_trace (vm, node, b0,
410 sizeof (*tr));
411 tr->next_index = next0;
412 tr->error = error0;
413 tr->h = lh0[0];
414 }
Florin Corase127a7e2016-02-18 22:20:01 +0100415
Florin Coras220beac2016-08-16 23:04:00 +0200416 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
417 n_left_to_next, bi0, next0);
418 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700419
420 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
421 }
Florin Coras0f6b7962016-06-21 22:32:47 +0200422
423 /* flush iface stats */
424 incr_decap_stats (lgm->vnet_main, cpu_index, 0, ~0, &last_sw_if_index,
Florin Coras220beac2016-08-16 23:04:00 +0200425 &n_packets, &n_bytes);
Florin Coras02655bd2016-04-26 00:17:24 +0200426 vlib_node_increment_counter (vm, lisp_gpe_ip4_input_node.index,
Florin Coras220beac2016-08-16 23:04:00 +0200427 LISP_GPE_ERROR_NO_TUNNEL, drops);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700428 return from_frame->n_vectors;
429}
430
Florin Coras02655bd2016-04-26 00:17:24 +0200431static uword
432lisp_gpe_ip4_input (vlib_main_t * vm, vlib_node_runtime_t * node,
Florin Coras220beac2016-08-16 23:04:00 +0200433 vlib_frame_t * from_frame)
Florin Coras02655bd2016-04-26 00:17:24 +0200434{
Florin Coras220beac2016-08-16 23:04:00 +0200435 return lisp_gpe_input_inline (vm, node, from_frame, 1);
Florin Coras02655bd2016-04-26 00:17:24 +0200436}
437
438static uword
439lisp_gpe_ip6_input (vlib_main_t * vm, vlib_node_runtime_t * node,
Florin Coras220beac2016-08-16 23:04:00 +0200440 vlib_frame_t * from_frame)
Florin Coras02655bd2016-04-26 00:17:24 +0200441{
Florin Coras220beac2016-08-16 23:04:00 +0200442 return lisp_gpe_input_inline (vm, node, from_frame, 0);
Florin Coras02655bd2016-04-26 00:17:24 +0200443}
444
Florin Coras220beac2016-08-16 23:04:00 +0200445static char *lisp_gpe_ip4_input_error_strings[] = {
Florin Corasf727db92016-06-23 15:01:58 +0200446#define lisp_gpe_error(n,s) s,
447#include <vnet/lisp-gpe/lisp_gpe_error.def>
448#undef lisp_gpe_error
449};
450
Florin Coras220beac2016-08-16 23:04:00 +0200451/* *INDENT-OFF* */
Florin Coras02655bd2016-04-26 00:17:24 +0200452VLIB_REGISTER_NODE (lisp_gpe_ip4_input_node) = {
453 .function = lisp_gpe_ip4_input,
454 .name = "lisp-gpe-ip4-input",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700455 /* Takes a vector of packets. */
456 .vector_size = sizeof (u32),
Ed Warnickecb9cada2015-12-08 15:45:58 -0700457 .n_next_nodes = LISP_GPE_INPUT_N_NEXT,
458 .next_nodes = {
459#define _(s,n) [LISP_GPE_INPUT_NEXT_##s] = n,
Florin Coras02655bd2016-04-26 00:17:24 +0200460 foreach_lisp_gpe_ip_input_next
461#undef _
462 },
463
Florin Corasf727db92016-06-23 15:01:58 +0200464 .n_errors = ARRAY_LEN (lisp_gpe_ip4_input_error_strings),
465 .error_strings = lisp_gpe_ip4_input_error_strings,
466
Florin Coras02655bd2016-04-26 00:17:24 +0200467 .format_buffer = format_lisp_gpe_header_with_length,
468 .format_trace = format_lisp_gpe_rx_trace,
469 // $$$$ .unformat_buffer = unformat_lisp_gpe_header,
470};
Florin Coras220beac2016-08-16 23:04:00 +0200471/* *INDENT-ON* */
Florin Coras02655bd2016-04-26 00:17:24 +0200472
Florin Coras220beac2016-08-16 23:04:00 +0200473/* *INDENT-OFF* */
Florin Coras02655bd2016-04-26 00:17:24 +0200474VLIB_REGISTER_NODE (lisp_gpe_ip6_input_node) = {
475 .function = lisp_gpe_ip6_input,
476 .name = "lisp-gpe-ip6-input",
477 /* Takes a vector of packets. */
478 .vector_size = sizeof (u32),
Florin Coras02655bd2016-04-26 00:17:24 +0200479 .n_next_nodes = LISP_GPE_INPUT_N_NEXT,
480 .next_nodes = {
481#define _(s,n) [LISP_GPE_INPUT_NEXT_##s] = n,
482 foreach_lisp_gpe_ip_input_next
Ed Warnickecb9cada2015-12-08 15:45:58 -0700483#undef _
484 },
485
Florin Corasf727db92016-06-23 15:01:58 +0200486 .n_errors = ARRAY_LEN (lisp_gpe_ip4_input_error_strings),
487 .error_strings = lisp_gpe_ip4_input_error_strings,
488
Ed Warnickecb9cada2015-12-08 15:45:58 -0700489 .format_buffer = format_lisp_gpe_header_with_length,
490 .format_trace = format_lisp_gpe_rx_trace,
491 // $$$$ .unformat_buffer = unformat_lisp_gpe_header,
492};
Florin Coras220beac2016-08-16 23:04:00 +0200493/* *INDENT-ON* */
494
495/*
496 * fd.io coding-style-patch-verification: ON
497 *
498 * Local Variables:
499 * eval: (c-set-style "gnu")
500 * End:
501 */