FIB recusrion loop checks traverse midchain adjacencies
[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     }
190   else
191     {
192       adj_nbr_midchain_stack_on_fib_entry
193         (ai,
194          t->p2p.fib_entry_index,
195          (t->transport == IPIP_TRANSPORT_IP6) ?
196          FIB_FORW_CHAIN_TYPE_UNICAST_IP6 : FIB_FORW_CHAIN_TYPE_UNICAST_IP4);
197     }
198 }
199
200 static adj_walk_rc_t
201 ipip_adj_walk_cb (adj_index_t ai, void *ctx)
202 {
203   ipip_tunnel_stack (ai);
204
205   return (ADJ_WALK_RC_CONTINUE);
206 }
207
208 static void
209 ipip_tunnel_restack (ipip_tunnel_t * gt)
210 {
211   fib_protocol_t proto;
212
213   /*
214    * walk all the adjacencies on th IPIP interface and restack them
215    */
216   FOR_EACH_FIB_IP_PROTOCOL (proto)
217   {
218     adj_nbr_walk (gt->sw_if_index, proto, ipip_adj_walk_cb, NULL);
219   }
220 }
221
222 void
223 ipip_update_adj (vnet_main_t * vnm, u32 sw_if_index, adj_index_t ai)
224 {
225   adj_midchain_fixup_t f;
226   ipip_tunnel_t *t;
227   adj_flags_t af;
228
229   t = ipip_tunnel_db_find_by_sw_if_index (sw_if_index);
230   if (!t)
231     return;
232
233   f = t->transport == IPIP_TRANSPORT_IP6 ? ipip6_fixup : ipip4_fixup;
234   af = ADJ_FLAG_MIDCHAIN_IP_STACK;
235   if (VNET_LINK_ETHERNET == adj_get_link_type (ai))
236     af |= ADJ_FLAG_MIDCHAIN_NO_COUNT;
237
238   adj_nbr_midchain_update_rewrite (ai, f, t, af,
239                                    ipip_build_rewrite (vnm,
240                                                        sw_if_index,
241                                                        adj_get_link_type
242                                                        (ai), NULL));
243   ipip_tunnel_stack (ai);
244 }
245
246 static u8 *
247 format_ipip_tunnel_name (u8 * s, va_list * args)
248 {
249   u32 dev_instance = va_arg (*args, u32);
250   ipip_main_t *gm = &ipip_main;
251   ipip_tunnel_t *t;
252
253   if (dev_instance >= vec_len (gm->tunnels))
254     return format (s, "<improperly-referenced>");
255
256   t = pool_elt_at_index (gm->tunnels, dev_instance);
257   return format (s, "ipip%d", t->user_instance);
258 }
259
260 static u8 *
261 format_ipip_device (u8 * s, va_list * args)
262 {
263   u32 dev_instance = va_arg (*args, u32);
264   CLIB_UNUSED (int verbose) = va_arg (*args, int);
265
266   s = format (s, "IPIP tunnel: id %d\n", dev_instance);
267   return s;
268 }
269
270 static clib_error_t *
271 ipip_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
272 {
273   vnet_hw_interface_t *hi;
274   ipip_tunnel_t *t;
275
276   hi = vnet_get_hw_interface (vnm, hw_if_index);
277
278   t = ipip_tunnel_db_find_by_sw_if_index (hi->sw_if_index);
279   if (!t)
280     return 0;
281
282   if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
283     vnet_hw_interface_set_flags (vnm, hw_if_index,
284                                  VNET_HW_INTERFACE_FLAG_LINK_UP);
285   else
286     vnet_hw_interface_set_flags (vnm, hw_if_index, 0 /* down */ );
287
288   ipip_tunnel_restack (t);
289
290   return /* no error */ 0;
291 }
292
293 /* *INDENT-OFF* */
294 VNET_DEVICE_CLASS(ipip_device_class) = {
295     .name = "IPIP tunnel device",
296     .format_device_name = format_ipip_tunnel_name,
297     .format_device = format_ipip_device,
298     .format_tx_trace = format_ipip_tx_trace,
299     .admin_up_down_function = ipip_interface_admin_up_down,
300 #ifdef SOON
301     .clear counter = 0;
302 #endif
303 };
304
305 VNET_HW_INTERFACE_CLASS(ipip_hw_interface_class) = {
306     .name = "IPIP",
307     //.format_header = format_ipip_header_with_length,
308     //.unformat_header = unformat_ipip_header,
309     .build_rewrite = ipip_build_rewrite,
310     .update_adjacency = ipip_update_adj,
311     .flags = VNET_HW_INTERFACE_CLASS_FLAG_P2P,
312 };
313 /* *INDENT-ON* */
314
315 ipip_tunnel_t *
316 ipip_tunnel_db_find (ipip_tunnel_key_t * key)
317 {
318   ipip_main_t *gm = &ipip_main;
319   uword *p;
320
321   p = hash_get_mem (gm->tunnel_by_key, key);
322   if (!p)
323     return (NULL);
324   return (pool_elt_at_index (gm->tunnels, p[0]));
325 }
326
327 ipip_tunnel_t *
328 ipip_tunnel_db_find_by_sw_if_index (u32 sw_if_index)
329 {
330   ipip_main_t *gm = &ipip_main;
331   if (vec_len (gm->tunnel_index_by_sw_if_index) <= sw_if_index)
332     return NULL;
333   u32 ti = gm->tunnel_index_by_sw_if_index[sw_if_index];
334   if (ti == ~0)
335     return NULL;
336   return pool_elt_at_index (gm->tunnels, ti);
337 }
338
339 void
340 ipip_tunnel_db_add (ipip_tunnel_t * t, ipip_tunnel_key_t * key)
341 {
342   ipip_main_t *gm = &ipip_main;
343
344   t->key = clib_mem_alloc (sizeof (*t->key));
345   clib_memcpy (t->key, key, sizeof (*key));
346   hash_set_mem (gm->tunnel_by_key, t->key, t->dev_instance);
347 }
348
349 void
350 ipip_tunnel_db_remove (ipip_tunnel_t * t)
351 {
352   ipip_main_t *gm = &ipip_main;
353
354   hash_unset_mem (gm->tunnel_by_key, t->key);
355   clib_mem_free (t->key);
356   t->key = NULL;
357 }
358
359 static ipip_tunnel_t *
360 ipip_tunnel_from_fib_node (fib_node_t * node)
361 {
362   ipip_main_t *gm = &ipip_main;
363   ASSERT (gm->fib_node_type == node->fn_type);
364   return ((ipip_tunnel_t *) (((char *) node) -
365                              offsetof (ipip_tunnel_t, p2p.node)));
366 }
367
368 static fib_node_back_walk_rc_t
369 ipip_tunnel_back_walk (fib_node_t * node, fib_node_back_walk_ctx_t * ctx)
370 {
371   ipip_tunnel_restack (ipip_tunnel_from_fib_node (node));
372
373   return (FIB_NODE_BACK_WALK_CONTINUE);
374 }
375
376 static fib_node_t *
377 ipip_tunnel_fib_node_get (fib_node_index_t index)
378 {
379   ipip_tunnel_t *gt;
380   ipip_main_t *gm;
381
382   gm = &ipip_main;
383   gt = pool_elt_at_index (gm->tunnels, index);
384
385   return (&gt->p2p.node);
386 }
387
388 static void
389 ipip_tunnel_last_lock_gone (fib_node_t * node)
390 {
391   /*
392    * The MPLS IPIP tunnel is a root of the graph. As such
393    * it never has children and thus is never locked.
394    */
395   ASSERT (0);
396 }
397
398 /*
399  * Virtual function table registered by IPIP tunnels
400  * for participation in the FIB object graph.
401  */
402 const static fib_node_vft_t ipip_vft = {
403   .fnv_get = ipip_tunnel_fib_node_get,
404   .fnv_last_lock = ipip_tunnel_last_lock_gone,
405   .fnv_back_walk = ipip_tunnel_back_walk,
406 };
407
408 static void
409 ipip_fib_add (ipip_tunnel_t * t)
410 {
411   ipip_main_t *gm = &ipip_main;
412   fib_prefix_t dst = {.fp_len = t->transport == IPIP_TRANSPORT_IP6 ? 128 : 32,
413     .fp_proto =
414       t->transport ==
415       IPIP_TRANSPORT_IP6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4,
416     .fp_addr = t->tunnel_dst
417   };
418
419   t->p2p.fib_entry_index =
420     fib_table_entry_special_add (t->fib_index, &dst, FIB_SOURCE_RR,
421                                  FIB_ENTRY_FLAG_NONE);
422   t->p2p.sibling_index =
423     fib_entry_child_add (t->p2p.fib_entry_index, gm->fib_node_type,
424                          t->dev_instance);
425 }
426
427 static void
428 ipip_fib_delete (ipip_tunnel_t * t)
429 {
430   fib_entry_child_remove (t->p2p.fib_entry_index, t->p2p.sibling_index);
431   fib_table_entry_delete_index (t->p2p.fib_entry_index, FIB_SOURCE_RR);
432   fib_node_deinit (&t->p2p.node);
433 }
434
435 int
436 ipip_add_tunnel (ipip_transport_t transport,
437                  u32 instance, ip46_address_t * src, ip46_address_t * dst,
438                  u32 fib_index, u8 tc_tos, u32 * sw_if_indexp)
439 {
440   ipip_main_t *gm = &ipip_main;
441   vnet_main_t *vnm = gm->vnet_main;
442   ip4_main_t *im4 = &ip4_main;
443   ip6_main_t *im6 = &ip6_main;
444   ipip_tunnel_t *t;
445   vnet_hw_interface_t *hi;
446   u32 hw_if_index, sw_if_index;
447   ipip_tunnel_key_t key = {.transport = transport,
448     .fib_index = fib_index,
449     .src = *src,
450     .dst = *dst
451   };
452   t = ipip_tunnel_db_find (&key);
453   if (t)
454     return VNET_API_ERROR_IF_ALREADY_EXISTS;
455
456   pool_get_aligned (gm->tunnels, t, CLIB_CACHE_LINE_BYTES);
457   clib_memset (t, 0, sizeof (*t));
458
459   /* Reconcile the real dev_instance and a possible requested instance */
460   u32 t_idx = t - gm->tunnels;  /* tunnel index (or instance) */
461   u32 u_idx = instance;         /* user specified instance */
462   if (u_idx == ~0)
463     u_idx = t_idx;
464   if (hash_get (gm->instance_used, u_idx))
465     {
466       pool_put (gm->tunnels, t);
467       return VNET_API_ERROR_INSTANCE_IN_USE;
468     }
469   hash_set (gm->instance_used, u_idx, 1);
470
471   t->dev_instance = t_idx;      /* actual */
472   t->user_instance = u_idx;     /* name */
473   fib_node_init (&t->p2p.node, gm->fib_node_type);
474
475   hw_if_index = vnet_register_interface (vnm, ipip_device_class.index, t_idx,
476                                          ipip_hw_interface_class.index,
477                                          t_idx);
478
479   hi = vnet_get_hw_interface (vnm, hw_if_index);
480   sw_if_index = hi->sw_if_index;
481
482   t->hw_if_index = hw_if_index;
483   t->fib_index = fib_index;
484   t->sw_if_index = sw_if_index;
485   t->tc_tos = tc_tos;
486
487   t->transport = transport;
488   vec_validate_init_empty (gm->tunnel_index_by_sw_if_index, sw_if_index, ~0);
489   gm->tunnel_index_by_sw_if_index[sw_if_index] = t_idx;
490
491   if (t->transport == IPIP_TRANSPORT_IP4)
492     {
493       vec_validate (im4->fib_index_by_sw_if_index, sw_if_index);
494       hi->min_packet_bytes = 64 + sizeof (ip4_header_t);
495     }
496   else
497     {
498       vec_validate (im6->fib_index_by_sw_if_index, sw_if_index);
499       hi->min_packet_bytes = 64 + sizeof (ip6_header_t);
500     }
501
502   /* Standard default ipip MTU. */
503   vnet_sw_interface_set_mtu (vnm, sw_if_index, 9000);
504
505   t->tunnel_src = *src;
506   t->tunnel_dst = *dst;
507
508   ipip_tunnel_db_add (t, &key);
509
510   /*
511    * Source the FIB entry for the tunnel's destination and become a
512    * child thereof. The tunnel will then get poked when the forwarding
513    * for the entry updates, and the tunnel can re-stack accordingly
514    */
515   ipip_fib_add (t);
516   if (sw_if_indexp)
517     *sw_if_indexp = sw_if_index;
518
519   if (t->transport == IPIP_TRANSPORT_IP6 && !gm->ip6_protocol_registered)
520     {
521       ip6_register_protocol (IP_PROTOCOL_IP_IN_IP, ipip6_input_node.index);
522       ip6_register_protocol (IP_PROTOCOL_IPV6, ipip6_input_node.index);
523       gm->ip6_protocol_registered = true;
524     }
525   else if (t->transport == IPIP_TRANSPORT_IP4 && !gm->ip4_protocol_registered)
526     {
527       ip4_register_protocol (IP_PROTOCOL_IP_IN_IP, ipip4_input_node.index);
528       ip4_register_protocol (IP_PROTOCOL_IPV6, ipip4_input_node.index);
529       gm->ip4_protocol_registered = true;
530     }
531   return 0;
532 }
533
534 int
535 ipip_del_tunnel (u32 sw_if_index)
536 {
537   ipip_main_t *gm = &ipip_main;
538   vnet_main_t *vnm = gm->vnet_main;
539   ipip_tunnel_t *t;
540
541
542   t = ipip_tunnel_db_find_by_sw_if_index (sw_if_index);
543   if (t == NULL)
544     return VNET_API_ERROR_NO_SUCH_ENTRY;
545
546   vnet_sw_interface_set_flags (vnm, sw_if_index, 0 /* down */ );
547   gm->tunnel_index_by_sw_if_index[sw_if_index] = ~0;
548   vnet_delete_hw_interface (vnm, t->hw_if_index);
549   ipip_fib_delete (t);
550   hash_unset (gm->instance_used, t->user_instance);
551   ipip_tunnel_db_remove (t);
552   pool_put (gm->tunnels, t);
553
554   return 0;
555 }
556
557 static clib_error_t *
558 ipip_init (vlib_main_t * vm)
559 {
560   ipip_main_t *gm = &ipip_main;
561
562   clib_memset (gm, 0, sizeof (gm[0]));
563   gm->vlib_main = vm;
564   gm->vnet_main = vnet_get_main ();
565   gm->tunnel_by_key =
566     hash_create_mem (0, sizeof (ipip_tunnel_key_t), sizeof (uword));
567   gm->fib_node_type = fib_node_register_new_type (&ipip_vft);
568
569   return 0;
570 }
571
572 VLIB_INIT_FUNCTION (ipip_init);
573
574 /*
575  * fd.io coding-style-patch-verification: ON
576  *
577  * Local Variables:
578  * eval: (c-set-style "gnu")
579  * End:
580  */