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