LCOV - code coverage report
Current view: top level - plugins/ioam/lib-vxlan-gpe - vxlan_gpe_ioam.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 9 315 2.9 %
Date: 2023-10-26 01:39:38 Functions: 9 29 31.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : #include <vnet/vxlan-gpe/vxlan_gpe.h>
      16             : #include <vnet/vxlan-gpe/vxlan_gpe_packet.h>
      17             : #include <vnet/ip/format.h>
      18             : #include <ioam/lib-vxlan-gpe/vxlan_gpe_ioam.h>
      19             : #include <vnet/dpo/load_balance.h>
      20             : #include <vnet/fib/ip4_fib.h>
      21             : #include <vnet/fib/fib_entry.h>
      22             : #include <vnet/udp/udp_local.h>
      23             : 
      24             : vxlan_gpe_ioam_main_t vxlan_gpe_ioam_main;
      25             : 
      26             : int
      27           0 : vxlan_gpe_ioam_set_rewrite (vxlan_gpe_tunnel_t * t, int has_trace_option,
      28             :                             int has_pot_option, int has_ppc_option,
      29             :                             u8 ipv6_set)
      30             : {
      31           0 :   vxlan_gpe_ioam_main_t *hm = &vxlan_gpe_ioam_main;
      32             :   u32 size;
      33             :   vxlan_gpe_ioam_hdr_t *vxlan_gpe_ioam_hdr;
      34             :   u8 *current;
      35           0 :   u8 trace_data_size = 0;
      36           0 :   u8 pot_data_size = 0;
      37             : 
      38           0 :   if (has_trace_option == 0 && has_pot_option == 0)
      39           0 :     return -1;
      40             : 
      41             :   /* Work out how much space we need */
      42           0 :   size = sizeof (vxlan_gpe_ioam_hdr_t);
      43             : 
      44           0 :   if (has_trace_option
      45           0 :       && hm->add_options[VXLAN_GPE_OPTION_TYPE_IOAM_TRACE] != 0)
      46             :     {
      47           0 :       size += sizeof (vxlan_gpe_ioam_option_t);
      48           0 :       size += hm->options_size[VXLAN_GPE_OPTION_TYPE_IOAM_TRACE];
      49             :     }
      50           0 :   if (has_pot_option
      51           0 :       && hm->add_options[VXLAN_GPE_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT] != 0)
      52             :     {
      53           0 :       size += sizeof (vxlan_gpe_ioam_option_t);
      54           0 :       size += hm->options_size[VXLAN_GPE_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT];
      55             :     }
      56             : 
      57           0 :   t->rewrite_size = size;
      58             : 
      59           0 :   if (!ipv6_set)
      60             :     {
      61           0 :       vxlan4_gpe_rewrite (t, size, VXLAN_GPE_PROTOCOL_IOAM,
      62             :                           hm->encap_v4_next_node);
      63           0 :       vxlan_gpe_ioam_hdr =
      64           0 :         (vxlan_gpe_ioam_hdr_t *) (t->rewrite +
      65             :                                   sizeof (ip4_vxlan_gpe_header_t));
      66             :     }
      67             :   else
      68             :     {
      69           0 :       vxlan6_gpe_rewrite (t, size, VXLAN_GPE_PROTOCOL_IOAM,
      70             :                           VXLAN_GPE_ENCAP_NEXT_IP6_LOOKUP);
      71           0 :       vxlan_gpe_ioam_hdr =
      72           0 :         (vxlan_gpe_ioam_hdr_t *) (t->rewrite +
      73             :                                   sizeof (ip6_vxlan_gpe_header_t));
      74             :     }
      75             : 
      76             : 
      77           0 :   vxlan_gpe_ioam_hdr->type = VXLAN_GPE_PROTOCOL_IOAM;
      78             :   /* Length of the header in octets */
      79           0 :   vxlan_gpe_ioam_hdr->length = size;
      80           0 :   vxlan_gpe_ioam_hdr->protocol = t->protocol;
      81           0 :   current = (u8 *) vxlan_gpe_ioam_hdr + sizeof (vxlan_gpe_ioam_hdr_t);
      82             : 
      83           0 :   if (has_trace_option
      84           0 :       && hm->add_options[VXLAN_GPE_OPTION_TYPE_IOAM_TRACE] != 0)
      85             :     {
      86           0 :       if (0 != hm->add_options[VXLAN_GPE_OPTION_TYPE_IOAM_TRACE] (current,
      87             :                                                                   &trace_data_size))
      88           0 :         return -1;
      89           0 :       current += trace_data_size;
      90             :     }
      91           0 :   if (has_pot_option
      92           0 :       && hm->add_options[VXLAN_GPE_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT] != 0)
      93             :     {
      94           0 :       pot_data_size =
      95           0 :         hm->options_size[VXLAN_GPE_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT];
      96           0 :       if (0 ==
      97           0 :           hm->add_options[VXLAN_GPE_OPTION_TYPE_IOAM_PROOF_OF_TRANSIT]
      98             :           (current, &pot_data_size))
      99           0 :         current += pot_data_size;
     100             :     }
     101             : 
     102           0 :   return 0;
     103             : }
     104             : 
     105             : int
     106           0 : vxlan_gpe_ioam_clear_rewrite (vxlan_gpe_tunnel_t * t, int has_trace_option,
     107             :                               int has_pot_option, int has_ppc_option,
     108             :                               u8 ipv6_set)
     109             : {
     110             : 
     111           0 :   t->rewrite_size = 0;
     112             : 
     113           0 :   if (!ipv6_set)
     114             :     {
     115           0 :       vxlan4_gpe_rewrite (t, 0, 0, VXLAN_GPE_ENCAP_NEXT_IP4_LOOKUP);
     116             :     }
     117             :   else
     118             :     {
     119           0 :       vxlan6_gpe_rewrite (t, 0, 0, VXLAN_GPE_ENCAP_NEXT_IP6_LOOKUP);
     120             :     }
     121             : 
     122             : 
     123           0 :   return 0;
     124             : }
     125             : 
     126             : clib_error_t *
     127           0 : vxlan_gpe_ioam_clear (vxlan_gpe_tunnel_t * t,
     128             :                       int has_trace_option, int has_pot_option,
     129             :                       int has_ppc_option, u8 ipv6_set)
     130             : {
     131             :   int rv;
     132           0 :   rv = vxlan_gpe_ioam_clear_rewrite (t, 0, 0, 0, 0);
     133             : 
     134           0 :   if (rv == 0)
     135             :     {
     136           0 :       return (0);
     137             :     }
     138             :   else
     139             :     {
     140           0 :       return clib_error_return_code (0, rv, 0,
     141             :                                      "vxlan_gpe_ioam_clear_rewrite returned %d",
     142             :                                      rv);
     143             :     }
     144             : 
     145             : }
     146             : 
     147             : 
     148             : clib_error_t *
     149           0 : vxlan_gpe_ioam_set (vxlan_gpe_tunnel_t * t,
     150             :                     int has_trace_option, int has_pot_option,
     151             :                     int has_ppc_option, u8 ipv6_set)
     152             : {
     153             :   int rv;
     154           0 :   rv = vxlan_gpe_ioam_set_rewrite (t, has_trace_option,
     155             :                                    has_pot_option, has_ppc_option, ipv6_set);
     156             : 
     157           0 :   if (rv == 0)
     158             :     {
     159           0 :       return (0);
     160             :     }
     161             :   else
     162             :     {
     163           0 :       return clib_error_return_code (0, rv, 0,
     164             :                                      "vxlan_gpe_ioam_set_rewrite returned %d",
     165             :                                      rv);
     166             :     }
     167             : 
     168             : }
     169             : 
     170             : static void
     171           0 : vxlan_gpe_set_clear_output_feature_on_intf (vlib_main_t * vm,
     172             :                                             u32 sw_if_index0, u8 is_add)
     173             : {
     174             : 
     175             : 
     176             : 
     177           0 :   vnet_feature_enable_disable ("ip4-output", "vxlan-gpe-transit-ioam",
     178             :                                sw_if_index0, is_add,
     179             :                                0 /* void *feature_config */ ,
     180             :                                0 /* u32 n_feature_config_bytes */ );
     181           0 :   return;
     182             : }
     183             : 
     184             : void
     185           0 : vxlan_gpe_clear_output_feature_on_all_intfs (vlib_main_t * vm)
     186             : {
     187           0 :   vnet_sw_interface_t *si = 0;
     188           0 :   vnet_main_t *vnm = vnet_get_main ();
     189           0 :   vnet_interface_main_t *im = &vnm->interface_main;
     190             : 
     191           0 :   pool_foreach (si, im->sw_interfaces)
     192             :   {
     193           0 :     vxlan_gpe_set_clear_output_feature_on_intf (vm, si->sw_if_index, 0);
     194             :   }
     195           0 :   return;
     196             : }
     197             : 
     198             : 
     199             : extern fib_forward_chain_type_t
     200             : fib_entry_get_default_chain_type (const fib_entry_t * fib_entry);
     201             : 
     202             : int
     203           0 : vxlan_gpe_enable_disable_ioam_for_dest (vlib_main_t * vm,
     204             :                                         ip46_address_t dst_addr,
     205             :                                         u32 outer_fib_index,
     206             :                                         u8 is_ipv4, u8 is_add)
     207             : {
     208           0 :   vxlan_gpe_ioam_main_t *hm = &vxlan_gpe_ioam_main;
     209           0 :   u32 fib_index0 = 0;
     210           0 :   u32 sw_if_index0 = ~0;
     211             : 
     212           0 :   fib_node_index_t fei = ~0;
     213             :   fib_entry_t *fib_entry;
     214             :   u32 adj_index0;
     215             :   ip_adjacency_t *adj0;
     216             :   fib_prefix_t fib_prefix;
     217             :   //fib_forward_chain_type_t fct;
     218             :   load_balance_t *lb_m, *lb_b;
     219             :   const dpo_id_t *dpo0, *dpo1;
     220             :   u32 i, j;
     221             :   //vnet_hw_interface_t *hw;
     222             : 
     223           0 :   if (is_ipv4)
     224             :     {
     225           0 :       clib_memset (&fib_prefix, 0, sizeof (fib_prefix_t));
     226           0 :       fib_prefix.fp_len = 32;
     227           0 :       fib_prefix.fp_proto = FIB_PROTOCOL_IP4;
     228           0 :       fib_prefix.fp_addr = dst_addr;
     229             :     }
     230             :   else
     231             :     {
     232           0 :       return 0;
     233             :     }
     234             : 
     235           0 :   fei = fib_table_lookup (fib_index0, &fib_prefix);
     236           0 :   fib_entry = fib_entry_get (fei);
     237             : 
     238             :   //fct = fib_entry_get_default_chain_type (fib_entry);
     239             : 
     240           0 :   if (!dpo_id_is_valid (&fib_entry->fe_lb /*[fct] */ ))
     241             :     {
     242           0 :       return (-1);
     243             :     }
     244             : 
     245           0 :   lb_m = load_balance_get (fib_entry->fe_lb /*[fct] */ .dpoi_index);
     246             : 
     247           0 :   for (i = 0; i < lb_m->lb_n_buckets; i++)
     248             :     {
     249           0 :       dpo0 = load_balance_get_bucket_i (lb_m, i);
     250             : 
     251           0 :       if (dpo0->dpoi_type == DPO_LOAD_BALANCE)
     252             :         {
     253           0 :           lb_b = load_balance_get (dpo0->dpoi_index);
     254             : 
     255           0 :           for (j = 0; j < lb_b->lb_n_buckets; j++)
     256             :             {
     257           0 :               dpo1 = load_balance_get_bucket_i (lb_b, j);
     258             : 
     259           0 :               if (dpo1->dpoi_type == DPO_ADJACENCY)
     260             :                 {
     261           0 :                   adj_index0 = dpo1->dpoi_index;
     262             : 
     263           0 :                   if (ADJ_INDEX_INVALID == adj_index0)
     264             :                     {
     265           0 :                       continue;
     266             :                     }
     267             : 
     268           0 :                   adj0 = adj_get (adj_index0);
     269           0 :                   sw_if_index0 = adj0->rewrite_header.sw_if_index;
     270             : 
     271           0 :                   if (~0 == sw_if_index0)
     272             :                     {
     273           0 :                       continue;
     274             :                     }
     275             : 
     276             : 
     277           0 :                   if (is_add)
     278             :                     {
     279           0 :                       vnet_feature_enable_disable ("ip4-output",
     280             :                                                    "vxlan-gpe-transit-ioam",
     281             :                                                    sw_if_index0, is_add, 0
     282             :                                                    /* void *feature_config */
     283             :                                                    , 0  /* u32 n_feature_config_bytes */
     284             :                         );
     285             : 
     286           0 :                       vec_validate_init_empty (hm->bool_ref_by_sw_if_index,
     287             :                                                sw_if_index0, ~0);
     288           0 :                       hm->bool_ref_by_sw_if_index[sw_if_index0] = 1;
     289             :                     }
     290             :                   else
     291             :                     {
     292           0 :                       hm->bool_ref_by_sw_if_index[sw_if_index0] = ~0;
     293             :                     }
     294             :                 }
     295             :             }
     296             :         }
     297             :     }
     298             : 
     299           0 :   if (is_ipv4)
     300             :     {
     301             : 
     302           0 :       uword *t = NULL;
     303             :       vxlan_gpe_ioam_dest_tunnels_t *t1;
     304             :       fib_prefix_t key4, *key4_copy;
     305             :       hash_pair_t *hp;
     306           0 :       clib_memset (&key4, 0, sizeof (key4));
     307           0 :       key4.fp_proto = FIB_PROTOCOL_IP4;
     308           0 :       key4.fp_addr.ip4.as_u32 = fib_prefix.fp_addr.ip4.as_u32;
     309           0 :       t = hash_get_mem (hm->dst_by_ip4, &key4);
     310           0 :       if (is_add)
     311             :         {
     312           0 :           if (t)
     313             :             {
     314           0 :               return 0;
     315             :             }
     316           0 :           pool_get_aligned (hm->dst_tunnels, t1, CLIB_CACHE_LINE_BYTES);
     317           0 :           clib_memset (t1, 0, sizeof (*t1));
     318           0 :           t1->fp_proto = FIB_PROTOCOL_IP4;
     319           0 :           t1->dst_addr.ip4.as_u32 = fib_prefix.fp_addr.ip4.as_u32;
     320           0 :           key4_copy = clib_mem_alloc (sizeof (*key4_copy));
     321           0 :           clib_memcpy (key4_copy, &key4, sizeof (*key4_copy));
     322           0 :           hash_set_mem (hm->dst_by_ip4, key4_copy, t1 - hm->dst_tunnels);
     323             :           /*
     324             :            * Attach to the FIB entry for the VxLAN-GPE destination
     325             :            * and become its child. The dest route will invoke a callback
     326             :            * when the fib entry changes, it can be used to
     327             :            * re-program the output feature on the egress interface.
     328             :            */
     329             : 
     330           0 :           const fib_prefix_t tun_dst_pfx = {
     331             :             .fp_len = 32,
     332             :             .fp_proto = FIB_PROTOCOL_IP4,
     333           0 :             .fp_addr = {.ip4 = t1->dst_addr.ip4,}
     334             :           };
     335             : 
     336           0 :           t1->fib_entry_index =
     337           0 :             fib_table_entry_special_add (outer_fib_index,
     338             :                                          &tun_dst_pfx,
     339             :                                          FIB_SOURCE_RR, FIB_ENTRY_FLAG_NONE);
     340           0 :           t1->sibling_index =
     341           0 :             fib_entry_child_add (t1->fib_entry_index,
     342           0 :                                  hm->fib_entry_type, t1 - hm->dst_tunnels);
     343           0 :           t1->outer_fib_index = outer_fib_index;
     344             : 
     345             :         }
     346             :       else
     347             :         {
     348           0 :           if (!t)
     349             :             {
     350           0 :               return 0;
     351             :             }
     352           0 :           t1 = pool_elt_at_index (hm->dst_tunnels, t[0]);
     353           0 :           hp = hash_get_pair (hm->dst_by_ip4, &key4);
     354           0 :           key4_copy = (void *) (hp->key);
     355           0 :           hash_unset_mem (hm->dst_by_ip4, &key4);
     356           0 :           clib_mem_free (key4_copy);
     357           0 :           pool_put (hm->dst_tunnels, t1);
     358             :         }
     359             :     }
     360             :   else
     361             :     {
     362             :       // TBD for IPv6
     363             :     }
     364             : 
     365           0 :   return 0;
     366             : }
     367             : 
     368             : void
     369           0 : vxlan_gpe_refresh_output_feature_on_all_dest (void)
     370             : {
     371           0 :   vxlan_gpe_ioam_main_t *hm = &vxlan_gpe_ioam_main;
     372             :   vxlan_gpe_ioam_dest_tunnels_t *t;
     373             :   u32 i;
     374           0 :   if (pool_elts (hm->dst_tunnels) == 0)
     375           0 :     return;
     376           0 :   vxlan_gpe_clear_output_feature_on_all_intfs (hm->vlib_main);
     377           0 :   i = vec_len (hm->bool_ref_by_sw_if_index);
     378           0 :   vec_free (hm->bool_ref_by_sw_if_index);
     379           0 :   vec_validate_init_empty (hm->bool_ref_by_sw_if_index, i, ~0);
     380           0 :   pool_foreach (t, hm->dst_tunnels)
     381             :   {
     382           0 :     vxlan_gpe_enable_disable_ioam_for_dest
     383             :       (hm->vlib_main, t->dst_addr, t->outer_fib_index,
     384           0 :        (t->fp_proto == FIB_PROTOCOL_IP4), 1 /* is_add */ );
     385             :   }
     386           0 :   return;
     387             : }
     388             : 
     389             : void
     390           0 : vxlan_gpe_clear_output_feature_on_select_intfs (void)
     391             : {
     392           0 :   vxlan_gpe_ioam_main_t *hm = &vxlan_gpe_ioam_main;
     393           0 :   u32 sw_if_index0 = 0;
     394           0 :   for (sw_if_index0 = 0;
     395           0 :        sw_if_index0 < vec_len (hm->bool_ref_by_sw_if_index); sw_if_index0++)
     396             :     {
     397           0 :       if (hm->bool_ref_by_sw_if_index[sw_if_index0] == 0xFF)
     398             :         {
     399           0 :           vxlan_gpe_set_clear_output_feature_on_intf
     400             :             (hm->vlib_main, sw_if_index0, 0);
     401             :         }
     402             :     }
     403             : 
     404           0 :   return;
     405             : }
     406             : 
     407             : static clib_error_t *
     408           0 : vxlan_gpe_set_ioam_rewrite_command_fn (vlib_main_t *
     409             :                                        vm,
     410             :                                        unformat_input_t
     411             :                                        * input, vlib_cli_command_t * cmd)
     412             : {
     413           0 :   vxlan_gpe_ioam_main_t *hm = &vxlan_gpe_ioam_main;
     414             :   ip46_address_t local, remote;
     415           0 :   u8 local_set = 0;
     416           0 :   u8 remote_set = 0;
     417           0 :   u8 ipv4_set = 0;
     418           0 :   u8 ipv6_set = 0;
     419             :   u32 vni;
     420           0 :   u8 vni_set = 0;
     421           0 :   u8 disable = 0;
     422           0 :   clib_error_t *rv = 0;
     423             :   vxlan4_gpe_tunnel_key_t key4;
     424             :   vxlan6_gpe_tunnel_key_t key6;
     425             :   uword *p;
     426           0 :   vxlan_gpe_main_t *gm = &vxlan_gpe_main;
     427           0 :   vxlan_gpe_tunnel_t *t = 0;
     428           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     429             :     {
     430           0 :       if (unformat (input, "local %U", unformat_ip4_address, &local.ip4))
     431             :         {
     432           0 :           local_set = 1;
     433           0 :           ipv4_set = 1;
     434             :         }
     435             :       else
     436           0 :         if (unformat (input, "remote %U", unformat_ip4_address, &remote.ip4))
     437             :         {
     438           0 :           remote_set = 1;
     439           0 :           ipv4_set = 1;
     440             :         }
     441           0 :       else if (unformat (input, "local %U", unformat_ip6_address, &local.ip6))
     442             :         {
     443           0 :           local_set = 1;
     444           0 :           ipv6_set = 1;
     445             :         }
     446             :       else
     447           0 :         if (unformat (input, "remote %U", unformat_ip6_address, &remote.ip6))
     448             :         {
     449           0 :           remote_set = 1;
     450           0 :           ipv6_set = 1;
     451             :         }
     452           0 :       else if (unformat (input, "vni %d", &vni))
     453           0 :         vni_set = 1;
     454           0 :       else if (unformat (input, "disable"))
     455           0 :         disable = 1;
     456             :       else
     457           0 :         break;
     458             :     }
     459             : 
     460           0 :   if (local_set == 0)
     461           0 :     return clib_error_return (0, "tunnel local address not specified");
     462           0 :   if (remote_set == 0)
     463           0 :     return clib_error_return (0, "tunnel remote address not specified");
     464           0 :   if (ipv4_set && ipv6_set)
     465           0 :     return clib_error_return (0, "both IPv4 and IPv6 addresses specified");
     466           0 :   if ((ipv4_set
     467           0 :        && memcmp (&local.ip4, &remote.ip4,
     468           0 :                   sizeof (local.ip4)) == 0) || (ipv6_set
     469           0 :                                                 &&
     470           0 :                                                 memcmp
     471             :                                                 (&local.ip6,
     472             :                                                  &remote.ip6,
     473             :                                                  sizeof (local.ip6)) == 0))
     474           0 :     return clib_error_return (0, "src and dst addresses are identical");
     475           0 :   if (vni_set == 0)
     476           0 :     return clib_error_return (0, "vni not specified");
     477           0 :   if (!ipv6_set)
     478             :     {
     479           0 :       key4.local = local.ip4.as_u32;
     480           0 :       key4.remote = remote.ip4.as_u32;
     481           0 :       key4.vni = clib_host_to_net_u32 (vni << 8);
     482           0 :       key4.port = clib_host_to_net_u16 (UDP_DST_PORT_VXLAN_GPE);
     483           0 :       p = hash_get_mem (gm->vxlan4_gpe_tunnel_by_key, &key4);
     484             :     }
     485             :   else
     486             :     {
     487           0 :       key6.local.as_u64[0] = local.ip6.as_u64[0];
     488           0 :       key6.local.as_u64[1] = local.ip6.as_u64[1];
     489           0 :       key6.remote.as_u64[0] = remote.ip6.as_u64[0];
     490           0 :       key6.remote.as_u64[1] = remote.ip6.as_u64[1];
     491           0 :       key6.vni = clib_host_to_net_u32 (vni << 8);
     492           0 :       key6.port = clib_host_to_net_u16 (UDP_DST_PORT_VXLAN6_GPE);
     493           0 :       p = hash_get_mem (gm->vxlan6_gpe_tunnel_by_key, &key6);
     494             :     }
     495             : 
     496           0 :   if (!p)
     497           0 :     return clib_error_return (0, "VxLAN Tunnel not found");
     498           0 :   t = pool_elt_at_index (gm->tunnels, p[0]);
     499           0 :   if (!disable)
     500             :     {
     501             :       rv =
     502           0 :         vxlan_gpe_ioam_set (t, hm->has_trace_option,
     503           0 :                             hm->has_pot_option, hm->has_ppc_option, ipv6_set);
     504             :     }
     505             :   else
     506             :     {
     507           0 :       rv = vxlan_gpe_ioam_clear (t, 0, 0, 0, 0);
     508             :     }
     509           0 :   return rv;
     510             : }
     511             : 
     512             : 
     513             : /* *INDENT-OFF* */
     514      186217 : VLIB_CLI_COMMAND (vxlan_gpe_set_ioam_rewrite_cmd, static) = {
     515             :   .path = "set vxlan-gpe-ioam",
     516             :   .short_help = "set vxlan-gpe-ioam vxlan <src-ip> <dst_ip> <vnid> [disable]",
     517             :   .function = vxlan_gpe_set_ioam_rewrite_command_fn,
     518             : };
     519             : /* *INDENT-ON* */
     520             : 
     521             : 
     522             : 
     523             : clib_error_t *
     524           0 : vxlan_gpe_ioam_enable (int has_trace_option,
     525             :                        int has_pot_option, int has_ppc_option)
     526             : {
     527           0 :   vxlan_gpe_ioam_main_t *hm = &vxlan_gpe_ioam_main;
     528           0 :   hm->has_trace_option = has_trace_option;
     529           0 :   hm->has_pot_option = has_pot_option;
     530           0 :   hm->has_ppc_option = has_ppc_option;
     531           0 :   if (hm->has_trace_option)
     532             :     {
     533           0 :       vxlan_gpe_trace_profile_setup ();
     534             :     }
     535             : 
     536           0 :   return 0;
     537             : }
     538             : 
     539             : clib_error_t *
     540           0 : vxlan_gpe_ioam_disable (int
     541             :                         has_trace_option,
     542             :                         int has_pot_option, int has_ppc_option)
     543             : {
     544           0 :   vxlan_gpe_ioam_main_t *hm = &vxlan_gpe_ioam_main;
     545           0 :   hm->has_trace_option = has_trace_option;
     546           0 :   hm->has_pot_option = has_pot_option;
     547           0 :   hm->has_ppc_option = has_ppc_option;
     548           0 :   if (!hm->has_trace_option)
     549             :     {
     550           0 :       vxlan_gpe_trace_profile_cleanup ();
     551             :     }
     552             : 
     553           0 :   return 0;
     554             : }
     555             : 
     556             : void
     557           0 : vxlan_gpe_set_next_override (uword next)
     558             : {
     559           0 :   vxlan_gpe_ioam_main_t *hm = &vxlan_gpe_ioam_main;
     560           0 :   hm->decap_v4_next_override = next;
     561           0 :   return;
     562             : }
     563             : 
     564             : static clib_error_t *
     565           0 : vxlan_gpe_set_ioam_flags_command_fn (vlib_main_t * vm,
     566             :                                      unformat_input_t
     567             :                                      * input, vlib_cli_command_t * cmd)
     568             : {
     569           0 :   int has_trace_option = 0;
     570           0 :   int has_pot_option = 0;
     571           0 :   int has_ppc_option = 0;
     572           0 :   clib_error_t *rv = 0;
     573           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     574             :     {
     575           0 :       if (unformat (input, "trace"))
     576           0 :         has_trace_option = 1;
     577           0 :       else if (unformat (input, "pot"))
     578           0 :         has_pot_option = 1;
     579           0 :       else if (unformat (input, "ppc encap"))
     580           0 :         has_ppc_option = PPC_ENCAP;
     581           0 :       else if (unformat (input, "ppc decap"))
     582           0 :         has_ppc_option = PPC_DECAP;
     583           0 :       else if (unformat (input, "ppc none"))
     584           0 :         has_ppc_option = PPC_NONE;
     585             :       else
     586           0 :         break;
     587             :     }
     588             : 
     589             : 
     590             :   rv =
     591           0 :     vxlan_gpe_ioam_enable (has_trace_option, has_pot_option, has_ppc_option);
     592           0 :   return rv;
     593             : }
     594             : 
     595             : /* *INDENT-OFF* */
     596      186217 : VLIB_CLI_COMMAND (vxlan_gpe_set_ioam_flags_cmd, static) =
     597             : {
     598             : .path = "set vxlan-gpe-ioam rewrite",
     599             : .short_help = "set vxlan-gpe-ioam [trace] [pot] [ppc <encap|decap>]",
     600             : .function = vxlan_gpe_set_ioam_flags_command_fn,};
     601             : /* *INDENT-ON* */
     602             : 
     603             : 
     604           0 : int vxlan_gpe_ioam_disable_for_dest
     605             :   (vlib_main_t * vm, ip46_address_t dst_addr, u32 outer_fib_index,
     606             :    u8 ipv4_set)
     607             : {
     608             :   vxlan_gpe_ioam_dest_tunnels_t *t;
     609           0 :   vxlan_gpe_ioam_main_t *hm = &vxlan_gpe_ioam_main;
     610             : 
     611           0 :   vxlan_gpe_enable_disable_ioam_for_dest (hm->vlib_main,
     612             :                                           dst_addr, outer_fib_index, ipv4_set,
     613             :                                           0);
     614           0 :   if (pool_elts (hm->dst_tunnels) == 0)
     615             :     {
     616           0 :       vxlan_gpe_clear_output_feature_on_select_intfs ();
     617           0 :       return 0;
     618             :     }
     619             : 
     620           0 :   pool_foreach (t, hm->dst_tunnels)
     621             :   {
     622           0 :     vxlan_gpe_enable_disable_ioam_for_dest
     623             :       (hm->vlib_main,
     624             :        t->dst_addr,
     625             :        t->outer_fib_index,
     626           0 :        (t->fp_proto == FIB_PROTOCOL_IP4), 1 /* is_add */ );
     627             :   }
     628           0 :   vxlan_gpe_clear_output_feature_on_select_intfs ();
     629           0 :   return (0);
     630             : 
     631             : }
     632             : 
     633           0 : static clib_error_t *vxlan_gpe_set_ioam_transit_rewrite_command_fn
     634             :   (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
     635             : {
     636           0 :   vxlan_gpe_ioam_main_t *hm = &vxlan_gpe_ioam_main;
     637             :   ip46_address_t dst_addr;
     638           0 :   u8 dst_addr_set = 0;
     639           0 :   u8 ipv4_set = 0;
     640           0 :   u8 ipv6_set = 0;
     641           0 :   u8 disable = 0;
     642           0 :   clib_error_t *rv = 0;
     643           0 :   u32 outer_fib_index = 0;
     644           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     645             :     {
     646           0 :       if (unformat (input, "dst-ip %U", unformat_ip4_address, &dst_addr.ip4))
     647             :         {
     648           0 :           dst_addr_set = 1;
     649           0 :           ipv4_set = 1;
     650             :         }
     651             :       else
     652           0 :         if (unformat
     653             :             (input, "dst-ip %U", unformat_ip6_address, &dst_addr.ip6))
     654             :         {
     655           0 :           dst_addr_set = 1;
     656           0 :           ipv6_set = 1;
     657             :         }
     658           0 :       else if (unformat (input, "outer-fib-index %d", &outer_fib_index))
     659             :         {
     660             :         }
     661             : 
     662           0 :       else if (unformat (input, "disable"))
     663           0 :         disable = 1;
     664             :       else
     665           0 :         break;
     666             :     }
     667             : 
     668           0 :   if (dst_addr_set == 0)
     669           0 :     return clib_error_return (0, "tunnel destination address not specified");
     670           0 :   if (ipv4_set && ipv6_set)
     671           0 :     return clib_error_return (0, "both IPv4 and IPv6 addresses specified");
     672           0 :   if (!disable)
     673             :     {
     674           0 :       vxlan_gpe_enable_disable_ioam_for_dest (hm->vlib_main,
     675             :                                               dst_addr, outer_fib_index,
     676             :                                               ipv4_set, 1);
     677             :     }
     678             :   else
     679             :     {
     680           0 :       vxlan_gpe_ioam_disable_for_dest
     681             :         (vm, dst_addr, outer_fib_index, ipv4_set);
     682             :     }
     683           0 :   return rv;
     684             : }
     685             : 
     686             :        /* *INDENT-OFF* */
     687      186217 : VLIB_CLI_COMMAND (vxlan_gpe_set_ioam_transit_rewrite_cmd, static) = {
     688             :   .path = "set vxlan-gpe-ioam-transit",
     689             :   .short_help = "set vxlan-gpe-ioam-transit dst-ip <dst_ip> [outer-fib-index <outer_fib_index>] [disable]",
     690             :   .function = vxlan_gpe_set_ioam_transit_rewrite_command_fn,
     691             : };
     692             : /* *INDENT-ON* */
     693             : 
     694           0 : clib_error_t *clear_vxlan_gpe_ioam_rewrite_command_fn
     695             :   (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
     696             : {
     697           0 :   return (vxlan_gpe_ioam_disable (0, 0, 0));
     698             : }
     699             : 
     700             : /* *INDENT-OFF* */
     701      186217 : VLIB_CLI_COMMAND (vxlan_gpe_clear_ioam_flags_cmd, static) =
     702             : {
     703             : .path = "clear vxlan-gpe-ioam rewrite",
     704             : .short_help = "clear vxlan-gpe-ioam rewrite",
     705             : .function = clear_vxlan_gpe_ioam_rewrite_command_fn,
     706             : };
     707             : /* *INDENT-ON* */
     708             : 
     709             : 
     710             : /**
     711             :  * Function definition to backwalk a FIB node
     712             :  */
     713             : static fib_node_back_walk_rc_t
     714           0 : vxlan_gpe_ioam_back_walk (fib_node_t * node, fib_node_back_walk_ctx_t * ctx)
     715             : {
     716           0 :   vxlan_gpe_refresh_output_feature_on_all_dest ();
     717           0 :   return (FIB_NODE_BACK_WALK_CONTINUE);
     718             : }
     719             : 
     720             : /**
     721             :  * Function definition to get a FIB node from its index
     722             :  */
     723             : static fib_node_t *
     724           0 : vxlan_gpe_ioam_fib_node_get (fib_node_index_t index)
     725             : {
     726           0 :   vxlan_gpe_ioam_main_t *hm = &vxlan_gpe_ioam_main;
     727           0 :   return (&hm->node);
     728             : }
     729             : 
     730             : /**
     731             :  * Function definition to inform the FIB node that its last lock has gone.
     732             :  */
     733             : static void
     734           0 : vxlan_gpe_ioam_last_lock_gone (fib_node_t * node)
     735             : {
     736           0 :   ASSERT (0);
     737           0 : }
     738             : 
     739             : 
     740             : /*
     741             :  * Virtual function table registered by MPLS GRE tunnels
     742             :  * for participation in the FIB object graph.
     743             :  */
     744             : const static fib_node_vft_t vxlan_gpe_ioam_vft = {
     745             :   .fnv_get = vxlan_gpe_ioam_fib_node_get,
     746             :   .fnv_last_lock = vxlan_gpe_ioam_last_lock_gone,
     747             :   .fnv_back_walk = vxlan_gpe_ioam_back_walk,
     748             : };
     749             : 
     750             : void
     751         575 : vxlan_gpe_ioam_interface_init (void)
     752             : {
     753         575 :   vxlan_gpe_ioam_main_t *hm = &vxlan_gpe_ioam_main;
     754         575 :   hm->fib_entry_type =
     755         575 :     fib_node_register_new_type ("vxlan-gpe", &vxlan_gpe_ioam_vft);
     756         575 :   return;
     757             : }
     758             : 
     759             : /*
     760             :  * fd.io coding-style-patch-verification: ON
     761             :  *
     762             :  * Local Variables:
     763             :  * eval: (c-set-style "gnu")
     764             :  * End:
     765             :  */

Generated by: LCOV version 1.14