LCOV - code coverage report
Current view: top level - plugins/tracedump - graph_api.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 15 93 16.1 %
Date: 2023-07-05 22:20:52 Functions: 6 10 60.0 %

          Line data    Source code
       1             : /* Hey Emacs use -*- mode: C -*- */
       2             : /*
       3             :  * Copyright 2020 Rubicon Communications, LLC.
       4             :  *
       5             :  * Licensed under the Apache License, Version 2.0 (the "License");
       6             :  * you may not use this file except in compliance with the License.
       7             :  * You may obtain a copy of the License at:
       8             :  *
       9             :  *     http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  * Unless required by applicable law or agreed to in writing, software
      12             :  * distributed under the License is distributed on an "AS IS" BASIS,
      13             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  * See the License for the specific language governing permissions and
      15             :  * limitations under the License.
      16             :  */
      17             : 
      18             : #include <vnet/vnet.h>
      19             : #include <vlibmemory/api.h>
      20             : 
      21             : #include <tracedump/graph.api_enum.h>
      22             : #include <tracedump/graph.api_types.h>
      23             : 
      24             : #define REPLY_MSG_ID_BASE       gmp->msg_id_base
      25             : #include <vlibapi/api_helper_macros.h>
      26             : 
      27             : #include <tracedump/graph.h>
      28             : 
      29             : 
      30             : graph_main_t graph_main;
      31             : 
      32             : 
      33             : #define MIN(x,y)        (((x) < (y)) ? (x) : (y))
      34             : 
      35             : 
      36             : /*
      37             :  * If ever the graph or set of nodes changes, this cache of
      38             :  * nodes in sorted order should be invalidated.
      39             :  */
      40             : void
      41        1207 : graph_node_invalid_cache (void)
      42             : {
      43        1207 :   graph_main_t *gmp = &graph_main;
      44             : 
      45        1207 :   vec_free (gmp->sorted_node_vec);
      46        1207 : }
      47             : 
      48             : 
      49             : static clib_error_t *
      50        1207 : graph_node_cache_reaper (u32 client_index)
      51             : {
      52        1207 :   graph_node_invalid_cache ();
      53        1207 :   return 0;
      54             : }
      55             : 
      56         559 : VL_MSG_API_REAPER_FUNCTION (graph_node_cache_reaper);
      57             : 
      58             : 
      59             : static void
      60           0 : send_graph_node_reply (vl_api_registration_t * rp,
      61             :                        u32 context, u32 retval, u32 cursor)
      62             : {
      63           0 :   graph_main_t *gmp = &graph_main;
      64             :   vl_api_graph_node_get_reply_t *rmp;
      65             : 
      66           0 :   rmp = vl_msg_api_alloc (sizeof (*rmp));
      67           0 :   rmp->_vl_msg_id = htons (VL_API_GRAPH_NODE_GET_REPLY + gmp->msg_id_base);
      68           0 :   rmp->context = context;
      69           0 :   rmp->retval = clib_host_to_net_u32 (retval);
      70           0 :   rmp->cursor = htonl (cursor);
      71             : 
      72           0 :   vl_api_send_msg (rp, (u8 *) rmp);
      73           0 : }
      74             : 
      75             : 
      76             : static void
      77           0 : send_graph_node_details (vlib_node_main_t * nm,
      78             :                          vl_api_registration_t * reg,
      79             :                          u32 context, vlib_node_t * n, bool want_arcs)
      80             : {
      81           0 :   graph_main_t *gmp = &graph_main;
      82             :   vl_api_graph_node_details_t *mp;
      83             :   u32 msg_size;
      84             : 
      85           0 :   msg_size = sizeof (*mp);
      86           0 :   if (want_arcs)
      87           0 :     msg_size += vec_len (n->next_nodes) * sizeof (*n->next_nodes);
      88             : 
      89           0 :   mp = vl_msg_api_alloc (msg_size);
      90           0 :   if (!mp)
      91           0 :     return;
      92             : 
      93           0 :   clib_memset (mp, 0, msg_size);
      94             : 
      95           0 :   mp->_vl_msg_id = htons (VL_API_GRAPH_NODE_DETAILS + gmp->msg_id_base);
      96           0 :   mp->context = context;
      97           0 :   mp->index = htonl (n->index);
      98           0 :   mp->flags = htonl (n->flags);
      99             : 
     100           0 :   clib_strncpy ((char *) mp->name, (char *) n->name,
     101             :                 MIN (sizeof (mp->name) - 1, vec_len (n->name)));
     102             : 
     103           0 :   if (want_arcs)
     104             :     {
     105             :       int i;
     106             : 
     107           0 :       mp->n_arcs = htonl (vec_len (n->next_nodes));
     108           0 :       for (i = 0; i < vec_len (n->next_nodes); ++i)
     109             :         {
     110           0 :           mp->arcs_out[i] = htonl (n->next_nodes[i]);
     111             :         }
     112             :     }
     113             : 
     114           0 :   vl_api_send_msg (reg, (u8 *) mp);
     115             : }
     116             : 
     117             : 
     118             : static int
     119           0 : node_cmp (void *a1, void *a2)
     120             : {
     121           0 :   vlib_node_t **n1 = a1;
     122           0 :   vlib_node_t **n2 = a2;
     123             : 
     124           0 :   return vec_cmp (n1[0]->name, n2[0]->name);
     125             : }
     126             : 
     127             : 
     128             : /*
     129             :  * When cursor == ~0, it begins a request:
     130             :  *    if index != ~0, dump node with given index
     131             :  *    if index == ~0 and name[0] != 0, dump node with given name
     132             :  *    if index == ~0 and name[0] == 0, and flag != 0, dump flagged nodes
     133             :  *    else
     134             :  *        index == ~0 and name[0] == 0 and flag == 0, so dump all nodes.
     135             :  *
     136             :  * When cursor != ~0, it is the middle of a request:
     137             :  *    The same (index, name, and flag) parameters are assumed,
     138             :  *    The next results resume from cursor.
     139             :  */
     140             : static void
     141           0 : vl_api_graph_node_get_t_handler (vl_api_graph_node_get_t * mp)
     142             : {
     143             :   vl_api_registration_t *rp;
     144             : 
     145           0 :   rp = vl_api_client_index_to_registration (mp->client_index);
     146           0 :   if (!rp)
     147           0 :     return;
     148             : 
     149           0 :   vlib_main_t *vm = vlib_get_main ();
     150           0 :   vlib_node_main_t *nm = &vm->node_main;
     151           0 :   graph_main_t *gmp = &graph_main;
     152             :   vlib_node_t *n;
     153             :   u32 cursor;
     154             :   u32 node_index;
     155             :   bool want_arcs;
     156             : 
     157           0 :   want_arcs = ! !mp->want_arcs;
     158           0 :   cursor = ntohl (mp->cursor);
     159           0 :   n = 0;
     160             : 
     161             :   /*
     162             :    * Return details on a specific node by index?
     163             :    */
     164           0 :   node_index = ntohl (mp->index);
     165           0 :   if (cursor == ~0 && node_index != ~0)
     166             :     {
     167           0 :       if (node_index < vec_len (nm->nodes))
     168           0 :         n = vlib_get_node (vm, node_index);
     169           0 :       if (!n)
     170             :         {
     171           0 :           send_graph_node_reply (rp, mp->context,
     172             :                                  VNET_API_ERROR_NO_SUCH_ENTRY, ~0);
     173           0 :           return;
     174             :         }
     175           0 :       send_graph_node_details (nm, rp, mp->context, n, want_arcs);
     176           0 :       send_graph_node_reply (rp, mp->context, 0, ~0);
     177           0 :       return;
     178             :     }
     179             : 
     180             :   /*
     181             :    * Return details on a specific node by name?
     182             :    */
     183           0 :   if (cursor == ~0 && mp->name[0] != 0)
     184             :     {
     185           0 :       n = vlib_get_node_by_name (vm, (u8 *) mp->name);
     186           0 :       if (!n)
     187             :         {
     188           0 :           send_graph_node_reply (rp, mp->context,
     189             :                                  VNET_API_ERROR_NO_SUCH_ENTRY, ~0);
     190           0 :           return;
     191             :         }
     192             : 
     193           0 :       send_graph_node_details (nm, rp, mp->context, n, want_arcs);
     194           0 :       send_graph_node_reply (rp, mp->context, 0, ~0);
     195           0 :       return;
     196             :     }
     197             : 
     198             :   /*
     199             :    * Inspect all nodes, but potentially limit them by flag selection.
     200             :    * As iteration my need to occur over multiple streaming API calls,
     201             :    * determine the API client index and cache a sorted list of nodes.
     202             :    *
     203             :    * First time through, make a sorted node list and cache it.
     204             :    */
     205           0 :   vlib_node_t **nodes = gmp->sorted_node_vec;
     206           0 :   if (!nodes)
     207             :     {
     208           0 :       nodes = vec_dup (nm->nodes);
     209           0 :       vec_sort_with_function (nodes, node_cmp);
     210           0 :       gmp->sorted_node_vec = nodes;
     211             :     }
     212             : 
     213           0 :   u32 flags = ntohl (mp->flags);
     214           0 :   u32 first_index = (cursor == ~0) ? 0 : cursor;
     215             : 
     216             :   /* Don't overflow the existing queue space. */
     217           0 :   svm_queue_t *q = rp->vl_input_queue;
     218           0 :   u32 queue_slots_available = q->maxsize - q->cursize;
     219           0 :   int chunk = (queue_slots_available > 0) ? queue_slots_available - 1 : 0;
     220             :   u32 i;
     221             : 
     222           0 :   for (i = first_index; i < vec_len (nodes); ++i)
     223             :     {
     224           0 :       if (chunk-- == 0)
     225             :         {
     226             :           /*
     227             :            * Pick up again at cursor = i.
     228             :            */
     229           0 :           send_graph_node_reply (rp, mp->context, VNET_API_ERROR_EAGAIN, i);
     230           0 :           return;
     231             :         }
     232             : 
     233           0 :       n = nodes[i];
     234           0 :       if (flags == 0 || (n->flags & flags))
     235             :         {
     236           0 :           send_graph_node_details (nm, rp, mp->context, n, want_arcs);
     237             :         }
     238             :     }
     239             : 
     240           0 :   send_graph_node_reply (rp, mp->context, 0, ~0);
     241             : }
     242             : 
     243             : 
     244             : #include <vnet/format_fns.h>
     245             : #include <tracedump/graph.api.c>
     246             : 
     247             : static clib_error_t *
     248         559 : graph_api_hookup (vlib_main_t * vm)
     249             : {
     250         559 :   api_main_t *am = vlibapi_get_main ();
     251         559 :   graph_main_t *gmp = &graph_main;
     252             : 
     253         559 :   gmp->msg_id_base = setup_message_id_table ();
     254             : 
     255         559 :   vl_api_set_msg_thread_safe (am, gmp->msg_id_base + VL_API_GRAPH_NODE_GET, 1);
     256             : 
     257         559 :   return 0;
     258             : }
     259             : 
     260        1119 : VLIB_INIT_FUNCTION (graph_api_hookup);
     261             : 
     262             : /*
     263             :  * fd.io coding-style-patch-verification: ON
     264             :  *
     265             :  * Local Variables:
     266             :  * eval: (c-set-style "gnu")
     267             :  * End:
     268             :  */

Generated by: LCOV version 1.14