A Protocol Independent Hierarchical FIB (VPP-352)
[vpp.git] / vnet / vnet / gre / node.c
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 <vnet/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 #define _(s,n) GRE_INPUT_NEXT_##s,
34   foreach_gre_input_next
35 #undef _
36   GRE_INPUT_N_NEXT,
37 } gre_input_next_t;
38
39 typedef struct {
40   u32 tunnel_id;
41   u32 length;
42   ip4_address_t src;
43   ip4_address_t dst;
44 } gre_rx_trace_t;
45
46 u8 * format_gre_rx_trace (u8 * s, va_list * args)
47 {
48   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
49   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
50   gre_rx_trace_t * t = va_arg (*args, gre_rx_trace_t *);
51     
52   s = format (s, "GRE: tunnel %d len %d src %U dst %U",
53               t->tunnel_id, clib_net_to_host_u16(t->length),
54               format_ip4_address, &t->src.as_u8,
55               format_ip4_address, &t->dst.as_u8);
56   return s;
57 }
58
59 typedef struct {
60   /* Sparse vector mapping gre protocol in network byte order
61      to next index. */
62   u16 * next_by_protocol;
63 } gre_input_runtime_t;
64
65 static uword
66 gre_input (vlib_main_t * vm,
67            vlib_node_runtime_t * node,
68            vlib_frame_t * from_frame)
69 {
70   gre_main_t * gm = &gre_main;
71   mpls_main_t * mm = &mpls_main;
72   ip4_main_t * ip4m = &ip4_main;
73   gre_input_runtime_t * rt = (void *) node->runtime_data;
74   __attribute__((unused)) u32 n_left_from, next_index, * from, * to_next;
75   u64 cached_tunnel_key = (u64) ~0;
76   u32 cached_tunnel_sw_if_index = 0, tunnel_sw_if_index = 0;
77   u32 cached_tunnel_fib_index = 0, tunnel_fib_index;
78
79   u32 cpu_index = os_get_cpu_number();
80   u32 len;
81   vnet_interface_main_t *im = &gm->vnet_main->interface_main;
82
83   from = vlib_frame_vector_args (from_frame);
84   n_left_from = from_frame->n_vectors;
85
86   next_index = node->cached_next_index;
87
88   while (n_left_from > 0)
89     {
90       u32 n_left_to_next;
91
92       vlib_get_next_frame (vm, node, next_index,
93                            to_next, n_left_to_next);
94
95       while (n_left_from >= 4 && n_left_to_next >= 2)
96         {
97           u32 bi0, bi1;
98           vlib_buffer_t * b0, * b1;
99           gre_header_t * h0, * h1;
100           u16 version0, version1;
101           int verr0, verr1;
102           u32 i0, i1, next0, next1, protocol0, protocol1;
103           ip4_header_t *ip0, *ip1;
104
105           /* Prefetch next iteration. */
106           {
107             vlib_buffer_t * p2, * p3;
108
109             p2 = vlib_get_buffer (vm, from[2]);
110             p3 = vlib_get_buffer (vm, from[3]);
111
112             vlib_prefetch_buffer_header (p2, LOAD);
113             vlib_prefetch_buffer_header (p3, LOAD);
114
115             CLIB_PREFETCH (p2->data, sizeof (h0[0]), LOAD);
116             CLIB_PREFETCH (p3->data, sizeof (h1[0]), LOAD);
117           }
118
119           bi0 = from[0];
120           bi1 = from[1];
121           to_next[0] = bi0;
122           to_next[1] = bi1;
123           from += 2;
124           to_next += 2;
125           n_left_to_next -= 2;
126           n_left_from -= 2;
127
128           b0 = vlib_get_buffer (vm, bi0);
129           b1 = vlib_get_buffer (vm, bi1);
130
131           /* ip4_local hands us the ip header, not the gre header */
132           ip0 = vlib_buffer_get_current (b0);
133           ip1 = vlib_buffer_get_current (b1);
134
135           /* Save src + dst ip4 address, e.g. for mpls-o-gre */
136           vnet_buffer(b0)->gre.src = ip0->src_address.as_u32;
137           vnet_buffer(b0)->gre.dst = ip0->dst_address.as_u32;
138           vnet_buffer(b1)->gre.src = ip1->src_address.as_u32;
139           vnet_buffer(b1)->gre.dst = ip1->dst_address.as_u32;
140
141           vlib_buffer_advance (b0, sizeof (*ip0));
142           vlib_buffer_advance (b1, sizeof (*ip1));
143
144           h0 = vlib_buffer_get_current (b0);
145           h1 = vlib_buffer_get_current (b1);
146
147           /* Index sparse array with network byte order. */
148           protocol0 = h0->protocol;
149           protocol1 = h1->protocol;
150           sparse_vec_index2 (rt->next_by_protocol, protocol0, protocol1,
151                              &i0, &i1);
152           next0 = vec_elt(rt->next_by_protocol, i0);
153           next1 = vec_elt(rt->next_by_protocol, i1);
154
155           b0->error = node->errors[i0 == SPARSE_VEC_INVALID_INDEX ? GRE_ERROR_UNKNOWN_PROTOCOL : GRE_ERROR_NONE];
156           b1->error = node->errors[i1 == SPARSE_VEC_INVALID_INDEX ? GRE_ERROR_UNKNOWN_PROTOCOL : GRE_ERROR_NONE];
157           
158           version0 = clib_net_to_host_u16 (h0->flags_and_version);
159           verr0 =  version0 & GRE_VERSION_MASK;
160           version1 = clib_net_to_host_u16 (h1->flags_and_version);
161           verr1 =  version1 & GRE_VERSION_MASK;
162
163           b0->error = verr0 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION]
164               : b0->error;
165           next0 = verr0 ? GRE_INPUT_NEXT_DROP : next0;
166           b1->error = verr1 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION]
167               : b1->error;
168           next1 = verr1 ? GRE_INPUT_NEXT_DROP : next1;
169
170
171           /* RPF check for ip4/ip6 input */
172           if (PREDICT_FALSE(next0 == GRE_INPUT_NEXT_IP4_INPUT
173                             || next0 == GRE_INPUT_NEXT_IP6_INPUT
174                             || next0 == GRE_INPUT_NEXT_ETHERNET_INPUT))
175             {
176               u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) |
177                          (u64)(vnet_buffer(b0)->gre.src);
178
179               if (cached_tunnel_key != key)
180                 {
181                   vnet_hw_interface_t * hi;
182                   gre_tunnel_t * t;
183                   uword * p;
184
185                   p = hash_get (gm->tunnel_by_key, key);
186                   if (!p)
187                     {
188                       next0 = GRE_INPUT_NEXT_DROP;
189                       b0->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL];
190                       goto drop0;
191                     }
192                   t = pool_elt_at_index (gm->tunnels, p[0]);
193                   hi = vnet_get_hw_interface (gm->vnet_main,
194                             t->hw_if_index);
195                   tunnel_sw_if_index = hi->sw_if_index;
196                   tunnel_fib_index = vec_elt (ip4m->fib_index_by_sw_if_index,
197                                               tunnel_sw_if_index);
198
199                   cached_tunnel_sw_if_index = tunnel_sw_if_index;
200                   cached_tunnel_fib_index = tunnel_fib_index;
201                 }
202               else
203                 {
204                   tunnel_sw_if_index = cached_tunnel_sw_if_index;
205                   tunnel_fib_index = cached_tunnel_fib_index;
206                 }
207             }
208           else if (PREDICT_TRUE(next0 == GRE_INPUT_NEXT_MPLS_INPUT))
209             {
210               u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) |
211                          (u64)(vnet_buffer(b0)->gre.src);
212
213               if (cached_tunnel_key != key)
214                 {
215                   vnet_hw_interface_t * hi;
216                   mpls_gre_tunnel_t * t;
217                   uword * p;
218
219                   p = hash_get (gm->tunnel_by_key, key);
220                   if (!p)
221                     {
222                       next0 = GRE_INPUT_NEXT_DROP;
223                       b0->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL];
224                       goto drop0;
225                     }
226                   t = pool_elt_at_index (mm->gre_tunnels, p[0]);
227                   hi = vnet_get_hw_interface (gm->vnet_main,
228                                               t->hw_if_index);
229                   tunnel_sw_if_index = hi->sw_if_index;
230                   tunnel_fib_index = vec_elt (ip4m->fib_index_by_sw_if_index,
231                                               tunnel_sw_if_index);
232
233                   cached_tunnel_sw_if_index = tunnel_sw_if_index;
234                   cached_tunnel_fib_index = tunnel_fib_index;
235                 }
236               else
237                 {
238                   tunnel_sw_if_index = cached_tunnel_sw_if_index;
239                   tunnel_fib_index = cached_tunnel_fib_index;
240                 }
241             }
242           else
243             {
244                 next0 = GRE_INPUT_NEXT_DROP;
245                 goto drop0;
246             }
247           len = vlib_buffer_length_in_chain (vm, b0);
248           vlib_increment_combined_counter (im->combined_sw_if_counters
249                                            + VNET_INTERFACE_COUNTER_RX,
250                                            cpu_index,
251                                            tunnel_sw_if_index,
252                                            1 /* packets */,
253                                            len /* bytes */);
254
255           vnet_buffer(b0)->sw_if_index[VLIB_TX] = tunnel_fib_index;
256           vnet_buffer(b0)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;
257
258 drop0:
259           if (PREDICT_FALSE(next1 == GRE_INPUT_NEXT_IP4_INPUT
260                             || next1 == GRE_INPUT_NEXT_IP6_INPUT
261                             || next1 == GRE_INPUT_NEXT_ETHERNET_INPUT))
262             {
263               u64 key = ((u64)(vnet_buffer(b1)->gre.dst) << 32) |
264                          (u64)(vnet_buffer(b1)->gre.src);
265
266               if (cached_tunnel_key != key)
267                 {
268                   vnet_hw_interface_t * hi;
269                   gre_tunnel_t * t;
270                   uword * p;
271
272                   p = hash_get (gm->tunnel_by_key, key);
273                   if (!p)
274                     {
275                       next1 = GRE_INPUT_NEXT_DROP;
276                       b1->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL];
277                       goto drop1;
278                     }
279                   t = pool_elt_at_index (gm->tunnels, p[0]);
280                   hi = vnet_get_hw_interface (gm->vnet_main,
281                             t->hw_if_index);
282                   tunnel_sw_if_index = hi->sw_if_index;
283                   tunnel_fib_index = vec_elt (ip4m->fib_index_by_sw_if_index,
284                                               tunnel_sw_if_index);
285
286                   cached_tunnel_sw_if_index = tunnel_sw_if_index;
287                   cached_tunnel_fib_index = tunnel_fib_index;
288                 }
289               else
290                 {
291                   tunnel_sw_if_index = cached_tunnel_sw_if_index;
292                   tunnel_fib_index = cached_tunnel_fib_index;
293                 }
294             }
295           else if (PREDICT_TRUE(next1 == GRE_INPUT_NEXT_MPLS_INPUT))
296             {
297               u64 key = ((u64)(vnet_buffer(b1)->gre.dst) << 32) |
298                          (u64)(vnet_buffer(b1)->gre.src);
299
300               if (cached_tunnel_key != key)
301                 {
302                   vnet_hw_interface_t * hi;
303                   mpls_gre_tunnel_t * t;
304                   uword * p;
305
306                   ip4_main_t * ip4m = &ip4_main;
307                   p = hash_get (gm->tunnel_by_key, key);
308                   if (!p)
309                     {
310                       next1 = GRE_INPUT_NEXT_DROP;
311                       b1->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL];
312                       goto drop1;
313                     }
314                   t = pool_elt_at_index (mm->gre_tunnels, p[0]);
315                   hi = vnet_get_hw_interface (gm->vnet_main,
316                                               t->hw_if_index);
317                   tunnel_sw_if_index = hi->sw_if_index;
318                   tunnel_fib_index = vec_elt (ip4m->fib_index_by_sw_if_index,
319                                               tunnel_sw_if_index);
320
321                   cached_tunnel_sw_if_index = tunnel_sw_if_index;
322                   cached_tunnel_fib_index = tunnel_fib_index;
323                 }
324               else
325                 {
326                   tunnel_sw_if_index = cached_tunnel_sw_if_index;
327                   tunnel_fib_index = cached_tunnel_fib_index;
328                 }
329             }
330           else
331             {
332                 next1 = GRE_INPUT_NEXT_DROP;
333                 goto drop1;
334             }
335           len = vlib_buffer_length_in_chain (vm, b1);
336           vlib_increment_combined_counter (im->combined_sw_if_counters
337                                            + VNET_INTERFACE_COUNTER_RX,
338                                            cpu_index,
339                                            tunnel_sw_if_index,
340                                            1 /* packets */,
341                                            len /* bytes */);
342
343           vnet_buffer(b1)->sw_if_index[VLIB_TX] = tunnel_fib_index;
344           vnet_buffer(b1)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;
345
346 drop1:
347           if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
348             {
349               gre_rx_trace_t *tr = vlib_add_trace (vm, node,
350                                                    b0, sizeof (*tr));
351               tr->tunnel_id = ~0;
352               tr->length = ip0->length;
353               tr->src.as_u32 = ip0->src_address.as_u32;
354               tr->dst.as_u32 = ip0->dst_address.as_u32;
355             }
356
357           if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
358             {
359               gre_rx_trace_t *tr = vlib_add_trace (vm, node,
360                                                    b1, sizeof (*tr));
361               tr->tunnel_id = ~0;
362               tr->length = ip1->length;
363               tr->src.as_u32 = ip1->src_address.as_u32;
364               tr->dst.as_u32 = ip1->dst_address.as_u32;
365             }
366
367           vlib_buffer_advance (b0, sizeof (*h0));
368           vlib_buffer_advance (b1, sizeof (*h1));
369
370           vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
371                                            to_next, n_left_to_next,
372                                            bi0, bi1, next0, next1);
373         }
374     
375       while (n_left_from > 0 && n_left_to_next > 0)
376         {
377           u32 bi0;
378           vlib_buffer_t * b0;
379           gre_header_t * h0;
380           ip4_header_t * ip0;
381           u16 version0;
382           int verr0;
383           u32 i0, next0;
384
385           bi0 = from[0];
386           to_next[0] = bi0;
387           from += 1;
388           to_next += 1;
389           n_left_from -= 1;
390           n_left_to_next -= 1;
391
392           b0 = vlib_get_buffer (vm, bi0);
393           ip0 = vlib_buffer_get_current (b0);
394
395           vnet_buffer(b0)->gre.src = ip0->src_address.as_u32;
396           vnet_buffer(b0)->gre.dst = ip0->dst_address.as_u32;
397
398           vlib_buffer_advance (b0, sizeof (*ip0));
399
400           h0 = vlib_buffer_get_current (b0);
401
402           i0 = sparse_vec_index (rt->next_by_protocol, h0->protocol);
403           next0 = vec_elt(rt->next_by_protocol, i0);
404
405           b0->error = 
406               node->errors[i0 == SPARSE_VEC_INVALID_INDEX 
407                            ? GRE_ERROR_UNKNOWN_PROTOCOL : GRE_ERROR_NONE];
408           
409           version0 = clib_net_to_host_u16 (h0->flags_and_version);
410           verr0 =  version0 & GRE_VERSION_MASK;
411           b0->error = verr0 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION] 
412               : b0->error;
413           next0 = verr0 ? GRE_INPUT_NEXT_DROP : next0;
414
415
416           /* For IP payload we need to find source interface
417              so we can increase counters and help forward node to
418              pick right FIB */
419           /* RPF check for ip4/ip6 input */
420           if (PREDICT_FALSE(next0 == GRE_INPUT_NEXT_IP4_INPUT
421                             || next0 == GRE_INPUT_NEXT_IP6_INPUT
422                             || next0 == GRE_INPUT_NEXT_ETHERNET_INPUT))
423             {
424               u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) |
425                          (u64)(vnet_buffer(b0)->gre.src);
426
427               if (cached_tunnel_key != key)
428                 {
429                   vnet_hw_interface_t * hi;
430                   gre_tunnel_t * t;
431                   uword * p;
432
433                   p = hash_get (gm->tunnel_by_key, key);
434                   if (!p)
435                     {
436                       next0 = GRE_INPUT_NEXT_DROP;
437                       b0->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL];
438                       goto drop;
439                     }
440                   t = pool_elt_at_index (gm->tunnels, p[0]);
441                   hi = vnet_get_hw_interface (gm->vnet_main,
442                             t->hw_if_index);
443                   tunnel_sw_if_index = hi->sw_if_index;
444                   tunnel_fib_index = vec_elt (ip4m->fib_index_by_sw_if_index,
445                                               tunnel_sw_if_index);
446
447                   cached_tunnel_sw_if_index = tunnel_sw_if_index;
448                   cached_tunnel_fib_index = tunnel_fib_index;
449                 }
450               else
451                 {
452                   tunnel_sw_if_index = cached_tunnel_sw_if_index;
453                   tunnel_fib_index = cached_tunnel_fib_index;
454                 }
455             }
456           else if (PREDICT_TRUE(next0 == GRE_INPUT_NEXT_MPLS_INPUT))
457             {
458               u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) |
459                          (u64)(vnet_buffer(b0)->gre.src);
460
461               if (cached_tunnel_key != key)
462                 {
463                   vnet_hw_interface_t * hi;
464                   mpls_gre_tunnel_t * t;
465                   uword * p;
466
467                   p = hash_get (gm->tunnel_by_key, key);
468                   if (!p)
469                     {
470                       next0 = GRE_INPUT_NEXT_DROP;
471                       b0->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL];
472                       goto drop;
473                     }
474                   t = pool_elt_at_index (mm->gre_tunnels, p[0]);
475                   hi = vnet_get_hw_interface (gm->vnet_main,
476                                               t->hw_if_index);
477                   tunnel_sw_if_index = hi->sw_if_index;
478                   tunnel_fib_index = vec_elt (ip4m->fib_index_by_sw_if_index,
479                                               tunnel_sw_if_index);
480
481                   cached_tunnel_sw_if_index = tunnel_sw_if_index;
482                   cached_tunnel_fib_index = tunnel_fib_index;
483                 }
484               else
485                 {
486                   tunnel_sw_if_index = cached_tunnel_sw_if_index;
487                   tunnel_fib_index = cached_tunnel_fib_index;
488                 }
489             }
490           else
491             {
492                 next0 = GRE_INPUT_NEXT_DROP;
493                 goto drop;
494             }
495           len = vlib_buffer_length_in_chain (vm, b0);
496           vlib_increment_combined_counter (im->combined_sw_if_counters
497                                            + VNET_INTERFACE_COUNTER_RX,
498                                            cpu_index,
499                                            tunnel_sw_if_index,
500                                            1 /* packets */,
501                                            len /* bytes */);
502
503           vnet_buffer(b0)->sw_if_index[VLIB_TX] = tunnel_fib_index;
504           vnet_buffer(b0)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;
505
506 drop:
507           if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) 
508             {
509               gre_rx_trace_t *tr = vlib_add_trace (vm, node, 
510                                                    b0, sizeof (*tr));
511               tr->tunnel_id = tunnel_sw_if_index;
512               tr->length = ip0->length;
513               tr->src.as_u32 = ip0->src_address.as_u32;
514               tr->dst.as_u32 = ip0->dst_address.as_u32;
515             }
516
517           vlib_buffer_advance (b0, sizeof (*h0));
518
519           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
520                                            to_next, n_left_to_next,
521                                            bi0, next0);
522         }
523
524       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
525     }
526   vlib_node_increment_counter (vm, gre_input_node.index,
527                                GRE_ERROR_PKTS_DECAP, from_frame->n_vectors);
528   return from_frame->n_vectors;
529 }
530
531 static char * gre_error_strings[] = {
532 #define gre_error(n,s) s,
533 #include "error.def"
534 #undef gre_error
535 };
536
537 VLIB_REGISTER_NODE (gre_input_node) = {
538   .function = gre_input,
539   .name = "gre-input",
540   /* Takes a vector of packets. */
541   .vector_size = sizeof (u32),
542
543   .runtime_data_bytes = sizeof (gre_input_runtime_t),
544
545   .n_errors = GRE_N_ERROR,
546   .error_strings = gre_error_strings,
547
548   .n_next_nodes = GRE_INPUT_N_NEXT,
549   .next_nodes = {
550 #define _(s,n) [GRE_INPUT_NEXT_##s] = n,
551     foreach_gre_input_next
552 #undef _
553   },
554
555   .format_buffer = format_gre_header_with_length,
556   .format_trace = format_gre_rx_trace,
557   .unformat_buffer = unformat_gre_header,
558 };
559
560 VLIB_NODE_FUNCTION_MULTIARCH (gre_input_node, gre_input)
561
562 void
563 gre_register_input_protocol (vlib_main_t * vm,
564                              gre_protocol_t protocol,
565                              u32 node_index)
566 {
567   gre_main_t * em = &gre_main;
568   gre_protocol_info_t * pi;
569   gre_input_runtime_t * rt;
570   u16 * n;
571
572   {
573     clib_error_t * error = vlib_call_init_function (vm, gre_input_init);
574     if (error)
575       clib_error_report (error);
576   }
577
578   pi = gre_get_protocol_info (em, protocol);
579   pi->node_index = node_index;
580   pi->next_index = vlib_node_add_next (vm, 
581                                        gre_input_node.index,
582                                        node_index);
583
584   /* Setup gre protocol -> next index sparse vector mapping. */
585   rt = vlib_node_get_runtime_data (vm, gre_input_node.index);
586   n = sparse_vec_validate (rt->next_by_protocol, 
587                            clib_host_to_net_u16 (protocol));
588   n[0] = pi->next_index;
589 }
590
591 static void
592 gre_setup_node (vlib_main_t * vm, u32 node_index)
593 {
594   vlib_node_t * n = vlib_get_node (vm, node_index);
595   pg_node_t * pn = pg_get_node (node_index);
596
597   n->format_buffer = format_gre_header_with_length;
598   n->unformat_buffer = unformat_gre_header;
599   pn->unformat_edit = unformat_pg_gre_header;
600 }
601
602 static clib_error_t * gre_input_init (vlib_main_t * vm)
603 {
604   gre_input_runtime_t * rt;
605   vlib_node_t *ethernet_input, *ip4_input, *ip6_input, *mpls_unicast_input;
606
607   {
608     clib_error_t * error; 
609     error = vlib_call_init_function (vm, gre_init);
610     if (error)
611       clib_error_report (error);
612   }
613
614   gre_setup_node (vm, gre_input_node.index);
615
616   rt = vlib_node_get_runtime_data (vm, gre_input_node.index);
617
618   rt->next_by_protocol = sparse_vec_new
619     (/* elt bytes */ sizeof (rt->next_by_protocol[0]),
620      /* bits in index */ BITS (((gre_header_t *) 0)->protocol));
621
622   /* These could be moved to the supported protocol input node defn's */
623   ethernet_input = vlib_get_node_by_name (vm, (u8 *)"ethernet-input");
624   ASSERT(ethernet_input);
625   ip4_input = vlib_get_node_by_name (vm, (u8 *)"ip4-input");
626   ASSERT(ip4_input);
627   ip6_input = vlib_get_node_by_name (vm, (u8 *)"ip6-input");
628   ASSERT(ip6_input);
629   mpls_unicast_input = vlib_get_node_by_name (vm, (u8 *)"mpls-input");
630   ASSERT(mpls_unicast_input);
631
632   gre_register_input_protocol (vm, GRE_PROTOCOL_teb,
633                                ethernet_input->index);
634
635   gre_register_input_protocol (vm, GRE_PROTOCOL_ip4, 
636                                ip4_input->index);
637
638   gre_register_input_protocol (vm, GRE_PROTOCOL_ip6, 
639                                ip6_input->index);
640
641   gre_register_input_protocol (vm, GRE_PROTOCOL_mpls_unicast,
642                                mpls_unicast_input->index);
643
644   ip4_register_protocol (IP_PROTOCOL_GRE, gre_input_node.index);
645
646   return 0;
647 }
648
649 VLIB_INIT_FUNCTION (gre_input_init);