LCOV - code coverage report
Current view: top level - vnet/tunnel - tunnel.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 78 111 70.3 %
Date: 2023-10-26 01:39:38 Functions: 10 15 66.7 %

          Line data    Source code
       1             : /*
       2             :  * tunnel.h: shared definitions for tunnels.
       3             :  *
       4             :  * Copyright (c) 2019 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 <vnet/tunnel/tunnel.h>
      19             : #include <vnet/fib/fib_table.h>
      20             : #include <vnet/fib/fib_entry_track.h>
      21             : 
      22             : #include <vnet/ip/ip6_inlines.h>
      23             : 
      24             : const u8 TUNNEL_ENCAP_DECAP_FLAG_MASK = (
      25             : #define _(a, b, c) TUNNEL_ENCAP_DECAP_FLAG_##a |
      26             :   foreach_tunnel_encap_decap_flag
      27             : #undef _
      28             :   0);
      29             : const u8 TUNNEL_FLAG_MASK = (
      30             : #define _(a, b, c) TUNNEL_FLAG_##a |
      31             :   foreach_tunnel_flag
      32             : #undef _
      33             :   0);
      34             : 
      35             : u8 *
      36         615 : format_tunnel_mode (u8 * s, va_list * args)
      37             : {
      38         615 :   tunnel_mode_t mode = va_arg (*args, int);
      39             : 
      40         615 :   switch (mode)
      41             :     {
      42             : #define _(n, v) case TUNNEL_MODE_##n:       \
      43             :         s = format (s, "%s", v);            \
      44             :         break;
      45         615 :       foreach_tunnel_mode
      46             : #undef _
      47             :     }
      48             : 
      49         615 :   return (s);
      50             : }
      51             : 
      52             : uword
      53           0 : unformat_tunnel_mode (unformat_input_t * input, va_list * args)
      54             : {
      55           0 :   tunnel_mode_t *m = va_arg (*args, tunnel_mode_t *);
      56             : 
      57           0 :   if (unformat (input, "p2p"))
      58           0 :     *m = TUNNEL_MODE_P2P;
      59           0 :   else if (unformat (input, "p2mp") || unformat (input, "mp"))
      60           0 :     *m = TUNNEL_MODE_MP;
      61             :   else
      62           0 :     return 0;
      63           0 :   return 1;
      64             : }
      65             : 
      66             : u8 *
      67         615 : format_tunnel_encap_decap_flags (u8 * s, va_list * args)
      68             : {
      69         615 :   tunnel_encap_decap_flags_t f = va_arg (*args, u32);
      70             : 
      71         615 :   if (f == TUNNEL_ENCAP_DECAP_FLAG_NONE)
      72         609 :     s = format (s, "none");
      73             :   else
      74             :     {
      75             : #define _(a, b, c)                                                            \
      76             :   if (f & TUNNEL_ENCAP_DECAP_FLAG_##a)                                        \
      77             :     s = format (s, "%s ", b);
      78           6 :       foreach_tunnel_encap_decap_flag
      79             : #undef _
      80             :     }
      81         615 :   return (s);
      82             : }
      83             : 
      84             : uword
      85           0 : unformat_tunnel_encap_decap_flags (unformat_input_t * input, va_list * args)
      86             : {
      87           0 :   tunnel_encap_decap_flags_t *f =
      88             :     va_arg (*args, tunnel_encap_decap_flags_t *);
      89             : #define _(a,b,c) if (unformat(input, b)) {\
      90             :   *f |= TUNNEL_ENCAP_DECAP_FLAG_##a;\
      91             :   return 1;\
      92             :   }
      93           0 :   foreach_tunnel_encap_decap_flag;
      94             : #undef _
      95           0 :   return 0;
      96             : }
      97             : 
      98             : u8 *
      99         615 : format_tunnel_flags (u8 *s, va_list *args)
     100             : {
     101         615 :   tunnel_flags_t f = va_arg (*args, u32);
     102             : 
     103         615 :   if (f == TUNNEL_FLAG_NONE)
     104           0 :     s = format (s, "none");
     105             :   else
     106             :     {
     107             : #define _(a, b, c)                                                            \
     108             :   if (f & TUNNEL_FLAG_##a)                                                    \
     109             :     s = format (s, "%s ", c);
     110         615 :       foreach_tunnel_flag
     111             : #undef _
     112             :     }
     113         615 :   return (s);
     114             : }
     115             : 
     116             : uword
     117           0 : unformat_tunnel_flags (unformat_input_t *input, va_list *args)
     118             : {
     119           0 :   tunnel_flags_t *f = va_arg (*args, tunnel_flags_t *);
     120             : #define _(a, b, c)                                                            \
     121             :   if (unformat (input, c))                                                    \
     122             :     {                                                                         \
     123             :       *f |= TUNNEL_FLAG_##a;                                                  \
     124             :       return 1;                                                               \
     125             :     }
     126           0 :   foreach_tunnel_flag;
     127             : #undef _
     128           0 :   return 0;
     129             : }
     130             : 
     131             : ip_address_family_t
     132           0 : tunnel_get_af (const tunnel_t *t)
     133             : {
     134           0 :   return (ip_addr_version (&t->t_src));
     135             : }
     136             : 
     137             : void
     138        7032 : tunnel_copy (const tunnel_t *src, tunnel_t *dst)
     139             : {
     140        7032 :   ip_address_copy (&dst->t_dst, &src->t_dst);
     141        7032 :   ip_address_copy (&dst->t_src, &src->t_src);
     142             : 
     143        7032 :   dst->t_encap_decap_flags = src->t_encap_decap_flags;
     144        7032 :   dst->t_flags = src->t_flags;
     145        7032 :   dst->t_mode = src->t_mode;
     146        7032 :   dst->t_table_id = src->t_table_id;
     147        7032 :   dst->t_dscp = src->t_dscp;
     148        7032 :   dst->t_hop_limit = src->t_hop_limit;
     149        7032 :   dst->t_fib_index = src->t_fib_index;
     150             : 
     151        7032 :   dst->t_flags &= ~TUNNEL_FLAG_RESOLVED;
     152        7032 :   dst->t_fib_entry_index = FIB_NODE_INDEX_INVALID;
     153        7032 :   dst->t_sibling = ~0;
     154        7032 : }
     155             : 
     156             : u8 *
     157         615 : format_tunnel (u8 *s, va_list *args)
     158             : {
     159         615 :   const tunnel_t *t = va_arg (*args, tunnel_t *);
     160         615 :   u32 indent = va_arg (*args, u32);
     161             : 
     162         615 :   s = format (s, "%Utable-ID:%d [%U->%U] hop-limit:%d %U %U [%U] [%U]",
     163             :               format_white_space, indent, t->t_table_id, format_ip_address,
     164         615 :               &t->t_src, format_ip_address, &t->t_dst, t->t_hop_limit,
     165         615 :               format_tunnel_mode, t->t_mode, format_ip_dscp, t->t_dscp,
     166         615 :               format_tunnel_flags, t->t_flags, format_tunnel_encap_decap_flags,
     167         615 :               t->t_encap_decap_flags);
     168         615 :   if (t->t_flags & TUNNEL_FLAG_RESOLVED)
     169         615 :     s = format (s, " [resolved via fib-entry: %d]", t->t_fib_entry_index);
     170             : 
     171         615 :   return (s);
     172             : }
     173             : 
     174             : uword
     175           0 : unformat_tunnel (unformat_input_t *input, va_list *args)
     176             : {
     177           0 :   tunnel_t *t = va_arg (*args, tunnel_t *);
     178             : 
     179           0 :   if (!unformat (input, "tunnel"))
     180           0 :     return (0);
     181             : 
     182           0 :   unformat (input, "src %U", unformat_ip_address, &t->t_src);
     183           0 :   unformat (input, "dst %U", unformat_ip_address, &t->t_dst);
     184           0 :   unformat (input, "table-id %d", &t->t_table_id);
     185           0 :   unformat (input, "hop-limit %d", &t->t_hop_limit);
     186           0 :   unformat (input, "%U", unformat_ip_dscp, &t->t_dscp);
     187           0 :   unformat (input, "%U", unformat_tunnel_encap_decap_flags,
     188             :             &t->t_encap_decap_flags);
     189           0 :   unformat (input, "%U", unformat_tunnel_flags, &t->t_flags);
     190           0 :   unformat (input, "%U", unformat_tunnel_mode, &t->t_mode);
     191             : 
     192           0 :   return (1);
     193             : }
     194             : 
     195             : int
     196        3388 : tunnel_resolve (tunnel_t *t, fib_node_type_t child_type, index_t child_index)
     197             : {
     198             :   fib_prefix_t pfx;
     199             : 
     200        3388 :   ip_address_to_fib_prefix (&t->t_dst, &pfx);
     201             : 
     202        3388 :   t->t_fib_index = fib_table_find (pfx.fp_proto, t->t_table_id);
     203             : 
     204        3388 :   if (t->t_fib_index == ~((u32) 0))
     205           0 :     return VNET_API_ERROR_NO_SUCH_FIB;
     206             : 
     207        3388 :   t->t_fib_entry_index = fib_entry_track (t->t_fib_index, &pfx, child_type,
     208             :                                           child_index, &t->t_sibling);
     209             : 
     210        3388 :   t->t_flags |= TUNNEL_FLAG_RESOLVED;
     211             : 
     212        3388 :   return (0);
     213             : }
     214             : 
     215             : void
     216        7032 : tunnel_unresolve (tunnel_t *t)
     217             : {
     218        7032 :   if (t->t_flags & TUNNEL_FLAG_RESOLVED)
     219        3388 :     fib_entry_untrack (t->t_fib_entry_index, t->t_sibling);
     220             : 
     221        7032 :   t->t_flags &= ~TUNNEL_FLAG_RESOLVED;
     222        7032 : }
     223             : 
     224             : void
     225        3535 : tunnel_contribute_forwarding (const tunnel_t *t, dpo_id_t *dpo)
     226             : {
     227             :   fib_forward_chain_type_t fct;
     228             : 
     229        3535 :   fct = fib_forw_chain_type_from_fib_proto (
     230        3535 :     ip_address_family_to_fib_proto (ip_addr_version (&t->t_src)));
     231             : 
     232        3535 :   fib_entry_contribute_forwarding (t->t_fib_entry_index, fct, dpo);
     233        3535 : }
     234             : 
     235             : void
     236        1660 : tunnel_build_v6_hdr (const tunnel_t *t, ip_protocol_t next_proto,
     237             :                      ip6_header_t *ip)
     238             : {
     239        1660 :   ip->ip_version_traffic_class_and_flow_label =
     240        1660 :     clib_host_to_net_u32 (0x60000000);
     241        1660 :   ip6_set_dscp_network_order (ip, t->t_dscp);
     242             : 
     243        1660 :   ip->hop_limit = 254;
     244        1660 :   ip6_address_copy (&ip->src_address, &ip_addr_v6 (&t->t_src));
     245        1660 :   ip6_address_copy (&ip->dst_address, &ip_addr_v6 (&t->t_dst));
     246             : 
     247        1660 :   ip->protocol = next_proto;
     248        1660 :   ip->hop_limit = (t->t_hop_limit == 0 ? 254 : t->t_hop_limit);
     249        1660 :   ip6_set_flow_label_network_order (
     250             :     ip, ip6_compute_flow_hash (ip, IP_FLOW_HASH_DEFAULT));
     251        1660 : }
     252             : 
     253             : void
     254        1728 : tunnel_build_v4_hdr (const tunnel_t *t, ip_protocol_t next_proto,
     255             :                      ip4_header_t *ip)
     256             : {
     257        1728 :   ip->ip_version_and_header_length = 0x45;
     258        1728 :   ip->ttl = (t->t_hop_limit == 0 ? 254 : t->t_hop_limit);
     259        1728 :   ip->src_address.as_u32 = t->t_src.ip.ip4.as_u32;
     260        1728 :   ip->dst_address.as_u32 = t->t_dst.ip.ip4.as_u32;
     261        1728 :   ip->tos = t->t_dscp << 2;
     262        1728 :   ip->protocol = next_proto;
     263        1728 :   ip->checksum = ip4_header_checksum (ip);
     264        1728 : }
     265             : 
     266             : /*
     267             :  * fd.io coding-style-patch-verification: ON
     268             :  *
     269             :  * Local Variables:
     270             :  * eval: (c-set-style "gnu")
     271             :  * End:
     272             :  */

Generated by: LCOV version 1.14