FD.io VPP  v17.07.01-10-g3be13f0
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  args.log2_ring_size = min_log2 (ring_size);
80 
81  if (rx_queues > 255 || rx_queues < 1)
82  return clib_error_return (0, "rx queue must be between 1 - 255");
83  if (tx_queues > 255 || tx_queues < 1)
84  return clib_error_return (0, "tx queue must be between 1 - 255");
85 
86  args.rx_queues = rx_queues;
87  args.tx_queues = tx_queues;
88 
89  r = memif_create_if (vm, &args);
90 
92  vec_free (args.secret);
93 
94  if (r <= VNET_API_ERROR_SYSCALL_ERROR_1
95  && r >= VNET_API_ERROR_SYSCALL_ERROR_10)
96  return clib_error_return (0, "%s (errno %d)", strerror (errno), errno);
97 
98  if (r == VNET_API_ERROR_INVALID_INTERFACE)
99  return clib_error_return (0, "Invalid interface name");
100 
101  if (r == VNET_API_ERROR_SUBIF_ALREADY_EXISTS)
102  return clib_error_return (0, "Interface with same id already exists");
103 
104  return 0;
105 }
106 
107 /* *INDENT-OFF* */
108 VLIB_CLI_COMMAND (memif_create_command, static) = {
109  .path = "create memif",
110  .short_help = "create memif [id <id>] [socket <path>] "
111  "[ring-size <size>] [buffer-size <size>] [hw-addr <mac-address>] "
112  "<master|slave> [rx-queues <number>] [tx-queues <number>]"
113  "[mode ip]",
114  .function = memif_create_command_fn,
115 };
116 /* *INDENT-ON* */
117 
118 static clib_error_t *
120  vlib_cli_command_t * cmd)
121 {
122  unformat_input_t _line_input, *line_input = &_line_input;
123  u32 sw_if_index = ~0;
125  memif_main_t *mm = &memif_main;
126  memif_if_t *mif;
127  vnet_main_t *vnm = vnet_get_main ();
128 
129  /* Get a line of input. */
130  if (!unformat_user (input, unformat_line_input, line_input))
131  return 0;
132 
133  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
134  {
135  if (unformat (line_input, "sw_if_index %d", &sw_if_index))
136  ;
137  else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
138  vnm, &sw_if_index))
139  ;
140  else
141  return clib_error_return (0, "unknown input `%U'",
142  format_unformat_error, input);
143  }
144  unformat_free (line_input);
145 
146  if (sw_if_index == ~0)
147  return clib_error_return (0,
148  "please specify interface name or sw_if_index");
149 
150  hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
151  if (hw == NULL || memif_device_class.index != hw->dev_class_index)
152  return clib_error_return (0, "not a memif interface");
153 
154  mif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
155  memif_delete_if (vm, mif);
156 
157  return 0;
158 }
159 
160 /* *INDENT-OFF* */
161 VLIB_CLI_COMMAND (memif_delete_command, static) = {
162  .path = "delete memif",
163  .short_help = "delete memif {<interface> | sw_if_index <sw_idx>}",
164  .function = memif_delete_command_fn,
165 };
166 /* *INDENT-ON* */
167 
168 static u8 *
169 format_memif_if_flags (u8 * s, va_list * args)
170 {
171  u32 flags = va_arg (*args, u32);
172 #define _(a,b,c) if ( flags & (1 << a)) s = format (s, " %s", c);
174 #undef _
175  return s;
176 }
177 
178 static u8 *
179 format_memif_if_mode (u8 * s, va_list * args)
180 {
181  memif_if_t *mif = va_arg (*args, memif_if_t *);
183  return format (s, "ethernet");
184  if (mif->mode == MEMIF_INTERFACE_MODE_IP)
185  return format (s, "ip");
187  return format (s, "punt-inject");
188  return format (s, "unknown mode (%u)", mif->mode);;
189 }
190 
191 static u8 *
192 format_memif_queue (u8 * s, va_list * args)
193 {
194  memif_if_t *mif = va_arg (*args, memif_if_t *);
195  memif_queue_t *mq = va_arg (*args, memif_queue_t *);
196  uword i = va_arg (*args, uword);
197  uword indent = format_get_indent (s);
198 
199  s = format (s, "%U%s ring %u:\n",
200  format_white_space, indent,
201  (mif->flags & MEMIF_IF_FLAG_IS_SLAVE) ?
202  "slave-to-master" : "master-to-slave", i);
203  s = format (s, "%Uregion %u offset %u ring-size %u int-fd %d\n",
204  format_white_space, indent + 4,
205  mq->region, mq->offset, (1 << mq->log2_ring_size), mq->int_fd);
206 
207  if (mq->ring)
208  s = format (s, "%Uhead %u tail %u flags 0x%04x interrupts %u\n",
209  format_white_space, indent + 4,
210  mq->ring->head, mq->ring->tail, mq->ring->flags,
211  mq->int_count);
212 
213  return s;
214 }
215 
216 static u8 *
217 format_memif_descriptor (u8 * s, va_list * args)
218 {
219  memif_if_t *mif = va_arg (*args, memif_if_t *);
220  memif_queue_t *mq = va_arg (*args, memif_queue_t *);
221  uword indent = format_get_indent (s);
222  memif_ring_t *ring;
223  u16 ring_size;
224  u16 slot;
225 
226  ring_size = 1 << mq->log2_ring_size;
227  ring = mq->ring;
228  if (ring)
229  {
230  s = format (s, "%Udescriptor table:\n", format_white_space, indent);
231  s =
232  format (s,
233  "%Uid flags buf len desc len address offset user address\n",
234  format_white_space, indent);
235  s =
236  format (s,
237  "%U===== ===== ======= ======== ================== ====== ==================\n",
238  format_white_space, indent);
239  for (slot = 0; slot < ring_size; slot++)
240  {
241  s = format (s, "%U%-5d %-5d %-7d %-7d 0x%016lx %-6d 0x%016lx\n",
242  format_white_space, indent, slot,
243  ring->desc[slot].flags, ring->desc[slot].buffer_length,
244  ring->desc[slot].length,
245  mif->regions[ring->desc[slot].region].shm,
246  ring->desc[slot].offset, memif_get_buffer (mif, ring,
247  slot));
248  }
249  s = format (s, "\n");
250  }
251 
252  return s;
253 }
254 
255 static clib_error_t *
257  vlib_cli_command_t * cmd)
258 {
259  memif_main_t *mm = &memif_main;
260  memif_if_t *mif;
261  vnet_main_t *vnm = vnet_get_main ();
262  memif_queue_t *mq;
263  uword i;
264  int show_descr = 0;
265  clib_error_t *error = 0;
266  u32 hw_if_index, *hw_if_indices = 0;
267 
269  {
270  if (unformat
271  (input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
272  vec_add1 (hw_if_indices, hw_if_index);
273  else if (unformat (input, "descriptors"))
274  show_descr = 1;
275  else
276  {
277  error = clib_error_return (0, "unknown input `%U'",
278  format_unformat_error, input);
279  goto done;
280  }
281  }
282 
283  if (vec_len (hw_if_indices) == 0)
284  {
285  /* *INDENT-OFF* */
286  pool_foreach (mif, mm->interfaces,
287  vec_add1 (hw_if_indices, mif->hw_if_index);
288  );
289  /* *INDENT-ON* */
290  }
291 
292  for (hw_if_index = 0; hw_if_index < vec_len (hw_if_indices); hw_if_index++)
293  {
295  vnet_get_hw_interface (vnm, hw_if_indices[hw_if_index]);
296  mif = pool_elt_at_index (mm->interfaces, hi->dev_instance);
298  mif->socket_file_index);
299  vlib_cli_output (vm, "interface %U", format_vnet_sw_if_index_name,
300  vnm, mif->sw_if_index);
301  if (mif->remote_name)
302  vlib_cli_output (vm, " remote-name \"%s\"", mif->remote_name);
303  if (mif->remote_if_name)
304  vlib_cli_output (vm, " remote-interface \"%s\"",
305  mif->remote_if_name);
306  vlib_cli_output (vm, " id %d mode %U file %s", mif->id,
307  format_memif_if_mode, mif, msf->filename);
308  vlib_cli_output (vm, " flags%U", format_memif_if_flags, mif->flags);
309  vlib_cli_output (vm, " listener-fd %d conn-fd %d", msf->fd,
310  mif->conn_fd);
311  vlib_cli_output (vm,
312  " num-s2m-rings %u num-m2s-rings %u buffer-size %u",
313  mif->run.num_s2m_rings, mif->run.num_m2s_rings,
314  mif->run.buffer_size);
315 
316  if (mif->local_disc_string)
317  vlib_cli_output (vm, " local-disc-reason \"%s\"",
318  mif->local_disc_string);
319  if (mif->remote_disc_string)
320  vlib_cli_output (vm, " remote-disc-reason \"%s\"",
321  mif->remote_disc_string);
322 
323  vec_foreach_index (i, mif->tx_queues)
324  {
325  mq = vec_elt_at_index (mif->tx_queues, i);
326  vlib_cli_output (vm, " %U", format_memif_queue, mif, mq, i);
327  if (show_descr)
328  vlib_cli_output (vm, " %U", format_memif_descriptor, mif, mq);
329  }
330  vec_foreach_index (i, mif->rx_queues)
331  {
332  mq = vec_elt_at_index (mif->rx_queues, i);
333  vlib_cli_output (vm, " %U", format_memif_queue, mif, mq, i);
334  if (show_descr)
335  vlib_cli_output (vm, " %U", format_memif_descriptor, mif, mq);
336  }
337  }
338 done:
339  vec_free (hw_if_indices);
340  return error;
341 }
342 
343 /* *INDENT-OFF* */
344 VLIB_CLI_COMMAND (memif_show_command, static) = {
345  .path = "show memif",
346  .short_help = "show memif {<interface>] [descriptors]",
347  .function = memif_show_command_fn,
348 };
349 /* *INDENT-ON* */
350 
351 clib_error_t *
353 {
354  return 0;
355 }
356 
358 
359 /*
360  * fd.io coding-style-patch-verification: ON
361  *
362  * Local Variables:
363  * eval: (c-set-style "gnu")
364  * End:
365  */
memif_if_t * interfaces
Definition: private.h:189
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
memif_ring_t * ring
Definition: private.h:100
memif_desc_t desc[0]
Definition: memif.h:174
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
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:192
#define NULL
Definition: clib.h:55
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:169
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:522
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:983
memif_interface_mode_t mode
Definition: private.h:216
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:164
format_function_t format_vnet_sw_if_index_name
static uword min_log2(uword x)
Definition: clib.h:189
uint32_t length
Definition: memif.h:152
uint32_t buffer_length
Definition: memif.h:151
u8 * remote_name
Definition: private.h:157
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
static uword format_get_indent(u8 *s)
Definition: format.h:72
uword socket_file_index
Definition: private.h:142
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
u16 buffer_size
Definition: private.h:165
memif_log2_ring_size_t log2_ring_size
Definition: private.h:217
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:103
void * shm
Definition: private.h:86
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:119
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:397
static clib_error_t * memif_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: cli.c:256
int memif_delete_if(vlib_main_t *vm, memif_if_t *mif)
Definition: memif.c:472
struct _unformat_input_t unformat_input_t
memif_interface_id_t id
Definition: private.h:212
int memif_create_if(vlib_main_t *vm, memif_create_if_args_t *args)
Definition: memif.c:542
#define MEMIF_DEFAULT_TX_QUEUES
Definition: private.h:24
memif_queue_t * tx_queues
Definition: private.h:151
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
u8 * local_disc_string
Definition: private.h:177
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
struct memif_if_t::@331 run
static u8 * format_memif_if_mode(u8 *s, va_list *args)
Definition: cli.c:179
#define MEMIF_DEFAULT_BUFFER_SIZE
Definition: private.h:25
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
memif_region_t * regions
Definition: private.h:148
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:251
u32 flags
Definition: private.h:132
int conn_fd
Definition: private.h:143
#define MEMIF_DEFAULT_RX_QUEUES
Definition: private.h:23
u32 hw_if_index
Definition: private.h:134
u64 int_count
Definition: private.h:111
static uword is_pow2(uword x)
Definition: clib.h:272
u64 uword
Definition: types.h:112
memif_region_offset_t offset
Definition: memif.h:154
u8 num_s2m_rings
Definition: private.h:163
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:352
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
u8 * remote_if_name
Definition: private.h:158
memif_interface_id_t id
Definition: private.h:133
memif_log2_ring_size_t log2_ring_size
Definition: private.h:101
static u8 * format_memif_descriptor(u8 *s, va_list *args)
Definition: cli.c:217
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define MEMIF_DEFAULT_RING_SIZE
Definition: private.h:22
uint16_t flags
Definition: memif.h:168
u8 * remote_disc_string
Definition: private.h:178
volatile uint16_t head
Definition: memif.h:170
memif_queue_t * rx_queues
Definition: private.h:150
static u8 * format_memif_queue(u8 *s, va_list *args)
Definition: cli.c:192
u32 flags
Definition: vhost-user.h:76
memif_main_t memif_main
Definition: memif.c:42
memif_region_index_t region
Definition: private.h:102
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:680
u32 sw_if_index
Definition: private.h:135
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:137
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169