FD.io VPP  v21.01.1
Vector Packet Processing
graph_api.c
Go to the documentation of this file.
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
26 
27 #include <tracedump/graph.h>
28 
29 
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
42 {
43  graph_main_t *gmp = &graph_main;
44 
46 }
47 
48 
49 static clib_error_t *
51 {
53  return 0;
54 }
55 
57 
58 
59 static void
61  u32 context, u32 retval, u32 cursor)
62 {
63  graph_main_t *gmp = &graph_main;
65 
66  rmp = vl_msg_api_alloc (sizeof (*rmp));
67  rmp->_vl_msg_id = htons (VL_API_GRAPH_NODE_GET_REPLY + gmp->msg_id_base);
68  rmp->context = context;
69  rmp->retval = clib_host_to_net_u32 (retval);
70  rmp->cursor = htonl (cursor);
71 
72  vl_api_send_msg (rp, (u8 *) rmp);
73 }
74 
75 
76 static void
79  u32 context, vlib_node_t * n, bool want_arcs)
80 {
81  graph_main_t *gmp = &graph_main;
83  u32 msg_size;
84 
85  msg_size = sizeof (*mp);
86  if (want_arcs)
87  msg_size += vec_len (n->next_nodes) * sizeof (*n->next_nodes);
88 
89  mp = vl_msg_api_alloc (msg_size);
90  if (!mp)
91  return;
92 
93  clib_memset (mp, 0, msg_size);
94 
95  mp->_vl_msg_id = htons (VL_API_GRAPH_NODE_DETAILS + gmp->msg_id_base);
96  mp->context = context;
97  mp->index = htonl (n->index);
98  mp->flags = htonl (n->flags);
99 
100  clib_strncpy ((char *) mp->name, (char *) n->name,
101  MIN (sizeof (mp->name) - 1, vec_len (n->name)));
102 
103  if (want_arcs)
104  {
105  int i;
106 
107  mp->n_arcs = htonl (vec_len (n->next_nodes));
108  for (i = 0; i < vec_len (n->next_nodes); ++i)
109  {
110  mp->arcs_out[i] = htonl (n->next_nodes[i]);
111  }
112  }
113 
114  vl_api_send_msg (reg, (u8 *) mp);
115 }
116 
117 
118 static int
119 node_cmp (void *a1, void *a2)
120 {
121  vlib_node_t **n1 = a1;
122  vlib_node_t **n2 = a2;
123 
124  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
142 {
144 
146  if (!rp)
147  return;
148 
150  vlib_node_main_t *nm = &vm->node_main;
151  graph_main_t *gmp = &graph_main;
152  vlib_node_t *n;
153  u32 cursor;
154  u32 node_index;
155  bool want_arcs;
156 
157  want_arcs = ! !mp->want_arcs;
158  cursor = ntohl (mp->cursor);
159  n = 0;
160 
161  /*
162  * Return details on a specific node by index?
163  */
164  node_index = ntohl (mp->index);
165  if (cursor == ~0 && node_index != ~0)
166  {
167  if (node_index < vec_len (nm->nodes))
168  n = vlib_get_node (vm, node_index);
169  if (!n)
170  {
172  VNET_API_ERROR_NO_SUCH_ENTRY, ~0);
173  return;
174  }
175  send_graph_node_details (nm, rp, mp->context, n, want_arcs);
176  send_graph_node_reply (rp, mp->context, 0, ~0);
177  return;
178  }
179 
180  /*
181  * Return details on a specific node by name?
182  */
183  if (cursor == ~0 && mp->name[0] != 0)
184  {
185  n = vlib_get_node_by_name (vm, (u8 *) mp->name);
186  if (!n)
187  {
189  VNET_API_ERROR_NO_SUCH_ENTRY, ~0);
190  return;
191  }
192 
193  send_graph_node_details (nm, rp, mp->context, n, want_arcs);
194  send_graph_node_reply (rp, mp->context, 0, ~0);
195  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  vlib_node_t **nodes = gmp->sorted_node_vec;
206  if (!nodes)
207  {
208  nodes = vec_dup (nm->nodes);
210  gmp->sorted_node_vec = nodes;
211  }
212 
213  u32 flags = ntohl (mp->flags);
214  u32 first_index = (cursor == ~0) ? 0 : cursor;
215 
216  /* Don't overflow the existing queue space. */
217  svm_queue_t *q = rp->vl_input_queue;
218  u32 queue_slots_available = q->maxsize - q->cursize;
219  int chunk = (queue_slots_available > 0) ? queue_slots_available - 1 : 0;
220  u32 i;
221 
222  for (i = first_index; i < vec_len (nodes); ++i)
223  {
224  if (chunk-- == 0)
225  {
226  /*
227  * Pick up again at cursor = i.
228  */
229  send_graph_node_reply (rp, mp->context, VNET_API_ERROR_EAGAIN, i);
230  return;
231  }
232 
233  n = nodes[i];
234  if (flags == 0 || (n->flags & flags))
235  {
236  send_graph_node_details (nm, rp, mp->context, n, want_arcs);
237  }
238  }
239 
240  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 *
249 {
250  api_main_t *am = vlibapi_get_main ();
251  graph_main_t *gmp = &graph_main;
252 
254 
255  am->is_mp_safe[gmp->msg_id_base + VL_API_GRAPH_NODE_GET] = 1;
256 
257  return 0;
258 }
259 
261 
262 /*
263  * fd.io coding-style-patch-verification: ON
264  *
265  * Local Variables:
266  * eval: (c-set-style "gnu")
267  * End:
268  */
u32 * next_nodes
Definition: node.h:335
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
Details for each graph node.
Definition: graph.api:80
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
u32 index
Definition: node.h:280
static void vl_api_send_msg(vl_api_registration_t *rp, u8 *elem)
Definition: api.h:35
u16 flags
Definition: node.h:289
vl_api_node_flag_t flags
Definition: graph.api:85
static clib_error_t * graph_api_hookup(vlib_main_t *vm)
Definition: graph_api.c:248
vlib_main_t * vm
Definition: in2out_ed.c:1580
void * vl_msg_api_alloc(int nbytes)
unsigned char u8
Definition: types.h:56
static int node_cmp(void *a1, void *a2)
Definition: graph_api.c:119
static void send_graph_node_details(vlib_node_main_t *nm, vl_api_registration_t *reg, u32 context, vlib_node_t *n, bool want_arcs)
Definition: graph_api.c:77
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
vlib_node_t ** nodes
Definition: node.h:680
unsigned int u32
Definition: types.h:88
static clib_error_t * graph_node_cache_reaper(u32 client_index)
Definition: graph_api.c:50
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
svm_queue_t * vl_input_queue
shared memory only: pointer to client input queue
Definition: api_common.h:62
#define vec_dup(V)
Return copy of vector (no header, no alignment)
Definition: vec.h:429
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:227
u8 * name
Definition: node.h:264
An API client registration, only in vpp/vlib.
Definition: api_common.h:47
static void setup_message_id_table(api_main_t *am)
Definition: bfd_api.c:409
#define clib_strncpy(d, s, n)
Definition: string.h:978
u16 msg_id_base
Definition: graph.h:22
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
static void send_graph_node_reply(vl_api_registration_t *rp, u32 context, u32 retval, u32 cursor)
Definition: graph_api.c:60
graph_main_t graph_main
Definition: graph_api.c:30
void graph_node_invalid_cache(void)
Definition: graph_api.c:41
static vl_api_registration_t * vl_api_client_index_to_registration(u32 index)
Definition: api.h:79
string name[64]
Definition: ip.api:44
static void vl_api_graph_node_get_t_handler(vl_api_graph_node_get_t *mp)
Definition: graph_api.c:141
#define vec_cmp(v1, v2)
Compare two vectors (only applicable to vectors of signed numbers).
Definition: vec.h:991
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vl_api_node_flag_t flags
Definition: graph.api:61
vlib_node_main_t node_main
Definition: main.h:188
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:1055
#define MIN(x, y)
Definition: graph_api.c:33
struct _svm_queue svm_queue_t
static api_main_t * vlibapi_get_main(void)
Definition: api_common.h:389
u8 * is_mp_safe
Message is mp safe vector.
Definition: api_common.h:250
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:85
graph_node_get - Get nodes of the packet processing graph In order: if index != ~0, dump node with given index if index == ~0 and name[0] != 0, dump named node if index == ~0 and name[0] == 0 and flag != 0, dump flagged nodes otherwise when no selection criteria given, dump all nodes.
Definition: graph.api:54
VL_MSG_API_REAPER_FUNCTION(graph_node_cache_reaper)
vlib_node_t ** sorted_node_vec
Definition: graph.h:23