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