xref: /dpdk/doc/guides/prog_guide/cmdline.rst (revision 620b269600244c269e1f3698b18c47c84d9d2a25)
1449dc649SBruce Richardson..  SPDX-License-Identifier: BSD-3-Clause
2449dc649SBruce Richardson    Copyright(c) 2023 Intel Corporation.
3449dc649SBruce Richardson
4449dc649SBruce RichardsonCommand-line Library
5449dc649SBruce Richardson====================
6449dc649SBruce Richardson
7449dc649SBruce RichardsonSince its earliest versions, DPDK has included a command-line library -
8449dc649SBruce Richardsonprimarily for internal use by, for example, ``dpdk-testpmd`` and the ``dpdk-test`` binaries,
9449dc649SBruce Richardsonbut the library is also exported on install and can be used by any end application.
10449dc649SBruce RichardsonThis chapter covers the basics of the command-line library and how to use it in an application.
11449dc649SBruce Richardson
12449dc649SBruce RichardsonLibrary Features
13449dc649SBruce Richardson----------------
14449dc649SBruce Richardson
15449dc649SBruce RichardsonThe DPDK command-line library supports the following features:
16449dc649SBruce Richardson
17449dc649SBruce Richardson* Tab-completion available for interactive terminal sessions
18449dc649SBruce Richardson
19449dc649SBruce Richardson* Ability to read and process commands taken from an input file, e.g. startup script
20449dc649SBruce Richardson
21449dc649SBruce Richardson* Parameterized commands able to take multiple parameters with different datatypes:
22449dc649SBruce Richardson
23449dc649SBruce Richardson   * Strings
24449dc649SBruce Richardson   * Signed/unsigned 16/32/64-bit integers
25449dc649SBruce Richardson   * IP Addresses
26449dc649SBruce Richardson   * Ethernet Addresses
27449dc649SBruce Richardson
28449dc649SBruce Richardson* Ability to multiplex multiple commands to a single callback function
29449dc649SBruce Richardson
30449dc649SBruce RichardsonAdding Command-line to an Application
31449dc649SBruce Richardson-------------------------------------
32449dc649SBruce Richardson
33449dc649SBruce RichardsonAdding a command-line instance to an application involves a number of coding steps.
34449dc649SBruce Richardson
35449dc649SBruce Richardson#. Define the result structure for the command, specifying the command parameters
36449dc649SBruce Richardson
37449dc649SBruce Richardson#. Provide an initializer for each field in the result
38449dc649SBruce Richardson
39449dc649SBruce Richardson#. Define the callback function for the command
40449dc649SBruce Richardson
41449dc649SBruce Richardson#. Provide a parse result structure instance for the command, linking the callback to the command
42449dc649SBruce Richardson
43449dc649SBruce Richardson#. Add the parse result structure to a command-line context
44449dc649SBruce Richardson
45449dc649SBruce Richardson#. Within your main application code, create a new command-line instance passing in the context.
46449dc649SBruce Richardson
4737666691SBruce RichardsonMany of these steps can be automated using the script ``dpdk-cmdline-gen.py`` installed by DPDK,
4837666691SBruce Richardsonand found in the ``buildtools`` folder in the source tree.
4937666691SBruce RichardsonThis section covers adding a command-line using this script to generate the boiler plate,
5037666691SBruce Richardsonwhile the following section,
5137666691SBruce Richardson`Worked Example of Adding Command-line to an Application`_ covers the steps to do so manually.
5237666691SBruce Richardson
5337666691SBruce RichardsonCreating a Command List File
5437666691SBruce Richardson~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5537666691SBruce Richardson
5637666691SBruce RichardsonThe ``dpdk-cmdline-gen.py`` script takes as input a list of commands to be used by the application.
5737666691SBruce RichardsonWhile these can be piped to it via standard input, using a list file is probably best.
5837666691SBruce Richardson
5937666691SBruce RichardsonThe format of the list file must be:
6037666691SBruce Richardson
6137666691SBruce Richardson* Comment lines start with '#' as first non-whitespace character
6237666691SBruce Richardson
6337666691SBruce Richardson* One command per line
6437666691SBruce Richardson
6537666691SBruce Richardson* Variable fields are prefixed by the type-name in angle-brackets, for example:
6637666691SBruce Richardson
6737666691SBruce Richardson  * ``<STRING>message``
6837666691SBruce Richardson
6937666691SBruce Richardson  * ``<UINT16>port_id``
7037666691SBruce Richardson
7137666691SBruce Richardson  * ``<IP>src_ip``
7237666691SBruce Richardson
73fb8a2784SBruce Richardson  * ``<IPv4>dst_ip4``
74fb8a2784SBruce Richardson
75fb8a2784SBruce Richardson  * ``<IPv6>dst_ip6``
76fb8a2784SBruce Richardson
771cd1716bSBruce Richardson* Variable fields, which take their values from a list of options,
781cd1716bSBruce Richardson  have the comma-separated option list placed in braces, rather than a the type name.
791cd1716bSBruce Richardson  For example,
801cd1716bSBruce Richardson
811cd1716bSBruce Richardson  * ``<(rx,tx,rxtx)>mode``
821cd1716bSBruce Richardson
8337666691SBruce Richardson* The help text for a command is given in the form of a comment on the same line as the command
8437666691SBruce Richardson
8537666691SBruce RichardsonAn example list file, with a variety of (unrelated) commands, is shown below::
8637666691SBruce Richardson
8737666691SBruce Richardson   # example list file
8837666691SBruce Richardson   list                     # show all entries
8937666691SBruce Richardson   add <UINT16>x <UINT16>y  # add x and y
9037666691SBruce Richardson   echo <STRING>message     # print message to screen
9137666691SBruce Richardson   add socket <STRING>path  # add unix socket with the given path
921cd1716bSBruce Richardson   set mode <(rx,tx)>rxtx   # set Rx-only or Tx-only mode
9337666691SBruce Richardson   quit                     # close the application
9437666691SBruce Richardson
9537666691SBruce RichardsonRunning the Generator Script
9637666691SBruce Richardson~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9737666691SBruce Richardson
9837666691SBruce RichardsonTo generate the necessary definitions for a command-line, run ``dpdk-cmdline-gen.py`` passing the list file as parameter.
9937666691SBruce RichardsonThe script will output the generated C code to standard output,
10037666691SBruce Richardsonthe contents of which are in the form of a C header file.
10137666691SBruce RichardsonOptionally, an output filename may be specified via the ``-o/--output-file`` argument.
10237666691SBruce Richardson
10337666691SBruce RichardsonThe generated content includes:
10437666691SBruce Richardson
10537666691SBruce Richardson* The result structure definitions for each command
10637666691SBruce Richardson
10737666691SBruce Richardson* The token initializers for each structure field
10837666691SBruce Richardson
10937666691SBruce Richardson* An "extern" function prototype for the callback for each command
11037666691SBruce Richardson
11137666691SBruce Richardson* A parse context for each command, including the per-command comments as help string
11237666691SBruce Richardson
11337666691SBruce Richardson* A command-line context array definition, suitable for passing to ``cmdline_new``
11437666691SBruce Richardson
11537666691SBruce RichardsonIf so desired, the script can also output function stubs for the callback functions for each command.
11637666691SBruce RichardsonThis behaviour is triggered by passing the ``--stubs`` flag to the script.
11737666691SBruce RichardsonIn this case, an output file must be provided with a filename ending in ".h",
11837666691SBruce Richardsonand the callback stubs will be written to an equivalent ".c" file.
11937666691SBruce Richardson
12037666691SBruce Richardson.. note::
12137666691SBruce Richardson
12237666691SBruce Richardson   The stubs are written to a separate file,
12337666691SBruce Richardson   to allow continuous use of the script to regenerate the command-line header,
12437666691SBruce Richardson   without overwriting any code the user has added to the callback functions.
12537666691SBruce Richardson   This makes it easy to incrementally add new commands to an existing application.
12637666691SBruce Richardson
12737666691SBruce RichardsonProviding the Function Callbacks
12837666691SBruce Richardson~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12937666691SBruce Richardson
13037666691SBruce RichardsonAs discussed above, the script output is a header file, containing structure definitions,
13137666691SBruce Richardsonbut the callback functions themselves obviously have to be provided by the user.
13237666691SBruce RichardsonThese callback functions must be provided as non-static functions in a C file,
13337666691SBruce Richardsonand named ``cmd_<cmdname>_parsed``.
13437666691SBruce RichardsonThe function prototypes can be seen in the generated output header.
13537666691SBruce Richardson
13637666691SBruce RichardsonThe "cmdname" part of the function name is built up by combining the non-variable initial tokens in the command.
13737666691SBruce RichardsonSo, given the commands in our worked example below: ``quit`` and ``show port stats <n>``,
13837666691SBruce Richardsonthe callback functions would be:
13937666691SBruce Richardson
14037666691SBruce Richardson.. code:: c
14137666691SBruce Richardson
14237666691SBruce Richardson   void
14337666691SBruce Richardson   cmd_quit_parsed(void *parsed_result, struct cmdline *cl, void *data)
14437666691SBruce Richardson   {
14537666691SBruce Richardson        ...
14637666691SBruce Richardson   }
14737666691SBruce Richardson
14837666691SBruce Richardson   void
14937666691SBruce Richardson   cmd_show_port_stats_parsed(void *parsed_result, struct cmdline *cl, void *data)
15037666691SBruce Richardson   {
15137666691SBruce Richardson        ...
15237666691SBruce Richardson   }
15337666691SBruce Richardson
15437666691SBruce RichardsonThese functions must be provided by the developer, but, as stated above,
15537666691SBruce Richardsonstub functions may be generated by the script automatically using the ``--stubs`` parameter.
15637666691SBruce Richardson
15737666691SBruce RichardsonThe same "cmdname" stem is used in the naming of the generated structures too.
15837666691SBruce RichardsonTo get at the results structure for each command above,
15937666691SBruce Richardsonthe ``parsed_result`` parameter should be cast to ``struct cmd_quit_result``
16037666691SBruce Richardsonor ``struct cmd_show_port_stats_result`` respectively.
16137666691SBruce Richardson
162*620b2696SBruce Richardson.. note::
163*620b2696SBruce Richardson
164*620b2696SBruce Richardson  In some cases, the user may want to have an optional variable parameter at the end of a command.
165*620b2696SBruce Richardson  Such a variable parameter would not normally be included in the "cmdname" string,
166*620b2696SBruce Richardson  leading to duplicate definition errors.
167*620b2696SBruce Richardson  To work around this,
168*620b2696SBruce Richardson  any variable token with a name prefixed by ``'__'`` will be included in the "cmdname" string,
169*620b2696SBruce Richardson  with the prefix removed.
170*620b2696SBruce Richardson  Using this, it is possible to have commands, such as:
171*620b2696SBruce Richardson  ``start tx_first`` and ``start tx_first <UINT16>__n``, without them conflicting.
172*620b2696SBruce Richardson  The resulting code generated will expect functions called ``cmd_start_tx_first_parsed``
173*620b2696SBruce Richardson  and ``cmd_start_tx_first_n_parsed`` respectively.
174*620b2696SBruce Richardson
17537666691SBruce RichardsonIntegrating with the Application
17637666691SBruce Richardson~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17737666691SBruce Richardson
17837666691SBruce RichardsonTo integrate the script output with the application,
17937666691SBruce Richardsonwe must ``#include`` the generated header into our applications C file,
18037666691SBruce Richardsonand then have the command-line created via either ``cmdline_new`` or ``cmdline_stdin_new``.
18137666691SBruce RichardsonThe first parameter to the function call should be the context array in the generated header file,
18237666691SBruce Richardson``ctx`` by default. (Modifiable via script parameter).
18337666691SBruce Richardson
18437666691SBruce RichardsonThe callback functions may be in this same file, or in a separate one -
18537666691SBruce Richardsonthey just need to be available to the linker at build-time.
18637666691SBruce Richardson
18737666691SBruce RichardsonLimitations of the Script Approach
18837666691SBruce Richardson~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18937666691SBruce Richardson
19037666691SBruce RichardsonThe script approach works for most commands that a user may wish to add to an application.
19137666691SBruce RichardsonHowever, it does not support the full range of functions possible with the DPDK command-line library.
19237666691SBruce RichardsonFor example,
19337666691SBruce Richardsonit is not possible using the script to multiplex multiple commands into a single callback function.
19437666691SBruce RichardsonTo use this functionality, the user should follow the instructions in the next section
19537666691SBruce Richardson`Worked Example of Adding Command-line to an Application`_ to manually configure a command-line instance.
19637666691SBruce Richardson
19737666691SBruce RichardsonWorked Example of Adding Command-line to an Application
19837666691SBruce Richardson-------------------------------------------------------
19937666691SBruce Richardson
20037666691SBruce RichardsonThe next few subsections will cover each of the steps listed in `Adding Command-line to an Application`_ in more detail,
201449dc649SBruce Richardsonworking through an example to add two commands to a command-line instance.
202449dc649SBruce RichardsonThose two commands will be:
203449dc649SBruce Richardson
204449dc649SBruce Richardson#. ``quit`` - as the name suggests, to close the application
205449dc649SBruce Richardson
206449dc649SBruce Richardson#. ``show port stats <n>`` - to display on-screen the statistics for a given ethernet port
207449dc649SBruce Richardson
208449dc649SBruce Richardson.. note::
209449dc649SBruce Richardson
210449dc649SBruce Richardson   For further examples of use of the command-line, see
211449dc649SBruce Richardson   :doc:`cmdline example application <../sample_app_ug/cmd_line>`
212449dc649SBruce Richardson
213449dc649SBruce RichardsonDefining Command Result Structure
214449dc649SBruce Richardson~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
215449dc649SBruce Richardson
216449dc649SBruce RichardsonThe first structure to be defined is the structure which will be created on successful parse of a command.
217449dc649SBruce RichardsonThis structure contains one member field for each token, or word, in the command.
218449dc649SBruce RichardsonThe simplest case is for a one-word command, like ``quit``.
219449dc649SBruce RichardsonFor this, we only need to define a structure with a single string parameter to contain that word.
220449dc649SBruce Richardson
221449dc649SBruce Richardson.. code-block:: c
222449dc649SBruce Richardson
223449dc649SBruce Richardson   struct cmd_quit_result {
224449dc649SBruce Richardson      cmdline_fixed_string_t quit;
225449dc649SBruce Richardson   };
226449dc649SBruce Richardson
227449dc649SBruce RichardsonFor readability, the name of the struct member should match that of the token in the command.
228449dc649SBruce Richardson
229449dc649SBruce RichardsonFor our second command, we need a structure with four member fields in it,
230449dc649SBruce Richardsonas there are four words/tokens in our command.
231449dc649SBruce RichardsonThe first three are strings, and the final one is a 16-bit numeric value.
232449dc649SBruce RichardsonThe resulting struct looks like:
233449dc649SBruce Richardson
234449dc649SBruce Richardson.. code-block:: c
235449dc649SBruce Richardson
236449dc649SBruce Richardson   struct cmd_show_port_stats_result {
237449dc649SBruce Richardson      cmdline_fixed_string_t show;
238449dc649SBruce Richardson      cmdline_fixed_string_t port;
239449dc649SBruce Richardson      cmdline_fixed_string_t stats;
240449dc649SBruce Richardson      uint16_t n;
241449dc649SBruce Richardson   };
242449dc649SBruce Richardson
243449dc649SBruce RichardsonAs before, we choose names to match the tokens in the command.
244449dc649SBruce RichardsonSince our numeric parameter is a 16-bit value, we use ``uint16_t`` type for it.
245449dc649SBruce RichardsonAny of the standard sized integer types can be used as parameters, depending on the desired result.
246449dc649SBruce Richardson
247449dc649SBruce RichardsonBeyond the standard integer types,
248449dc649SBruce Richardsonthe library also allows variable parameters to be of a number of other types,
249449dc649SBruce Richardsonas called out in the feature list above.
250449dc649SBruce Richardson
251449dc649SBruce Richardson* For variable string parameters,
252449dc649SBruce Richardson  the type should be ``cmdline_fixed_string_t`` - the same as for fixed tokens,
253449dc649SBruce Richardson  but these will be initialized differently (as described below).
254449dc649SBruce Richardson
255449dc649SBruce Richardson* For ethernet addresses use type ``struct rte_ether_addr``
256449dc649SBruce Richardson
257449dc649SBruce Richardson* For IP addresses use type ``cmdline_ipaddr_t``
258449dc649SBruce Richardson
259449dc649SBruce RichardsonProviding Field Initializers
260449dc649SBruce Richardson~~~~~~~~~~~~~~~~~~~~~~~~~~~~
261449dc649SBruce Richardson
262449dc649SBruce RichardsonEach field of our result structure needs an initializer.
263449dc649SBruce RichardsonFor fixed string tokens, like "quit", "show" and "port", the initializer will be the string itself.
264449dc649SBruce Richardson
265449dc649SBruce Richardson.. code-block:: c
266449dc649SBruce Richardson
267449dc649SBruce Richardson   static cmdline_parse_token_string_t cmd_quit_quit_tok =
268449dc649SBruce Richardson      TOKEN_STRING_INITIALIZER(struct cmd_quit_result, quit, "quit");
269449dc649SBruce Richardson
270449dc649SBruce RichardsonThe convention for naming used here is to include the base name of the overall result structure -
271449dc649SBruce Richardson``cmd_quit`` in this case,
272449dc649SBruce Richardsonas well as the name of the field within that structure - ``quit`` in this case, followed by ``_tok``.
273449dc649SBruce Richardson(This is why there is a double ``quit`` in the name above).
274449dc649SBruce Richardson
275449dc649SBruce RichardsonThis naming convention is seen in our second example,
276449dc649SBruce Richardsonwhich also demonstrates how to define a numeric initializer.
277449dc649SBruce Richardson
278449dc649SBruce Richardson
279449dc649SBruce Richardson.. code-block:: c
280449dc649SBruce Richardson
281449dc649SBruce Richardson   static cmdline_parse_token_string_t cmd_show_port_stats_show_tok =
282449dc649SBruce Richardson      TOKEN_STRING_INITIALIZER(struct cmd_show_port_stats_result, show, "show");
283449dc649SBruce Richardson   static cmdline_parse_token_string_t cmd_show_port_stats_port_tok =
284449dc649SBruce Richardson      TOKEN_STRING_INITIALIZER(struct cmd_show_port_stats_result, port, "port");
285449dc649SBruce Richardson   static cmdline_parse_token_string_t cmd_show_port_stats_stats_tok =
286449dc649SBruce Richardson      TOKEN_STRING_INITIALIZER(struct cmd_show_port_stats_result, stats, "stats");
287449dc649SBruce Richardson   static cmdline_parse_token_num_t cmd_show_port_stats_n_tok =
288449dc649SBruce Richardson      TOKEN_NUM_INITIALIZER(struct cmd_show_port_stats_result, n, RTE_UINT16);
289449dc649SBruce Richardson
290449dc649SBruce RichardsonFor variable string tokens, the same ``TOKEN_STRING_INITIALIZER`` macro should be used.
291449dc649SBruce RichardsonHowever, the final parameter should be ``NULL`` rather than a hard-coded token string.
292449dc649SBruce Richardson
293449dc649SBruce RichardsonFor numeric parameters, the final parameter to the ``TOKEN_NUM_INITIALIZER`` macro should be the
294449dc649SBruce Richardsoncmdline type matching the variable type defined in the result structure,
295449dc649SBruce Richardsone.g. RTE_UINT8, RTE_UINT32, etc.
296449dc649SBruce Richardson
297449dc649SBruce RichardsonFor IP addresses, the macro ``TOKEN_IPADDR_INITIALIZER`` should be used.
298449dc649SBruce Richardson
299449dc649SBruce RichardsonFor ethernet addresses, the macro ``TOKEN_ETHERADDR_INITIALIZER`` should be used.
300449dc649SBruce Richardson
301449dc649SBruce RichardsonDefining Callback Function
302449dc649SBruce Richardson~~~~~~~~~~~~~~~~~~~~~~~~~~
303449dc649SBruce Richardson
304449dc649SBruce RichardsonFor each command, we need to define a function to be called once the command has been recognised.
305449dc649SBruce RichardsonThe callback function should have type:
306449dc649SBruce Richardson
307449dc649SBruce Richardson.. code:: c
308449dc649SBruce Richardson
309449dc649SBruce Richardson   void (*f)(void *, struct cmdline *, void *)
310449dc649SBruce Richardson
311449dc649SBruce Richardsonwhere the first parameter is a pointer to the result structure defined above,
312449dc649SBruce Richardsonthe second parameter is the command-line instance,
313449dc649SBruce Richardsonand the final parameter is a user-defined pointer provided when we associate the callback with the command.
314449dc649SBruce RichardsonMost callback functions only use the first parameter, or none at all,
315449dc649SBruce Richardsonbut the additional two parameters provide some extra flexibility,
316449dc649SBruce Richardsonto allow the callback to work with non-global state in your application.
317449dc649SBruce Richardson
318449dc649SBruce RichardsonFor our two example commands, the relevant callback functions would look very similar in definition.
319449dc649SBruce RichardsonHowever, within the function body,
320449dc649SBruce Richardsonwe assume that the user would need to reference the result structure to extract the port number in
321449dc649SBruce Richardsonthe second case.
322449dc649SBruce Richardson
323449dc649SBruce Richardson.. code:: c
324449dc649SBruce Richardson
325449dc649SBruce Richardson   void
326449dc649SBruce Richardson   cmd_quit_parsed(void *parsed_result, struct cmdline *cl, void *data)
327449dc649SBruce Richardson   {
328449dc649SBruce Richardson      quit = 1;
329449dc649SBruce Richardson   }
330449dc649SBruce Richardson   void
331449dc649SBruce Richardson   cmd_show_port_stats_parsed(void *parsed_result, struct cmdline *cl, void *data)
332449dc649SBruce Richardson   {
333449dc649SBruce Richardson      struct cmd_show_port_stats_result *res = parsed_result;
334449dc649SBruce Richardson      uint16_t port_id = res->n;
335449dc649SBruce Richardson      ...
336449dc649SBruce Richardson   }
337449dc649SBruce Richardson
338449dc649SBruce Richardson
339449dc649SBruce RichardsonAssociating Callback and Command
340449dc649SBruce Richardson~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
341449dc649SBruce Richardson
342449dc649SBruce RichardsonThe ``cmdline_parse_inst_t`` type defines a "parse instance",
343449dc649SBruce Richardsoni.e. a sequence of tokens to be matched and then an associated function to be called.
344449dc649SBruce RichardsonAlso included in the instance type are a field for help text for the command,
345449dc649SBruce Richardsonand any additional user-defined parameter to be passed to the callback functions referenced above.
346449dc649SBruce RichardsonFor example, for our simple "quit" command:
347449dc649SBruce Richardson
348449dc649SBruce Richardson.. code-block:: c
349449dc649SBruce Richardson
350449dc649SBruce Richardson   static cmdline_parse_inst_t cmd_quit = {
351449dc649SBruce Richardson       .f = cmd_quit_parsed,
352449dc649SBruce Richardson       .data = NULL,
353449dc649SBruce Richardson       .help_str = "Close the application",
354449dc649SBruce Richardson       .tokens = {
355449dc649SBruce Richardson           (void *)&cmd_quit_quit_tok,
356449dc649SBruce Richardson           NULL
357449dc649SBruce Richardson       }
358449dc649SBruce Richardson   };
359449dc649SBruce Richardson
360449dc649SBruce RichardsonIn this case, we firstly identify the callback function to be called,
361449dc649SBruce Richardsonthen set the user-defined parameter to NULL,
362449dc649SBruce Richardsonprovide a help message to be given, on request, to the user explaining the command,
363449dc649SBruce Richardsonbefore finally listing out the single token to be matched for this command instance.
364449dc649SBruce Richardson
365449dc649SBruce RichardsonFor our second, port stats, example,
366449dc649SBruce Richardsonas well as making things a little more complicated by having multiple tokens to be matched,
367449dc649SBruce Richardsonwe can also demonstrate passing in a parameter to the function.
368449dc649SBruce RichardsonLet us suppose that our application does not always use all the ports available to it,
369449dc649SBruce Richardsonbut instead only uses a subset of the ports, stored in an array called ``active_ports``.
370449dc649SBruce RichardsonOur stats command, therefore, should only display stats for the currently in-use ports,
371449dc649SBruce Richardsonso we pass this ``active_ports`` array.
372449dc649SBruce Richardson(For simplicity of illustration, we shall assume that the array uses a terminating marker,
373449dc649SBruce Richardsone.g. -1 for the end of the port list, so we don't need to pass in a length parameter too.)
374449dc649SBruce Richardson
375449dc649SBruce Richardson.. code-block:: c
376449dc649SBruce Richardson
377449dc649SBruce Richardson   extern int16_t active_ports[];
378449dc649SBruce Richardson   ...
379449dc649SBruce Richardson   static cmdline_parse_inst_t cmd_show_port_stats = {
380449dc649SBruce Richardson       .f = cmd_show_port_stats_parsed,
381449dc649SBruce Richardson       .data = active_ports,
382449dc649SBruce Richardson       .help_str = "Show statistics for active network ports",
383449dc649SBruce Richardson       .tokens = {
384449dc649SBruce Richardson           (void *)&cmd_show_port_stats_show_tok,
385449dc649SBruce Richardson           (void *)&cmd_show_port_stats_port_tok,
386449dc649SBruce Richardson           (void *)&cmd_show_port_stats_stats_tok,
387449dc649SBruce Richardson           (void *)&cmd_show_port_stats_n_tok,
388449dc649SBruce Richardson           NULL
389449dc649SBruce Richardson       }
390449dc649SBruce Richardson   };
391449dc649SBruce Richardson
392449dc649SBruce Richardson
393449dc649SBruce RichardsonAdding Command to Command-line Context
394449dc649SBruce Richardson~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
395449dc649SBruce Richardson
396449dc649SBruce RichardsonNow that we have configured each individual command and callback,
397449dc649SBruce Richardsonwe need to merge these into a single array of command-line "contexts".
398449dc649SBruce RichardsonThis context array will be used to create the actual command-line instance in the application.
399449dc649SBruce RichardsonThankfully, each context entry is the same as each parse instance,
400449dc649SBruce Richardsonso our array is defined by simply listing out the previously defined command parse instances.
401449dc649SBruce Richardson
402449dc649SBruce Richardson.. code-block:: c
403449dc649SBruce Richardson
404449dc649SBruce Richardson   static cmdline_parse_ctx_t ctx[] = {
405449dc649SBruce Richardson       &cmd_quit,
406449dc649SBruce Richardson       &cmd_show_port_stats,
407449dc649SBruce Richardson       NULL
408449dc649SBruce Richardson   };
409449dc649SBruce Richardson
410449dc649SBruce RichardsonThe context list must be terminated by a NULL entry.
411449dc649SBruce Richardson
412449dc649SBruce RichardsonCreating a Command-line Instance
413449dc649SBruce Richardson~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
414449dc649SBruce Richardson
415449dc649SBruce RichardsonOnce we have our ``ctx`` variable defined,
416449dc649SBruce Richardsonwe now just need to call the API to create the new command-line instance in our application.
417449dc649SBruce RichardsonThe basic API is ``cmdline_new`` which will create an interactive command-line with all commands available.
418449dc649SBruce RichardsonHowever, if additional features for interactive use - such as tab-completion -
419449dc649SBruce Richardsonare desired, it is recommended that ``cmdline_new_stdin`` be used instead.
420449dc649SBruce Richardson
421449dc649SBruce RichardsonA pattern that can be used in applications is to use ``cmdline_new`` for processing any startup commands,
422449dc649SBruce Richardsoneither from file or from the environment (as is done in the "dpdk-test" application),
423449dc649SBruce Richardsonand then using ``cmdline_stdin_new`` thereafter to handle the interactive part.
424449dc649SBruce RichardsonFor example, to handle a startup file and then provide an interactive prompt:
425449dc649SBruce Richardson
426449dc649SBruce Richardson.. code-block:: c
427449dc649SBruce Richardson
428449dc649SBruce Richardson   struct cmdline *cl;
429449dc649SBruce Richardson   int fd = open(startup_file, O_RDONLY);
430449dc649SBruce Richardson
431449dc649SBruce Richardson   if (fd >= 0) {
432449dc649SBruce Richardson       cl = cmdline_new(ctx, "", fd, STDOUT_FILENO);
433449dc649SBruce Richardson       if (cl == NULL) {
434449dc649SBruce Richardson           /* error handling */
435449dc649SBruce Richardson       }
436449dc649SBruce Richardson       cmdline_interact(cl);
437449dc649SBruce Richardson       cmdline_quit(cl);
438449dc649SBruce Richardson       close(fd);
439449dc649SBruce Richardson   }
440449dc649SBruce Richardson
441449dc649SBruce Richardson   cl = cmdline_stdin_new(ctx, "Proxy>> ");
442449dc649SBruce Richardson   if (cl == NULL) {
443449dc649SBruce Richardson       /* error handling */
444449dc649SBruce Richardson   }
445449dc649SBruce Richardson   cmdline_interact(cl);
446449dc649SBruce Richardson   cmdline_stdin_exit(cl);
447449dc649SBruce Richardson
448449dc649SBruce Richardson
449449dc649SBruce RichardsonMultiplexing Multiple Commands to a Single Function
450449dc649SBruce Richardson~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
451449dc649SBruce Richardson
452449dc649SBruce RichardsonTo reduce the amount of boiler-plate code needed when creating a command-line for an application,
453449dc649SBruce Richardsonit is possible to merge a number of commands together to have them call a separate function.
454449dc649SBruce RichardsonThis can be done in a number of different ways:
455449dc649SBruce Richardson
456449dc649SBruce Richardson* A callback function can be used as the target for a number of different commands.
457449dc649SBruce Richardson  Which command was used for entry to the function can be determined by examining the first parameter,
458449dc649SBruce Richardson  ``parsed_result`` in our examples above.
459449dc649SBruce Richardson
460449dc649SBruce Richardson* For simple string commands, multiple options can be concatenated using the "#" character.
461449dc649SBruce Richardson  For example: ``exit#quit``, specified as a token initializer,
462449dc649SBruce Richardson  will match either on the string "exit" or the string "quit".
463449dc649SBruce Richardson
464449dc649SBruce RichardsonAs a concrete example,
465449dc649SBruce Richardsonthese two techniques are used in the DPDK unit test application ``dpdk-test``,
466449dc649SBruce Richardsonwhere a single command ``cmdline_parse_t`` instance is used for all the "dump_<item>" test cases.
467449dc649SBruce Richardson
468449dc649SBruce Richardson.. literalinclude:: ../../../app/test/commands.c
469449dc649SBruce Richardson    :language: c
470449dc649SBruce Richardson    :start-after: Add the dump_* tests cases 8<
471449dc649SBruce Richardson    :end-before: >8 End of add the dump_* tests cases
472449dc649SBruce Richardson
473449dc649SBruce Richardson
474449dc649SBruce RichardsonExamples of Command-line Use in DPDK
475449dc649SBruce Richardson------------------------------------
476449dc649SBruce Richardson
477449dc649SBruce RichardsonTo help the user follow the steps provided above,
478449dc649SBruce Richardsonthe following DPDK files can be consulted for examples of command-line use.
479449dc649SBruce Richardson
480449dc649SBruce Richardson.. note::
481449dc649SBruce Richardson
482449dc649SBruce Richardson   This is not an exhaustive list of examples of command-line use in DPDK.
483449dc649SBruce Richardson   It is simply a list of a few files that may be of use to the application developer.
484449dc649SBruce Richardson   Some of these referenced files contain more complex examples of use that others.
485449dc649SBruce Richardson
486449dc649SBruce Richardson* ``commands.c/.h`` in ``examples/cmdline``
487449dc649SBruce Richardson
488449dc649SBruce Richardson* ``mp_commands.c/.h`` in ``examples/multi_process/simple_mp``
489449dc649SBruce Richardson
490449dc649SBruce Richardson* ``commands.c`` in ``app/test``
491