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 : */
|