IPIP: Add IP{v4,v6} over IP{v4,v6} configured tunnel support.
[vpp.git] / src / vnet / ipip / ipip.c
1 /*
2  * ipip.c: ipip
3  *
4  * Copyright (c) 2018 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 aipiped 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 <stddef.h>
19 #include <vnet/adj/adj_midchain.h>
20 #include <vnet/ipip/ipip.h>
21 #include <vnet/vnet.h>
22 #include <vnet/adj/adj_nbr.h>
23 #include <vnet/fib/ip4_fib.h>
24 #include <vnet/fib/ip6_fib.h>
25 #include <vnet/ip/format.h>
26 #include <vnet/ipip/ipip.h>
27
28 ipip_main_t ipip_main;
29
30 /* Packet trace structure */
31 typedef struct
32 {
33   u32 tunnel_id;
34   u32 length;
35   ip46_address_t src;
36   ip46_address_t dst;
37 } ipip_tx_trace_t;
38
39 u8 *
40 format_ipip_tx_trace (u8 * s, va_list * args)
41 {
42   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
43   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
44   ipip_tx_trace_t *t = va_arg (*args, ipip_tx_trace_t *);
45
46   s =
47     format (s, "IPIP: tunnel %d len %d src %U dst %U", t->tunnel_id,
48             t->length, format_ip46_address, &t->src, IP46_TYPE_ANY,
49             format_ip46_address, &t->dst, IP46_TYPE_ANY);
50   return s;
51 }
52
53 static u8 *
54 ipip_build_rewrite (vnet_main_t * vnm, u32 sw_if_index,
55                     vnet_link_t link_type, const void *dst_address)
56 {
57   ip4_header_t *ip4;
58   ip6_header_t *ip6;
59   u8 *rewrite = NULL;
60   ipip_tunnel_t *t = ipip_tunnel_db_find_by_sw_if_index (sw_if_index);
61
62   if (!t)
63     /* not one of ours */
64     return (0);
65
66   switch (t->transport)
67     {
68     case IPIP_TRANSPORT_IP4:
69       vec_validate (rewrite, sizeof (*ip4) - 1);
70       ip4 = (ip4_header_t *) rewrite;
71       ip4->ip_version_and_header_length = 0x45;
72       ip4->ttl = 64;
73       /* fixup ip4 header length, protocol and checksum after-the-fact */
74       ip4->src_address.as_u32 = t->tunnel_src.ip4.as_u32;
75       ip4->dst_address.as_u32 = t->tunnel_dst.ip4.as_u32;
76       ip4->checksum = ip4_header_checksum (ip4);
77       break;
78
79     case IPIP_TRANSPORT_IP6:
80       vec_validate (rewrite, sizeof (*ip6) - 1);
81       ip6 = (ip6_header_t *) rewrite;
82       ip6->ip_version_traffic_class_and_flow_label =
83         clib_host_to_net_u32 (6 << 28);
84       ip6->hop_limit = 64;
85       /* fixup ip6 header length and protocol after-the-fact */
86       ip6->src_address.as_u64[0] = t->tunnel_src.ip6.as_u64[0];
87       ip6->src_address.as_u64[1] = t->tunnel_src.ip6.as_u64[1];
88       ip6->dst_address.as_u64[0] = t->tunnel_dst.ip6.as_u64[0];
89       ip6->dst_address.as_u64[1] = t->tunnel_dst.ip6.as_u64[1];
90       break;
91     default:
92       /* pass through */
93       ;
94     }
95   return (rewrite);
96 }
97
98 static void
99 ipip4_fixup (vlib_main_t * vm, ip_adjacency_t * adj, vlib_buffer_t * b,
100              const void *data)
101 {
102   ip4_header_t *ip4;
103
104   ip4 = vlib_buffer_get_current (b);
105   ip4->length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b));
106   ip4->protocol =
107     adj->ia_link == VNET_LINK_IP6 ? IP_PROTOCOL_IPV6 : IP_PROTOCOL_IP_IN_IP;
108   ip4->checksum = ip4_header_checksum (ip4);
109 }
110
111 static void
112 ipip6_fixup (vlib_main_t * vm, ip_adjacency_t * adj, vlib_buffer_t * b,
113              const void *data)
114 {
115   ip6_header_t *ip6;
116
117   ip6 = vlib_buffer_get_current (b);
118   ip6->payload_length =
119     clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b) -
120                           sizeof (*ip6));
121   ip6->protocol =
122     adj->ia_link == VNET_LINK_IP6 ? IP_PROTOCOL_IPV6 : IP_PROTOCOL_IP_IN_IP;
123 }
124
125 static void
126 ipip_tunnel_stack (adj_index_t ai)
127 {
128   ip_adjacency_t *adj;
129   ipip_tunnel_t *t;
130   u32 sw_if_index;
131
132   adj = adj_get (ai);
133   sw_if_index = adj->rewrite_header.sw_if_index;
134
135   t = ipip_tunnel_db_find_by_sw_if_index (sw_if_index);
136   if (!t)
137     return;
138
139   if ((vnet_hw_interface_get_flags (vnet_get_main (), t->hw_if_index) &
140        VNET_HW_INTERFACE_FLAG_LINK_UP) == 0)
141     {
142       adj_nbr_midchain_unstack (ai);
143       return;
144     }
145
146   dpo_id_t tmp = DPO_INVALID;
147   fib_forward_chain_type_t fib_fwd =
148     t->transport ==
149     IPIP_TRANSPORT_IP6 ? FIB_FORW_CHAIN_TYPE_UNICAST_IP6 :
150     FIB_FORW_CHAIN_TYPE_UNICAST_IP4;
151
152   fib_entry_contribute_forwarding (t->p2p.fib_entry_index, fib_fwd, &tmp);
153   if (DPO_LOAD_BALANCE == tmp.dpoi_type)
154     {
155       /*
156        * post IPIP rewrite we will load-balance. However, the IPIP encap
157        * is always the same for this adjacency/tunnel and hence the IP/IPIP
158        * src,dst hash is always the same result too. So we do that hash now and
159        * stack on the choice.
160        * If the choice is an incomplete adj then we will need a poke when
161        * it becomes complete. This happens since the adj update walk propagates
162        * as far a recursive paths.
163        */
164       const dpo_id_t *choice;
165       load_balance_t *lb;
166       int hash;
167
168       lb = load_balance_get (tmp.dpoi_index);
169
170       if (fib_fwd == FIB_FORW_CHAIN_TYPE_UNICAST_IP4)
171         hash = ip4_compute_flow_hash ((ip4_header_t *) adj_get_rewrite (ai),
172                                       lb->lb_hash_config);
173       else
174         hash = ip6_compute_flow_hash ((ip6_header_t *) adj_get_rewrite (ai),
175                                       lb->lb_hash_config);
176       choice =
177         load_balance_get_bucket_i (lb, hash & lb->lb_n_buckets_minus_1);
178       dpo_copy (&tmp, choice);
179     }
180
181   adj_nbr_midchain_stack (ai, &tmp);
182   dpo_reset (&tmp);
183 }
184
185 static adj_walk_rc_t
186 ipip_adj_walk_cb (adj_index_t ai, void *ctx)
187 {
188   ipip_tunnel_stack (ai);
189
190   return (ADJ_WALK_RC_CONTINUE);
191 }
192
193 static void
194 ipip_tunnel_restack (ipip_tunnel_t * gt)
195 {
196   fib_protocol_t proto;
197
198   /*
199    * walk all the adjacencies on th IPIP interface and restack them
200    */
201   FOR_EACH_FIB_IP_PROTOCOL (proto)
202   {
203     adj_nbr_walk (gt->sw_if_index, proto, ipip_adj_walk_cb, NULL);
204   }
205 }
206
207 void
208 ipip_update_adj (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai)
209 {
210   ipip_tunnel_t *t;
211   adj_midchain_fixup_t f;
212
213   t = ipip_tunnel_db_find_by_sw_if_index (sw_if_index);
214   if (!t)
215     return;
216
217   f = t->transport == IPIP_TRANSPORT_IP6 ? ipip6_fixup : ipip4_fixup;
218
219   adj_nbr_midchain_update_rewrite (ai, f, NULL,
220                                    (VNET_LINK_ETHERNET ==
221                                     adj_get_link_type (ai) ?
222                                     ADJ_FLAG_MIDCHAIN_NO_COUNT :
223                                     ADJ_FLAG_NONE), ipip_build_rewrite (vnm,
224                                                                         sw_if_index,
225                                                                         adj_get_link_type
226                                                                         (ai),
227                                                                         NULL));
228   ipip_tunnel_stack (ai);
229 }
230
231 static u8 *
232 format_ipip_tunnel_name (u8 * s, va_list * args)
233 {
234   u32 dev_instance = va_arg (*args, u32);
235   ipip_main_t *gm = &ipip_main;
236   ipip_tunnel_t *t;
237
238   if (dev_instance >= vec_len (gm->tunnels))
239     return format (s, "<improperly-referenced>");
240
241   t = pool_elt_at_index (gm->tunnels, dev_instance);
242   return format (s, "ipip%d", t->user_instance);
243 }
244
245 static u8 *
246 format_ipip_device (u8 * s, va_list * args)
247 {
248   u32 dev_instance = va_arg (*args, u32);
249   CLIB_UNUSED (int verbose) = va_arg (*args, int);
250
251   s = format (s, "IPIP tunnel: id %d\n", dev_instance);
252   return s;
253 }
254
255 static clib_error_t *
256 ipip_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
257 {
258   vnet_hw_interface_t *hi;
259   ipip_tunnel_t *t;
260
261   hi = vnet_get_hw_interface (vnm, hw_if_index);
262
263   t = ipip_tunnel_db_find_by_sw_if_index (hi->sw_if_index);
264   if (!t)
265     return 0;
266
267   if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
268     vnet_hw_interface_set_flags (vnm, hw_if_index,
269                                  VNET_HW_INTERFACE_FLAG_LINK_UP);
270   else
271     vnet_hw_interface_set_flags (vnm, hw_if_index, 0 /* down */ );
272
273   ipip_tunnel_restack (t);
274
275   return /* no error */ 0;
276 }
277
278 /* *INDENT-OFF* */
279 VNET_DEVICE_CLASS(ipip_device_class) = {
280     .name = "IPIP tunnel device",
281     .format_device_name = format_ipip_tunnel_name,
282     .format_device = format_ipip_device,
283     .format_tx_trace = format_ipip_tx_trace,
284     .admin_up_down_function = ipip_interface_admin_up_down,
285 #ifdef SOON
286     .clear counter = 0;
287 #endif
288 };
289
290 VNET_HW_INTERFACE_CLASS(ipip_hw_interface_class) = {
291     .name = "IPIP",
292     //.format_header = format_ipip_header_with_length,
293     //.unformat_header = unformat_ipip_header,
294     .build_rewrite = ipip_build_rewrite,
295     .update_adjacency = ipip_update_adj,
296     .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
297 };
298 /* *INDENT-ON* */
299
300 ipip_tunnel_t *
301 ipip_tunnel_db_find (ipip_tunnel_key_t * key)
302 {
303   ipip_main_t *gm = &ipip_main;
304   uword *p;
305
306   p = hash_get_mem (gm->tunnel_by_key, key);
307   if (!p)
308     return (NULL);
309   return (pool_elt_at_index (gm->tunnels, p[0]));
310 }
311
312 ipip_tunnel_t *
313 ipip_tunnel_db_find_by_sw_if_index (u32 sw_if_index)
314 {
315   ipip_main_t *gm = &ipip_main;
316   if (vec_len (gm->tunnel_index_by_sw_if_index) < sw_if_index)
317     return NULL;
318   u32 ti = gm->tunnel_index_by_sw_if_index[sw_if_index];
319   if (ti == ~0)
320     return NULL;
321   return pool_elt_at_index (gm->tunnels, ti);
322 }
323
324 void
325 ipip_tunnel_db_add (ipip_tunnel_t * t, ipip_tunnel_key_t * key)
326 {
327   ipip_main_t *gm = &ipip_main;
328
329   t->key = clib_mem_alloc (sizeof (*t->key));
330   clib_memcpy (t->key, key, sizeof (*key));
331   hash_set_mem (gm->tunnel_by_key, t->key, t->dev_instance);
332 }
333
334 void
335 ipip_tunnel_db_remove (ipip_tunnel_t * t)
336 {
337   ipip_main_t *gm = &ipip_main;
338
339   hash_unset_mem (gm->tunnel_by_key, t->key);
340   clib_mem_free (t->key);
341   t->key = NULL;
342 }
343
344 static ipip_tunnel_t *
345 ipip_tunnel_from_fib_node (fib_node_t * node)
346 {
347   ipip_main_t *gm = &ipip_main;
348   ASSERT (gm->fib_node_type == node->fn_type);
349   return ((ipip_tunnel_t *) (((char *) node) -
350                              offsetof (ipip_tunnel_t, p2p.node)));
351 }
352
353 static fib_node_back_walk_rc_t
354 ipip_tunnel_back_walk (fib_node_t * node, fib_node_back_walk_ctx_t * ctx)
355 {
356   ipip_tunnel_restack (ipip_tunnel_from_fib_node (node));
357
358   return (FIB_NODE_BACK_WALK_CONTINUE);
359 }
360
361 static fib_node_t *
362 ipip_tunnel_fib_node_get (fib_node_index_t index)
363 {
364   ipip_tunnel_t *gt;
365   ipip_main_t *gm;
366
367   gm = &ipip_main;
368   gt = pool_elt_at_index (gm->tunnels, index);
369
370   return (&gt->p2p.node);
371 }
372
373 static void
374 ipip_tunnel_last_lock_gone (fib_node_t * node)
375 {
376   /*
377    * The MPLS IPIP tunnel is a root of the graph. As such
378    * it never has children and thus is never locked.
379    */
380   ASSERT (0);
381 }
382
383 /*
384  * Virtual function table registered by IPIP tunnels
385  * for participation in the FIB object graph.
386  */
387 const static fib_node_vft_t ipip_vft = {
388   .fnv_get = ipip_tunnel_fib_node_get,
389   .fnv_last_lock = ipip_tunnel_last_lock_gone,
390   .fnv_back_walk = ipip_tunnel_back_walk,
391 };
392
393 static void
394 ipip_fib_add (ipip_tunnel_t * t)
395 {
396   ipip_main_t *gm = &ipip_main;
397   fib_prefix_t dst = {.fp_len = t->transport == IPIP_TRANSPORT_IP6 ? 128 : 32,
398     .fp_proto =
399       t->transport ==
400       IPIP_TRANSPORT_IP6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4,
401     .fp_addr = t->tunnel_dst
402   };
403
404   t->p2p.fib_entry_index =
405     fib_table_entry_special_add (t->fib_index, &dst, FIB_SOURCE_RR,
406                                  FIB_ENTRY_FLAG_NONE);
407   t->p2p.sibling_index =
408     fib_entry_child_add (t->p2p.fib_entry_index, gm->fib_node_type,
409                          t->dev_instance);
410 }
411
412 static void
413 ipip_fib_delete (ipip_tunnel_t * t)
414 {
415   fib_entry_child_remove (t->p2p.fib_entry_index, t->p2p.sibling_index);
416   fib_table_entry_delete_index (t->p2p.fib_entry_index, FIB_SOURCE_RR);
417   fib_node_deinit (&t->p2p.node);
418 }
419
420 int
421 ipip_add_tunnel (ipip_transport_t transport,
422                  u32 instance, ip46_address_t * src, ip46_address_t * dst,
423                  u32 fib_index, u32 * sw_if_indexp)
424 {
425   ipip_main_t *gm = &ipip_main;
426   vnet_main_t *vnm = gm->vnet_main;
427   ip4_main_t *im4 = &ip4_main;
428   ip6_main_t *im6 = &ip6_main;
429   ipip_tunnel_t *t;
430   vnet_hw_interface_t *hi;
431   u32 hw_if_index, sw_if_index;
432   ipip_tunnel_key_t key = {.transport = transport,
433     .fib_index = fib_index,
434     .src = *src,
435     .dst = *dst
436   };
437   t = ipip_tunnel_db_find (&key);
438   if (t)
439     return VNET_API_ERROR_IF_ALREADY_EXISTS;
440
441   pool_get_aligned (gm->tunnels, t, CLIB_CACHE_LINE_BYTES);
442   memset (t, 0, sizeof (*t));
443
444   /* Reconcile the real dev_instance and a possible requested instance */
445   u32 t_idx = t - gm->tunnels;  /* tunnel index (or instance) */
446   u32 u_idx = instance;         /* user specified instance */
447   if (u_idx == ~0)
448     u_idx = t_idx;
449   if (hash_get (gm->instance_used, u_idx))
450     {
451       pool_put (gm->tunnels, t);
452       return VNET_API_ERROR_INSTANCE_IN_USE;
453     }
454   hash_set (gm->instance_used, u_idx, 1);
455
456   t->dev_instance = t_idx;      /* actual */
457   t->user_instance = u_idx;     /* name */
458   fib_node_init (&t->p2p.node, gm->fib_node_type);
459
460   hw_if_index = vnet_register_interface (vnm, ipip_device_class.index, t_idx,
461                                          ipip_hw_interface_class.index,
462                                          t_idx);
463
464   hi = vnet_get_hw_interface (vnm, hw_if_index);
465   sw_if_index = hi->sw_if_index;
466
467   t->hw_if_index = hw_if_index;
468   t->fib_index = fib_index;
469   t->sw_if_index = sw_if_index;
470
471   t->transport = transport;
472   vec_validate_init_empty (gm->tunnel_index_by_sw_if_index, sw_if_index, ~0);
473   gm->tunnel_index_by_sw_if_index[sw_if_index] = t_idx;
474
475   if (t->transport == IPIP_TRANSPORT_IP4)
476     {
477       vec_validate (im4->fib_index_by_sw_if_index, sw_if_index);
478       hi->min_packet_bytes = 64 + sizeof (ip4_header_t);
479     }
480   else
481     {
482       vec_validate (im6->fib_index_by_sw_if_index, sw_if_index);
483       hi->min_packet_bytes = 64 + sizeof (ip6_header_t);
484     }
485
486   hi->per_packet_overhead_bytes = /* preamble */ 8 + /* inter frame gap */ 12;
487
488   /* Standard default ipip MTU. */
489   hi->max_l3_packet_bytes[VLIB_RX] = hi->max_l3_packet_bytes[VLIB_TX] = 9000;
490
491   t->tunnel_src = *src;
492   t->tunnel_dst = *dst;
493
494   ipip_tunnel_db_add (t, &key);
495
496   /*
497    * Source the FIB entry for the tunnel's destination and become a
498    * child thereof. The tunnel will then get poked when the forwarding
499    * for the entry updates, and the tunnel can re-stack accordingly
500    */
501   ipip_fib_add (t);
502   if (sw_if_indexp)
503     *sw_if_indexp = sw_if_index;
504
505   if (t->transport == IPIP_TRANSPORT_IP6 && !gm->ip6_protocol_registered)
506     {
507       ip6_register_protocol (IP_PROTOCOL_IP_IN_IP, ipip6_input_node.index);
508       ip6_register_protocol (IP_PROTOCOL_IPV6, ipip6_input_node.index);
509       gm->ip6_protocol_registered = true;
510     }
511   else if (t->transport == IPIP_TRANSPORT_IP4 && !gm->ip4_protocol_registered)
512     {
513       ip4_register_protocol (IP_PROTOCOL_IP_IN_IP, ipip4_input_node.index);
514       ip4_register_protocol (IP_PROTOCOL_IPV6, ipip4_input_node.index);
515       gm->ip4_protocol_registered = true;
516     }
517   return 0;
518 }
519
520 int
521 ipip_del_tunnel (u32 sw_if_index)
522 {
523   ipip_main_t *gm = &ipip_main;
524   vnet_main_t *vnm = gm->vnet_main;
525   ipip_tunnel_t *t;
526
527
528   t = ipip_tunnel_db_find_by_sw_if_index (sw_if_index);
529   if (t == NULL)
530     return VNET_API_ERROR_NO_SUCH_ENTRY;
531
532   vnet_sw_interface_set_flags (vnm, sw_if_index, 0 /* down */ );
533   gm->tunnel_index_by_sw_if_index[sw_if_index] = ~0;
534   vnet_delete_hw_interface (vnm, t->hw_if_index);
535   ipip_fib_delete (t);
536   hash_unset (gm->instance_used, t->user_instance);
537   ipip_tunnel_db_remove (t);
538   pool_put (gm->tunnels, t);
539
540   return 0;
541 }
542
543 static clib_error_t *
544 ipip_init (vlib_main_t * vm)
545 {
546   ipip_main_t *gm = &ipip_main;
547
548   memset (gm, 0, sizeof (gm[0]));
549   gm->vlib_main = vm;
550   gm->vnet_main = vnet_get_main ();
551   gm->tunnel_by_key =
552     hash_create_mem (0, sizeof (ipip_tunnel_key_t), sizeof (uword));
553   gm->fib_node_type = fib_node_register_new_type (&ipip_vft);
554
555   return 0;
556 }
557
558 VLIB_INIT_FUNCTION (ipip_init);
559
560 /*
561  * fd.io coding-style-patch-verification: ON
562  *
563  * Local Variables:
564  * eval: (c-set-style "gnu")
565  * End:
566  */