FD.io VPP  v18.01-8-g0eacf49
Vector Packet Processing
cli.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2016 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17 #include <stdint.h>
18 #include <net/if.h>
19 #include <sys/ioctl.h>
20 #include <inttypes.h>
21 
22 #include <vlib/vlib.h>
23 #include <vlib/unix/unix.h>
24 #include <vnet/ethernet/ethernet.h>
25 
26 #include <memif/memif.h>
27 #include <memif/private.h>
28 
29 static clib_error_t *
31  vlib_cli_command_t * cmd)
32 {
33  unformat_input_t _line_input, *line_input = &_line_input;
34  int r;
35  u32 ring_size = MEMIF_DEFAULT_RING_SIZE;
36  memif_create_if_args_t args = { 0 };
38  u32 rx_queues = MEMIF_DEFAULT_RX_QUEUES;
39  u32 tx_queues = MEMIF_DEFAULT_TX_QUEUES;
40 
41  /* Get a line of input. */
42  if (!unformat_user (input, unformat_line_input, line_input))
43  return 0;
44 
45  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
46  {
47  if (unformat (line_input, "id %u", &args.id))
48  ;
49  else if (unformat (line_input, "socket %s", &args.socket_filename))
50  ;
51  else if (unformat (line_input, "secret %s", &args.secret))
52  ;
53  else if (unformat (line_input, "ring-size %u", &ring_size))
54  ;
55  else if (unformat (line_input, "rx-queues %u", &rx_queues))
56  ;
57  else if (unformat (line_input, "tx-queues %u", &tx_queues))
58  ;
59  else if (unformat (line_input, "buffer-size %u", &args.buffer_size))
60  ;
61  else if (unformat (line_input, "master"))
62  args.is_master = 1;
63  else if (unformat (line_input, "slave"))
64  args.is_master = 0;
65  else if (unformat (line_input, "mode ip"))
67  else if (unformat (line_input, "hw-addr %U",
69  args.hw_addr_set = 1;
70  else
71  return clib_error_return (0, "unknown input `%U'",
72  format_unformat_error, input);
73  }
74  unformat_free (line_input);
75 
76  if (!is_pow2 (ring_size))
77  return clib_error_return (0, "ring size must be power of 2");
78 
79  if (ring_size > 32768)
80  return clib_error_return (0, "maximum ring size is 32768");
81 
82  args.log2_ring_size = min_log2 (ring_size);
83 
84  if (rx_queues > 255 || rx_queues < 1)
85  return clib_error_return (0, "rx queue must be between 1 - 255");
86  if (tx_queues > 255 || tx_queues < 1)
87  return clib_error_return (0, "tx queue must be between 1 - 255");
88 
89  args.rx_queues = rx_queues;
90  args.tx_queues = tx_queues;
91 
92  r = memif_create_if (vm, &args);
93 
95  vec_free (args.secret);
96 
97  if (r <= VNET_API_ERROR_SYSCALL_ERROR_1
98  && r >= VNET_API_ERROR_SYSCALL_ERROR_10)
99  return clib_error_return (0, "%s (errno %d)", strerror (errno), errno);
100 
101  if (r == VNET_API_ERROR_INVALID_INTERFACE)
102  return clib_error_return (0, "Invalid interface name");
103 
104  if (r == VNET_API_ERROR_SUBIF_ALREADY_EXISTS)
105  return clib_error_return (0, "Interface with same id already exists");
106 
107  return 0;
108 }
109 
110 /* *INDENT-OFF* */
111 VLIB_CLI_COMMAND (memif_create_command, static) = {
112  .path = "create memif",
113  .short_help = "create memif [id <id>] [socket <path>] "
114  "[ring-size <size>] [buffer-size <size>] [hw-addr <mac-address>] "
115  "<master|slave> [rx-queues <number>] [tx-queues <number>] "
116  "[mode ip] [secret <string>]",
117  .function = memif_create_command_fn,
118 };
119 /* *INDENT-ON* */
120 
121 static clib_error_t *
123  vlib_cli_command_t * cmd)
124 {
125  unformat_input_t _line_input, *line_input = &_line_input;
126  u32 sw_if_index = ~0;
128  memif_main_t *mm = &memif_main;
129  memif_if_t *mif;
130  vnet_main_t *vnm = vnet_get_main ();
131 
132  /* Get a line of input. */
133  if (!unformat_user (input, unformat_line_input, line_input))
134  return 0;
135 
136  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
137  {
138  if (unformat (line_input, "sw_if_index %d", &sw_if_index))
139  ;
140  else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
141  vnm, &sw_if_index))
142  ;
143  else
144  return clib_error_return (0, "unknown input `%U'",
145  format_unformat_error, input);
146  }
147  unformat_free (line_input);
148 
149  if (sw_if_index == ~0)
150  return clib_error_return (0,
151  "please specify interface name or sw_if_index");
152 
153  hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
154  if (hw == NULL || memif_device_class.index != hw->dev_class_index)
155  return clib_error_return (0, "not a memif interface");
156 
157  mif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
158  memif_delete_if (vm, mif);
159 
160  return 0;
161 }
162 
163 /* *INDENT-OFF* */
164 VLIB_CLI_COMMAND (memif_delete_command, static) = {
165  .path = "delete memif",
166  .short_help = "delete memif {<interface> | sw_if_index <sw_idx>}",
167  .function = memif_delete_command_fn,
168 };
169 /* *INDENT-ON* */
170 
171 static u8 *
172 format_memif_if_flags (u8 * s, va_list * args)
173 {
174  u32 flags = va_arg (*args, u32);
175 #define _(a,b,c) if ( flags & (1 << a)) s = format (s, " %s", c);
177 #undef _
178  return s;
179 }
180 
181 static u8 *
182 format_memif_if_mode (u8 * s, va_list * args)
183 {
184  memif_if_t *mif = va_arg (*args, memif_if_t *);
186  return format (s, "ethernet");
187  if (mif->mode == MEMIF_INTERFACE_MODE_IP)
188  return format (s, "ip");
190  return format (s, "punt-inject");
191  return format (s, "unknown mode (%u)", mif->mode);;
192 }
193 
194 static u8 *
195 format_memif_queue (u8 * s, va_list * args)
196 {
197  memif_if_t *mif = va_arg (*args, memif_if_t *);
198  memif_queue_t *mq = va_arg (*args, memif_queue_t *);
199  uword i = va_arg (*args, uword);
200  u32 indent = format_get_indent (s);
201 
202  s = format (s, "%U%s ring %u:\n",
203  format_white_space, indent,
204  (mif->flags & MEMIF_IF_FLAG_IS_SLAVE) ?
205  "slave-to-master" : "master-to-slave", i);
206  s = format (s, "%Uregion %u offset %u ring-size %u int-fd %d\n",
207  format_white_space, indent + 4,
208  mq->region, mq->offset, (1 << mq->log2_ring_size), mq->int_fd);
209 
210  if (mq->ring)
211  s = format (s, "%Uhead %u tail %u flags 0x%04x interrupts %u\n",
212  format_white_space, indent + 4,
213  mq->ring->head, mq->ring->tail, mq->ring->flags,
214  mq->int_count);
215 
216  return s;
217 }
218 
219 static u8 *
220 format_memif_descriptor (u8 * s, va_list * args)
221 {
222  memif_if_t *mif = va_arg (*args, memif_if_t *);
223  memif_queue_t *mq = va_arg (*args, memif_queue_t *);
224  u32 indent = format_get_indent (s);
225  memif_ring_t *ring;
226  u16 ring_size;
227  u16 slot;
228 
229  ring_size = 1 << mq->log2_ring_size;
230  ring = mq->ring;
231  if (ring)
232  {
233  s = format (s, "%Udescriptor table:\n", format_white_space, indent);
234  s =
235  format (s,
236  "%Uid flags buf len desc len address offset user address\n",
237  format_white_space, indent);
238  s =
239  format (s,
240  "%U===== ===== ======= ======== ================== ====== ==================\n",
241  format_white_space, indent);
242  for (slot = 0; slot < ring_size; slot++)
243  {
244  s = format (s, "%U%-5d %-5d %-7d %-7d 0x%016lx %-6d 0x%016lx\n",
245  format_white_space, indent, slot,
246  ring->desc[slot].flags, ring->desc[slot].buffer_length,
247  ring->desc[slot].length,
248  mif->regions[ring->desc[slot].region].shm,
249  ring->desc[slot].offset, memif_get_buffer (mif, ring,
250  slot));
251  }
252  s = format (s, "\n");
253  }
254 
255  return s;
256 }
257 
258 static clib_error_t *
260  vlib_cli_command_t * cmd)
261 {
262  memif_main_t *mm = &memif_main;
263  memif_if_t *mif;
264  vnet_main_t *vnm = vnet_get_main ();
265  memif_queue_t *mq;
266  uword i;
267  int show_descr = 0;
268  clib_error_t *error = 0;
269  u32 hw_if_index, *hw_if_indices = 0;
270 
272  {
273  if (unformat
274  (input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
275  vec_add1 (hw_if_indices, hw_if_index);
276  else if (unformat (input, "descriptors"))
277  show_descr = 1;
278  else
279  {
280  error = clib_error_return (0, "unknown input `%U'",
281  format_unformat_error, input);
282  goto done;
283  }
284  }
285 
286  if (vec_len (hw_if_indices) == 0)
287  {
288  /* *INDENT-OFF* */
289  pool_foreach (mif, mm->interfaces,
290  vec_add1 (hw_if_indices, mif->hw_if_index);
291  );
292  /* *INDENT-ON* */
293  }
294 
295  for (hw_if_index = 0; hw_if_index < vec_len (hw_if_indices); hw_if_index++)
296  {
298  vnet_get_hw_interface (vnm, hw_if_indices[hw_if_index]);
299  mif = pool_elt_at_index (mm->interfaces, hi->dev_instance);
301  mif->socket_file_index);
302  vlib_cli_output (vm, "interface %U", format_vnet_sw_if_index_name,
303  vnm, mif->sw_if_index);
304  if (mif->remote_name)
305  vlib_cli_output (vm, " remote-name \"%s\"", mif->remote_name);
306  if (mif->remote_if_name)
307  vlib_cli_output (vm, " remote-interface \"%s\"",
308  mif->remote_if_name);
309  vlib_cli_output (vm, " id %d mode %U file %s", mif->id,
310  format_memif_if_mode, mif, msf->filename);
311  vlib_cli_output (vm, " flags%U", format_memif_if_flags, mif->flags);
312  vlib_cli_output (vm, " listener-fd %d conn-fd %d",
313  msf->sock ? msf->sock->fd : 0,
314  mif->sock ? mif->sock->fd : 0);
315  vlib_cli_output (vm,
316  " num-s2m-rings %u num-m2s-rings %u buffer-size %u",
317  mif->run.num_s2m_rings, mif->run.num_m2s_rings,
318  mif->run.buffer_size);
319 
320  if (mif->local_disc_string)
321  vlib_cli_output (vm, " local-disc-reason \"%s\"",
322  mif->local_disc_string);
323  if (mif->remote_disc_string)
324  vlib_cli_output (vm, " remote-disc-reason \"%s\"",
325  mif->remote_disc_string);
326 
327  vec_foreach_index (i, mif->tx_queues)
328  {
329  mq = vec_elt_at_index (mif->tx_queues, i);
330  vlib_cli_output (vm, " %U", format_memif_queue, mif, mq, i);
331  if (show_descr)
332  vlib_cli_output (vm, " %U", format_memif_descriptor, mif, mq);
333  }
334  vec_foreach_index (i, mif->rx_queues)
335  {
336  mq = vec_elt_at_index (mif->rx_queues, i);
337  vlib_cli_output (vm, " %U", format_memif_queue, mif, mq, i);
338  if (show_descr)
339  vlib_cli_output (vm, " %U", format_memif_descriptor, mif, mq);
340  }
341  }
342 done:
343  vec_free (hw_if_indices);
344  return error;
345 }
346 
347 /* *INDENT-OFF* */
348 VLIB_CLI_COMMAND (memif_show_command, static) = {
349  .path = "show memif",
350  .short_help = "show memif {<interface>] [descriptors]",
351  .function = memif_show_command_fn,
352 };
353 /* *INDENT-ON* */
354 
355 clib_error_t *
357 {
358  return 0;
359 }
360 
362 
363 /*
364  * fd.io coding-style-patch-verification: ON
365  *
366  * Local Variables:
367  * eval: (c-set-style "gnu")
368  * End:
369  */
memif_if_t * interfaces
Definition: private.h:181
unformat_function_t unformat_vnet_hw_interface
vmrglw vmrglh hi
#define vec_foreach_index(var, v)
Iterate over vector indices.
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
memif_socket_file_t * socket_files
Definition: private.h:184
#define NULL
Definition: clib.h:55
struct memif_if_t::@366 run
static clib_error_t * memif_create_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:30
static u8 * format_memif_if_flags(u8 *s, va_list *args)
Definition: cli.c:172
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:518
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:983
static u32 format_get_indent(u8 *s)
Definition: format.h:72
memif_interface_mode_t mode
Definition: private.h:208
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
unformat_function_t unformat_vnet_sw_interface
u8 num_m2s_rings
Definition: private.h:156
format_function_t format_vnet_sw_if_index_name
static uword min_log2(uword x)
Definition: clib.h:197
uint32_t length
Definition: memif.h:152
uint32_t buffer_length
Definition: memif.h:151
u8 * remote_name
Definition: private.h:149
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:438
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
uword socket_file_index
Definition: private.h:139
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
u16 buffer_size
Definition: private.h:157
memif_log2_ring_size_t log2_ring_size
Definition: private.h:209
uint16_t flags
Definition: memif.h:148
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
vnet_device_class_t memif_device_class
#define clib_error_return(e, args...)
Definition: error.h:99
memif_region_offset_t offset
Definition: private.h:99
unformat_function_t unformat_line_input
Definition: format.h:281
memif_region_index_t region
Definition: memif.h:150
static clib_error_t * memif_delete_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:122
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:459
memif_desc_t desc[0]
Definition: memif.h:174
static clib_error_t * memif_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:259
int memif_delete_if(vlib_main_t *vm, memif_if_t *mif)
Definition: memif.c:466
struct _unformat_input_t unformat_input_t
memif_interface_id_t id
Definition: private.h:204
int memif_create_if(vlib_main_t *vm, memif_create_if_args_t *args)
Definition: memif.c:543
#define MEMIF_DEFAULT_TX_QUEUES
Definition: private.h:23
memif_queue_t * tx_queues
Definition: private.h:146
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
vlib_main_t * vm
Definition: buffer.c:283
u8 * local_disc_string
Definition: private.h:169
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
static u8 * format_memif_if_mode(u8 *s, va_list *args)
Definition: cli.c:182
#define MEMIF_DEFAULT_BUFFER_SIZE
Definition: private.h:24
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
memif_region_t * regions
Definition: private.h:143
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
Definition: format.c:227
unsigned int u32
Definition: types.h:88
static_always_inline void * memif_get_buffer(memif_if_t *mif, memif_ring_t *ring, u16 slot)
Definition: private.h:225
u32 flags
Definition: private.h:128
memif_ring_t * ring
Definition: private.h:96
#define MEMIF_DEFAULT_RX_QUEUES
Definition: private.h:22
u32 hw_if_index
Definition: private.h:130
u64 int_count
Definition: private.h:107
static uword is_pow2(uword x)
Definition: clib.h:280
u64 uword
Definition: types.h:112
memif_region_offset_t offset
Definition: memif.h:154
u8 num_s2m_rings
Definition: private.h:155
unsigned short u16
Definition: types.h:57
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
clib_error_t * memif_cli_init(vlib_main_t *vm)
Definition: cli.c:356
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
void * shm
Definition: private.h:82
u8 * remote_if_name
Definition: private.h:150
memif_interface_id_t id
Definition: private.h:129
memif_log2_ring_size_t log2_ring_size
Definition: private.h:97
static u8 * format_memif_descriptor(u8 *s, va_list *args)
Definition: cli.c:220
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define MEMIF_DEFAULT_RING_SIZE
Definition: private.h:21
uint16_t flags
Definition: memif.h:168
u8 * remote_disc_string
Definition: private.h:170
volatile uint16_t head
Definition: memif.h:170
clib_socket_t * sock
Definition: private.h:138
memif_queue_t * rx_queues
Definition: private.h:145
static u8 * format_memif_queue(u8 *s, va_list *args)
Definition: cli.c:195
u32 flags
Definition: vhost-user.h:77
memif_main_t memif_main
Definition: memif.c:43
memif_region_index_t region
Definition: private.h:98
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:680
clib_socket_t * sock
Definition: private.h:68
u32 sw_if_index
Definition: private.h:131
volatile uint16_t tail
Definition: memif.h:172
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
memif_interface_mode_t mode
Definition: private.h:133
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169