LCOV - code coverage report
Current view: top level - vpp/api - api_format.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 57 492 11.6 %
Date: 2023-10-26 01:39:38 Functions: 11 54 20.4 %

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * api_format.c
       4             :  *
       5             :  * Copyright (c) 2014-2020 Cisco and/or its affiliates.
       6             :  * Licensed under the Apache License, Version 2.0 (the "License");
       7             :  * you may not use this file except in compliance with the License.
       8             :  * You may obtain a copy of the License at:
       9             :  *
      10             :  *     http://www.apache.org/licenses/LICENSE-2.0
      11             :  *
      12             :  * Unless required by applicable law or agreed to in writing, software
      13             :  * distributed under the License is distributed on an "AS IS" BASIS,
      14             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15             :  * See the License for the specific language governing permissions and
      16             :  * limitations under the License.
      17             :  *------------------------------------------------------------------
      18             :  */
      19             : 
      20             : #include <vat/vat.h>
      21             : #include <vlib/pci/pci.h>
      22             : #include <vpp/api/types.h>
      23             : #include <vppinfra/socket.h>
      24             : #include <vlibapi/api.h>
      25             : #include <vlibmemory/api.h>
      26             : #include <vnet/ip/ip.h>
      27             : #include <vnet/ip-neighbor/ip_neighbor.h>
      28             : #include <vnet/ip/ip_types_api.h>
      29             : #include <vnet/l2/l2_input.h>
      30             : #include <vnet/udp/udp_local.h>
      31             : 
      32             : #include <vnet/l2/l2_classify.h>
      33             : #include <vnet/l2/l2_vtr.h>
      34             : #include <vnet/classify/in_out_acl.h>
      35             : #include <vnet/classify/policer_classify.h>
      36             : #include <vnet/classify/flow_classify.h>
      37             : #include <vnet/mpls/mpls.h>
      38             : #include <vnet/ipsec/ipsec.h>
      39             : #include <inttypes.h>
      40             : #include <vnet/ip/ip6_hop_by_hop.h>
      41             : #include <vnet/ip/ip_source_and_port_range_check.h>
      42             : #include <vnet/policer/xlate.h>
      43             : #include <vnet/span/span.h>
      44             : #include <vnet/policer/policer.h>
      45             : #include <vnet/policer/police.h>
      46             : #include <vnet/mfib/mfib_types.h>
      47             : #include <vnet/bonding/node.h>
      48             : #include <vnet/qos/qos_types.h>
      49             : #include <vnet/ethernet/ethernet_types_api.h>
      50             : #include <vnet/ip/ip_types_api.h>
      51             : #include "vat/json_format.h"
      52             : #include <vnet/ip/ip_types_api.h>
      53             : #include <vnet/ethernet/ethernet_types_api.h>
      54             : 
      55             : #include <inttypes.h>
      56             : #include <sys/stat.h>
      57             : 
      58             : #include <vlibmemory/memclnt.api_enum.h>
      59             : #include <vlibmemory/memclnt.api_types.h>
      60             : #include <vlibmemory/memclnt.api_tojson.h>
      61             : #include <vlibmemory/memclnt.api_fromjson.h>
      62             : 
      63             : #define vl_endianfun            /* define message structures */
      64             : #include <vlibmemory/memclnt.api.h>
      65             : #undef vl_endianfun
      66             : 
      67             : #define vl_calcsizefun
      68             : #include <vlibmemory/memclnt.api.h>
      69             : #undef vl_calcsizefun
      70             : 
      71             : /* instantiate all the print functions we know about */
      72             : #define vl_printfun
      73             : #include <vlibmemory/memclnt.api.h>
      74             : #undef vl_printfun
      75             : 
      76             : #define __plugin_msg_base 0
      77             : #include <vlibapi/vat_helper_macros.h>
      78             : 
      79             : void vl_api_set_elog_main (elog_main_t * m);
      80             : int vl_api_set_elog_trace_api_messages (int enable);
      81             : 
      82             : #if VPP_API_TEST_BUILTIN == 0
      83             : #include <netdb.h>
      84             : 
      85             : u32
      86             : vl (void *p)
      87             : {
      88             :   return vec_len (p);
      89             : }
      90             : 
      91             : int
      92             : vat_socket_connect (vat_main_t * vam)
      93             : {
      94             :   int rv;
      95             :   api_main_t *am = vlibapi_get_main ();
      96             :   vam->socket_client_main = &socket_client_main;
      97             :   if ((rv = vl_socket_client_connect ((char *) vam->socket_name,
      98             :                                       "vpp_api_test",
      99             :                                       0 /* default socket rx, tx buffer */ )))
     100             :     return rv;
     101             : 
     102             :   /* vpp expects the client index in network order */
     103             :   vam->my_client_index = htonl (socket_client_main.client_index);
     104             :   am->my_client_index = vam->my_client_index;
     105             :   return 0;
     106             : }
     107             : #else /* vpp built-in case, we don't do sockets... */
     108             : int
     109           0 : vat_socket_connect (vat_main_t * vam)
     110             : {
     111           0 :   return 0;
     112             : }
     113             : 
     114             : int
     115           0 : vl_socket_client_read (int wait)
     116             : {
     117           0 :   return -1;
     118             : };
     119             : 
     120             : int
     121           0 : vl_socket_client_write ()
     122             : {
     123           0 :   return -1;
     124             : };
     125             : 
     126             : void *
     127           0 : vl_socket_client_msg_alloc (int nbytes)
     128             : {
     129           0 :   return 0;
     130             : }
     131             : #endif
     132             : 
     133             : 
     134             : f64
     135      785397 : vat_time_now (vat_main_t * vam)
     136             : {
     137             : #if VPP_API_TEST_BUILTIN
     138      785397 :   return vlib_time_now (vam->vlib_main);
     139             : #else
     140             :   return clib_time_now (&vam->clib_time);
     141             : #endif
     142             : }
     143             : 
     144             : void
     145           2 : errmsg (char *fmt, ...)
     146             : {
     147           2 :   vat_main_t *vam = &vat_main;
     148             :   va_list va;
     149             :   u8 *s;
     150             : 
     151           2 :   va_start (va, fmt);
     152           2 :   s = va_format (0, fmt, &va);
     153           2 :   va_end (va);
     154             : 
     155           2 :   vec_add1 (s, 0);
     156             : 
     157             : #if VPP_API_TEST_BUILTIN
     158           2 :   vlib_cli_output (vam->vlib_main, (char *) s);
     159             : #else
     160             :   {
     161             :     if (vam->ifp != stdin)
     162             :       fformat (vam->ofp, "%s(%d): \n", vam->current_file,
     163             :                vam->input_line_number);
     164             :     else
     165             :       fformat (vam->ofp, "%s\n", (char *) s);
     166             :     fflush (vam->ofp);
     167             :   }
     168             : #endif
     169             : 
     170           2 :   vec_free (s);
     171           2 : }
     172             : 
     173             : #if VPP_API_TEST_BUILTIN == 0
     174             : 
     175             : /* Parse an IP4 address %d.%d.%d.%d. */
     176             : uword
     177             : unformat_ip4_address (unformat_input_t * input, va_list * args)
     178             : {
     179             :   u8 *result = va_arg (*args, u8 *);
     180             :   unsigned a[4];
     181             : 
     182             :   if (!unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
     183             :     return 0;
     184             : 
     185             :   if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
     186             :     return 0;
     187             : 
     188             :   result[0] = a[0];
     189             :   result[1] = a[1];
     190             :   result[2] = a[2];
     191             :   result[3] = a[3];
     192             : 
     193             :   return 1;
     194             : }
     195             : 
     196             : uword
     197             : unformat_ethernet_address (unformat_input_t * input, va_list * args)
     198             : {
     199             :   u8 *result = va_arg (*args, u8 *);
     200             :   u32 i, a[6];
     201             : 
     202             :   if (!unformat (input, "%_%x:%x:%x:%x:%x:%x%_",
     203             :                  &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
     204             :     return 0;
     205             : 
     206             :   /* Check range. */
     207             :   for (i = 0; i < 6; i++)
     208             :     if (a[i] >= (1 << 8))
     209             :       return 0;
     210             : 
     211             :   for (i = 0; i < 6; i++)
     212             :     result[i] = a[i];
     213             : 
     214             :   return 1;
     215             : }
     216             : 
     217             : /* Returns ethernet type as an int in host byte order. */
     218             : uword
     219             : unformat_ethernet_type_host_byte_order (unformat_input_t * input,
     220             :                                         va_list * args)
     221             : {
     222             :   u16 *result = va_arg (*args, u16 *);
     223             :   int type;
     224             : 
     225             :   /* Numeric type. */
     226             :   if (unformat (input, "0x%x", &type) || unformat (input, "%d", &type))
     227             :     {
     228             :       if (type >= (1 << 16))
     229             :         return 0;
     230             :       *result = type;
     231             :       return 1;
     232             :     }
     233             :   return 0;
     234             : }
     235             : 
     236             : /* Parse an IP46 address. */
     237             : uword
     238             : unformat_ip46_address (unformat_input_t * input, va_list * args)
     239             : {
     240             :   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
     241             :   ip46_type_t type = va_arg (*args, ip46_type_t);
     242             :   if ((type != IP46_TYPE_IP6) &&
     243             :       unformat (input, "%U", unformat_ip4_address, &ip46->ip4))
     244             :     {
     245             :       ip46_address_mask_ip4 (ip46);
     246             :       return 1;
     247             :     }
     248             :   else if ((type != IP46_TYPE_IP4) &&
     249             :            unformat (input, "%U", unformat_ip6_address, &ip46->ip6))
     250             :     {
     251             :       return 1;
     252             :     }
     253             :   return 0;
     254             : }
     255             : 
     256             : /* Parse an IP6 address. */
     257             : uword
     258             : unformat_ip6_address (unformat_input_t * input, va_list * args)
     259             : {
     260             :   ip6_address_t *result = va_arg (*args, ip6_address_t *);
     261             :   u16 hex_quads[8];
     262             :   uword hex_quad, n_hex_quads, hex_digit, n_hex_digits;
     263             :   uword c, n_colon, double_colon_index;
     264             : 
     265             :   n_hex_quads = hex_quad = n_hex_digits = n_colon = 0;
     266             :   double_colon_index = ARRAY_LEN (hex_quads);
     267             :   while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
     268             :     {
     269             :       hex_digit = 16;
     270             :       if (c >= '0' && c <= '9')
     271             :         hex_digit = c - '0';
     272             :       else if (c >= 'a' && c <= 'f')
     273             :         hex_digit = c + 10 - 'a';
     274             :       else if (c >= 'A' && c <= 'F')
     275             :         hex_digit = c + 10 - 'A';
     276             :       else if (c == ':' && n_colon < 2)
     277             :         n_colon++;
     278             :       else
     279             :         {
     280             :           unformat_put_input (input);
     281             :           break;
     282             :         }
     283             : 
     284             :       /* Too many hex quads. */
     285             :       if (n_hex_quads >= ARRAY_LEN (hex_quads))
     286             :         return 0;
     287             : 
     288             :       if (hex_digit < 16)
     289             :         {
     290             :           hex_quad = (hex_quad << 4) | hex_digit;
     291             : 
     292             :           /* Hex quad must fit in 16 bits. */
     293             :           if (n_hex_digits >= 4)
     294             :             return 0;
     295             : 
     296             :           n_colon = 0;
     297             :           n_hex_digits++;
     298             :         }
     299             : 
     300             :       /* Save position of :: */
     301             :       if (n_colon == 2)
     302             :         {
     303             :           /* More than one :: ? */
     304             :           if (double_colon_index < ARRAY_LEN (hex_quads))
     305             :             return 0;
     306             :           double_colon_index = n_hex_quads;
     307             :         }
     308             : 
     309             :       if (n_colon > 0 && n_hex_digits > 0)
     310             :         {
     311             :           hex_quads[n_hex_quads++] = hex_quad;
     312             :           hex_quad = 0;
     313             :           n_hex_digits = 0;
     314             :         }
     315             :     }
     316             : 
     317             :   if (n_hex_digits > 0)
     318             :     hex_quads[n_hex_quads++] = hex_quad;
     319             : 
     320             :   {
     321             :     word i;
     322             : 
     323             :     /* Expand :: to appropriate number of zero hex quads. */
     324             :     if (double_colon_index < ARRAY_LEN (hex_quads))
     325             :       {
     326             :         word n_zero = ARRAY_LEN (hex_quads) - n_hex_quads;
     327             : 
     328             :         for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--)
     329             :           hex_quads[n_zero + i] = hex_quads[i];
     330             : 
     331             :         for (i = 0; i < n_zero; i++)
     332             :           hex_quads[double_colon_index + i] = 0;
     333             : 
     334             :         n_hex_quads = ARRAY_LEN (hex_quads);
     335             :       }
     336             : 
     337             :     /* Too few hex quads given. */
     338             :     if (n_hex_quads < ARRAY_LEN (hex_quads))
     339             :       return 0;
     340             : 
     341             :     for (i = 0; i < ARRAY_LEN (hex_quads); i++)
     342             :       result->as_u16[i] = clib_host_to_net_u16 (hex_quads[i]);
     343             : 
     344             :     return 1;
     345             :   }
     346             : }
     347             : 
     348             : uword
     349             : unformat_ipsec_policy_action (unformat_input_t * input, va_list * args)
     350             : {
     351             :   u32 *r = va_arg (*args, u32 *);
     352             : 
     353             :   if (0);
     354             : #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_POLICY_ACTION_##f;
     355             :   foreach_ipsec_policy_action
     356             : #undef _
     357             :     else
     358             :     return 0;
     359             :   return 1;
     360             : }
     361             : 
     362             : u8 *
     363             : format_ipsec_crypto_alg (u8 * s, va_list * args)
     364             : {
     365             :   u32 i = va_arg (*args, u32);
     366             :   u8 *t = 0;
     367             : 
     368             :   switch (i)
     369             :     {
     370             : #define _(v,f,str) case IPSEC_CRYPTO_ALG_##f: t = (u8 *) str; break;
     371             :       foreach_ipsec_crypto_alg
     372             : #undef _
     373             :     default:
     374             :       return format (s, "unknown");
     375             :     }
     376             :   return format (s, "%s", t);
     377             : }
     378             : 
     379             : u8 *
     380             : format_ipsec_integ_alg (u8 * s, va_list * args)
     381             : {
     382             :   u32 i = va_arg (*args, u32);
     383             :   u8 *t = 0;
     384             : 
     385             :   switch (i)
     386             :     {
     387             : #define _(v,f,str) case IPSEC_INTEG_ALG_##f: t = (u8 *) str; break;
     388             :       foreach_ipsec_integ_alg
     389             : #undef _
     390             :     default:
     391             :       return format (s, "unknown");
     392             :     }
     393             :   return format (s, "%s", t);
     394             : }
     395             : 
     396             : #else /* VPP_API_TEST_BUILTIN == 1 */
     397             : static uword
     398           0 : api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
     399             : {
     400           0 :   vat_main_t *vam __clib_unused = va_arg (*args, vat_main_t *);
     401           0 :   vnet_main_t *vnm = vnet_get_main ();
     402           0 :   u32 *result = va_arg (*args, u32 *);
     403             : 
     404           0 :   return unformat (input, "%U", unformat_vnet_sw_interface, vnm, result);
     405             : }
     406             : 
     407             : #endif /* VPP_API_TEST_BUILTIN */
     408             : 
     409             : #if (VPP_API_TEST_BUILTIN==0)
     410             : 
     411             : static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
     412             : static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG;
     413             : static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
     414             : static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
     415             : 
     416             : uword
     417             : unformat_mfib_itf_flags (unformat_input_t * input, va_list * args)
     418             : {
     419             :   mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *);
     420             :   mfib_itf_attribute_t attr;
     421             : 
     422             :   old = *iflags;
     423             :   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
     424             :   {
     425             :     if (unformat (input, mfib_itf_flag_long_names[attr]))
     426             :       *iflags |= (1 << attr);
     427             :   }
     428             :   FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
     429             :   {
     430             :     if (unformat (input, mfib_itf_flag_names[attr]))
     431             :       *iflags |= (1 << attr);
     432             :   }
     433             : 
     434             :   return (old == *iflags ? 0 : 1);
     435             : }
     436             : 
     437             : uword
     438             : unformat_mfib_entry_flags (unformat_input_t * input, va_list * args)
     439             : {
     440             :   mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *);
     441             :   mfib_entry_attribute_t attr;
     442             : 
     443             :   old = *eflags;
     444             :   FOR_EACH_MFIB_ATTRIBUTE (attr)
     445             :   {
     446             :     if (unformat (input, mfib_flag_long_names[attr]))
     447             :       *eflags |= (1 << attr);
     448             :   }
     449             :   FOR_EACH_MFIB_ATTRIBUTE (attr)
     450             :   {
     451             :     if (unformat (input, mfib_flag_names[attr]))
     452             :       *eflags |= (1 << attr);
     453             :   }
     454             : 
     455             :   return (old == *eflags ? 0 : 1);
     456             : }
     457             : 
     458             : u8 *
     459             : format_ip4_address (u8 * s, va_list * args)
     460             : {
     461             :   u8 *a = va_arg (*args, u8 *);
     462             :   return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
     463             : }
     464             : 
     465             : u8 *
     466             : format_ip6_address (u8 * s, va_list * args)
     467             : {
     468             :   ip6_address_t *a = va_arg (*args, ip6_address_t *);
     469             :   u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
     470             : 
     471             :   i_max_n_zero = ARRAY_LEN (a->as_u16);
     472             :   max_n_zeros = 0;
     473             :   i_first_zero = i_max_n_zero;
     474             :   n_zeros = 0;
     475             :   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
     476             :     {
     477             :       u32 is_zero = a->as_u16[i] == 0;
     478             :       if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
     479             :         {
     480             :           i_first_zero = i;
     481             :           n_zeros = 0;
     482             :         }
     483             :       n_zeros += is_zero;
     484             :       if ((!is_zero && n_zeros > max_n_zeros)
     485             :           || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
     486             :         {
     487             :           i_max_n_zero = i_first_zero;
     488             :           max_n_zeros = n_zeros;
     489             :           i_first_zero = ARRAY_LEN (a->as_u16);
     490             :           n_zeros = 0;
     491             :         }
     492             :     }
     493             : 
     494             :   last_double_colon = 0;
     495             :   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
     496             :     {
     497             :       if (i == i_max_n_zero && max_n_zeros > 1)
     498             :         {
     499             :           s = format (s, "::");
     500             :           i += max_n_zeros - 1;
     501             :           last_double_colon = 1;
     502             :         }
     503             :       else
     504             :         {
     505             :           s = format (s, "%s%x",
     506             :                       (last_double_colon || i == 0) ? "" : ":",
     507             :                       clib_net_to_host_u16 (a->as_u16[i]));
     508             :           last_double_colon = 0;
     509             :         }
     510             :     }
     511             : 
     512             :   return s;
     513             : }
     514             : 
     515             : /* Format an IP46 address. */
     516             : u8 *
     517             : format_ip46_address (u8 * s, va_list * args)
     518             : {
     519             :   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
     520             :   ip46_type_t type = va_arg (*args, ip46_type_t);
     521             :   int is_ip4 = 1;
     522             : 
     523             :   switch (type)
     524             :     {
     525             :     case IP46_TYPE_ANY:
     526             :       is_ip4 = ip46_address_is_ip4 (ip46);
     527             :       break;
     528             :     case IP46_TYPE_IP4:
     529             :       is_ip4 = 1;
     530             :       break;
     531             :     case IP46_TYPE_IP6:
     532             :       is_ip4 = 0;
     533             :       break;
     534             :     }
     535             : 
     536             :   return is_ip4 ?
     537             :     format (s, "%U", format_ip4_address, &ip46->ip4) :
     538             :     format (s, "%U", format_ip6_address, &ip46->ip6);
     539             : }
     540             : 
     541             : u8 *
     542             : format_ethernet_address (u8 * s, va_list * args)
     543             : {
     544             :   u8 *a = va_arg (*args, u8 *);
     545             : 
     546             :   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
     547             :                  a[0], a[1], a[2], a[3], a[4], a[5]);
     548             : }
     549             : #endif
     550             : 
     551             : void
     552      130444 : ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
     553             : {
     554      130444 :   if (is_ip4)
     555      125522 :     dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
     556             :   else
     557        4922 :     clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
     558             :                       sizeof (ip6_address_t));
     559      130444 : }
     560             : 
     561             : 
     562           0 : static void vl_api_get_first_msg_id_reply_t_handler
     563             :   (vl_api_get_first_msg_id_reply_t * mp)
     564             : {
     565           0 :   vat_main_t *vam = &vat_main;
     566           0 :   i32 retval = ntohl (mp->retval);
     567             : 
     568           0 :   if (vam->async_mode)
     569             :     {
     570           0 :       vam->async_errors += (retval < 0);
     571             :     }
     572             :   else
     573             :     {
     574           0 :       vam->retval = retval;
     575           0 :       vam->result_ready = 1;
     576             :     }
     577           0 :   if (retval >= 0)
     578             :     {
     579           0 :       errmsg ("first message id %d", ntohs (mp->first_msg_id));
     580             :     }
     581           0 : }
     582             : 
     583           0 : static void vl_api_get_first_msg_id_reply_t_handler_json
     584             :   (vl_api_get_first_msg_id_reply_t * mp)
     585             : {
     586           0 :   vat_main_t *vam = &vat_main;
     587             :   vat_json_node_t node;
     588             : 
     589           0 :   vat_json_init_object (&node);
     590           0 :   vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
     591           0 :   vat_json_object_add_uint (&node, "first_msg_id",
     592           0 :                             (uint) ntohs (mp->first_msg_id));
     593             : 
     594           0 :   vat_json_print (vam->ofp, &node);
     595           0 :   vat_json_free (&node);
     596             : 
     597           0 :   vam->retval = ntohl (mp->retval);
     598           0 :   vam->result_ready = 1;
     599           0 : }
     600             : 
     601             : /* Format hex dump. */
     602             : u8 *
     603     1133310 : format_hex_bytes (u8 * s, va_list * va)
     604             : {
     605     1133310 :   u8 *bytes = va_arg (*va, u8 *);
     606     1133310 :   int n_bytes = va_arg (*va, int);
     607             :   uword i;
     608             : 
     609             :   /* Print short or long form depending on byte count. */
     610     1133310 :   uword short_form = n_bytes <= 32;
     611     1133310 :   u32 indent = format_get_indent (s);
     612             : 
     613     1133310 :   if (n_bytes == 0)
     614           0 :     return s;
     615             : 
     616    83164000 :   for (i = 0; i < n_bytes; i++)
     617             :     {
     618    82030700 :       if (!short_form && (i % 32) == 0)
     619     2451700 :         s = format (s, "%08x: ", i);
     620    82030700 :       s = format (s, "%02x", bytes[i]);
     621    82030700 :       if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
     622     1702000 :         s = format (s, "\n%U", format_white_space, indent);
     623             :     }
     624             : 
     625     1133310 :   return s;
     626             : }
     627             : 
     628             : static void
     629           2 : vl_api_control_ping_reply_t_handler (vl_api_control_ping_reply_t *mp)
     630             : {
     631           2 :   vat_main_t *vam = &vat_main;
     632           2 :   i32 retval = ntohl (mp->retval);
     633           2 :   if (vam->async_mode)
     634             :     {
     635           0 :       vam->async_errors += (retval < 0);
     636             :     }
     637             :   else
     638             :     {
     639           2 :       vam->retval = retval;
     640           2 :       vam->result_ready = 1;
     641             :     }
     642           2 :   if (vam->socket_client_main)
     643           0 :     vam->socket_client_main->control_pings_outstanding--;
     644           2 : }
     645             : 
     646             : static void
     647           0 : vl_api_control_ping_reply_t_handler_json (vl_api_control_ping_reply_t *mp)
     648             : {
     649           0 :   vat_main_t *vam = &vat_main;
     650           0 :   i32 retval = ntohl (mp->retval);
     651             : 
     652           0 :   if (VAT_JSON_NONE != vam->json_tree.type)
     653             :     {
     654           0 :       vat_json_print (vam->ofp, &vam->json_tree);
     655           0 :       vat_json_free (&vam->json_tree);
     656           0 :       vam->json_tree.type = VAT_JSON_NONE;
     657             :     }
     658             :   else
     659             :     {
     660             :       /* just print [] */
     661           0 :       vat_json_init_array (&vam->json_tree);
     662           0 :       vat_json_print (vam->ofp, &vam->json_tree);
     663           0 :       vam->json_tree.type = VAT_JSON_NONE;
     664             :     }
     665             : 
     666           0 :   vam->retval = retval;
     667           0 :   vam->result_ready = 1;
     668           0 : }
     669             : 
     670             : /*
     671             :  * Generate boilerplate reply handlers, which
     672             :  * dig the return value out of the xxx_reply_t API message,
     673             :  * stick it into vam->retval, and set vam->result_ready
     674             :  *
     675             :  * Could also do this by pointing N message decode slots at
     676             :  * a single function, but that could break in subtle ways.
     677             :  */
     678             : 
     679             : #define foreach_standard_reply_retval_handler
     680             : 
     681             : #define _(n)                                    \
     682             :     static void vl_api_##n##_t_handler          \
     683             :     (vl_api_##n##_t * mp)                       \
     684             :     {                                           \
     685             :         vat_main_t * vam = &vat_main;           \
     686             :         i32 retval = ntohl(mp->retval);         \
     687             :         if (vam->async_mode) {                  \
     688             :             vam->async_errors += (retval < 0);  \
     689             :         } else {                                \
     690             :             vam->retval = retval;               \
     691             :             vam->result_ready = 1;              \
     692             :         }                                       \
     693             :     }
     694             : foreach_standard_reply_retval_handler;
     695             : #undef _
     696             : 
     697             : #define _(n)                                    \
     698             :     static void vl_api_##n##_t_handler_json     \
     699             :     (vl_api_##n##_t * mp)                       \
     700             :     {                                           \
     701             :         vat_main_t * vam = &vat_main;           \
     702             :         vat_json_node_t node;                   \
     703             :         vat_json_init_object(&node);            \
     704             :         vat_json_object_add_int(&node, "retval", ntohl(mp->retval));    \
     705             :         vat_json_print(vam->ofp, &node);        \
     706             :         vam->retval = ntohl(mp->retval);        \
     707             :         vam->result_ready = 1;                  \
     708             :     }
     709             : foreach_standard_reply_retval_handler;
     710             : #undef _
     711             : 
     712             : /*
     713             :  * Table of message reply handlers, must include boilerplate handlers
     714             :  * we just generated
     715             :  */
     716             : 
     717             : #define foreach_vpe_api_reply_msg                                             \
     718             :   _ (GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply)                          \
     719             :   _ (CONTROL_PING_REPLY, control_ping_reply)
     720             : 
     721             : #define foreach_standalone_reply_msg                                    \
     722             : 
     723             : typedef struct
     724             : {
     725             :   u8 *name;
     726             :   u32 value;
     727             : } name_sort_t;
     728             : 
     729             : #define STR_VTR_OP_CASE(op)     \
     730             :     case L2_VTR_ ## op:         \
     731             :         return "" # op;
     732             : 
     733             : static const char *
     734           0 : str_vtr_op (u32 vtr_op)
     735             : {
     736           0 :   switch (vtr_op)
     737             :     {
     738           0 :       STR_VTR_OP_CASE (DISABLED);
     739           0 :       STR_VTR_OP_CASE (PUSH_1);
     740           0 :       STR_VTR_OP_CASE (PUSH_2);
     741           0 :       STR_VTR_OP_CASE (POP_1);
     742           0 :       STR_VTR_OP_CASE (POP_2);
     743           0 :       STR_VTR_OP_CASE (TRANSLATE_1_1);
     744           0 :       STR_VTR_OP_CASE (TRANSLATE_1_2);
     745           0 :       STR_VTR_OP_CASE (TRANSLATE_2_1);
     746           0 :       STR_VTR_OP_CASE (TRANSLATE_2_2);
     747             :     }
     748             : 
     749           0 :   return "UNKNOWN";
     750             : }
     751             : 
     752             : uword
     753      170775 : unformat_vlib_pci_addr (unformat_input_t *input, va_list *args)
     754             : {
     755      170775 :   vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
     756             :   u32 x[4];
     757             : 
     758      170775 :   if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
     759           0 :     return 0;
     760             : 
     761      170775 :   addr->domain = x[0];
     762      170775 :   addr->bus = x[1];
     763      170775 :   addr->slot = x[2];
     764      170775 :   addr->function = x[3];
     765             : 
     766      170775 :   return 1;
     767             : }
     768             : 
     769             : uword
     770           0 : unformat_fib_path (unformat_input_t *input, va_list *args)
     771             : {
     772           0 :   vat_main_t *vam = va_arg (*args, vat_main_t *);
     773           0 :   vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
     774             :   u32 weight, preference;
     775             :   mpls_label_t out_label;
     776             : 
     777           0 :   clib_memset (path, 0, sizeof (*path));
     778           0 :   path->weight = 1;
     779           0 :   path->sw_if_index = ~0;
     780           0 :   path->rpf_id = ~0;
     781           0 :   path->n_labels = 0;
     782             : 
     783           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     784             :     {
     785           0 :       if (unformat (input, "%U %U", unformat_vl_api_ip4_address,
     786             :                     &path->nh.address.ip4, api_unformat_sw_if_index, vam,
     787             :                     &path->sw_if_index))
     788             :         {
     789           0 :           path->proto = FIB_API_PATH_NH_PROTO_IP4;
     790             :         }
     791           0 :       else if (unformat (input, "%U %U",
     792             :                          unformat_vl_api_ip6_address,
     793             :                          &path->nh.address.ip6,
     794             :                          api_unformat_sw_if_index, vam, &path->sw_if_index))
     795             :         {
     796           0 :           path->proto = FIB_API_PATH_NH_PROTO_IP6;
     797             :         }
     798           0 :       else if (unformat (input, "weight %u", &weight))
     799             :         {
     800           0 :           path->weight = weight;
     801             :         }
     802           0 :       else if (unformat (input, "preference %u", &preference))
     803             :         {
     804           0 :           path->preference = preference;
     805             :         }
     806           0 :       else if (unformat (input, "%U next-hop-table %d",
     807             :                          unformat_vl_api_ip4_address,
     808             :                          &path->nh.address.ip4, &path->table_id))
     809             :         {
     810           0 :           path->proto = FIB_API_PATH_NH_PROTO_IP4;
     811             :         }
     812           0 :       else if (unformat (input, "%U next-hop-table %d",
     813             :                          unformat_vl_api_ip6_address,
     814             :                          &path->nh.address.ip6, &path->table_id))
     815             :         {
     816           0 :           path->proto = FIB_API_PATH_NH_PROTO_IP6;
     817             :         }
     818           0 :       else if (unformat (input, "%U",
     819             :                          unformat_vl_api_ip4_address, &path->nh.address.ip4))
     820             :         {
     821             :           /*
     822             :            * the recursive next-hops are by default in the default table
     823             :            */
     824           0 :           path->table_id = 0;
     825           0 :           path->sw_if_index = ~0;
     826           0 :           path->proto = FIB_API_PATH_NH_PROTO_IP4;
     827             :         }
     828           0 :       else if (unformat (input, "%U",
     829             :                          unformat_vl_api_ip6_address, &path->nh.address.ip6))
     830             :         {
     831             :           /*
     832             :            * the recursive next-hops are by default in the default table
     833             :            */
     834           0 :           path->table_id = 0;
     835           0 :           path->sw_if_index = ~0;
     836           0 :           path->proto = FIB_API_PATH_NH_PROTO_IP6;
     837             :         }
     838           0 :       else if (unformat (input, "resolve-via-host"))
     839             :         {
     840           0 :           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
     841             :         }
     842           0 :       else if (unformat (input, "resolve-via-attached"))
     843             :         {
     844           0 :           path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
     845             :         }
     846           0 :       else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
     847             :         {
     848           0 :           path->type = FIB_API_PATH_TYPE_LOCAL;
     849           0 :           path->sw_if_index = ~0;
     850           0 :           path->proto = FIB_API_PATH_NH_PROTO_IP4;
     851             :         }
     852           0 :       else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
     853             :         {
     854           0 :           path->type = FIB_API_PATH_TYPE_LOCAL;
     855           0 :           path->sw_if_index = ~0;
     856           0 :           path->proto = FIB_API_PATH_NH_PROTO_IP6;
     857             :         }
     858           0 :       else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
     859             :         ;
     860           0 :       else if (unformat (input, "via-label %d", &path->nh.via_label))
     861             :         {
     862           0 :           path->proto = FIB_API_PATH_NH_PROTO_MPLS;
     863           0 :           path->sw_if_index = ~0;
     864             :         }
     865           0 :       else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
     866             :         {
     867           0 :           path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
     868           0 :           path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
     869             :         }
     870           0 :       else if (unformat (input, "local"))
     871             :         {
     872           0 :           path->type = FIB_API_PATH_TYPE_LOCAL;
     873             :         }
     874           0 :       else if (unformat (input, "out-labels"))
     875             :         {
     876           0 :           while (unformat (input, "%d", &out_label))
     877             :             {
     878           0 :               path->label_stack[path->n_labels].label = out_label;
     879           0 :               path->label_stack[path->n_labels].is_uniform = 0;
     880           0 :               path->label_stack[path->n_labels].ttl = 64;
     881           0 :               path->n_labels++;
     882             :             }
     883             :         }
     884           0 :       else if (unformat (input, "via"))
     885             :         {
     886             :           /* new path, back up and return */
     887           0 :           unformat_put_input (input);
     888           0 :           unformat_put_input (input);
     889           0 :           unformat_put_input (input);
     890           0 :           unformat_put_input (input);
     891           0 :           break;
     892             :         }
     893             :       else
     894             :         {
     895           0 :           return (0);
     896             :         }
     897             :     }
     898             : 
     899           0 :   path->proto = ntohl (path->proto);
     900           0 :   path->type = ntohl (path->type);
     901           0 :   path->flags = ntohl (path->flags);
     902           0 :   path->table_id = ntohl (path->table_id);
     903           0 :   path->sw_if_index = ntohl (path->sw_if_index);
     904             : 
     905           0 :   return (1);
     906             : }
     907             : 
     908             : #define foreach_create_subif_bit                \
     909             : _(no_tags)                                      \
     910             : _(one_tag)                                      \
     911             : _(two_tags)                                     \
     912             : _(dot1ad)                                       \
     913             : _(exact_match)                                  \
     914             : _(default_sub)                                  \
     915             : _(outer_vlan_id_any)                            \
     916             : _(inner_vlan_id_any)
     917             : 
     918             : #define foreach_create_subif_flag               \
     919             : _(0, "no_tags")                                       \
     920             : _(1, "one_tag")                                       \
     921             : _(2, "two_tags")                              \
     922             : _(3, "dot1ad")                                        \
     923             : _(4, "exact_match")                           \
     924             : _(5, "default_sub")                           \
     925             : _(6, "outer_vlan_id_any")                     \
     926             : _(7, "inner_vlan_id_any")
     927             : 
     928             : 
     929             : #define foreach_tcp_proto_field                                               \
     930             :   _ (src_port)                                                                \
     931             :   _ (dst_port)
     932             : 
     933             : #define foreach_udp_proto_field                                               \
     934             :   _ (src_port)                                                                \
     935             :   _ (dst_port)
     936             : 
     937             : #define foreach_ip4_proto_field                                               \
     938             :   _ (src_address)                                                             \
     939             :   _ (dst_address)                                                             \
     940             :   _ (tos)                                                                     \
     941             :   _ (length)                                                                  \
     942             :   _ (fragment_id)                                                             \
     943             :   _ (ttl)                                                                     \
     944             :   _ (protocol)                                                                \
     945             :   _ (checksum)
     946             : 
     947             : typedef struct
     948             : {
     949             :   u16 src_port, dst_port;
     950             : } tcpudp_header_t;
     951             : 
     952             : #if VPP_API_TEST_BUILTIN == 0
     953             : uword
     954             : unformat_tcp_mask (unformat_input_t *input, va_list *args)
     955             : {
     956             :   u8 **maskp = va_arg (*args, u8 **);
     957             :   u8 *mask = 0;
     958             :   u8 found_something = 0;
     959             :   tcp_header_t *tcp;
     960             : 
     961             : #define _(a) u8 a = 0;
     962             :   foreach_tcp_proto_field;
     963             : #undef _
     964             : 
     965             :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     966             :     {
     967             :       if (0)
     968             :         ;
     969             : #define _(a) else if (unformat (input, #a)) a = 1;
     970             :       foreach_tcp_proto_field
     971             : #undef _
     972             :         else break;
     973             :     }
     974             : 
     975             : #define _(a) found_something += a;
     976             :   foreach_tcp_proto_field;
     977             : #undef _
     978             : 
     979             :   if (found_something == 0)
     980             :     return 0;
     981             : 
     982             :   vec_validate (mask, sizeof (*tcp) - 1);
     983             : 
     984             :   tcp = (tcp_header_t *) mask;
     985             : 
     986             : #define _(a)                                                                  \
     987             :   if (a)                                                                      \
     988             :     clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
     989             :   foreach_tcp_proto_field;
     990             : #undef _
     991             : 
     992             :   *maskp = mask;
     993             :   return 1;
     994             : }
     995             : 
     996             : uword
     997             : unformat_udp_mask (unformat_input_t *input, va_list *args)
     998             : {
     999             :   u8 **maskp = va_arg (*args, u8 **);
    1000             :   u8 *mask = 0;
    1001             :   u8 found_something = 0;
    1002             :   udp_header_t *udp;
    1003             : 
    1004             : #define _(a) u8 a = 0;
    1005             :   foreach_udp_proto_field;
    1006             : #undef _
    1007             : 
    1008             :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1009             :     {
    1010             :       if (0)
    1011             :         ;
    1012             : #define _(a) else if (unformat (input, #a)) a = 1;
    1013             :       foreach_udp_proto_field
    1014             : #undef _
    1015             :         else break;
    1016             :     }
    1017             : 
    1018             : #define _(a) found_something += a;
    1019             :   foreach_udp_proto_field;
    1020             : #undef _
    1021             : 
    1022             :   if (found_something == 0)
    1023             :     return 0;
    1024             : 
    1025             :   vec_validate (mask, sizeof (*udp) - 1);
    1026             : 
    1027             :   udp = (udp_header_t *) mask;
    1028             : 
    1029             : #define _(a)                                                                  \
    1030             :   if (a)                                                                      \
    1031             :     clib_memset (&udp->a, 0xff, sizeof (udp->a));
    1032             :   foreach_udp_proto_field;
    1033             : #undef _
    1034             : 
    1035             :   *maskp = mask;
    1036             :   return 1;
    1037             : }
    1038             : 
    1039             : uword
    1040             : unformat_l4_mask (unformat_input_t *input, va_list *args)
    1041             : {
    1042             :   u8 **maskp = va_arg (*args, u8 **);
    1043             :   u16 src_port = 0, dst_port = 0;
    1044             :   tcpudp_header_t *tcpudp;
    1045             : 
    1046             :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1047             :     {
    1048             :       if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
    1049             :         return 1;
    1050             :       else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
    1051             :         return 1;
    1052             :       else if (unformat (input, "src_port"))
    1053             :         src_port = 0xFFFF;
    1054             :       else if (unformat (input, "dst_port"))
    1055             :         dst_port = 0xFFFF;
    1056             :       else
    1057             :         return 0;
    1058             :     }
    1059             : 
    1060             :   if (!src_port && !dst_port)
    1061             :     return 0;
    1062             : 
    1063             :   u8 *mask = 0;
    1064             :   vec_validate (mask, sizeof (tcpudp_header_t) - 1);
    1065             : 
    1066             :   tcpudp = (tcpudp_header_t *) mask;
    1067             :   tcpudp->src_port = src_port;
    1068             :   tcpudp->dst_port = dst_port;
    1069             : 
    1070             :   *maskp = mask;
    1071             : 
    1072             :   return 1;
    1073             : }
    1074             : 
    1075             : uword
    1076             : unformat_ip4_mask (unformat_input_t * input, va_list * args)
    1077             : {
    1078             :   u8 **maskp = va_arg (*args, u8 **);
    1079             :   u8 *mask = 0;
    1080             :   u8 found_something = 0;
    1081             :   ip4_header_t *ip;
    1082             : 
    1083             : #define _(a) u8 a=0;
    1084             :   foreach_ip4_proto_field;
    1085             : #undef _
    1086             :   u8 version = 0;
    1087             :   u8 hdr_length = 0;
    1088             : 
    1089             : 
    1090             :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1091             :     {
    1092             :       if (unformat (input, "version"))
    1093             :         version = 1;
    1094             :       else if (unformat (input, "hdr_length"))
    1095             :         hdr_length = 1;
    1096             :       else if (unformat (input, "src"))
    1097             :         src_address = 1;
    1098             :       else if (unformat (input, "dst"))
    1099             :         dst_address = 1;
    1100             :       else if (unformat (input, "proto"))
    1101             :         protocol = 1;
    1102             : 
    1103             : #define _(a) else if (unformat (input, #a)) a=1;
    1104             :       foreach_ip4_proto_field
    1105             : #undef _
    1106             :         else
    1107             :         break;
    1108             :     }
    1109             : 
    1110             : #define _(a) found_something += a;
    1111             :   foreach_ip4_proto_field;
    1112             : #undef _
    1113             : 
    1114             :   if (found_something == 0)
    1115             :     return 0;
    1116             : 
    1117             :   vec_validate (mask, sizeof (*ip) - 1);
    1118             : 
    1119             :   ip = (ip4_header_t *) mask;
    1120             : 
    1121             : #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
    1122             :   foreach_ip4_proto_field;
    1123             : #undef _
    1124             : 
    1125             :   ip->ip_version_and_header_length = 0;
    1126             : 
    1127             :   if (version)
    1128             :     ip->ip_version_and_header_length |= 0xF0;
    1129             : 
    1130             :   if (hdr_length)
    1131             :     ip->ip_version_and_header_length |= 0x0F;
    1132             : 
    1133             :   *maskp = mask;
    1134             :   return 1;
    1135             : }
    1136             : 
    1137             : #define foreach_ip6_proto_field                 \
    1138             : _(src_address)                                  \
    1139             : _(dst_address)                                  \
    1140             : _(payload_length)                               \
    1141             : _(hop_limit)                                    \
    1142             : _(protocol)
    1143             : 
    1144             : uword
    1145             : unformat_ip6_mask (unformat_input_t * input, va_list * args)
    1146             : {
    1147             :   u8 **maskp = va_arg (*args, u8 **);
    1148             :   u8 *mask = 0;
    1149             :   u8 found_something = 0;
    1150             :   ip6_header_t *ip;
    1151             :   u32 ip_version_traffic_class_and_flow_label;
    1152             : 
    1153             : #define _(a) u8 a=0;
    1154             :   foreach_ip6_proto_field;
    1155             : #undef _
    1156             :   u8 version = 0;
    1157             :   u8 traffic_class = 0;
    1158             :   u8 flow_label = 0;
    1159             : 
    1160             :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1161             :     {
    1162             :       if (unformat (input, "version"))
    1163             :         version = 1;
    1164             :       else if (unformat (input, "traffic-class"))
    1165             :         traffic_class = 1;
    1166             :       else if (unformat (input, "flow-label"))
    1167             :         flow_label = 1;
    1168             :       else if (unformat (input, "src"))
    1169             :         src_address = 1;
    1170             :       else if (unformat (input, "dst"))
    1171             :         dst_address = 1;
    1172             :       else if (unformat (input, "proto"))
    1173             :         protocol = 1;
    1174             : 
    1175             : #define _(a) else if (unformat (input, #a)) a=1;
    1176             :       foreach_ip6_proto_field
    1177             : #undef _
    1178             :         else
    1179             :         break;
    1180             :     }
    1181             : 
    1182             : #define _(a) found_something += a;
    1183             :   foreach_ip6_proto_field;
    1184             : #undef _
    1185             : 
    1186             :   if (found_something == 0)
    1187             :     return 0;
    1188             : 
    1189             :   vec_validate (mask, sizeof (*ip) - 1);
    1190             : 
    1191             :   ip = (ip6_header_t *) mask;
    1192             : 
    1193             : #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
    1194             :   foreach_ip6_proto_field;
    1195             : #undef _
    1196             : 
    1197             :   ip_version_traffic_class_and_flow_label = 0;
    1198             : 
    1199             :   if (version)
    1200             :     ip_version_traffic_class_and_flow_label |= 0xF0000000;
    1201             : 
    1202             :   if (traffic_class)
    1203             :     ip_version_traffic_class_and_flow_label |= 0x0FF00000;
    1204             : 
    1205             :   if (flow_label)
    1206             :     ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
    1207             : 
    1208             :   ip->ip_version_traffic_class_and_flow_label =
    1209             :     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
    1210             : 
    1211             :   *maskp = mask;
    1212             :   return 1;
    1213             : }
    1214             : 
    1215             : uword
    1216             : unformat_l3_mask (unformat_input_t * input, va_list * args)
    1217             : {
    1218             :   u8 **maskp = va_arg (*args, u8 **);
    1219             : 
    1220             :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1221             :     {
    1222             :       if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
    1223             :         return 1;
    1224             :       else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
    1225             :         return 1;
    1226             :       else
    1227             :         break;
    1228             :     }
    1229             :   return 0;
    1230             : }
    1231             : 
    1232             : uword
    1233             : unformat_l2_mask (unformat_input_t * input, va_list * args)
    1234             : {
    1235             :   u8 **maskp = va_arg (*args, u8 **);
    1236             :   u8 *mask = 0;
    1237             :   u8 src = 0;
    1238             :   u8 dst = 0;
    1239             :   u8 proto = 0;
    1240             :   u8 tag1 = 0;
    1241             :   u8 tag2 = 0;
    1242             :   u8 ignore_tag1 = 0;
    1243             :   u8 ignore_tag2 = 0;
    1244             :   u8 cos1 = 0;
    1245             :   u8 cos2 = 0;
    1246             :   u8 dot1q = 0;
    1247             :   u8 dot1ad = 0;
    1248             :   int len = 14;
    1249             : 
    1250             :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1251             :     {
    1252             :       if (unformat (input, "src"))
    1253             :         src = 1;
    1254             :       else if (unformat (input, "dst"))
    1255             :         dst = 1;
    1256             :       else if (unformat (input, "proto"))
    1257             :         proto = 1;
    1258             :       else if (unformat (input, "tag1"))
    1259             :         tag1 = 1;
    1260             :       else if (unformat (input, "tag2"))
    1261             :         tag2 = 1;
    1262             :       else if (unformat (input, "ignore-tag1"))
    1263             :         ignore_tag1 = 1;
    1264             :       else if (unformat (input, "ignore-tag2"))
    1265             :         ignore_tag2 = 1;
    1266             :       else if (unformat (input, "cos1"))
    1267             :         cos1 = 1;
    1268             :       else if (unformat (input, "cos2"))
    1269             :         cos2 = 1;
    1270             :       else if (unformat (input, "dot1q"))
    1271             :         dot1q = 1;
    1272             :       else if (unformat (input, "dot1ad"))
    1273             :         dot1ad = 1;
    1274             :       else
    1275             :         break;
    1276             :     }
    1277             :   if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
    1278             :        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
    1279             :     return 0;
    1280             : 
    1281             :   if (tag1 || ignore_tag1 || cos1 || dot1q)
    1282             :     len = 18;
    1283             :   if (tag2 || ignore_tag2 || cos2 || dot1ad)
    1284             :     len = 22;
    1285             : 
    1286             :   vec_validate (mask, len - 1);
    1287             : 
    1288             :   if (dst)
    1289             :     clib_memset (mask, 0xff, 6);
    1290             : 
    1291             :   if (src)
    1292             :     clib_memset (mask + 6, 0xff, 6);
    1293             : 
    1294             :   if (tag2 || dot1ad)
    1295             :     {
    1296             :       /* inner vlan tag */
    1297             :       if (tag2)
    1298             :         {
    1299             :           mask[19] = 0xff;
    1300             :           mask[18] = 0x0f;
    1301             :         }
    1302             :       if (cos2)
    1303             :         mask[18] |= 0xe0;
    1304             :       if (proto)
    1305             :         mask[21] = mask[20] = 0xff;
    1306             :       if (tag1)
    1307             :         {
    1308             :           mask[15] = 0xff;
    1309             :           mask[14] = 0x0f;
    1310             :         }
    1311             :       if (cos1)
    1312             :         mask[14] |= 0xe0;
    1313             :       *maskp = mask;
    1314             :       return 1;
    1315             :     }
    1316             :   if (tag1 | dot1q)
    1317             :     {
    1318             :       if (tag1)
    1319             :         {
    1320             :           mask[15] = 0xff;
    1321             :           mask[14] = 0x0f;
    1322             :         }
    1323             :       if (cos1)
    1324             :         mask[14] |= 0xe0;
    1325             :       if (proto)
    1326             :         mask[16] = mask[17] = 0xff;
    1327             : 
    1328             :       *maskp = mask;
    1329             :       return 1;
    1330             :     }
    1331             :   if (cos2)
    1332             :     mask[18] |= 0xe0;
    1333             :   if (cos1)
    1334             :     mask[14] |= 0xe0;
    1335             :   if (proto)
    1336             :     mask[12] = mask[13] = 0xff;
    1337             : 
    1338             :   *maskp = mask;
    1339             :   return 1;
    1340             : }
    1341             : 
    1342             : uword
    1343             : unformat_classify_mask (unformat_input_t * input, va_list * args)
    1344             : {
    1345             :   u8 **maskp = va_arg (*args, u8 **);
    1346             :   u32 *skipp = va_arg (*args, u32 *);
    1347             :   u32 *matchp = va_arg (*args, u32 *);
    1348             :   u32 match;
    1349             :   u8 *mask = 0;
    1350             :   u8 *l2 = 0;
    1351             :   u8 *l3 = 0;
    1352             :   u8 *l4 = 0;
    1353             :   int i;
    1354             : 
    1355             :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1356             :     {
    1357             :       if (unformat (input, "hex %U", unformat_hex_string, &mask))
    1358             :         ;
    1359             :       else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
    1360             :         ;
    1361             :       else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
    1362             :         ;
    1363             :       else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
    1364             :         ;
    1365             :       else
    1366             :         break;
    1367             :     }
    1368             : 
    1369             :   if (l4 && !l3)
    1370             :     {
    1371             :       vec_free (mask);
    1372             :       vec_free (l2);
    1373             :       vec_free (l4);
    1374             :       return 0;
    1375             :     }
    1376             : 
    1377             :   if (mask || l2 || l3 || l4)
    1378             :     {
    1379             :       if (l2 || l3 || l4)
    1380             :         {
    1381             :           /* "With a free Ethernet header in every package" */
    1382             :           if (l2 == 0)
    1383             :             vec_validate (l2, 13);
    1384             :           mask = l2;
    1385             :           if (vec_len (l3))
    1386             :             {
    1387             :               vec_append (mask, l3);
    1388             :               vec_free (l3);
    1389             :             }
    1390             :           if (vec_len (l4))
    1391             :             {
    1392             :               vec_append (mask, l4);
    1393             :               vec_free (l4);
    1394             :             }
    1395             :         }
    1396             : 
    1397             :       /* Scan forward looking for the first significant mask octet */
    1398             :       for (i = 0; i < vec_len (mask); i++)
    1399             :         if (mask[i])
    1400             :           break;
    1401             : 
    1402             :       /* compute (skip, match) params */
    1403             :       *skipp = i / sizeof (u32x4);
    1404             :       vec_delete (mask, *skipp * sizeof (u32x4), 0);
    1405             : 
    1406             :       /* Pad mask to an even multiple of the vector size */
    1407             :       while (vec_len (mask) % sizeof (u32x4))
    1408             :         vec_add1 (mask, 0);
    1409             : 
    1410             :       match = vec_len (mask) / sizeof (u32x4);
    1411             : 
    1412             :       for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
    1413             :         {
    1414             :           u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
    1415             :           if (*tmp || *(tmp + 1))
    1416             :             break;
    1417             :           match--;
    1418             :         }
    1419             :       if (match == 0)
    1420             :         clib_warning ("BUG: match 0");
    1421             : 
    1422             :       vec_set_len (mask, match * sizeof (u32x4));
    1423             : 
    1424             :       *matchp = match;
    1425             :       *maskp = mask;
    1426             : 
    1427             :       return 1;
    1428             :     }
    1429             : 
    1430             :   return 0;
    1431             : }
    1432             : #endif /* VPP_API_TEST_BUILTIN */
    1433             : 
    1434             : #define foreach_l2_next                         \
    1435             : _(drop, DROP)                                   \
    1436             : _(ethernet, ETHERNET_INPUT)                     \
    1437             : _(ip4, IP4_INPUT)                               \
    1438             : _(ip6, IP6_INPUT)
    1439             : 
    1440             : uword
    1441           0 : unformat_l2_next_index (unformat_input_t * input, va_list * args)
    1442             : {
    1443           0 :   u32 *miss_next_indexp = va_arg (*args, u32 *);
    1444           0 :   u32 next_index = 0;
    1445             :   u32 tmp;
    1446             : 
    1447             : #define _(n,N) \
    1448             :   if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
    1449           0 :   foreach_l2_next;
    1450             : #undef _
    1451             : 
    1452           0 :   if (unformat (input, "%d", &tmp))
    1453             :     {
    1454           0 :       next_index = tmp;
    1455           0 :       goto out;
    1456             :     }
    1457             : 
    1458           0 :   return 0;
    1459             : 
    1460           0 : out:
    1461           0 :   *miss_next_indexp = next_index;
    1462           0 :   return 1;
    1463             : }
    1464             : 
    1465             : #define foreach_ip_next                         \
    1466             : _(drop, DROP)                                   \
    1467             : _(local, LOCAL)                                 \
    1468             : _(rewrite, REWRITE)
    1469             : 
    1470             : uword
    1471           0 : api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
    1472             : {
    1473           0 :   u32 *miss_next_indexp = va_arg (*args, u32 *);
    1474           0 :   u32 next_index = 0;
    1475             :   u32 tmp;
    1476             : 
    1477             : #define _(n,N) \
    1478             :   if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
    1479           0 :   foreach_ip_next;
    1480             : #undef _
    1481             : 
    1482           0 :   if (unformat (input, "%d", &tmp))
    1483             :     {
    1484           0 :       next_index = tmp;
    1485           0 :       goto out;
    1486             :     }
    1487             : 
    1488           0 :   return 0;
    1489             : 
    1490           0 : out:
    1491           0 :   *miss_next_indexp = next_index;
    1492           0 :   return 1;
    1493             : }
    1494             : 
    1495             : #define foreach_acl_next                        \
    1496             : _(deny, DENY)
    1497             : 
    1498             : uword
    1499           0 : api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
    1500             : {
    1501           0 :   u32 *miss_next_indexp = va_arg (*args, u32 *);
    1502           0 :   u32 next_index = 0;
    1503             :   u32 tmp;
    1504             : 
    1505             : #define _(n,N) \
    1506             :   if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
    1507           0 :   foreach_acl_next;
    1508             : #undef _
    1509             : 
    1510           0 :   if (unformat (input, "permit"))
    1511             :     {
    1512           0 :       next_index = ~0;
    1513           0 :       goto out;
    1514             :     }
    1515           0 :   else if (unformat (input, "%d", &tmp))
    1516             :     {
    1517           0 :       next_index = tmp;
    1518           0 :       goto out;
    1519             :     }
    1520             : 
    1521           0 :   return 0;
    1522             : 
    1523           0 : out:
    1524           0 :   *miss_next_indexp = next_index;
    1525           0 :   return 1;
    1526             : }
    1527             : 
    1528             : uword
    1529           0 : unformat_policer_precolor (unformat_input_t * input, va_list * args)
    1530             : {
    1531           0 :   u32 *r = va_arg (*args, u32 *);
    1532             : 
    1533           0 :   if (unformat (input, "conform-color"))
    1534           0 :     *r = POLICE_CONFORM;
    1535           0 :   else if (unformat (input, "exceed-color"))
    1536           0 :     *r = POLICE_EXCEED;
    1537             :   else
    1538           0 :     return 0;
    1539             : 
    1540           0 :   return 1;
    1541             : }
    1542             : 
    1543             : #if VPP_API_TEST_BUILTIN == 0
    1544             : uword
    1545             : unformat_l4_match (unformat_input_t * input, va_list * args)
    1546             : {
    1547             :   u8 **matchp = va_arg (*args, u8 **);
    1548             : 
    1549             :   u8 *proto_header = 0;
    1550             :   int src_port = 0;
    1551             :   int dst_port = 0;
    1552             : 
    1553             :   tcpudp_header_t h;
    1554             : 
    1555             :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1556             :     {
    1557             :       if (unformat (input, "src_port %d", &src_port))
    1558             :         ;
    1559             :       else if (unformat (input, "dst_port %d", &dst_port))
    1560             :         ;
    1561             :       else
    1562             :         return 0;
    1563             :     }
    1564             : 
    1565             :   h.src_port = clib_host_to_net_u16 (src_port);
    1566             :   h.dst_port = clib_host_to_net_u16 (dst_port);
    1567             :   vec_validate (proto_header, sizeof (h) - 1);
    1568             :   memcpy (proto_header, &h, sizeof (h));
    1569             : 
    1570             :   *matchp = proto_header;
    1571             : 
    1572             :   return 1;
    1573             : }
    1574             : 
    1575             : uword
    1576             : unformat_ip4_match (unformat_input_t * input, va_list * args)
    1577             : {
    1578             :   u8 **matchp = va_arg (*args, u8 **);
    1579             :   u8 *match = 0;
    1580             :   ip4_header_t *ip;
    1581             :   int version = 0;
    1582             :   u32 version_val;
    1583             :   int hdr_length = 0;
    1584             :   u32 hdr_length_val;
    1585             :   int src = 0, dst = 0;
    1586             :   ip4_address_t src_val, dst_val;
    1587             :   int proto = 0;
    1588             :   u32 proto_val;
    1589             :   int tos = 0;
    1590             :   u32 tos_val;
    1591             :   int length = 0;
    1592             :   u32 length_val;
    1593             :   int fragment_id = 0;
    1594             :   u32 fragment_id_val;
    1595             :   int ttl = 0;
    1596             :   int ttl_val;
    1597             :   int checksum = 0;
    1598             :   u32 checksum_val;
    1599             : 
    1600             :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1601             :     {
    1602             :       if (unformat (input, "version %d", &version_val))
    1603             :         version = 1;
    1604             :       else if (unformat (input, "hdr_length %d", &hdr_length_val))
    1605             :         hdr_length = 1;
    1606             :       else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
    1607             :         src = 1;
    1608             :       else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
    1609             :         dst = 1;
    1610             :       else if (unformat (input, "proto %d", &proto_val))
    1611             :         proto = 1;
    1612             :       else if (unformat (input, "tos %d", &tos_val))
    1613             :         tos = 1;
    1614             :       else if (unformat (input, "length %d", &length_val))
    1615             :         length = 1;
    1616             :       else if (unformat (input, "fragment_id %d", &fragment_id_val))
    1617             :         fragment_id = 1;
    1618             :       else if (unformat (input, "ttl %d", &ttl_val))
    1619             :         ttl = 1;
    1620             :       else if (unformat (input, "checksum %d", &checksum_val))
    1621             :         checksum = 1;
    1622             :       else
    1623             :         break;
    1624             :     }
    1625             : 
    1626             :   if (version + hdr_length + src + dst + proto + tos + length + fragment_id
    1627             :       + ttl + checksum == 0)
    1628             :     return 0;
    1629             : 
    1630             :   /*
    1631             :    * Aligned because we use the real comparison functions
    1632             :    */
    1633             :   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
    1634             : 
    1635             :   ip = (ip4_header_t *) match;
    1636             : 
    1637             :   /* These are realistically matched in practice */
    1638             :   if (src)
    1639             :     ip->src_address.as_u32 = src_val.as_u32;
    1640             : 
    1641             :   if (dst)
    1642             :     ip->dst_address.as_u32 = dst_val.as_u32;
    1643             : 
    1644             :   if (proto)
    1645             :     ip->protocol = proto_val;
    1646             : 
    1647             : 
    1648             :   /* These are not, but they're included for completeness */
    1649             :   if (version)
    1650             :     ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
    1651             : 
    1652             :   if (hdr_length)
    1653             :     ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
    1654             : 
    1655             :   if (tos)
    1656             :     ip->tos = tos_val;
    1657             : 
    1658             :   if (length)
    1659             :     ip->length = clib_host_to_net_u16 (length_val);
    1660             : 
    1661             :   if (ttl)
    1662             :     ip->ttl = ttl_val;
    1663             : 
    1664             :   if (checksum)
    1665             :     ip->checksum = clib_host_to_net_u16 (checksum_val);
    1666             : 
    1667             :   *matchp = match;
    1668             :   return 1;
    1669             : }
    1670             : 
    1671             : uword
    1672             : unformat_ip6_match (unformat_input_t * input, va_list * args)
    1673             : {
    1674             :   u8 **matchp = va_arg (*args, u8 **);
    1675             :   u8 *match = 0;
    1676             :   ip6_header_t *ip;
    1677             :   int version = 0;
    1678             :   u32 version_val;
    1679             :   u8 traffic_class = 0;
    1680             :   u32 traffic_class_val = 0;
    1681             :   u8 flow_label = 0;
    1682             :   u8 flow_label_val;
    1683             :   int src = 0, dst = 0;
    1684             :   ip6_address_t src_val, dst_val;
    1685             :   int proto = 0;
    1686             :   u32 proto_val;
    1687             :   int payload_length = 0;
    1688             :   u32 payload_length_val;
    1689             :   int hop_limit = 0;
    1690             :   int hop_limit_val;
    1691             :   u32 ip_version_traffic_class_and_flow_label;
    1692             : 
    1693             :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1694             :     {
    1695             :       if (unformat (input, "version %d", &version_val))
    1696             :         version = 1;
    1697             :       else if (unformat (input, "traffic_class %d", &traffic_class_val))
    1698             :         traffic_class = 1;
    1699             :       else if (unformat (input, "flow_label %d", &flow_label_val))
    1700             :         flow_label = 1;
    1701             :       else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
    1702             :         src = 1;
    1703             :       else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
    1704             :         dst = 1;
    1705             :       else if (unformat (input, "proto %d", &proto_val))
    1706             :         proto = 1;
    1707             :       else if (unformat (input, "payload_length %d", &payload_length_val))
    1708             :         payload_length = 1;
    1709             :       else if (unformat (input, "hop_limit %d", &hop_limit_val))
    1710             :         hop_limit = 1;
    1711             :       else
    1712             :         break;
    1713             :     }
    1714             : 
    1715             :   if (version + traffic_class + flow_label + src + dst + proto +
    1716             :       payload_length + hop_limit == 0)
    1717             :     return 0;
    1718             : 
    1719             :   /*
    1720             :    * Aligned because we use the real comparison functions
    1721             :    */
    1722             :   vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
    1723             : 
    1724             :   ip = (ip6_header_t *) match;
    1725             : 
    1726             :   if (src)
    1727             :     clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
    1728             : 
    1729             :   if (dst)
    1730             :     clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
    1731             : 
    1732             :   if (proto)
    1733             :     ip->protocol = proto_val;
    1734             : 
    1735             :   ip_version_traffic_class_and_flow_label = 0;
    1736             : 
    1737             :   if (version)
    1738             :     ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
    1739             : 
    1740             :   if (traffic_class)
    1741             :     ip_version_traffic_class_and_flow_label |=
    1742             :       (traffic_class_val & 0xFF) << 20;
    1743             : 
    1744             :   if (flow_label)
    1745             :     ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
    1746             : 
    1747             :   ip->ip_version_traffic_class_and_flow_label =
    1748             :     clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
    1749             : 
    1750             :   if (payload_length)
    1751             :     ip->payload_length = clib_host_to_net_u16 (payload_length_val);
    1752             : 
    1753             :   if (hop_limit)
    1754             :     ip->hop_limit = hop_limit_val;
    1755             : 
    1756             :   *matchp = match;
    1757             :   return 1;
    1758             : }
    1759             : 
    1760             : uword
    1761             : unformat_l3_match (unformat_input_t * input, va_list * args)
    1762             : {
    1763             :   u8 **matchp = va_arg (*args, u8 **);
    1764             : 
    1765             :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1766             :     {
    1767             :       if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
    1768             :         return 1;
    1769             :       else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
    1770             :         return 1;
    1771             :       else
    1772             :         break;
    1773             :     }
    1774             :   return 0;
    1775             : }
    1776             : 
    1777             : uword
    1778             : unformat_vlan_tag (unformat_input_t * input, va_list * args)
    1779             : {
    1780             :   u8 *tagp = va_arg (*args, u8 *);
    1781             :   u32 tag;
    1782             : 
    1783             :   if (unformat (input, "%d", &tag))
    1784             :     {
    1785             :       tagp[0] = (tag >> 8) & 0x0F;
    1786             :       tagp[1] = tag & 0xFF;
    1787             :       return 1;
    1788             :     }
    1789             : 
    1790             :   return 0;
    1791             : }
    1792             : 
    1793             : uword
    1794             : unformat_l2_match (unformat_input_t * input, va_list * args)
    1795             : {
    1796             :   u8 **matchp = va_arg (*args, u8 **);
    1797             :   u8 *match = 0;
    1798             :   u8 src = 0;
    1799             :   u8 src_val[6];
    1800             :   u8 dst = 0;
    1801             :   u8 dst_val[6];
    1802             :   u8 proto = 0;
    1803             :   u16 proto_val;
    1804             :   u8 tag1 = 0;
    1805             :   u8 tag1_val[2];
    1806             :   u8 tag2 = 0;
    1807             :   u8 tag2_val[2];
    1808             :   int len = 14;
    1809             :   u8 ignore_tag1 = 0;
    1810             :   u8 ignore_tag2 = 0;
    1811             :   u8 cos1 = 0;
    1812             :   u8 cos2 = 0;
    1813             :   u32 cos1_val = 0;
    1814             :   u32 cos2_val = 0;
    1815             : 
    1816             :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1817             :     {
    1818             :       if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
    1819             :         src = 1;
    1820             :       else
    1821             :         if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
    1822             :         dst = 1;
    1823             :       else if (unformat (input, "proto %U",
    1824             :                          unformat_ethernet_type_host_byte_order, &proto_val))
    1825             :         proto = 1;
    1826             :       else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
    1827             :         tag1 = 1;
    1828             :       else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
    1829             :         tag2 = 1;
    1830             :       else if (unformat (input, "ignore-tag1"))
    1831             :         ignore_tag1 = 1;
    1832             :       else if (unformat (input, "ignore-tag2"))
    1833             :         ignore_tag2 = 1;
    1834             :       else if (unformat (input, "cos1 %d", &cos1_val))
    1835             :         cos1 = 1;
    1836             :       else if (unformat (input, "cos2 %d", &cos2_val))
    1837             :         cos2 = 1;
    1838             :       else
    1839             :         break;
    1840             :     }
    1841             :   if ((src + dst + proto + tag1 + tag2 +
    1842             :        ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
    1843             :     return 0;
    1844             : 
    1845             :   if (tag1 || ignore_tag1 || cos1)
    1846             :     len = 18;
    1847             :   if (tag2 || ignore_tag2 || cos2)
    1848             :     len = 22;
    1849             : 
    1850             :   vec_validate_aligned (match, len - 1, sizeof (u32x4));
    1851             : 
    1852             :   if (dst)
    1853             :     clib_memcpy (match, dst_val, 6);
    1854             : 
    1855             :   if (src)
    1856             :     clib_memcpy (match + 6, src_val, 6);
    1857             : 
    1858             :   if (tag2)
    1859             :     {
    1860             :       /* inner vlan tag */
    1861             :       match[19] = tag2_val[1];
    1862             :       match[18] = tag2_val[0];
    1863             :       if (cos2)
    1864             :         match[18] |= (cos2_val & 0x7) << 5;
    1865             :       if (proto)
    1866             :         {
    1867             :           match[21] = proto_val & 0xff;
    1868             :           match[20] = proto_val >> 8;
    1869             :         }
    1870             :       if (tag1)
    1871             :         {
    1872             :           match[15] = tag1_val[1];
    1873             :           match[14] = tag1_val[0];
    1874             :         }
    1875             :       if (cos1)
    1876             :         match[14] |= (cos1_val & 0x7) << 5;
    1877             :       *matchp = match;
    1878             :       return 1;
    1879             :     }
    1880             :   if (tag1)
    1881             :     {
    1882             :       match[15] = tag1_val[1];
    1883             :       match[14] = tag1_val[0];
    1884             :       if (proto)
    1885             :         {
    1886             :           match[17] = proto_val & 0xff;
    1887             :           match[16] = proto_val >> 8;
    1888             :         }
    1889             :       if (cos1)
    1890             :         match[14] |= (cos1_val & 0x7) << 5;
    1891             : 
    1892             :       *matchp = match;
    1893             :       return 1;
    1894             :     }
    1895             :   if (cos2)
    1896             :     match[18] |= (cos2_val & 0x7) << 5;
    1897             :   if (cos1)
    1898             :     match[14] |= (cos1_val & 0x7) << 5;
    1899             :   if (proto)
    1900             :     {
    1901             :       match[13] = proto_val & 0xff;
    1902             :       match[12] = proto_val >> 8;
    1903             :     }
    1904             : 
    1905             :   *matchp = match;
    1906             :   return 1;
    1907             : }
    1908             : 
    1909             : uword
    1910             : unformat_qos_source (unformat_input_t * input, va_list * args)
    1911             : {
    1912             :   int *qs = va_arg (*args, int *);
    1913             : 
    1914             :   if (unformat (input, "ip"))
    1915             :     *qs = QOS_SOURCE_IP;
    1916             :   else if (unformat (input, "mpls"))
    1917             :     *qs = QOS_SOURCE_MPLS;
    1918             :   else if (unformat (input, "ext"))
    1919             :     *qs = QOS_SOURCE_EXT;
    1920             :   else if (unformat (input, "vlan"))
    1921             :     *qs = QOS_SOURCE_VLAN;
    1922             :   else
    1923             :     return 0;
    1924             : 
    1925             :   return 1;
    1926             : }
    1927             : #endif
    1928             : 
    1929             : uword
    1930           0 : api_unformat_classify_match (unformat_input_t * input, va_list * args)
    1931             : {
    1932           0 :   u8 **matchp = va_arg (*args, u8 **);
    1933           0 :   u32 skip_n_vectors = va_arg (*args, u32);
    1934           0 :   u32 match_n_vectors = va_arg (*args, u32);
    1935             : 
    1936           0 :   u8 *match = 0;
    1937           0 :   u8 *l2 = 0;
    1938           0 :   u8 *l3 = 0;
    1939           0 :   u8 *l4 = 0;
    1940             : 
    1941           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1942             :     {
    1943           0 :       if (unformat (input, "hex %U", unformat_hex_string, &match))
    1944             :         ;
    1945           0 :       else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
    1946             :         ;
    1947           0 :       else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
    1948             :         ;
    1949           0 :       else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
    1950             :         ;
    1951             :       else
    1952           0 :         break;
    1953             :     }
    1954             : 
    1955           0 :   if (l4 && !l3)
    1956             :     {
    1957           0 :       vec_free (match);
    1958           0 :       vec_free (l2);
    1959           0 :       vec_free (l4);
    1960           0 :       return 0;
    1961             :     }
    1962             : 
    1963           0 :   if (match || l2 || l3 || l4)
    1964             :     {
    1965           0 :       if (l2 || l3 || l4)
    1966             :         {
    1967             :           /* "Win a free Ethernet header in every packet" */
    1968           0 :           if (l2 == 0)
    1969           0 :             vec_validate_aligned (l2, 13, sizeof (u32x4));
    1970           0 :           match = l2;
    1971           0 :           if (vec_len (l3))
    1972             :             {
    1973           0 :               vec_append_aligned (match, l3, sizeof (u32x4));
    1974           0 :               vec_free (l3);
    1975             :             }
    1976           0 :           if (vec_len (l4))
    1977             :             {
    1978           0 :               vec_append_aligned (match, l4, sizeof (u32x4));
    1979           0 :               vec_free (l4);
    1980             :             }
    1981             :         }
    1982             : 
    1983             :       /* Make sure the vector is big enough even if key is all 0's */
    1984           0 :       vec_validate_aligned
    1985             :         (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
    1986             :          sizeof (u32x4));
    1987             : 
    1988             :       /* Set size, include skipped vectors */
    1989           0 :       vec_set_len (match, (match_n_vectors + skip_n_vectors) * sizeof (u32x4));
    1990             : 
    1991           0 :       *matchp = match;
    1992             : 
    1993           0 :       return 1;
    1994             :     }
    1995             : 
    1996           0 :   return 0;
    1997             : }
    1998             : 
    1999             : #define foreach_vtr_op                                                        \
    2000             :   _ ("disable", L2_VTR_DISABLED)                                              \
    2001             :   _ ("push-1", L2_VTR_PUSH_1)                                                 \
    2002             :   _ ("push-2", L2_VTR_PUSH_2)                                                 \
    2003             :   _ ("pop-1", L2_VTR_POP_1)                                                   \
    2004             :   _ ("pop-2", L2_VTR_POP_2)                                                   \
    2005             :   _ ("translate-1-1", L2_VTR_TRANSLATE_1_1)                                   \
    2006             :   _ ("translate-1-2", L2_VTR_TRANSLATE_1_2)                                   \
    2007             :   _ ("translate-2-1", L2_VTR_TRANSLATE_2_1)                                   \
    2008             :   _ ("translate-2-2", L2_VTR_TRANSLATE_2_2)
    2009             : 
    2010             : static int
    2011           0 : api_get_first_msg_id (vat_main_t *vam)
    2012             : {
    2013             :   vl_api_get_first_msg_id_t *mp;
    2014           0 :   unformat_input_t *i = vam->input;
    2015             :   u8 *name;
    2016           0 :   u8 name_set = 0;
    2017             :   int ret;
    2018             : 
    2019           0 :   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    2020             :     {
    2021           0 :       if (unformat (i, "client %s", &name))
    2022           0 :         name_set = 1;
    2023             :       else
    2024           0 :         break;
    2025             :     }
    2026             : 
    2027           0 :   if (name_set == 0)
    2028             :     {
    2029           0 :       errmsg ("missing client name");
    2030           0 :       return -99;
    2031             :     }
    2032           0 :   vec_add1 (name, 0);
    2033             : 
    2034           0 :   if (vec_len (name) > 63)
    2035             :     {
    2036           0 :       errmsg ("client name too long");
    2037           0 :       return -99;
    2038             :     }
    2039             : 
    2040           0 :   M (GET_FIRST_MSG_ID, mp);
    2041           0 :   clib_memcpy (mp->name, name, vec_len (name));
    2042           0 :   S (mp);
    2043           0 :   W (ret);
    2044           0 :   return ret;
    2045             : }
    2046             : 
    2047             : #define foreach_pbb_vtr_op      \
    2048             : _("disable",  L2_VTR_DISABLED)  \
    2049             : _("pop",  L2_VTR_POP_2)         \
    2050             : _("push",  L2_VTR_PUSH_2)
    2051             : 
    2052             : static int
    2053           0 : api_sock_init_shm (vat_main_t * vam)
    2054             : {
    2055             : #if VPP_API_TEST_BUILTIN == 0
    2056             :   unformat_input_t *i = vam->input;
    2057             :   vl_api_shm_elem_config_t *config = 0;
    2058             :   u64 size = 64 << 20;
    2059             :   int rv;
    2060             : 
    2061             :   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
    2062             :     {
    2063             :       if (unformat (i, "size %U", unformat_memory_size, &size))
    2064             :         ;
    2065             :       else
    2066             :         break;
    2067             :     }
    2068             : 
    2069             :   /*
    2070             :    * Canned custom ring allocator config.
    2071             :    * Should probably parse all of this
    2072             :    */
    2073             :   vec_validate (config, 6);
    2074             :   config[0].type = VL_API_VLIB_RING;
    2075             :   config[0].size = 256;
    2076             :   config[0].count = 32;
    2077             : 
    2078             :   config[1].type = VL_API_VLIB_RING;
    2079             :   config[1].size = 1024;
    2080             :   config[1].count = 16;
    2081             : 
    2082             :   config[2].type = VL_API_VLIB_RING;
    2083             :   config[2].size = 4096;
    2084             :   config[2].count = 2;
    2085             : 
    2086             :   config[3].type = VL_API_CLIENT_RING;
    2087             :   config[3].size = 256;
    2088             :   config[3].count = 32;
    2089             : 
    2090             :   config[4].type = VL_API_CLIENT_RING;
    2091             :   config[4].size = 1024;
    2092             :   config[4].count = 16;
    2093             : 
    2094             :   config[5].type = VL_API_CLIENT_RING;
    2095             :   config[5].size = 4096;
    2096             :   config[5].count = 2;
    2097             : 
    2098             :   config[6].type = VL_API_QUEUE;
    2099             :   config[6].count = 128;
    2100             :   config[6].size = sizeof (uword);
    2101             : 
    2102             :   rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
    2103             :   if (!rv)
    2104             :     vam->client_index_invalid = 1;
    2105             :   return rv;
    2106             : #else
    2107           0 :   return -99;
    2108             : #endif
    2109             : }
    2110             : 
    2111             : static int
    2112           0 : q_or_quit (vat_main_t * vam)
    2113             : {
    2114             : #if VPP_API_TEST_BUILTIN == 0
    2115             :   longjmp (vam->jump_buf, 1);
    2116             : #endif
    2117           0 :   return 0;                     /* not so much */
    2118             : }
    2119             : 
    2120             : static int
    2121           0 : q (vat_main_t * vam)
    2122             : {
    2123           0 :   return q_or_quit (vam);
    2124             : }
    2125             : 
    2126             : static int
    2127           0 : quit (vat_main_t * vam)
    2128             : {
    2129           0 :   return q_or_quit (vam);
    2130             : }
    2131             : 
    2132             : static int
    2133           0 : comment (vat_main_t * vam)
    2134             : {
    2135           0 :   return 0;
    2136             : }
    2137             : 
    2138             : static int
    2139           0 : elog_save (vat_main_t * vam)
    2140             : {
    2141             : #if VPP_API_TEST_BUILTIN == 0
    2142             :   elog_main_t *em = &vam->elog_main;
    2143             :   unformat_input_t *i = vam->input;
    2144             :   char *file, *chroot_file;
    2145             :   clib_error_t *error;
    2146             : 
    2147             :   if (!unformat (i, "%s", &file))
    2148             :     {
    2149             :       errmsg ("expected file name, got `%U'", format_unformat_error, i);
    2150             :       return 0;
    2151             :     }
    2152             : 
    2153             :   /* It's fairly hard to get "../oopsie" through unformat; just in case */
    2154             :   if (strstr (file, "..") || index (file, '/'))
    2155             :     {
    2156             :       errmsg ("illegal characters in filename '%s'", file);
    2157             :       return 0;
    2158             :     }
    2159             : 
    2160             :   chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
    2161             : 
    2162             :   vec_free (file);
    2163             : 
    2164             :   errmsg ("Saving %wd of %wd events to %s",
    2165             :           elog_n_events_in_buffer (em),
    2166             :           elog_buffer_capacity (em), chroot_file);
    2167             : 
    2168             :   error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
    2169             :   vec_free (chroot_file);
    2170             : 
    2171             :   if (error)
    2172             :     clib_error_report (error);
    2173             : #else
    2174           0 :   errmsg ("Use the vpp event loger...");
    2175             : #endif
    2176             : 
    2177           0 :   return 0;
    2178             : }
    2179             : 
    2180             : static int
    2181           0 : elog_setup (vat_main_t * vam)
    2182             : {
    2183             : #if VPP_API_TEST_BUILTIN == 0
    2184             :   elog_main_t *em = &vam->elog_main;
    2185             :   unformat_input_t *i = vam->input;
    2186             :   u32 nevents = 128 << 10;
    2187             : 
    2188             :   (void) unformat (i, "nevents %d", &nevents);
    2189             : 
    2190             :   elog_init (em, nevents);
    2191             :   vl_api_set_elog_main (em);
    2192             :   vl_api_set_elog_trace_api_messages (1);
    2193             :   errmsg ("Event logger initialized with %u events", nevents);
    2194             : #else
    2195           0 :   errmsg ("Use the vpp event loger...");
    2196             : #endif
    2197           0 :   return 0;
    2198             : }
    2199             : 
    2200             : static int
    2201           0 : elog_enable (vat_main_t * vam)
    2202             : {
    2203             : #if VPP_API_TEST_BUILTIN == 0
    2204             :   elog_main_t *em = &vam->elog_main;
    2205             : 
    2206             :   elog_enable_disable (em, 1 /* enable */ );
    2207             :   vl_api_set_elog_trace_api_messages (1);
    2208             :   errmsg ("Event logger enabled...");
    2209             : #else
    2210           0 :   errmsg ("Use the vpp event loger...");
    2211             : #endif
    2212           0 :   return 0;
    2213             : }
    2214             : 
    2215             : static int
    2216           0 : elog_disable (vat_main_t * vam)
    2217             : {
    2218             : #if VPP_API_TEST_BUILTIN == 0
    2219             :   elog_main_t *em = &vam->elog_main;
    2220             : 
    2221             :   elog_enable_disable (em, 0 /* enable */ );
    2222             :   vl_api_set_elog_trace_api_messages (1);
    2223             :   errmsg ("Event logger disabled...");
    2224             : #else
    2225           0 :   errmsg ("Use the vpp event loger...");
    2226             : #endif
    2227           0 :   return 0;
    2228             : }
    2229             : 
    2230             : static int
    2231           0 : statseg (vat_main_t * vam)
    2232             : {
    2233           0 :   ssvm_private_t *ssvmp = &vam->stat_segment;
    2234           0 :   ssvm_shared_header_t *shared_header = ssvmp->sh;
    2235             :   vlib_counter_t **counters;
    2236             :   u64 thread0_index1_packets;
    2237             :   u64 thread0_index1_bytes;
    2238             :   f64 vector_rate, input_rate;
    2239             :   uword *p;
    2240             : 
    2241             :   uword *counter_vector_by_name;
    2242           0 :   if (vam->stat_segment_lockp == 0)
    2243             :     {
    2244           0 :       errmsg ("Stat segment not mapped...");
    2245           0 :       return -99;
    2246             :     }
    2247             : 
    2248             :   /* look up "/if/rx for sw_if_index 1 as a test */
    2249             : 
    2250           0 :   clib_spinlock_lock (vam->stat_segment_lockp);
    2251             : 
    2252           0 :   counter_vector_by_name = (uword *) shared_header->opaque[1];
    2253             : 
    2254           0 :   p = hash_get_mem (counter_vector_by_name, "/if/rx");
    2255           0 :   if (p == 0)
    2256             :     {
    2257           0 :       clib_spinlock_unlock (vam->stat_segment_lockp);
    2258           0 :       errmsg ("/if/tx not found?");
    2259           0 :       return -99;
    2260             :     }
    2261             : 
    2262             :   /* Fish per-thread vector of combined counters from shared memory */
    2263           0 :   counters = (vlib_counter_t **) p[0];
    2264             : 
    2265           0 :   if (vec_len (counters[0]) < 2)
    2266             :     {
    2267           0 :       clib_spinlock_unlock (vam->stat_segment_lockp);
    2268           0 :       errmsg ("/if/tx vector length %d", vec_len (counters[0]));
    2269           0 :       return -99;
    2270             :     }
    2271             : 
    2272             :   /* Read thread 0 sw_if_index 1 counter */
    2273           0 :   thread0_index1_packets = counters[0][1].packets;
    2274           0 :   thread0_index1_bytes = counters[0][1].bytes;
    2275             : 
    2276           0 :   p = hash_get_mem (counter_vector_by_name, "vector_rate");
    2277           0 :   if (p == 0)
    2278             :     {
    2279           0 :       clib_spinlock_unlock (vam->stat_segment_lockp);
    2280           0 :       errmsg ("vector_rate not found?");
    2281           0 :       return -99;
    2282             :     }
    2283             : 
    2284           0 :   vector_rate = *(f64 *) (p[0]);
    2285           0 :   p = hash_get_mem (counter_vector_by_name, "input_rate");
    2286           0 :   if (p == 0)
    2287             :     {
    2288           0 :       clib_spinlock_unlock (vam->stat_segment_lockp);
    2289           0 :       errmsg ("input_rate not found?");
    2290           0 :       return -99;
    2291             :     }
    2292           0 :   input_rate = *(f64 *) (p[0]);
    2293             : 
    2294           0 :   clib_spinlock_unlock (vam->stat_segment_lockp);
    2295             : 
    2296           0 :   print (vam->ofp, "vector_rate %.2f input_rate %.2f",
    2297             :          vector_rate, input_rate);
    2298           0 :   print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
    2299             :          thread0_index1_packets, thread0_index1_bytes);
    2300             : 
    2301           0 :   return 0;
    2302             : }
    2303             : 
    2304             : static int
    2305           0 : cmd_cmp (void *a1, void *a2)
    2306             : {
    2307           0 :   u8 **c1 = a1;
    2308           0 :   u8 **c2 = a2;
    2309             : 
    2310           0 :   return strcmp ((char *) (c1[0]), (char *) (c2[0]));
    2311             : }
    2312             : 
    2313             : static int
    2314           0 : help (vat_main_t * vam)
    2315             : {
    2316           0 :   u8 **cmds = 0;
    2317           0 :   u8 *name = 0;
    2318             :   hash_pair_t *p;
    2319           0 :   unformat_input_t *i = vam->input;
    2320             :   int j;
    2321             : 
    2322           0 :   if (unformat (i, "%s", &name))
    2323             :     {
    2324             :       uword *hs;
    2325             : 
    2326           0 :       vec_add1 (name, 0);
    2327             : 
    2328           0 :       hs = hash_get_mem (vam->help_by_name, name);
    2329           0 :       if (hs)
    2330           0 :         print (vam->ofp, "usage: %s %s", name, hs[0]);
    2331             :       else
    2332           0 :         print (vam->ofp, "No such msg / command '%s'", name);
    2333           0 :       vec_free (name);
    2334           0 :       return 0;
    2335             :     }
    2336             : 
    2337           0 :   print (vam->ofp, "Help is available for the following:");
    2338             : 
    2339           0 :     hash_foreach_pair (p, vam->function_by_name,
    2340             :     ({
    2341             :       vec_add1 (cmds, (u8 *)(p->key));
    2342             :     }));
    2343             : 
    2344           0 :   vec_sort_with_function (cmds, cmd_cmp);
    2345             : 
    2346           0 :   for (j = 0; j < vec_len (cmds); j++)
    2347           0 :     print (vam->ofp, "%s", cmds[j]);
    2348             : 
    2349           0 :   vec_free (cmds);
    2350           0 :   return 0;
    2351             : }
    2352             : 
    2353             : static int
    2354           0 : set (vat_main_t * vam)
    2355             : {
    2356           0 :   u8 *name = 0, *value = 0;
    2357           0 :   unformat_input_t *i = vam->input;
    2358             : 
    2359           0 :   if (unformat (i, "%s", &name))
    2360             :     {
    2361             :       /* The input buffer is a vector, not a string. */
    2362           0 :       value = vec_dup (i->buffer);
    2363           0 :       vec_delete (value, i->index, 0);
    2364             :       /* Almost certainly has a trailing newline */
    2365           0 :       if (value[vec_len (value) - 1] == '\n')
    2366           0 :         value[vec_len (value) - 1] = 0;
    2367             :       /* Make sure it's a proper string, one way or the other */
    2368           0 :       vec_add1 (value, 0);
    2369           0 :       (void) clib_macro_set_value (&vam->macro_main,
    2370             :                                    (char *) name, (char *) value);
    2371             :     }
    2372             :   else
    2373           0 :     errmsg ("usage: set <name> <value>");
    2374             : 
    2375           0 :   vec_free (name);
    2376           0 :   vec_free (value);
    2377           0 :   return 0;
    2378             : }
    2379             : 
    2380             : static int
    2381           0 : unset (vat_main_t * vam)
    2382             : {
    2383           0 :   u8 *name = 0;
    2384             : 
    2385           0 :   if (unformat (vam->input, "%s", &name))
    2386           0 :     if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
    2387           0 :       errmsg ("unset: %s wasn't set", name);
    2388           0 :   vec_free (name);
    2389           0 :   return 0;
    2390             : }
    2391             : 
    2392             : typedef struct
    2393             : {
    2394             :   u8 *name;
    2395             :   u8 *value;
    2396             : } macro_sort_t;
    2397             : 
    2398             : 
    2399             : static int
    2400           0 : macro_sort_cmp (void *a1, void *a2)
    2401             : {
    2402           0 :   macro_sort_t *s1 = a1;
    2403           0 :   macro_sort_t *s2 = a2;
    2404             : 
    2405           0 :   return strcmp ((char *) (s1->name), (char *) (s2->name));
    2406             : }
    2407             : 
    2408             : static int
    2409           0 : dump_macro_table (vat_main_t * vam)
    2410             : {
    2411           0 :   macro_sort_t *sort_me = 0, *sm;
    2412             :   int i;
    2413             :   hash_pair_t *p;
    2414             : 
    2415           0 :   hash_foreach_pair (p, vam->macro_main.the_value_table_hash, ({
    2416             :                        vec_add2 (sort_me, sm, 1);
    2417             :                        sm->name = (u8 *) (p->key);
    2418             :                        sm->value = (u8 *) (p->value[0]);
    2419             :                      }));
    2420             : 
    2421           0 :   vec_sort_with_function (sort_me, macro_sort_cmp);
    2422             : 
    2423           0 :   if (vec_len (sort_me))
    2424           0 :     print (vam->ofp, "%-15s%s", "Name", "Value");
    2425             :   else
    2426           0 :     print (vam->ofp, "The macro table is empty...");
    2427             : 
    2428           0 :   for (i = 0; i < vec_len (sort_me); i++)
    2429           0 :     print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
    2430           0 :   return 0;
    2431             : }
    2432             : 
    2433             : static int
    2434           0 : value_sort_cmp (void *a1, void *a2)
    2435             : {
    2436           0 :   name_sort_t *n1 = a1;
    2437           0 :   name_sort_t *n2 = a2;
    2438             : 
    2439           0 :   if (n1->value < n2->value)
    2440           0 :     return -1;
    2441           0 :   if (n1->value > n2->value)
    2442           0 :     return 1;
    2443           0 :   return 0;
    2444             : }
    2445             : 
    2446             : 
    2447             : static int
    2448           0 : dump_msg_api_table (vat_main_t * vam)
    2449             : {
    2450           0 :   api_main_t *am = vlibapi_get_main ();
    2451           0 :   name_sort_t *nses = 0, *ns;
    2452             :   hash_pair_t *hp;
    2453             :   int i;
    2454             : 
    2455           0 :   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
    2456             :   ({
    2457             :     vec_add2 (nses, ns, 1);
    2458             :     ns->name = (u8 *)(hp->key);
    2459             :     ns->value = (u32) hp->value[0];
    2460             :   }));
    2461             : 
    2462           0 :   vec_sort_with_function (nses, value_sort_cmp);
    2463             : 
    2464           0 :   for (i = 0; i < vec_len (nses); i++)
    2465           0 :     print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
    2466           0 :   vec_free (nses);
    2467           0 :   return 0;
    2468             : }
    2469             : 
    2470             : static int
    2471           0 : get_msg_id (vat_main_t * vam)
    2472             : {
    2473             :   u8 *name_and_crc;
    2474             :   u32 message_index;
    2475             : 
    2476           0 :   if (unformat (vam->input, "%s", &name_and_crc))
    2477             :     {
    2478           0 :       message_index = vl_msg_api_get_msg_index (name_and_crc);
    2479           0 :       if (message_index == ~0)
    2480             :         {
    2481           0 :           print (vam->ofp, " '%s' not found", name_and_crc);
    2482           0 :           return 0;
    2483             :         }
    2484           0 :       print (vam->ofp, " '%s' has message index %d",
    2485             :              name_and_crc, message_index);
    2486           0 :       return 0;
    2487             :     }
    2488           0 :   errmsg ("name_and_crc required...");
    2489           0 :   return 0;
    2490             : }
    2491             : 
    2492             : static int
    2493           0 : search_node_table (vat_main_t * vam)
    2494             : {
    2495           0 :   unformat_input_t *line_input = vam->input;
    2496             :   u8 *node_to_find;
    2497             :   int j;
    2498             :   vlib_node_t *node, *next_node;
    2499             :   uword *p;
    2500             : 
    2501           0 :   if (vam->graph_node_index_by_name == 0)
    2502             :     {
    2503           0 :       print (vam->ofp, "Node table empty, issue get_node_graph...");
    2504           0 :       return 0;
    2505             :     }
    2506             : 
    2507           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
    2508             :     {
    2509           0 :       if (unformat (line_input, "%s", &node_to_find))
    2510             :         {
    2511           0 :           vec_add1 (node_to_find, 0);
    2512           0 :           p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
    2513           0 :           if (p == 0)
    2514             :             {
    2515           0 :               print (vam->ofp, "%s not found...", node_to_find);
    2516           0 :               goto out;
    2517             :             }
    2518           0 :           node = vam->graph_nodes[0][p[0]];
    2519           0 :           print (vam->ofp, "[%d] %s", p[0], node->name);
    2520           0 :           for (j = 0; j < vec_len (node->next_nodes); j++)
    2521             :             {
    2522           0 :               if (node->next_nodes[j] != ~0)
    2523             :                 {
    2524           0 :                   next_node = vam->graph_nodes[0][node->next_nodes[j]];
    2525           0 :                   print (vam->ofp, "  [%d] %s", j, next_node->name);
    2526             :                 }
    2527             :             }
    2528             :         }
    2529             : 
    2530             :       else
    2531             :         {
    2532           0 :           clib_warning ("parse error '%U'", format_unformat_error,
    2533             :                         line_input);
    2534           0 :           return -99;
    2535             :         }
    2536             : 
    2537           0 :     out:
    2538           0 :       vec_free (node_to_find);
    2539             : 
    2540             :     }
    2541             : 
    2542           0 :   return 0;
    2543             : }
    2544             : 
    2545             : 
    2546             : static int
    2547           0 : script (vat_main_t * vam)
    2548             : {
    2549             : #if (VPP_API_TEST_BUILTIN==0)
    2550             :   u8 *s = 0;
    2551             :   char *save_current_file;
    2552             :   unformat_input_t save_input;
    2553             :   jmp_buf save_jump_buf;
    2554             :   u32 save_line_number;
    2555             : 
    2556             :   FILE *new_fp, *save_ifp;
    2557             : 
    2558             :   if (unformat (vam->input, "%s", &s))
    2559             :     {
    2560             :       new_fp = fopen ((char *) s, "r");
    2561             :       if (new_fp == 0)
    2562             :         {
    2563             :           errmsg ("Couldn't open script file %s", s);
    2564             :           vec_free (s);
    2565             :           return -99;
    2566             :         }
    2567             :     }
    2568             :   else
    2569             :     {
    2570             :       errmsg ("Missing script name");
    2571             :       return -99;
    2572             :     }
    2573             : 
    2574             :   clib_memcpy (&save_input, &vam->input, sizeof (save_input));
    2575             :   clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
    2576             :   save_ifp = vam->ifp;
    2577             :   save_line_number = vam->input_line_number;
    2578             :   save_current_file = (char *) vam->current_file;
    2579             : 
    2580             :   vam->input_line_number = 0;
    2581             :   vam->ifp = new_fp;
    2582             :   vam->current_file = s;
    2583             :   do_one_file (vam);
    2584             : 
    2585             :   clib_memcpy (&vam->input, &save_input, sizeof (save_input));
    2586             :   clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
    2587             :   vam->ifp = save_ifp;
    2588             :   vam->input_line_number = save_line_number;
    2589             :   vam->current_file = (u8 *) save_current_file;
    2590             :   vec_free (s);
    2591             : 
    2592             :   return 0;
    2593             : #else
    2594           0 :   clib_warning ("use the exec command...");
    2595           0 :   return -99;
    2596             : #endif
    2597             : }
    2598             : 
    2599             : static int
    2600           0 : echo (vat_main_t * vam)
    2601             : {
    2602           0 :   print (vam->ofp, "%v", vam->input->buffer);
    2603           0 :   return 0;
    2604             : }
    2605             : 
    2606             : int exec (vat_main_t *vam) __attribute__ ((weak));
    2607             : int
    2608           0 : exec (vat_main_t *vam)
    2609             : {
    2610           0 :   return -1;
    2611             : }
    2612             : 
    2613             : static int
    2614           0 : name_sort_cmp (void *a1, void *a2)
    2615             : {
    2616           0 :   name_sort_t *n1 = a1;
    2617           0 :   name_sort_t *n2 = a2;
    2618             : 
    2619           0 :   return strcmp ((char *) n1->name, (char *) n2->name);
    2620             : }
    2621             : 
    2622             : static int
    2623           0 : dump_interface_table (vat_main_t *vam)
    2624             : {
    2625             :   hash_pair_t *p;
    2626           0 :   name_sort_t *nses = 0, *ns;
    2627             : 
    2628           0 :   if (vam->json_output)
    2629             :     {
    2630           0 :       clib_warning (
    2631             :         "JSON output supported only for VPE API calls and dump_stats_table");
    2632           0 :       return -99;
    2633             :     }
    2634             : 
    2635           0 :   hash_foreach_pair (p, vam->sw_if_index_by_interface_name, ({
    2636             :                        vec_add2 (nses, ns, 1);
    2637             :                        ns->name = (u8 *) (p->key);
    2638             :                        ns->value = (u32) p->value[0];
    2639             :                      }));
    2640             : 
    2641           0 :   vec_sort_with_function (nses, name_sort_cmp);
    2642             : 
    2643           0 :   print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
    2644           0 :   vec_foreach (ns, nses)
    2645             :     {
    2646           0 :       print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
    2647             :     }
    2648           0 :   vec_free (nses);
    2649           0 :   return 0;
    2650             : }
    2651             : 
    2652             : static int
    2653           0 : dump_sub_interface_table (vat_main_t *vam)
    2654             : {
    2655           0 :   const sw_interface_subif_t *sub = NULL;
    2656             : 
    2657           0 :   if (vam->json_output)
    2658             :     {
    2659           0 :       clib_warning (
    2660             :         "JSON output supported only for VPE API calls and dump_stats_table");
    2661           0 :       return -99;
    2662             :     }
    2663             : 
    2664           0 :   print (vam->ofp, "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
    2665             :          "Interface", "sw_if_index", "sub id", "dot1ad", "tags", "outer id",
    2666             :          "inner id", "exact", "default", "outer any", "inner any");
    2667             : 
    2668           0 :   vec_foreach (sub, vam->sw_if_subif_table)
    2669             :     {
    2670           0 :       print (vam->ofp, "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
    2671             :              sub->interface_name, sub->sw_if_index, sub->sub_id,
    2672           0 :              sub->sub_dot1ad ? "dot1ad" : "dot1q", sub->sub_number_of_tags,
    2673           0 :              sub->sub_outer_vlan_id, sub->sub_inner_vlan_id,
    2674           0 :              sub->sub_exact_match, sub->sub_default,
    2675           0 :              sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
    2676           0 :       if (sub->vtr_op != L2_VTR_DISABLED)
    2677             :         {
    2678           0 :           print (vam->ofp,
    2679             :                  "  vlan-tag-rewrite - op: %-14s [ dot1q: %d "
    2680             :                  "tag1: %d tag2: %d ]",
    2681             :                  str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q, sub->vtr_tag1,
    2682             :                  sub->vtr_tag2);
    2683             :         }
    2684             :     }
    2685             : 
    2686           0 :   return 0;
    2687             : }
    2688             : 
    2689             : /* List of API message constructors, CLI names map to api_xxx */
    2690             : #define foreach_vpe_api_msg                                             \
    2691             : _(get_first_msg_id, "client <name>")                                    \
    2692             : _(sock_init_shm, "size <nnn>")                                          \
    2693             : /* List of command functions, CLI names map directly to functions */
    2694             : #define foreach_cli_function                                                  \
    2695             :   _ (comment, "usage: comment <ignore-rest-of-line>")                         \
    2696             :   _ (dump_interface_table, "usage: dump_interface_table")                     \
    2697             :   _ (dump_sub_interface_table, "usage: dump_sub_interface_table")             \
    2698             :   _ (dump_macro_table, "usage: dump_macro_table ")                            \
    2699             :   _ (dump_msg_api_table, "usage: dump_msg_api_table")                         \
    2700             :   _ (elog_setup, "usage: elog_setup [nevents, default 128K]")                 \
    2701             :   _ (elog_disable, "usage: elog_disable")                                     \
    2702             :   _ (elog_enable, "usage: elog_enable")                                       \
    2703             :   _ (elog_save, "usage: elog_save <filename>")                                \
    2704             :   _ (get_msg_id, "usage: get_msg_id name_and_crc")                            \
    2705             :   _ (echo, "usage: echo <message>")                                           \
    2706             :   _ (help, "usage: help")                                                     \
    2707             :   _ (q, "usage: quit")                                                        \
    2708             :   _ (quit, "usage: quit")                                                     \
    2709             :   _ (search_node_table, "usage: search_node_table <name>...")                 \
    2710             :   _ (set, "usage: set <variable-name> <value>")                               \
    2711             :   _ (script, "usage: script <file-name>")                                     \
    2712             :   _ (statseg, "usage: statseg")                                               \
    2713             :   _ (unset, "usage: unset <variable-name>")
    2714             : 
    2715             : #define _(N,n)                                  \
    2716             :     static void vl_api_##n##_t_handler_uni      \
    2717             :     (vl_api_##n##_t * mp)                       \
    2718             :     {                                           \
    2719             :         vat_main_t * vam = &vat_main;           \
    2720             :         if (vam->json_output) {                 \
    2721             :             vl_api_##n##_t_handler_json(mp);    \
    2722             :         } else {                                \
    2723             :             vl_api_##n##_t_handler(mp);         \
    2724             :         }                                       \
    2725             :     }
    2726           2 : foreach_vpe_api_reply_msg;
    2727             : #if VPP_API_TEST_BUILTIN == 0
    2728             : foreach_standalone_reply_msg;
    2729             : #endif
    2730             : #undef _
    2731             : 
    2732             : void
    2733         575 : vat_api_hookup (vat_main_t * vam)
    2734             : {
    2735             : #define _(N, n)                                                               \
    2736             :   vl_msg_api_config (&(vl_msg_api_msg_config_t){                              \
    2737             :     .id = VL_API_##N + 1,                                                     \
    2738             :     .name = #n,                                                               \
    2739             :     .handler = vl_api_##n##_t_handler_uni,                                    \
    2740             :     .endian = vl_api_##n##_t_endian,                                          \
    2741             :     .format_fn = vl_api_##n##_t_format,                                       \
    2742             :     .size = sizeof (vl_api_##n##_t),                                          \
    2743             :     .traced = 1,                                                              \
    2744             :     .tojson = vl_api_##n##_t_tojson,                                          \
    2745             :     .fromjson = vl_api_##n##_t_fromjson,                                      \
    2746             :     .calc_size = vl_api_##n##_t_calc_size,                                    \
    2747             :   });
    2748         575 :   foreach_vpe_api_reply_msg;
    2749             : #if VPP_API_TEST_BUILTIN == 0
    2750             :   foreach_standalone_reply_msg;
    2751             : #endif
    2752             : #undef _
    2753             : 
    2754             : #if (VPP_API_TEST_BUILTIN==0)
    2755             :   vl_msg_api_set_first_available_msg_id (VL_MSG_MEMCLNT_LAST + 1);
    2756             : 
    2757             :   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
    2758             : 
    2759             :   vam->function_by_name = hash_create_string (0, sizeof (uword));
    2760             : 
    2761             :   vam->help_by_name = hash_create_string (0, sizeof (uword));
    2762             : #endif
    2763             : 
    2764             :   /* API messages we can send */
    2765             : #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
    2766        1725 :   foreach_vpe_api_msg;
    2767             : #undef _
    2768             : 
    2769             :   /* Help strings */
    2770             : #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
    2771        1725 :   foreach_vpe_api_msg;
    2772             : #undef _
    2773             : 
    2774             :   /* CLI functions */
    2775             : #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
    2776       11500 :   foreach_cli_function;
    2777             : #undef _
    2778             : 
    2779             :   /* Help strings */
    2780             : #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
    2781       11500 :   foreach_cli_function;
    2782             : #undef _
    2783         575 : }
    2784             : 
    2785             : #if VPP_API_TEST_BUILTIN
    2786             : static clib_error_t *
    2787         575 : vat_api_hookup_shim (vlib_main_t * vm)
    2788             : {
    2789         575 :   vat_api_hookup (&vat_main);
    2790         575 :   return 0;
    2791             : }
    2792             : 
    2793       23039 : VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
    2794             : #endif
    2795             : 
    2796             : /*
    2797             :  * fd.io coding-style-patch-verification: ON
    2798             :  *
    2799             :  * Local Variables:
    2800             :  * eval: (c-set-style "gnu")
    2801             :  * End:
    2802             :  */

Generated by: LCOV version 1.14