LCOV - code coverage report
Current view: top level - vlibapi - node_serialize.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 0 98 0.0 %
Date: 2023-07-05 22:20:52 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : #include <vlib/vlib.h>
      16             : 
      17             : #include <vppinfra/serialize.h>
      18             : 
      19             : /* serialized representation of state strings */
      20             : 
      21             : #define foreach_state_string_code               \
      22             : _(STATE_DONE, "done")                           \
      23             : _(STATE_DISABLED, "disabled")                   \
      24             : _(STATE_TIME_WAIT, "time wait")                 \
      25             : _(STATE_EVENT_WAIT, "event wait")               \
      26             : _(STATE_ANY_WAIT, "any wait")                   \
      27             : _(STATE_POLLING, "polling")                     \
      28             : _(STATE_INTERRUPT_WAIT, "interrupt wait")       \
      29             : _(STATE_INTERNAL, "internal")
      30             : 
      31             : typedef enum
      32             : {
      33             : #define _(a,b) a,
      34             :   foreach_state_string_code
      35             : #undef _
      36             : } state_string_enum_t;
      37             : 
      38             : static char *state_strings[] = {
      39             : #define _(a,b) b,
      40             :   foreach_state_string_code
      41             : #undef _
      42             : };
      43             : 
      44             : /*
      45             :  * Serialize a vlib_node_main_t. Appends the result to vector.
      46             :  * Pass 0 to create a new vector, use vec_reset_length(vector)
      47             :  * to recycle a vector / avoid memory allocation, etc.
      48             :  * Switch heaps before/after to serialize into API client shared memory.
      49             :  */
      50             : u8 *
      51           0 : vlib_node_serialize (vlib_main_t * vm, vlib_node_t *** node_dups, u8 * vector,
      52             :                      int include_nexts, int include_stats)
      53             : {
      54           0 :   serialize_main_t _sm, *sm = &_sm;
      55             :   vlib_node_t *n;
      56             :   vlib_node_t **nodes;
      57             :   u8 *namep;
      58             :   u32 name_bytes;
      59             :   uword i, j, k;
      60             :   u64 l, v, c, d;
      61             :   state_string_enum_t state_code;
      62             : 
      63           0 :   serialize_open_vector (sm, vector);
      64           0 :   serialize_likely_small_unsigned_integer (sm, vec_len (node_dups));
      65             : 
      66           0 :   for (j = 0; j < vec_len (node_dups); j++)
      67             :     {
      68           0 :       nodes = node_dups[j];
      69             : 
      70           0 :       serialize_likely_small_unsigned_integer (sm, vec_len (nodes));
      71             : 
      72           0 :       for (i = 0; i < vec_len (nodes); i++)
      73             :         {
      74           0 :           n = nodes[i];
      75             : 
      76           0 :           l = n->stats_total.clocks - n->stats_last_clear.clocks;
      77           0 :           v = n->stats_total.vectors - n->stats_last_clear.vectors;
      78           0 :           c = n->stats_total.calls - n->stats_last_clear.calls;
      79           0 :           d = n->stats_total.suspends - n->stats_last_clear.suspends;
      80             : 
      81           0 :           state_code = STATE_INTERNAL;
      82             : 
      83           0 :           if (n->type == VLIB_NODE_TYPE_PROCESS)
      84             :             {
      85           0 :               vlib_process_t *p = vlib_get_process_from_node (vm, n);
      86             : 
      87           0 :               switch (p->flags
      88           0 :                       & (VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK
      89             :                          | VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT))
      90             :                 {
      91           0 :                 default:
      92           0 :                   if (!(p->flags & VLIB_PROCESS_IS_RUNNING))
      93           0 :                     state_code = STATE_DONE;
      94           0 :                   break;
      95             : 
      96           0 :                 case VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK:
      97           0 :                   state_code = STATE_TIME_WAIT;
      98           0 :                   break;
      99             : 
     100           0 :                 case VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT:
     101           0 :                   state_code = STATE_EVENT_WAIT;
     102           0 :                   break;
     103             : 
     104           0 :                 case (VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_EVENT | VLIB_PROCESS_IS_SUSPENDED_WAITING_FOR_CLOCK):
     105           0 :                   state_code =
     106             :                     STATE_ANY_WAIT;
     107           0 :                   break;
     108             :                 }
     109             :             }
     110           0 :           else if (n->type != VLIB_NODE_TYPE_INTERNAL)
     111             :             {
     112           0 :               state_code = STATE_POLLING;
     113           0 :               if (n->state == VLIB_NODE_STATE_DISABLED)
     114           0 :                 state_code = STATE_DISABLED;
     115           0 :               else if (n->state == VLIB_NODE_STATE_INTERRUPT)
     116           0 :                 state_code = STATE_INTERRUPT_WAIT;
     117             :             }
     118             : 
     119             :           /* See unserialize_cstring */
     120           0 :           name_bytes = vec_len (n->name);
     121           0 :           serialize_likely_small_unsigned_integer (sm, name_bytes);
     122           0 :           namep = serialize_get (sm, name_bytes);
     123           0 :           memcpy (namep, n->name, name_bytes);
     124             : 
     125           0 :           serialize_likely_small_unsigned_integer (sm, (u64) state_code);
     126           0 :           serialize_likely_small_unsigned_integer (sm, n->type);
     127           0 :           serialize_likely_small_unsigned_integer (sm, n->flags);
     128             : 
     129           0 :           if (include_nexts)
     130             :             {
     131           0 :               serialize_likely_small_unsigned_integer
     132           0 :                 (sm, vec_len (n->next_nodes));
     133           0 :               for (k = 0; k < vec_len (n->next_nodes); k++)
     134           0 :                 serialize_likely_small_unsigned_integer (sm,
     135           0 :                                                          n->next_nodes[k]);
     136             :             }
     137             :           else
     138           0 :             serialize_likely_small_unsigned_integer (sm, 0);
     139             : 
     140           0 :           if (include_stats)
     141             :             {
     142             :               /* stats present */
     143           0 :               serialize_likely_small_unsigned_integer (sm, 1);
     144             :               /* total clocks */
     145           0 :               serialize_integer (sm, l, 8);
     146             :               /* Total calls */
     147           0 :               serialize_integer (sm, c, 8);
     148             :               /* Total vectors */
     149           0 :               serialize_integer (sm, v, 8);
     150             :               /* Total suspends */
     151           0 :               serialize_integer (sm, d, 8);
     152             :             }
     153             :           else                  /* no stats */
     154           0 :             serialize_likely_small_unsigned_integer (sm, 0);
     155             :         }
     156             :     }
     157           0 :   return (serialize_close_vector (sm));
     158             : }
     159             : 
     160             : vlib_node_t ***
     161           0 : vlib_node_unserialize (u8 * vector)
     162             : {
     163           0 :   serialize_main_t _sm, *sm = &_sm;
     164             :   u32 nnodes, nnexts;
     165             :   u32 nstat_vms;
     166             :   vlib_node_t *node;
     167             :   vlib_node_t **nodes;
     168           0 :   vlib_node_t ***nodes_by_thread = 0;
     169             :   int i, j, k;
     170             :   u64 l, v, c, d;
     171             :   state_string_enum_t state_code;
     172             :   int stats_present;
     173             : 
     174           0 :   serialize_open_vector (sm, vector);
     175             : 
     176           0 :   nstat_vms = unserialize_likely_small_unsigned_integer (sm);
     177             : 
     178           0 :   vec_validate (nodes_by_thread, nstat_vms - 1);
     179           0 :   vec_set_len (nodes_by_thread, 0);
     180             : 
     181           0 :   for (i = 0; i < nstat_vms; i++)
     182             :     {
     183           0 :       nnodes = unserialize_likely_small_unsigned_integer (sm);
     184             : 
     185           0 :       nodes = 0;
     186           0 :       vec_validate (nodes, nnodes - 1);
     187           0 :       vec_add1 (nodes_by_thread, nodes);
     188             : 
     189           0 :       for (j = 0; j < nnodes; j++)
     190             :         {
     191           0 :           node = 0;
     192           0 :           vec_validate (node, 0);
     193           0 :           nodes[j] = node;
     194             : 
     195           0 :           unserialize_cstring (sm, (char **) &(node->name));
     196           0 :           state_code = unserialize_likely_small_unsigned_integer (sm);
     197           0 :           node->state_string = (u8 *) state_strings[state_code];
     198             : 
     199           0 :           node->type = unserialize_likely_small_unsigned_integer (sm);
     200           0 :           node->flags = unserialize_likely_small_unsigned_integer (sm);
     201           0 :           nnexts = unserialize_likely_small_unsigned_integer (sm);
     202           0 :           if (nnexts > 0)
     203           0 :             vec_validate (node->next_nodes, nnexts - 1);
     204           0 :           for (k = 0; k < nnexts; k++)
     205           0 :             node->next_nodes[k] =
     206           0 :               unserialize_likely_small_unsigned_integer (sm);
     207             : 
     208           0 :           stats_present = unserialize_likely_small_unsigned_integer (sm);
     209             : 
     210           0 :           if (stats_present)
     211             :             {
     212             :               /* total clocks */
     213           0 :               unserialize_integer (sm, &l, 8);
     214           0 :               node->stats_total.clocks = l;
     215           0 :               node->stats_last_clear.clocks = 0;
     216             : 
     217             :               /* Total calls */
     218           0 :               unserialize_integer (sm, &c, 8);
     219           0 :               node->stats_total.calls = c;
     220             : 
     221             :               /* Total vectors */
     222           0 :               unserialize_integer (sm, &v, 8);
     223           0 :               node->stats_total.vectors = v;
     224             : 
     225             :               /* Total suspends */
     226           0 :               unserialize_integer (sm, &d, 8);
     227           0 :               node->stats_total.suspends = d;
     228             :             }
     229             :         }
     230             :     }
     231           0 :   return nodes_by_thread;
     232             : }
     233             : 
     234             : #if TEST_CODE
     235             : 
     236             : static clib_error_t *
     237             : test_node_serialize_command_fn (vlib_main_t * vm,
     238             :                                 unformat_input_t * input,
     239             :                                 vlib_cli_command_t * cmd)
     240             : {
     241             :   vlib_node_main_t *nm = &vm->node_main;
     242             :   u8 *vector = 0;
     243             :   vlib_node_t ***nodes_by_thread;
     244             :   vlib_node_t **nodes;
     245             :   vlib_node_t *node;
     246             :   vlib_node_t *next_node;
     247             :   int i, j, k;
     248             :   u32 max_threads = (u32) ~ 0;
     249             :   int include_nexts = 0;
     250             :   int include_stats = 0;
     251             : 
     252             :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     253             :     {
     254             :       if (unformat (input, "max-threads %d", &max_threads))
     255             :         ;
     256             :       else if (unformat (input, "stats"))
     257             :         include_stats = 1;
     258             :       else if (unformat (input, "nexts"))
     259             :         include_nexts = 1;
     260             :       else
     261             :         break;
     262             :     }
     263             : 
     264             :   /*
     265             :    * Keep the number of memcpy ops to a minimum (e.g. 1).
     266             :    * The current size of the serialized vector is
     267             :    * slightly under 4K.
     268             :    */
     269             :   vec_validate (vector, 16383);
     270             :   vec_reset_length (vector);
     271             : 
     272             :   vector = vlib_node_serialize (nm, vector, max_threads,
     273             :                                 include_nexts, include_stats);
     274             : 
     275             :   vlib_cli_output (vm, "result vector %d bytes", vec_len (vector));
     276             : 
     277             :   nodes_by_thread = vlib_node_unserialize (vector);
     278             : 
     279             :   vec_free (vector);
     280             : 
     281             :   for (i = 0; i < vec_len (nodes_by_thread); i++)
     282             :     {
     283             :       nodes = nodes_by_thread[i];
     284             : 
     285             :       vlib_cli_output (vm, "thread %d", i);
     286             : 
     287             :       for (j = 0; j < vec_len (nodes); j++)
     288             :         {
     289             :           node = nodes[j];
     290             : 
     291             :           vlib_cli_output (vm, "[%d] %s state %s", j, node->name,
     292             :                            node->state_string);
     293             : 
     294             :           vlib_cli_output
     295             :             (vm, "    clocks %lld calls %lld suspends"
     296             :              " %lld vectors %lld",
     297             :              node->stats_total.clocks,
     298             :              node->stats_total.calls,
     299             :              node->stats_total.suspends, node->stats_total.vectors);
     300             : 
     301             :           for (k = 0; k < vec_len (node->next_nodes); k++)
     302             :             {
     303             :               if (node->next_nodes[k] != ~0)
     304             :                 {
     305             :                   next_node = nodes[node->next_nodes[k]];
     306             :                   vlib_cli_output (vm, "  [%d] %s", k, next_node->name);
     307             :                 }
     308             :             }
     309             :         }
     310             :     }
     311             : 
     312             :   for (j = 0; j < vec_len (nodes_by_thread); j++)
     313             :     {
     314             :       nodes = nodes_by_thread[j];
     315             : 
     316             :       for (i = 0; i < vec_len (nodes); i++)
     317             :         {
     318             :           vec_free (nodes[i]->name);
     319             :           vec_free (nodes[i]->next_nodes);
     320             :           vec_free (nodes[i]);
     321             :         }
     322             :       vec_free (nodes);
     323             :     }
     324             :   vec_free (nodes_by_thread);
     325             : 
     326             :   return 0;
     327             : }
     328             : 
     329             : /* *INDENT-OFF* */
     330             : VLIB_CLI_COMMAND (test_node_serialize_node, static) = {
     331             :     .path = "test node serialize",
     332             :     .short_help = "test node serialize [max-threads NN] nexts stats",
     333             :     .function = test_node_serialize_command_fn,
     334             : };
     335             : /* *INDENT-ON* */
     336             : #endif
     337             : 
     338             : /*
     339             :  * fd.io coding-style-patch-verification: ON
     340             :  *
     341             :  * Local Variables:
     342             :  * eval: (c-set-style "gnu")
     343             :  * End:
     344             :  */

Generated by: LCOV version 1.14