blob: fa8d5d2266eb7e48144e886a655012e50d900587 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15/*
16 * interface_cli.c: interface CLI
17 *
18 * Copyright (c) 2008 Eliot Dresselhaus
19 *
20 * Permission is hereby granted, free of charge, to any person obtaining
21 * a copy of this software and associated documentation files (the
22 * "Software"), to deal in the Software without restriction, including
23 * without limitation the rights to use, copy, modify, merge, publish,
24 * distribute, sublicense, and/or sell copies of the Software, and to
25 * permit persons to whom the Software is furnished to do so, subject to
26 * the following conditions:
27 *
28 * The above copyright notice and this permission notice shall be
29 * included in all copies or substantial portions of the Software.
30 *
31 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 */
39
Chris Luke16bcf7d2016-09-01 14:31:46 -040040/**
41 * @file
Billy McFalle9bac692017-08-11 14:05:11 -040042 * @brief Interface CLI.
43 *
44 * Source code for several CLI interface commands.
45 *
Chris Luke16bcf7d2016-09-01 14:31:46 -040046 */
47
Ed Warnickecb9cada2015-12-08 15:45:58 -070048#include <vnet/vnet.h>
49#include <vnet/ip/ip.h>
John Lobcebbb92016-04-05 15:47:43 -040050#include <vppinfra/bitmap.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010051#include <vnet/fib/ip4_fib.h>
52#include <vnet/fib/ip6_fib.h>
Eyal Bari942402b2017-07-26 11:57:04 +030053#include <vnet/l2/l2_output.h>
54#include <vnet/l2/l2_input.h>
Neale Rannsba4a5bf2020-01-09 06:43:14 +000055#include <vnet/classify/vnet_classify.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070056
Dave Barachba868bb2016-08-08 09:51:21 -040057static int
58compare_interface_names (void *a1, void *a2)
Ed Warnickecb9cada2015-12-08 15:45:58 -070059{
Dave Barachba868bb2016-08-08 09:51:21 -040060 u32 *hi1 = a1;
61 u32 *hi2 = a2;
Ed Warnickecb9cada2015-12-08 15:45:58 -070062
Dave Barachba868bb2016-08-08 09:51:21 -040063 return vnet_hw_interface_compare (vnet_get_main (), *hi1, *hi2);
Ed Warnickecb9cada2015-12-08 15:45:58 -070064}
65
66static clib_error_t *
67show_or_clear_hw_interfaces (vlib_main_t * vm,
68 unformat_input_t * input,
Benoît Ganne17814d72020-07-24 09:57:11 +020069 vlib_cli_command_t * cmd, int is_show)
Ed Warnickecb9cada2015-12-08 15:45:58 -070070{
Dave Barachba868bb2016-08-08 09:51:21 -040071 clib_error_t *error = 0;
72 vnet_main_t *vnm = vnet_get_main ();
73 vnet_interface_main_t *im = &vnm->interface_main;
74 vnet_hw_interface_t *hi;
75 u32 hw_if_index, *hw_if_indices = 0;
Benoît Ganne17814d72020-07-24 09:57:11 +020076 int i, verbose = -1, show_bond = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -070077
Ed Warnickecb9cada2015-12-08 15:45:58 -070078 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
79 {
80 /* See if user wants to show a specific interface. */
Dave Barachba868bb2016-08-08 09:51:21 -040081 if (unformat
82 (input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
83 vec_add1 (hw_if_indices, hw_if_index);
John Lobcebbb92016-04-05 15:47:43 -040084
Sean Hope679ea792016-02-22 15:12:01 -050085 /* See if user wants to show an interface with a specific hw_if_index. */
86 else if (unformat (input, "%u", &hw_if_index))
Dave Barachba868bb2016-08-08 09:51:21 -040087 vec_add1 (hw_if_indices, hw_if_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -070088
89 else if (unformat (input, "verbose"))
Dave Barachba868bb2016-08-08 09:51:21 -040090 verbose = 1; /* this is also the default */
Ed Warnickecb9cada2015-12-08 15:45:58 -070091
92 else if (unformat (input, "detail"))
93 verbose = 2;
94
95 else if (unformat (input, "brief"))
96 verbose = 0;
97
John Lobcebbb92016-04-05 15:47:43 -040098 else if (unformat (input, "bond"))
Dave Barachba868bb2016-08-08 09:51:21 -040099 {
100 show_bond = 1;
101 if (verbose < 0)
102 verbose = 0; /* default to brief for link bonding */
103 }
John Lobcebbb92016-04-05 15:47:43 -0400104
Ed Warnickecb9cada2015-12-08 15:45:58 -0700105 else
106 {
107 error = clib_error_return (0, "unknown input `%U'",
108 format_unformat_error, input);
109 goto done;
110 }
111 }
Dave Barachba868bb2016-08-08 09:51:21 -0400112
Ed Warnickecb9cada2015-12-08 15:45:58 -0700113 /* Gather interfaces. */
114 if (vec_len (hw_if_indices) == 0)
115 pool_foreach (hi, im->hw_interfaces,
116 vec_add1 (hw_if_indices, hi - im->hw_interfaces));
117
Dave Barachba868bb2016-08-08 09:51:21 -0400118 if (verbose < 0)
119 verbose = 1; /* default to verbose (except bond) */
John Lobcebbb92016-04-05 15:47:43 -0400120
Ed Warnickecb9cada2015-12-08 15:45:58 -0700121 if (is_show)
122 {
123 /* Sort by name. */
124 vec_sort_with_function (hw_if_indices, compare_interface_names);
125
126 vlib_cli_output (vm, "%U\n", format_vnet_hw_interface, vnm, 0, verbose);
127 for (i = 0; i < vec_len (hw_if_indices); i++)
128 {
129 hi = vnet_get_hw_interface (vnm, hw_if_indices[i]);
Dave Barachba868bb2016-08-08 09:51:21 -0400130 if (show_bond == 0) /* show all interfaces */
131 vlib_cli_output (vm, "%U\n", format_vnet_hw_interface, vnm,
132 hi, verbose);
133 else if ((hi->bond_info) &&
John Lobcebbb92016-04-05 15:47:43 -0400134 (hi->bond_info != VNET_HW_INTERFACE_BOND_INFO_SLAVE))
Dave Barachba868bb2016-08-08 09:51:21 -0400135 { /* show only bonded interface and all its slave interfaces */
John Lobcebbb92016-04-05 15:47:43 -0400136 int hw_idx;
Dave Barachba868bb2016-08-08 09:51:21 -0400137 vnet_hw_interface_t *shi;
138 vlib_cli_output (vm, "%U\n", format_vnet_hw_interface, vnm,
John Lobcebbb92016-04-05 15:47:43 -0400139 hi, verbose);
Dave Barachba868bb2016-08-08 09:51:21 -0400140
141 /* *INDENT-OFF* */
John Lobcebbb92016-04-05 15:47:43 -0400142 clib_bitmap_foreach (hw_idx, hi->bond_info,
Dave Barachba868bb2016-08-08 09:51:21 -0400143 ({
144 shi = vnet_get_hw_interface(vnm, hw_idx);
145 vlib_cli_output (vm, "%U\n",
146 format_vnet_hw_interface, vnm, shi, verbose);
147 }));
148 /* *INDENT-ON* */
John Lobcebbb92016-04-05 15:47:43 -0400149 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700150 }
151 }
152 else
153 {
154 for (i = 0; i < vec_len (hw_if_indices); i++)
155 {
Dave Barachba868bb2016-08-08 09:51:21 -0400156 vnet_device_class_t *dc;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700157
158 hi = vnet_get_hw_interface (vnm, hw_if_indices[i]);
159 dc = vec_elt_at_index (im->device_classes, hi->dev_class_index);
Dave Barachba868bb2016-08-08 09:51:21 -0400160
Ed Warnickecb9cada2015-12-08 15:45:58 -0700161 if (dc->clear_counters)
162 dc->clear_counters (hi->dev_instance);
163 }
164 }
165
Dave Barachba868bb2016-08-08 09:51:21 -0400166done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700167 vec_free (hw_if_indices);
168 return error;
169}
170
Benoît Ganne17814d72020-07-24 09:57:11 +0200171static clib_error_t *
172show_hw_interfaces (vlib_main_t * vm,
173 unformat_input_t * input, vlib_cli_command_t * cmd)
174{
175 return show_or_clear_hw_interfaces (vm, input, cmd, 1 /* is_show */ );
176}
177
178static clib_error_t *
179clear_hw_interfaces (vlib_main_t * vm,
180 unformat_input_t * input, vlib_cli_command_t * cmd)
181{
182 return show_or_clear_hw_interfaces (vm, input, cmd, 0 /* is_show */ );
183}
184
185
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700186/*?
Billy McFalle9bac692017-08-11 14:05:11 -0400187 * Display more detailed information about all or a list of given interfaces.
188 * The verboseness of the output can be controlled by the following optional
189 * parameters:
190 * - brief: Only show name, index and state (default for bonded interfaces).
191 * - verbose: Also display additional attributes (default for all other interfaces).
192 * - detail: Also display all remaining attributes and extended statistics.
193 *
194 * To limit the output of the command to bonded interfaces and their slave
195 * interfaces, use the '<em>bond</em>' optional parameter.
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700196 *
197 * @cliexpar
Billy McFalle9bac692017-08-11 14:05:11 -0400198 * Example of how to display default data for all interfaces:
199 * @cliexstart{show hardware-interfaces}
200 * Name Idx Link Hardware
201 * GigabitEthernet7/0/0 1 up GigabitEthernet7/0/0
202 * Ethernet address ec:f4:bb:c0:bc:fc
203 * Intel e1000
204 * carrier up full duplex speed 1000 mtu 9216
205 * rx queues 1, rx desc 1024, tx queues 3, tx desc 1024
206 * cpu socket 0
207 * GigabitEthernet7/0/1 2 up GigabitEthernet7/0/1
208 * Ethernet address ec:f4:bb:c0:bc:fd
209 * Intel e1000
210 * carrier up full duplex speed 1000 mtu 9216
211 * rx queues 1, rx desc 1024, tx queues 3, tx desc 1024
212 * cpu socket 0
213 * VirtualEthernet0/0/0 3 up VirtualEthernet0/0/0
214 * Ethernet address 02:fe:a5:a9:8b:8e
215 * VirtualEthernet0/0/1 4 up VirtualEthernet0/0/1
216 * Ethernet address 02:fe:c0:4e:3b:b0
217 * VirtualEthernet0/0/2 5 up VirtualEthernet0/0/2
218 * Ethernet address 02:fe:1f:73:92:81
219 * VirtualEthernet0/0/3 6 up VirtualEthernet0/0/3
220 * Ethernet address 02:fe:f2:25:c4:68
221 * local0 0 down local0
222 * local
223 * @cliexend
224 * Example of how to display '<em>verbose</em>' data for an interface by name and
225 * software index (where 2 is the software index):
226 * @cliexstart{show hardware-interfaces GigabitEthernet7/0/0 2 verbose}
227 * Name Idx Link Hardware
228 * GigabitEthernet7/0/0 1 up GigabitEthernet7/0/0
229 * Ethernet address ec:f4:bb:c0:bc:fc
230 * Intel e1000
231 * carrier up full duplex speed 1000 mtu 9216
232 * rx queues 1, rx desc 1024, tx queues 3, tx desc 1024
233 * cpu socket 0
234 * GigabitEthernet7/0/1 2 down GigabitEthernet7/0/1
235 * Ethernet address ec:f4:bb:c0:bc:fd
236 * Intel e1000
237 * carrier up full duplex speed 1000 mtu 9216
238 * rx queues 1, rx desc 1024, tx queues 3, tx desc 1024
239 * cpu socket 0
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700240 * @cliexend
241 ?*/
Billy McFalle9bac692017-08-11 14:05:11 -0400242/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700243VLIB_CLI_COMMAND (show_hw_interfaces_command, static) = {
244 .path = "show hardware-interfaces",
Billy McFalle9bac692017-08-11 14:05:11 -0400245 .short_help = "show hardware-interfaces [brief|verbose|detail] [bond] "
246 "[<interface> [<interface> [..]]] [<sw_idx> [<sw_idx> [..]]]",
Benoît Ganne17814d72020-07-24 09:57:11 +0200247 .function = show_hw_interfaces,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700248};
Dave Barachba868bb2016-08-08 09:51:21 -0400249/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700250
Billy McFalle9bac692017-08-11 14:05:11 -0400251
252/*?
253 * Clear the extended statistics for all or a list of given interfaces
254 * (statistics associated with the '<em>show hardware-interfaces</em>' command).
255 *
256 * @cliexpar
257 * Example of how to clear the extended statistics for all interfaces:
258 * @cliexcmd{clear hardware-interfaces}
259 * Example of how to clear the extended statistics for an interface by
260 * name and software index (where 2 is the software index):
261 * @cliexcmd{clear hardware-interfaces GigabitEthernet7/0/0 2}
262 ?*/
Dave Barachba868bb2016-08-08 09:51:21 -0400263/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700264VLIB_CLI_COMMAND (clear_hw_interface_counters_command, static) = {
265 .path = "clear hardware-interfaces",
Billy McFalle9bac692017-08-11 14:05:11 -0400266 .short_help = "clear hardware-interfaces "
267 "[<interface> [<interface> [..]]] [<sw_idx> [<sw_idx> [..]]]",
Benoît Ganne17814d72020-07-24 09:57:11 +0200268 .function = clear_hw_interfaces,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700269};
Dave Barachba868bb2016-08-08 09:51:21 -0400270/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700271
Dave Barachba868bb2016-08-08 09:51:21 -0400272static int
273sw_interface_name_compare (void *a1, void *a2)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700274{
275 vnet_sw_interface_t *si1 = a1;
276 vnet_sw_interface_t *si2 = a2;
277
Dave Barachba868bb2016-08-08 09:51:21 -0400278 return vnet_sw_interface_compare (vnet_get_main (),
279 si1->sw_if_index, si2->sw_if_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700280}
281
282static clib_error_t *
283show_sw_interfaces (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400284 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700285{
Dave Barachba868bb2016-08-08 09:51:21 -0400286 clib_error_t *error = 0;
287 vnet_main_t *vnm = vnet_get_main ();
Dave Barach525c9d02018-05-26 10:48:55 -0400288 unformat_input_t _linput, *linput = &_linput;
Dave Barachba868bb2016-08-08 09:51:21 -0400289 vnet_interface_main_t *im = &vnm->interface_main;
290 vnet_sw_interface_t *si, *sorted_sis = 0;
Damjan Marion22311502016-10-28 20:30:15 +0200291 u32 sw_if_index = ~(u32) 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700292 u8 show_addresses = 0;
Damjan Marion22311502016-10-28 20:30:15 +0200293 u8 show_features = 0;
Dave Barach7be864a2016-11-28 11:41:35 -0500294 u8 show_tag = 0;
Jon Loeliger9485d992019-11-08 15:05:23 -0600295 u8 show_vtr = 0;
Dave Barach525c9d02018-05-26 10:48:55 -0400296 int verbose = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700297
Dave Barach525c9d02018-05-26 10:48:55 -0400298 /*
299 * Get a line of input. Won't work if the user typed
300 * "show interface" and nothing more.
301 */
302 if (unformat_user (input, unformat_line_input, linput))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700303 {
Dave Barach525c9d02018-05-26 10:48:55 -0400304 while (unformat_check_input (linput) != UNFORMAT_END_OF_INPUT)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700305 {
Dave Barach525c9d02018-05-26 10:48:55 -0400306 /* See if user wants to show specific interface */
307 if (unformat
308 (linput, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
309 {
310 si = pool_elt_at_index (im->sw_interfaces, sw_if_index);
311 vec_add1 (sorted_sis, si[0]);
312 }
313 else if (unformat (linput, "address") || unformat (linput, "addr"))
314 show_addresses = 1;
315 else if (unformat (linput, "features") || unformat (linput, "feat"))
316 show_features = 1;
317 else if (unformat (linput, "tag"))
318 show_tag = 1;
Jon Loeliger9485d992019-11-08 15:05:23 -0600319 else if (unformat (linput, "vtr"))
320 show_vtr = 1;
Dave Barach525c9d02018-05-26 10:48:55 -0400321 else if (unformat (linput, "verbose"))
322 verbose = 1;
323 else
324 {
Dave Barach8fdde3c2019-05-17 10:46:40 -0400325 vec_free (sorted_sis);
Dave Barach525c9d02018-05-26 10:48:55 -0400326 error = clib_error_return (0, "unknown input `%U'",
327 format_unformat_error, linput);
328 goto done;
329 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700330 }
Dave Barach525c9d02018-05-26 10:48:55 -0400331 unformat_free (linput);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700332 }
Jon Loeliger9485d992019-11-08 15:05:23 -0600333 if (show_features || show_tag || show_vtr)
Damjan Marion22311502016-10-28 20:30:15 +0200334 {
335 if (sw_if_index == ~(u32) 0)
Dave Barach8fdde3c2019-05-17 10:46:40 -0400336 {
337 vec_free (sorted_sis);
338 return clib_error_return (0, "Interface not specified...");
339 }
Dave Barach7be864a2016-11-28 11:41:35 -0500340 }
Damjan Marion22311502016-10-28 20:30:15 +0200341
Dave Barach7be864a2016-11-28 11:41:35 -0500342 if (show_features)
343 {
Dave Barach525c9d02018-05-26 10:48:55 -0400344 vnet_interface_features_show (vm, sw_if_index, verbose);
Neale Ranns47a3d992020-09-29 15:38:51 +0000345 vlib_cli_output (vm, "%U", format_l2_input_features, sw_if_index, 1);
Eyal Bari942402b2017-07-26 11:57:04 +0300346
347 l2_output_config_t *l2_output = l2output_intf_config (sw_if_index);
348 vlib_cli_output (vm, "\nl2-output:");
349 if (l2_output->out_vtr_flag)
350 vlib_cli_output (vm, "%10s (%s)", "VTR", "--internal--");
351 vlib_cli_output (vm, "%U", format_l2_output_features,
Neale Ranns5d9df1d2018-11-09 08:19:27 -0800352 l2_output->feature_bitmap, 1);
Dave Barach8fdde3c2019-05-17 10:46:40 -0400353 vec_free (sorted_sis);
Damjan Marion22311502016-10-28 20:30:15 +0200354 return 0;
355 }
Dave Barach7be864a2016-11-28 11:41:35 -0500356 if (show_tag)
357 {
358 u8 *tag;
359 tag = vnet_get_sw_interface_tag (vnm, sw_if_index);
360 vlib_cli_output (vm, "%U: %s",
361 format_vnet_sw_if_index_name, vnm, sw_if_index,
362 tag ? (char *) tag : "(none)");
Dave Barach8fdde3c2019-05-17 10:46:40 -0400363 vec_free (sorted_sis);
Dave Barach7be864a2016-11-28 11:41:35 -0500364 return 0;
365 }
Damjan Marion22311502016-10-28 20:30:15 +0200366
Jon Loeliger9485d992019-11-08 15:05:23 -0600367 /*
368 * Show vlan tag rewrite data for one interface.
369 */
370 if (show_vtr)
371 {
372 u32 vtr_op = L2_VTR_DISABLED;
373 u32 push_dot1q = 0, tag1 = 0, tag2 = 0;
374
375 if (l2vtr_get (vm, vnm, sw_if_index,
376 &vtr_op, &push_dot1q, &tag1, &tag2) != 0)
377 {
378 vlib_cli_output (vm, "%U: Problem getting vlan tag-rewrite data",
379 format_vnet_sw_if_index_name, vnm, sw_if_index);
380 return 0;
381 }
382 vlib_cli_output (vm, "%U: VTR %0U",
383 format_vnet_sw_if_index_name, vnm, sw_if_index,
384 format_vtr, vtr_op, push_dot1q, tag1, tag2);
385 return 0;
386 }
387
Ed Warnickecb9cada2015-12-08 15:45:58 -0700388 if (!show_addresses)
Dave Barachba868bb2016-08-08 09:51:21 -0400389 vlib_cli_output (vm, "%U\n", format_vnet_sw_interface, vnm, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700390
Dave Barachba868bb2016-08-08 09:51:21 -0400391 if (vec_len (sorted_sis) == 0) /* Get all interfaces */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700392 {
393 /* Gather interfaces. */
Dave Barachba868bb2016-08-08 09:51:21 -0400394 sorted_sis =
395 vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700396 _vec_len (sorted_sis) = 0;
Dave Barach525c9d02018-05-26 10:48:55 -0400397 /* *INDENT-OFF* */
398 pool_foreach (si, im->sw_interfaces,
399 ({
400 int visible = vnet_swif_is_api_visible (si);
401 if (visible)
402 vec_add1 (sorted_sis, si[0]);}
403 ));
Ole Troand7231612018-06-07 10:17:57 +0200404 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700405 /* Sort by name. */
406 vec_sort_with_function (sorted_sis, sw_interface_name_compare);
407 }
408
409 if (show_addresses)
410 {
411 vec_foreach (si, sorted_sis)
Dave Barachba868bb2016-08-08 09:51:21 -0400412 {
Dave Barachba868bb2016-08-08 09:51:21 -0400413 ip4_main_t *im4 = &ip4_main;
414 ip6_main_t *im6 = &ip6_main;
415 ip_lookup_main_t *lm4 = &im4->lookup_main;
416 ip_lookup_main_t *lm6 = &im6->lookup_main;
417 ip_interface_address_t *ia = 0;
Dave Barachba868bb2016-08-08 09:51:21 -0400418 u32 fib_index4 = 0, fib_index6 = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700419
Dave Barachba868bb2016-08-08 09:51:21 -0400420 if (vec_len (im4->fib_index_by_sw_if_index) > si->sw_if_index)
421 fib_index4 = vec_elt (im4->fib_index_by_sw_if_index,
422 si->sw_if_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700423
Dave Barachba868bb2016-08-08 09:51:21 -0400424 if (vec_len (im6->fib_index_by_sw_if_index) > si->sw_if_index)
425 fib_index6 = vec_elt (im6->fib_index_by_sw_if_index,
426 si->sw_if_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700427
John Lo4478d8e2018-01-12 17:15:25 -0500428 ip4_fib_t *fib4 = ip4_fib_get (fib_index4);
429 ip6_fib_t *fib6 = ip6_fib_get (fib_index6);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700430
Dave Barachba868bb2016-08-08 09:51:21 -0400431 if (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
432 vlib_cli_output
433 (vm, "%U (%s): \n unnumbered, use %U",
John Lo4478d8e2018-01-12 17:15:25 -0500434 format_vnet_sw_if_index_name, vnm, si->sw_if_index,
Dave Barachba868bb2016-08-08 09:51:21 -0400435 (si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? "up" : "dn",
436 format_vnet_sw_if_index_name, vnm, si->unnumbered_sw_if_index);
Dave Barachba868bb2016-08-08 09:51:21 -0400437 else
John Lo4478d8e2018-01-12 17:15:25 -0500438 vlib_cli_output
439 (vm, "%U (%s):",
440 format_vnet_sw_if_index_name, vnm, si->sw_if_index,
441 (si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? "up" : "dn");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700442
Eyal Bari942402b2017-07-26 11:57:04 +0300443 /* Display any L2 info */
Neale Ranns47a3d992020-09-29 15:38:51 +0000444 vlib_cli_output (vm, "%U", format_l2_input, si->sw_if_index);
Dave Barachba868bb2016-08-08 09:51:21 -0400445
John Lo4478d8e2018-01-12 17:15:25 -0500446 /* *INDENT-OFF* */
Dave Barachba868bb2016-08-08 09:51:21 -0400447 /* Display any IP4 addressing info */
John Lo4478d8e2018-01-12 17:15:25 -0500448 foreach_ip_interface_address (lm4, ia, si->sw_if_index,
449 1 /* honor unnumbered */,
450 ({
451 ip4_address_t *r4 = ip_interface_address_get_address (lm4, ia);
452 if (fib4->table_id)
453 vlib_cli_output (vm, " L3 %U/%d ip4 table-id %d fib-idx %d",
454 format_ip4_address, r4, ia->address_length,
455 fib4->table_id,
456 ip4_fib_index_from_table_id (fib4->table_id));
457 else
458 vlib_cli_output (vm, " L3 %U/%d",
459 format_ip4_address, r4, ia->address_length);
460 }));
461 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700462
John Lo4478d8e2018-01-12 17:15:25 -0500463 /* *INDENT-OFF* */
Dave Barachba868bb2016-08-08 09:51:21 -0400464 /* Display any IP6 addressing info */
John Lo4478d8e2018-01-12 17:15:25 -0500465 foreach_ip_interface_address (lm6, ia, si->sw_if_index,
466 1 /* honor unnumbered */,
467 ({
468 ip6_address_t *r6 = ip_interface_address_get_address (lm6, ia);
469 if (fib6->table_id)
470 vlib_cli_output (vm, " L3 %U/%d ip6 table-id %d fib-idx %d",
471 format_ip6_address, r6, ia->address_length,
472 fib6->table_id,
473 ip6_fib_index_from_table_id (fib6->table_id));
474 else
475 vlib_cli_output (vm, " L3 %U/%d",
476 format_ip6_address, r6, ia->address_length);
477 }));
478 /* *INDENT-ON* */
Ole Troand7231612018-06-07 10:17:57 +0200479 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700480 }
Ole Troand7231612018-06-07 10:17:57 +0200481 else
482 {
483 vec_foreach (si, sorted_sis)
484 {
485 vlib_cli_output (vm, "%U\n", format_vnet_sw_interface, vnm, si);
486 }
487 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700488
Dave Barachba868bb2016-08-08 09:51:21 -0400489done:
Ole Troand7231612018-06-07 10:17:57 +0200490 vec_free (sorted_sis);
491 return error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700492}
493
Dave Barachba868bb2016-08-08 09:51:21 -0400494/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700495VLIB_CLI_COMMAND (show_sw_interfaces_command, static) = {
Dave Barach13ad1f02017-03-26 19:36:18 -0400496 .path = "show interface",
Jon Loeliger9485d992019-11-08 15:05:23 -0600497 .short_help = "show interface [address|addr|features|feat|vtr] [<interface> [<interface> [..]]] [verbose]",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700498 .function = show_sw_interfaces,
Steven Luongc5fa2b82019-04-25 11:19:49 -0700499 .is_mp_safe = 1,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700500};
Dave Barachba868bb2016-08-08 09:51:21 -0400501/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700502
503/* Root of all interface commands. */
Dave Barachba868bb2016-08-08 09:51:21 -0400504/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700505VLIB_CLI_COMMAND (vnet_cli_interface_command, static) = {
506 .path = "interface",
507 .short_help = "Interface commands",
508};
Dave Barachba868bb2016-08-08 09:51:21 -0400509/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700510
Dave Barachba868bb2016-08-08 09:51:21 -0400511/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700512VLIB_CLI_COMMAND (vnet_cli_set_interface_command, static) = {
513 .path = "set interface",
514 .short_help = "Interface commands",
515};
Dave Barachba868bb2016-08-08 09:51:21 -0400516/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700517
518static clib_error_t *
519clear_interface_counters (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400520 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700521{
Dave Barachba868bb2016-08-08 09:51:21 -0400522 vnet_main_t *vnm = vnet_get_main ();
523 vnet_interface_main_t *im = &vnm->interface_main;
524 vlib_simple_counter_main_t *sm;
525 vlib_combined_counter_main_t *cm;
Dave Barach8fdde3c2019-05-17 10:46:40 -0400526 int j, n_counters;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700527
528 n_counters = vec_len (im->combined_sw_if_counters);
529
530 for (j = 0; j < n_counters; j++)
531 {
Dave Barach8fdde3c2019-05-17 10:46:40 -0400532 im = &vnm->interface_main;
533 cm = im->combined_sw_if_counters + j;
534 vlib_clear_combined_counters (cm);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700535 }
536
537 n_counters = vec_len (im->sw_if_counters);
538
539 for (j = 0; j < n_counters; j++)
540 {
Dave Barach8fdde3c2019-05-17 10:46:40 -0400541 im = &vnm->interface_main;
542 sm = im->sw_if_counters + j;
543 vlib_clear_simple_counters (sm);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700544 }
545
546 return 0;
547}
548
Billy McFalle9bac692017-08-11 14:05:11 -0400549/*?
550 * Clear the statistics for all interfaces (statistics associated with the
551 * '<em>show interface</em>' command).
552 *
553 * @cliexpar
554 * Example of how to clear the statistics for all interfaces:
555 * @cliexcmd{clear interfaces}
556 ?*/
Dave Barachba868bb2016-08-08 09:51:21 -0400557/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700558VLIB_CLI_COMMAND (clear_interface_counters_command, static) = {
559 .path = "clear interfaces",
Billy McFalle9bac692017-08-11 14:05:11 -0400560 .short_help = "clear interfaces",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700561 .function = clear_interface_counters,
562};
Dave Barachba868bb2016-08-08 09:51:21 -0400563/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700564
Chris Luke16bcf7d2016-09-01 14:31:46 -0400565/**
566 * Parse subinterface names.
567 *
Dave Barachba868bb2016-08-08 09:51:21 -0400568 * The following subinterface syntax is supported. The first two are for
569 * backwards compatability:
570 *
571 * <intf-name> <id>
572 * - a subinterface with the name <intf-name>.<id>. The subinterface
573 * is a single dot1q vlan with vlan id <id> and exact-match semantics.
574 *
575 * <intf-name> <min_id>-<max_id>
576 * - a set of the above subinterfaces, repeating for each id
577 * in the range <min_id> to <max_id>
578 *
579 * In the following, exact-match semantics (i.e. the number of vlan tags on the
580 * packet must match the number of tags in the configuration) are used only if
581 * the keyword exact-match is present. Non-exact match is the default.
582 *
583 * <intf-name> <id> dot1q <outer_id> [exact-match]
584 * - a subinterface with the name <intf-name>.<id>. The subinterface
585 * is a single dot1q vlan with vlan id <outer_id>.
586 *
587 * <intf-name> <id> dot1q any [exact-match]
588 * - a subinterface with the name <intf-name>.<id>. The subinterface
589 * is a single dot1q vlan with any vlan id.
590 *
591 * <intf-name> <id> dot1q <outer_id> inner-dot1q <inner_id> [exact-match]
592 * - a subinterface with the name <intf-name>.<id>. The subinterface
593 * is a double dot1q vlan with outer vlan id <outer_id> and inner vlan id
594 * <inner_id>.
595 *
596 * <intf-name> <id> dot1q <outer_id> inner-dot1q any [exact-match]
597 * - a subinterface with the name <intf-name>.<id>. The subinterface
598 * is a double dot1q vlan with outer vlan id <id> and any inner vlan id.
599 *
600 * <intf-name> <id> dot1q any inner-dot1q any [exact-match]
601 *
602 * - a subinterface with the name <intf-name>.<id>. The subinterface
603 * is a double dot1q vlan with any outer vlan id and any inner vlan id.
604 *
605 * For each of the above CLI, there is a duplicate that uses the keyword
606 * "dot1ad" in place of the first "dot1q". These interfaces use ethertype
607 * 0x88ad in place of 0x8100 for the outer ethertype. Note that for double-
608 * tagged packets the inner ethertype is always 0x8100. Also note that
609 * the dot1q and dot1ad naming spaces are independent, so it is legal to
610 * have both "Gig3/0/0.1 dot1q 100" and "Gig3/0/0.2 dot1ad 100". For example:
611 *
612 * <intf-name> <id> dot1ad <outer_id> inner-dot1q <inner_id> [exact-match]
613 * - a subinterface with the name <intf-name>.<id>. The subinterface
614 * is a double dot1ad vlan with outer vlan id <outer_id> and inner vlan
615 * id <inner_id>.
616 *
617 * <intf-name> <id> untagged
618 * - a subinterface with the name <intf-name>.<id>. The subinterface
619 * has no vlan tags. Only one can be specified per interface.
620 *
621 * <intf-name> <id> default
622 * - a subinterface with the name <intf-name>.<id>. This is associated
623 * with a packet that did not match any other configured subinterface
624 * on this interface. Only one can be specified per interface.
625 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700626
627static clib_error_t *
Dave Barachba868bb2016-08-08 09:51:21 -0400628parse_vlan_sub_interfaces (unformat_input_t * input,
629 vnet_sw_interface_t * template)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700630{
Dave Barachba868bb2016-08-08 09:51:21 -0400631 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700632 u32 inner_vlan, outer_vlan;
633
Dave Barachba868bb2016-08-08 09:51:21 -0400634 if (unformat (input, "any inner-dot1q any"))
635 {
636 template->sub.eth.flags.two_tags = 1;
637 template->sub.eth.flags.outer_vlan_id_any = 1;
638 template->sub.eth.flags.inner_vlan_id_any = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700639 }
Dave Barachba868bb2016-08-08 09:51:21 -0400640 else if (unformat (input, "any"))
641 {
642 template->sub.eth.flags.one_tag = 1;
643 template->sub.eth.flags.outer_vlan_id_any = 1;
644 }
645 else if (unformat (input, "%d inner-dot1q any", &outer_vlan))
646 {
647 template->sub.eth.flags.two_tags = 1;
648 template->sub.eth.flags.inner_vlan_id_any = 1;
649 template->sub.eth.outer_vlan_id = outer_vlan;
650 }
651 else if (unformat (input, "%d inner-dot1q %d", &outer_vlan, &inner_vlan))
652 {
653 template->sub.eth.flags.two_tags = 1;
654 template->sub.eth.outer_vlan_id = outer_vlan;
655 template->sub.eth.inner_vlan_id = inner_vlan;
656 }
657 else if (unformat (input, "%d", &outer_vlan))
658 {
659 template->sub.eth.flags.one_tag = 1;
660 template->sub.eth.outer_vlan_id = outer_vlan;
661 }
662 else
663 {
664 error = clib_error_return (0, "expected dot1q config, got `%U'",
665 format_unformat_error, input);
666 goto done;
667 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700668
Dave Barachba868bb2016-08-08 09:51:21 -0400669 if (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
670 {
671 if (unformat (input, "exact-match"))
672 {
673 template->sub.eth.flags.exact_match = 1;
674 }
675 }
676
677done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700678 return error;
679}
680
681static clib_error_t *
682create_sub_interfaces (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400683 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700684{
Dave Barachba868bb2016-08-08 09:51:21 -0400685 vnet_main_t *vnm = vnet_get_main ();
686 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700687 u32 hw_if_index, sw_if_index;
Dave Barachba868bb2016-08-08 09:51:21 -0400688 vnet_hw_interface_t *hi;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700689 u32 id, id_min, id_max;
690 vnet_sw_interface_t template;
691
692 hw_if_index = ~0;
Dave Barachba868bb2016-08-08 09:51:21 -0400693 if (!unformat_user (input, unformat_vnet_hw_interface, vnm, &hw_if_index))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700694 {
695 error = clib_error_return (0, "unknown interface `%U'",
696 format_unformat_error, input);
697 goto done;
698 }
699
Dave Barachb7b92992018-10-17 10:38:51 -0400700 clib_memset (&template, 0, sizeof (template));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700701 template.sub.eth.raw_flags = 0;
702
Dave Barachba868bb2016-08-08 09:51:21 -0400703 if (unformat (input, "%d default", &id_min))
704 {
705 id_max = id_min;
706 template.sub.eth.flags.default_sub = 1;
707 }
708 else if (unformat (input, "%d untagged", &id_min))
709 {
710 id_max = id_min;
711 template.sub.eth.flags.no_tags = 1;
712 template.sub.eth.flags.exact_match = 1;
713 }
714 else if (unformat (input, "%d dot1q", &id_min))
715 {
716 /* parse dot1q config */
717 id_max = id_min;
718 error = parse_vlan_sub_interfaces (input, &template);
719 if (error)
720 goto done;
721 }
722 else if (unformat (input, "%d dot1ad", &id_min))
723 {
724 /* parse dot1ad config */
725 id_max = id_min;
726 template.sub.eth.flags.dot1ad = 1;
727 error = parse_vlan_sub_interfaces (input, &template);
728 if (error)
729 goto done;
730 }
731 else if (unformat (input, "%d-%d", &id_min, &id_max))
732 {
733 template.sub.eth.flags.one_tag = 1;
Dave Barachba868bb2016-08-08 09:51:21 -0400734 template.sub.eth.flags.exact_match = 1;
735 if (id_min > id_max)
736 goto id_error;
737 }
738 else if (unformat (input, "%d", &id_min))
739 {
740 id_max = id_min;
741 template.sub.eth.flags.one_tag = 1;
742 template.sub.eth.outer_vlan_id = id_min;
743 template.sub.eth.flags.exact_match = 1;
744 }
745 else
746 {
Ed Warnickecb9cada2015-12-08 15:45:58 -0700747 id_error:
748 error = clib_error_return (0, "expected ID or ID MIN-MAX, got `%U'",
749 format_unformat_error, input);
750 goto done;
Dave Barachba868bb2016-08-08 09:51:21 -0400751 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700752
753 hi = vnet_get_hw_interface (vnm, hw_if_index);
John Lobcebbb92016-04-05 15:47:43 -0400754
Dave Barachba868bb2016-08-08 09:51:21 -0400755 if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
756 {
757 error =
758 clib_error_return (0,
759 "not allowed as %v belong to a BondEthernet interface",
760 hi->name);
761 goto done;
762 }
John Lobcebbb92016-04-05 15:47:43 -0400763
Ed Warnickecb9cada2015-12-08 15:45:58 -0700764 for (id = id_min; id <= id_max; id++)
765 {
Dave Barachba868bb2016-08-08 09:51:21 -0400766 uword *p;
767 vnet_interface_main_t *im = &vnm->interface_main;
768 u64 sup_and_sub_key = ((u64) (hi->sw_if_index) << 32) | (u64) id;
769 u64 *kp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700770
771 p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
772 if (p)
Dave Barachba868bb2016-08-08 09:51:21 -0400773 {
774 if (CLIB_DEBUG > 0)
775 clib_warning ("sup sw_if_index %d, sub id %d already exists\n",
776 hi->sw_if_index, id);
777 continue;
778 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700779
Ed Warnickecb9cada2015-12-08 15:45:58 -0700780 template.type = VNET_SW_INTERFACE_TYPE_SUB;
Eyal Baric5b13602016-11-24 19:42:43 +0200781 template.flood_class = VNET_FLOOD_CLASS_NORMAL;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700782 template.sup_sw_if_index = hi->sw_if_index;
783 template.sub.id = id;
Eyal Baria4509cf2016-09-26 09:24:09 +0300784 if (id_min < id_max)
785 template.sub.eth.outer_vlan_id = id;
786
Ed Warnickecb9cada2015-12-08 15:45:58 -0700787 error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
Dave Barachba868bb2016-08-08 09:51:21 -0400788 if (error)
789 goto done;
Dave Barach16ad6ae2016-07-28 17:55:30 -0400790
Jon Loeligerb22e1f02019-12-19 09:03:52 -0600791 kp = clib_mem_alloc (sizeof (*kp));
792 *kp = sup_and_sub_key;
793
Ed Warnickecb9cada2015-12-08 15:45:58 -0700794 hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
795 hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
Dave Barachba868bb2016-08-08 09:51:21 -0400796 vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name,
797 vnet_get_main (), sw_if_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700798 }
799
Dave Barachba868bb2016-08-08 09:51:21 -0400800done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700801 return error;
802}
803
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700804/*?
Billy McFalle9bac692017-08-11 14:05:11 -0400805 * This command is used to add VLAN IDs to interfaces, also known as subinterfaces.
806 * The primary input to this command is the '<em>interface</em>' and '<em>subId</em>'
807 * (subinterface Id) parameters. If no additional VLAN ID is provide, the VLAN ID is
808 * assumed to be the '<em>subId</em>'. The VLAN ID and '<em>subId</em>' can be different,
809 * but this is not recommended.
810 *
811 * This command has several variations:
812 * - <b>create sub-interfaces <interface> <subId></b> - Create a subinterface to
813 * process packets with a given 802.1q VLAN ID (same value as the '<em>subId</em>').
814 *
815 * - <b>create sub-interfaces <interface> <subId> default</b> - Adding the
816 * '<em>default</em>' parameter indicates that packets with VLAN IDs that do not
817 * match any other subinterfaces should be sent to this subinterface.
818 *
819 * - <b>create sub-interfaces <interface> <subId> untagged</b> - Adding the
820 * '<em>untagged</em>' parameter indicates that packets no VLAN IDs should be sent
821 * to this subinterface.
822 *
823 * - <b>create sub-interfaces <interface> <subId>-<subId></b> - Create a range of
824 * subinterfaces to handle a range of VLAN IDs.
825 *
826 * - <b>create sub-interfaces <interface> <subId> dot1q|dot1ad <vlanId>|any [exact-match]</b> -
Paul Vinciguerrabdc0e6b2018-09-22 05:32:50 -0700827 * Use this command to specify the outer VLAN ID, to either be explicit or to make the
Billy McFalle9bac692017-08-11 14:05:11 -0400828 * VLAN ID different from the '<em>subId</em>'.
829 *
830 * - <b>create sub-interfaces <interface> <subId> dot1q|dot1ad <vlanId>|any inner-dot1q
831 * <vlanId>|any [exact-match]</b> - Use this command to specify the outer VLAN ID and
Paul Vinciguerrabdc0e6b2018-09-22 05:32:50 -0700832 * the inner VLAN ID.
Billy McFalle9bac692017-08-11 14:05:11 -0400833 *
Paul Vinciguerrabdc0e6b2018-09-22 05:32:50 -0700834 * When '<em>dot1q</em>' or '<em>dot1ad</em>' is explicitly entered, subinterfaces
Billy McFalle9bac692017-08-11 14:05:11 -0400835 * can be configured as either exact-match or non-exact match. Non-exact match is the CLI
836 * default. If '<em>exact-match</em>' is specified, packets must have the same number of
837 * VLAN tags as the configuration. For non-exact-match, packets must at least that number
838 * of tags. L3 (routed) interfaces must be configured as exact-match. L2 interfaces are
839 * typically configured as non-exact-match. If '<em>dot1q</em>' or '<em>dot1ad</em>' is NOT
840 * entered, then the default behavior is exact-match.
841 *
842 * Use the '<em>show interface</em>' command to display all subinterfaces.
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700843 *
844 * @cliexpar
Billy McFalle9bac692017-08-11 14:05:11 -0400845 * @parblock
846 * Example of how to create a VLAN subinterface 11 to process packets on 802.1q VLAN ID 11:
847 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 11}
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700848 *
Billy McFalle9bac692017-08-11 14:05:11 -0400849 * The previous example is shorthand and is equivalent to:
850 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 11 dot1q 11 exact-match}
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700851 *
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700852 *
Billy McFalle9bac692017-08-11 14:05:11 -0400853 * Example of how to create a subinterface number that is different from the VLAN ID:
854 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 11 dot1q 100}
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700855 *
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700856 *
Billy McFalle9bac692017-08-11 14:05:11 -0400857 * Examples of how to create q-in-q and q-in-any subinterfaces:
858 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 11 dot1q 100 inner-dot1q 200}
859 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 12 dot1q 100 inner-dot1q any}
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700860 *
Billy McFalle9bac692017-08-11 14:05:11 -0400861 * Examples of how to create dot1ad interfaces:
862 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 11 dot1ad 11}
863 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 12 dot1ad 100 inner-dot1q 200}
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700864 *
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700865 *
Billy McFalle9bac692017-08-11 14:05:11 -0400866 * Examples of '<em>exact-match</em>' versus non-exact match. A packet with
867 * outer VLAN 100 and inner VLAN 200 would match this interface, because the default
868 * is non-exact match:
869 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 5 dot1q 100}
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700870 *
Billy McFalle9bac692017-08-11 14:05:11 -0400871 * However, the same packet would NOT match this interface because '<em>exact-match</em>'
872 * is specified and only one VLAN is configured, but packet contains two VLANs:
873 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 5 dot1q 100 exact-match}
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700874 *
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700875 *
Billy McFalle9bac692017-08-11 14:05:11 -0400876 * Example of how to created a subinterface to process untagged packets:
877 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 5 untagged}
878 *
879 * Example of how to created a subinterface to process any packet with a VLAN ID that
880 * does not match any other subinterface:
881 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 7 default}
882 *
883 * When subinterfaces are created, they are in the down state. Example of how to
884 * enable a newly created subinterface:
885 * @cliexcmd{set interface GigabitEthernet2/0/0.7 up}
886 * @endparblock
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700887 ?*/
Billy McFalle9bac692017-08-11 14:05:11 -0400888/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700889VLIB_CLI_COMMAND (create_sub_interfaces_command, static) = {
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700890 .path = "create sub-interfaces",
Billy McFalle9bac692017-08-11 14:05:11 -0400891 .short_help = "create sub-interfaces <interface> "
892 "{<subId> [default|untagged]} | "
893 "{<subId>-<subId>} | "
894 "{<subId> dot1q|dot1ad <vlanId>|any [inner-dot1q <vlanId>|any] [exact-match]}",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700895 .function = create_sub_interfaces,
896};
Dave Barachba868bb2016-08-08 09:51:21 -0400897/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700898
899static clib_error_t *
900set_state (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400901 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700902{
Dave Barachba868bb2016-08-08 09:51:21 -0400903 vnet_main_t *vnm = vnet_get_main ();
904 clib_error_t *error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700905 u32 sw_if_index, flags;
906
907 sw_if_index = ~0;
Dave Barachba868bb2016-08-08 09:51:21 -0400908 if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700909 {
910 error = clib_error_return (0, "unknown interface `%U'",
911 format_unformat_error, input);
912 goto done;
913 }
914
Dave Barachba868bb2016-08-08 09:51:21 -0400915 if (!unformat (input, "%U", unformat_vnet_sw_interface_flags, &flags))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700916 {
917 error = clib_error_return (0, "unknown flags `%U'",
918 format_unformat_error, input);
919 goto done;
920 }
921
922 error = vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
923 if (error)
924 goto done;
925
Dave Barachba868bb2016-08-08 09:51:21 -0400926done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700927 return error;
928}
929
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700930
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700931/*?
Billy McFalle9bac692017-08-11 14:05:11 -0400932 * This command is used to change the admin state (up/down) of an interface.
933 *
934 * If an interface is down, the optional '<em>punt</em>' flag can also be set.
935 * The '<em>punt</em>' flag implies the interface is disabled for forwarding
936 * but punt all traffic to slow-path. Use the '<em>enable</em>' flag to clear
937 * '<em>punt</em>' flag (interface is still down).
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700938 *
939 * @cliexpar
Billy McFalle9bac692017-08-11 14:05:11 -0400940 * Example of how to configure the admin state of an interface to '<em>up</em?':
941 * @cliexcmd{set interface state GigabitEthernet2/0/0 up}
942 * Example of how to configure the admin state of an interface to '<em>down</em?':
943 * @cliexcmd{set interface state GigabitEthernet2/0/0 down}
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700944 ?*/
Billy McFalle9bac692017-08-11 14:05:11 -0400945/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700946VLIB_CLI_COMMAND (set_state_command, static) = {
947 .path = "set interface state",
Billy McFalle9bac692017-08-11 14:05:11 -0400948 .short_help = "set interface state <interface> [up|down|punt|enable]",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700949 .function = set_state,
950};
Dave Barachba868bb2016-08-08 09:51:21 -0400951/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700952
953static clib_error_t *
954set_unnumbered (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400955 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700956{
Dave Barachba868bb2016-08-08 09:51:21 -0400957 vnet_main_t *vnm = vnet_get_main ();
Neale Ranns2ae2bc52018-03-16 03:22:39 -0700958 u32 unnumbered_sw_if_index = ~0;
959 u32 inherit_from_sw_if_index = ~0;
960 int enable = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700961
Igor Mikhailov (imichail)ab3e42b2016-09-25 15:11:53 -0700962 if (unformat (input, "%U use %U",
963 unformat_vnet_sw_interface, vnm, &unnumbered_sw_if_index,
964 unformat_vnet_sw_interface, vnm, &inherit_from_sw_if_index))
Neale Ranns2ae2bc52018-03-16 03:22:39 -0700965 enable = 1;
Igor Mikhailov (imichail)ab3e42b2016-09-25 15:11:53 -0700966 else if (unformat (input, "del %U",
967 unformat_vnet_sw_interface, vnm,
968 &unnumbered_sw_if_index))
Neale Ranns2ae2bc52018-03-16 03:22:39 -0700969 enable = 0;
Igor Mikhailov (imichail)ab3e42b2016-09-25 15:11:53 -0700970 else
971 return clib_error_return (0, "parse error '%U'",
972 format_unformat_error, input);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700973
Neale Ranns2ae2bc52018-03-16 03:22:39 -0700974 if (~0 == unnumbered_sw_if_index)
975 return clib_error_return (0, "Specify the unnumbered interface");
976 if (enable && ~0 == inherit_from_sw_if_index)
Paul Vinciguerrabdc0e6b2018-09-22 05:32:50 -0700977 return clib_error_return (0, "When enabling unnumbered specify the"
Neale Ranns2ae2bc52018-03-16 03:22:39 -0700978 " IP enabled interface that it uses");
Neale Ranns898273f2017-03-18 02:57:38 -0700979
Neale Ranns2ae2bc52018-03-16 03:22:39 -0700980 vnet_sw_interface_update_unnumbered (unnumbered_sw_if_index,
981 inherit_from_sw_if_index, enable);
Neale Ranns898273f2017-03-18 02:57:38 -0700982
Neale Ranns2ae2bc52018-03-16 03:22:39 -0700983 return (NULL);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700984}
985
Dave Barachba868bb2016-08-08 09:51:21 -0400986/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700987VLIB_CLI_COMMAND (set_unnumbered_command, static) = {
988 .path = "set interface unnumbered",
Billy McFalle9bac692017-08-11 14:05:11 -0400989 .short_help = "set interface unnumbered [<interface> use <interface> | del <interface>]",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700990 .function = set_unnumbered,
991};
Dave Barachba868bb2016-08-08 09:51:21 -0400992/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700993
994
995
996static clib_error_t *
997set_hw_class (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400998 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700999{
Dave Barachba868bb2016-08-08 09:51:21 -04001000 vnet_main_t *vnm = vnet_get_main ();
1001 vnet_interface_main_t *im = &vnm->interface_main;
1002 clib_error_t *error;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001003 u32 hw_if_index, hw_class_index;
1004
1005 hw_if_index = ~0;
Dave Barachba868bb2016-08-08 09:51:21 -04001006 if (!unformat_user (input, unformat_vnet_hw_interface, vnm, &hw_if_index))
Ed Warnickecb9cada2015-12-08 15:45:58 -07001007 {
1008 error = clib_error_return (0, "unknown hardware interface `%U'",
1009 format_unformat_error, input);
1010 goto done;
1011 }
1012
Dave Barachba868bb2016-08-08 09:51:21 -04001013 if (!unformat_user (input, unformat_hash_string,
1014 im->hw_interface_class_by_name, &hw_class_index))
Ed Warnickecb9cada2015-12-08 15:45:58 -07001015 {
1016 error = clib_error_return (0, "unknown hardware class `%U'",
1017 format_unformat_error, input);
1018 goto done;
1019 }
1020
1021 error = vnet_hw_interface_set_class (vnm, hw_if_index, hw_class_index);
1022 if (error)
1023 goto done;
1024
Dave Barachba868bb2016-08-08 09:51:21 -04001025done:
Ed Warnickecb9cada2015-12-08 15:45:58 -07001026 return error;
1027}
1028
Dave Barachba868bb2016-08-08 09:51:21 -04001029/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001030VLIB_CLI_COMMAND (set_hw_class_command, static) = {
1031 .path = "set interface hw-class",
1032 .short_help = "Set interface hardware class",
1033 .function = set_hw_class,
1034};
Dave Barachba868bb2016-08-08 09:51:21 -04001035/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001036
Dave Barachba868bb2016-08-08 09:51:21 -04001037static clib_error_t *
1038vnet_interface_cli_init (vlib_main_t * vm)
1039{
1040 return 0;
1041}
Ed Warnickecb9cada2015-12-08 15:45:58 -07001042
1043VLIB_INIT_FUNCTION (vnet_interface_cli_init);
1044
Dave Barachba868bb2016-08-08 09:51:21 -04001045static clib_error_t *
Ed Warnickecb9cada2015-12-08 15:45:58 -07001046renumber_interface_command_fn (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -04001047 unformat_input_t * input,
1048 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001049{
1050 u32 hw_if_index;
1051 u32 new_dev_instance;
Dave Barachba868bb2016-08-08 09:51:21 -04001052 vnet_main_t *vnm = vnet_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -07001053 int rv;
1054
Dave Barachba868bb2016-08-08 09:51:21 -04001055 if (!unformat_user (input, unformat_vnet_hw_interface, vnm, &hw_if_index))
Ed Warnickecb9cada2015-12-08 15:45:58 -07001056 return clib_error_return (0, "unknown hardware interface `%U'",
Dave Barachba868bb2016-08-08 09:51:21 -04001057 format_unformat_error, input);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001058
Dave Barachba868bb2016-08-08 09:51:21 -04001059 if (!unformat (input, "%d", &new_dev_instance))
Ed Warnickecb9cada2015-12-08 15:45:58 -07001060 return clib_error_return (0, "new dev instance missing");
1061
1062 rv = vnet_interface_name_renumber (hw_if_index, new_dev_instance);
1063
1064 switch (rv)
1065 {
1066 case 0:
1067 break;
1068
1069 default:
1070 return clib_error_return (0, "vnet_interface_name_renumber returned %d",
Dave Barachba868bb2016-08-08 09:51:21 -04001071 rv);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001072
1073 }
1074
1075 return 0;
1076}
1077
1078
Dave Barachba868bb2016-08-08 09:51:21 -04001079/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001080VLIB_CLI_COMMAND (renumber_interface_command, static) = {
1081 .path = "renumber interface",
Billy McFalle9bac692017-08-11 14:05:11 -04001082 .short_help = "renumber interface <interface> <new-dev-instance>",
Ed Warnickecb9cada2015-12-08 15:45:58 -07001083 .function = renumber_interface_command_fn,
1084};
Dave Barachba868bb2016-08-08 09:51:21 -04001085/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001086
Damjan Marion8358ff92016-04-15 14:26:00 +02001087static clib_error_t *
1088promiscuous_cmd (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -04001089 unformat_input_t * input, vlib_cli_command_t * cmd)
Damjan Marion8358ff92016-04-15 14:26:00 +02001090{
Dave Barachba868bb2016-08-08 09:51:21 -04001091 vnet_main_t *vnm = vnet_get_main ();
Damjan Marion8358ff92016-04-15 14:26:00 +02001092 u32 hw_if_index;
1093 u32 flags = ETHERNET_INTERFACE_FLAG_ACCEPT_ALL;
Dave Barachba868bb2016-08-08 09:51:21 -04001094 ethernet_main_t *em = &ethernet_main;
1095 ethernet_interface_t *eif;
Damjan Marion8358ff92016-04-15 14:26:00 +02001096
1097 if (unformat (input, "on %U",
Dave Barachba868bb2016-08-08 09:51:21 -04001098 unformat_vnet_hw_interface, vnm, &hw_if_index))
Damjan Marion8358ff92016-04-15 14:26:00 +02001099 ;
1100 else if (unformat (input, "off %U",
Dave Barachba868bb2016-08-08 09:51:21 -04001101 unformat_ethernet_interface, vnm, &hw_if_index))
Damjan Marion8358ff92016-04-15 14:26:00 +02001102 flags = 0;
1103 else
1104 return clib_error_return (0, "unknown input `%U'",
Dave Barachba868bb2016-08-08 09:51:21 -04001105 format_unformat_error, input);
Damjan Marion8358ff92016-04-15 14:26:00 +02001106
1107 eif = ethernet_get_interface (em, hw_if_index);
1108 if (!eif)
1109 return clib_error_return (0, "not supported");
1110
1111 ethernet_set_flags (vnm, hw_if_index, flags);
1112 return 0;
1113}
1114
Dave Barachba868bb2016-08-08 09:51:21 -04001115/* *INDENT-OFF* */
Damjan Marion8358ff92016-04-15 14:26:00 +02001116VLIB_CLI_COMMAND (set_interface_promiscuous_cmd, static) = {
1117 .path = "set interface promiscuous",
Billy McFalle9bac692017-08-11 14:05:11 -04001118 .short_help = "set interface promiscuous [on|off] <interface>",
Damjan Marion8358ff92016-04-15 14:26:00 +02001119 .function = promiscuous_cmd,
1120};
Dave Barachba868bb2016-08-08 09:51:21 -04001121/* *INDENT-ON* */
Damjan Marion8358ff92016-04-15 14:26:00 +02001122
1123static clib_error_t *
1124mtu_cmd (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
1125{
Dave Barachba868bb2016-08-08 09:51:21 -04001126 vnet_main_t *vnm = vnet_get_main ();
Ole Troand7231612018-06-07 10:17:57 +02001127 u32 hw_if_index, sw_if_index, mtu;
Damjan Marionfe7d4a22018-04-13 19:43:39 +02001128 ethernet_main_t *em = &ethernet_main;
Ole Troand7231612018-06-07 10:17:57 +02001129 u32 mtus[VNET_N_MTU] = { 0, 0, 0, 0 };
Damjan Marion8358ff92016-04-15 14:26:00 +02001130
Damjan Marionfe7d4a22018-04-13 19:43:39 +02001131 if (unformat (input, "%d %U", &mtu,
1132 unformat_vnet_hw_interface, vnm, &hw_if_index))
Damjan Marion8358ff92016-04-15 14:26:00 +02001133 {
Ole Troand7231612018-06-07 10:17:57 +02001134 /*
1135 * Change physical MTU on interface. Only supported for Ethernet
1136 * interfaces
1137 */
Damjan Marionfe7d4a22018-04-13 19:43:39 +02001138 vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1139 ethernet_interface_t *eif = ethernet_get_interface (em, hw_if_index);
1140
1141 if (!eif)
1142 return clib_error_return (0, "not supported");
1143
1144 if (mtu < hi->min_supported_packet_bytes)
1145 return clib_error_return (0, "Invalid mtu (%d): "
1146 "must be >= min pkt bytes (%d)", mtu,
1147 hi->min_supported_packet_bytes);
1148
1149 if (mtu > hi->max_supported_packet_bytes)
1150 return clib_error_return (0, "Invalid mtu (%d): must be <= (%d)", mtu,
1151 hi->max_supported_packet_bytes);
1152
1153 vnet_hw_interface_set_mtu (vnm, hw_if_index, mtu);
Ole Troand7231612018-06-07 10:17:57 +02001154 goto done;
Damjan Marion8358ff92016-04-15 14:26:00 +02001155 }
Ole Troand7231612018-06-07 10:17:57 +02001156 else if (unformat (input, "packet %d %U", &mtu,
1157 unformat_vnet_sw_interface, vnm, &sw_if_index))
1158 /* Set default packet MTU (including L3 header */
1159 mtus[VNET_MTU_L3] = mtu;
1160 else if (unformat (input, "ip4 %d %U", &mtu,
1161 unformat_vnet_sw_interface, vnm, &sw_if_index))
1162 mtus[VNET_MTU_IP4] = mtu;
1163 else if (unformat (input, "ip6 %d %U", &mtu,
1164 unformat_vnet_sw_interface, vnm, &sw_if_index))
1165 mtus[VNET_MTU_IP6] = mtu;
1166 else if (unformat (input, "mpls %d %U", &mtu,
1167 unformat_vnet_sw_interface, vnm, &sw_if_index))
1168 mtus[VNET_MTU_MPLS] = mtu;
Damjan Marion8358ff92016-04-15 14:26:00 +02001169 else
Damjan Marionfe7d4a22018-04-13 19:43:39 +02001170 return clib_error_return (0, "unknown input `%U'",
1171 format_unformat_error, input);
Ole Troand7231612018-06-07 10:17:57 +02001172
1173 vnet_sw_interface_set_protocol_mtu (vnm, sw_if_index, mtus);
1174
1175done:
Damjan Marion8358ff92016-04-15 14:26:00 +02001176 return 0;
1177}
1178
Dave Barachba868bb2016-08-08 09:51:21 -04001179/* *INDENT-OFF* */
Damjan Marion8358ff92016-04-15 14:26:00 +02001180VLIB_CLI_COMMAND (set_interface_mtu_cmd, static) = {
1181 .path = "set interface mtu",
Ole Troand7231612018-06-07 10:17:57 +02001182 .short_help = "set interface mtu [packet|ip4|ip6|mpls] <value> <interface>",
Damjan Marion8358ff92016-04-15 14:26:00 +02001183 .function = mtu_cmd,
1184};
Dave Barachba868bb2016-08-08 09:51:21 -04001185/* *INDENT-ON* */
Damjan Marion8358ff92016-04-15 14:26:00 +02001186
Pavel Kotucekc631f2d2016-09-26 10:40:02 +02001187static clib_error_t *
Matthew Smithe0792fd2019-07-12 11:48:24 -05001188show_interface_sec_mac_addr_fn (vlib_main_t * vm, unformat_input_t * input,
1189 vlib_cli_command_t * cmd)
1190{
1191 vnet_main_t *vnm = vnet_get_main ();
1192 vnet_interface_main_t *im = &vnm->interface_main;
1193 ethernet_main_t *em = &ethernet_main;
1194 u32 sw_if_index = ~0;
1195 vnet_sw_interface_t *si, *sorted_sis = 0;
1196
1197 if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
1198 {
1199 si = pool_elt_at_index (im->sw_interfaces, sw_if_index);
1200 vec_add1 (sorted_sis, si[0]);
1201 }
1202
1203 /* if an interface name was not passed, get all interfaces */
1204 if (vec_len (sorted_sis) == 0)
1205 {
1206 sorted_sis =
1207 vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces));
1208 _vec_len (sorted_sis) = 0;
1209 /* *INDENT-OFF* */
1210 pool_foreach (si, im->sw_interfaces,
1211 ({
1212 int visible = vnet_swif_is_api_visible (si);
1213 if (visible)
1214 vec_add1 (sorted_sis, si[0]);}
1215 ));
1216 /* *INDENT-ON* */
1217 /* Sort by name. */
1218 vec_sort_with_function (sorted_sis, sw_interface_name_compare);
1219 }
1220
1221 vec_foreach (si, sorted_sis)
1222 {
1223 vnet_sw_interface_t *sup_si;
1224 ethernet_interface_t *ei;
1225
1226 sup_si = vnet_get_sup_sw_interface (vnm, si->sw_if_index);
1227 ei = ethernet_get_interface (em, sup_si->hw_if_index);
1228
1229 vlib_cli_output (vm, "%U (%s):",
1230 format_vnet_sw_if_index_name, vnm, si->sw_if_index,
1231 (si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
1232 "up" : "dn");
1233
1234 if (ei && ei->secondary_addrs)
1235 {
Benoît Ganneb44c77d2020-10-20 16:24:17 +02001236 ethernet_interface_address_t *sec_addr;
Matthew Smithe0792fd2019-07-12 11:48:24 -05001237
1238 vec_foreach (sec_addr, ei->secondary_addrs)
1239 {
Benoît Ganneb44c77d2020-10-20 16:24:17 +02001240 vlib_cli_output (vm, " %U", format_mac_address_t, &sec_addr->mac);
Matthew Smithe0792fd2019-07-12 11:48:24 -05001241 }
1242 }
1243 }
1244
1245 vec_free (sorted_sis);
1246 return 0;
1247}
1248
1249/*?
1250 * This command is used to display interface secondary mac addresses.
1251 *
1252 * @cliexpar
1253 * Example of how to display interface secondary mac addresses:
1254 * @cliexstart{show interface secondary-mac-address}
1255 * @cliexend
1256?*/
1257/* *INDENT-OFF* */
1258VLIB_CLI_COMMAND (show_interface_sec_mac_addr, static) = {
1259 .path = "show interface secondary-mac-address",
1260 .short_help = "show interface secondary-mac-address [<interface>]",
1261 .function = show_interface_sec_mac_addr_fn,
1262};
1263/* *INDENT-ON* */
1264
1265static clib_error_t *
1266interface_add_del_mac_address (vlib_main_t * vm, unformat_input_t * input,
1267 vlib_cli_command_t * cmd)
1268{
1269 vnet_main_t *vnm = vnet_get_main ();
1270 vnet_sw_interface_t *si = NULL;
1271 clib_error_t *error = 0;
1272 u32 sw_if_index = ~0;
1273 u8 mac[6] = { 0 };
1274 u8 is_add, is_del;
1275
1276 is_add = is_del = 0;
1277
1278 if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
1279 {
1280 error = clib_error_return (0, "unknown interface `%U'",
1281 format_unformat_error, input);
1282 goto done;
1283 }
1284 if (!unformat_user (input, unformat_ethernet_address, mac))
1285 {
1286 error = clib_error_return (0, "expected mac address `%U'",
1287 format_unformat_error, input);
1288 goto done;
1289 }
1290
1291 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1292 {
1293 if (unformat (input, "add"))
1294 is_add = 1;
1295 else if (unformat (input, "del"))
1296 is_del = 1;
1297 else
1298 break;
1299 }
1300
1301 if (is_add == is_del)
1302 {
1303 error = clib_error_return (0, "must choose one of add or del");
1304 goto done;
1305 }
1306
1307 si = vnet_get_sw_interface (vnm, sw_if_index);
1308 error =
1309 vnet_hw_interface_add_del_mac_address (vnm, si->hw_if_index, mac, is_add);
1310
1311done:
1312 return error;
1313}
1314
1315/*?
1316 * The '<em>set interface secondary-mac-address </em>' command allows adding
1317 * or deleting extra MAC addresses on a given interface without changing the
1318 * default MAC address. This could allow packets sent to these MAC addresses
1319 * to be received without setting the interface to promiscuous mode.
1320 * Not all interfaces support this operation. The ones that do are mostly
1321 * hardware NICs, though virtio does also.
1322 *
1323 * @cliexpar
1324 * @parblock
1325 * Example of how to add a secondary MAC Address on an interface:
1326 * @cliexcmd{set interface secondary-mac-address GigabitEthernet0/8/0 aa:bb:cc:dd:ee:01 add}
1327 * Example of how to delete a secondary MAC address from an interface:
1328 * @cliexcmd{set interface secondary-mac-address GigabitEthernet0/8/0 aa:bb:cc:dd:ee:01 del}
1329 * @endparblock
1330?*/
1331/* *INDENT-OFF* */
1332VLIB_CLI_COMMAND (interface_add_del_mac_address_cmd, static) = {
1333 .path = "set interface secondary-mac-address",
1334 .short_help = "set interface secondary-mac-address <interface> <mac-address> [(add|del)]",
1335 .function = interface_add_del_mac_address,
1336};
1337/* *INDENT-ON* */
1338
1339static clib_error_t *
Pavel Kotucekc631f2d2016-09-26 10:40:02 +02001340set_interface_mac_address (vlib_main_t * vm, unformat_input_t * input,
1341 vlib_cli_command_t * cmd)
1342{
1343 vnet_main_t *vnm = vnet_get_main ();
Neale Rannsd867a7c2017-10-04 02:29:07 -07001344 vnet_sw_interface_t *si = NULL;
Pavel Kotucekc631f2d2016-09-26 10:40:02 +02001345 clib_error_t *error = 0;
1346 u32 sw_if_index = ~0;
John Lo62fcc0a2017-10-31 14:31:10 -04001347 u8 mac[6] = { 0 };
Pavel Kotucekc631f2d2016-09-26 10:40:02 +02001348
1349 if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
1350 {
1351 error = clib_error_return (0, "unknown interface `%U'",
1352 format_unformat_error, input);
1353 goto done;
1354 }
John Lo62fcc0a2017-10-31 14:31:10 -04001355 if (!unformat_user (input, unformat_ethernet_address, mac))
Pavel Kotucekc631f2d2016-09-26 10:40:02 +02001356 {
1357 error = clib_error_return (0, "expected mac address `%U'",
1358 format_unformat_error, input);
1359 goto done;
1360 }
Neale Rannsd867a7c2017-10-04 02:29:07 -07001361 si = vnet_get_sw_interface (vnm, sw_if_index);
1362 error = vnet_hw_interface_change_mac_address (vnm, si->hw_if_index, mac);
Pavel Kotucekc631f2d2016-09-26 10:40:02 +02001363done:
1364 return error;
1365}
1366
1367/*?
1368 * The '<em>set interface mac address </em>' command allows to set MAC address of given interface.
1369 * In case of NIC interfaces the one has to support MAC address change. A side effect of MAC address
1370 * change are changes of MAC addresses in FIB tables (ipv4 and ipv6).
1371 *
1372 * @cliexpar
1373 * @parblock
1374 * Example of how to change MAC Address of interface:
1375 * @cliexcmd{set interface mac address GigabitEthernet0/8/0 aa:bb:cc:dd:ee:01}
1376 * @cliexcmd{set interface mac address host-vpp0 aa:bb:cc:dd:ee:02}
1377 * @cliexcmd{set interface mac address tap-0 aa:bb:cc:dd:ee:03}
1378 * @cliexcmd{set interface mac address pg0 aa:bb:cc:dd:ee:04}
1379 * @endparblock
1380?*/
1381/* *INDENT-OFF* */
1382VLIB_CLI_COMMAND (set_interface_mac_address_cmd, static) = {
1383 .path = "set interface mac address",
Billy McFalle9bac692017-08-11 14:05:11 -04001384 .short_help = "set interface mac address <interface> <mac-address>",
Pavel Kotucekc631f2d2016-09-26 10:40:02 +02001385 .function = set_interface_mac_address,
1386};
1387/* *INDENT-ON* */
1388
Dave Barach7be864a2016-11-28 11:41:35 -05001389static clib_error_t *
1390set_tag (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
1391{
1392 vnet_main_t *vnm = vnet_get_main ();
1393 u32 sw_if_index = ~0;
1394 u8 *tag = 0;
1395
1396 if (!unformat (input, "%U %s", unformat_vnet_sw_interface,
1397 vnm, &sw_if_index, &tag))
1398 return clib_error_return (0, "unknown input `%U'",
1399 format_unformat_error, input);
1400
1401 vnet_set_sw_interface_tag (vnm, tag, sw_if_index);
1402
1403 return 0;
1404}
1405
1406/* *INDENT-OFF* */
1407VLIB_CLI_COMMAND (set_tag_command, static) = {
1408 .path = "set interface tag",
Billy McFalle9bac692017-08-11 14:05:11 -04001409 .short_help = "set interface tag <interface> <tag>",
Dave Barach7be864a2016-11-28 11:41:35 -05001410 .function = set_tag,
1411};
1412/* *INDENT-ON* */
1413
1414static clib_error_t *
1415clear_tag (vlib_main_t * vm, unformat_input_t * input,
1416 vlib_cli_command_t * cmd)
1417{
1418 vnet_main_t *vnm = vnet_get_main ();
1419 u32 sw_if_index = ~0;
1420
1421 if (!unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
1422 return clib_error_return (0, "unknown input `%U'",
1423 format_unformat_error, input);
1424
1425 vnet_clear_sw_interface_tag (vnm, sw_if_index);
1426
1427 return 0;
1428}
1429
1430/* *INDENT-OFF* */
1431VLIB_CLI_COMMAND (clear_tag_command, static) = {
1432 .path = "clear interface tag",
Billy McFalle9bac692017-08-11 14:05:11 -04001433 .short_help = "clear interface tag <interface>",
Dave Barach7be864a2016-11-28 11:41:35 -05001434 .function = clear_tag,
1435};
1436/* *INDENT-ON* */
1437
Damjan Marion44036902017-04-28 12:29:15 +02001438static clib_error_t *
Neale Ranns1855b8e2018-07-11 10:31:26 -07001439set_ip_directed_broadcast (vlib_main_t * vm,
1440 unformat_input_t * input, vlib_cli_command_t * cmd)
1441{
1442 vnet_main_t *vnm = vnet_get_main ();
1443 u32 sw_if_index = ~0;
1444 u8 enable = 0;
1445
1446 if (!unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index));
1447 else if (unformat (input, "enable"))
1448 enable = 1;
1449 else if (unformat (input, "disable"))
1450 enable = 0;
1451 else
1452 return clib_error_return (0, "unknown input: `%U'",
1453 format_unformat_error, input);
1454
1455 if (~0 == sw_if_index)
1456 return clib_error_return (0, "specify an interface: `%U'",
1457 format_unformat_error, input);
1458
1459 vnet_sw_interface_ip_directed_broadcast (vnm, sw_if_index, enable);
1460
1461 return 0;
1462}
1463
1464/*?
1465 * This command is used to enable/disable IP directed broadcast
1466 * If directed broadcast is enabled a packet sent to the interface's
1467 * subnet broadcast address will be sent L2 broadcast on the interface,
1468 * otherwise it is dropped.
1469 ?*/
1470/* *INDENT-OFF* */
1471VLIB_CLI_COMMAND (set_ip_directed_broadcast_command, static) = {
1472 .path = "set interface ip directed-broadcast",
1473 .short_help = "set interface enable <interface> <enable|disable>",
1474 .function = set_ip_directed_broadcast,
1475};
1476/* *INDENT-ON* */
1477
1478static clib_error_t *
Stevene3a395c2017-05-09 16:19:50 -07001479set_hw_interface_rx_mode (vnet_main_t * vnm, u32 hw_if_index,
Damjan Marioneabd4242020-10-07 20:59:07 +02001480 u32 queue_id, vnet_hw_if_rx_mode mode)
Stevene3a395c2017-05-09 16:19:50 -07001481{
1482 vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
1483 vnet_device_class_t *dev_class =
1484 vnet_get_device_class (vnm, hw->dev_class_index);
1485 clib_error_t *error;
Damjan Marioneabd4242020-10-07 20:59:07 +02001486 vnet_hw_if_rx_mode old_mode;
Stevene3a395c2017-05-09 16:19:50 -07001487 int rv;
1488
Damjan Marioneabd4242020-10-07 20:59:07 +02001489 if (mode == VNET_HW_IF_RX_MODE_DEFAULT)
Damjan Marion4e53a0d2017-06-21 14:29:44 +02001490 mode = hw->default_rx_mode;
1491
Stevene3a395c2017-05-09 16:19:50 -07001492 rv = vnet_hw_interface_get_rx_mode (vnm, hw_if_index, queue_id, &old_mode);
1493 switch (rv)
1494 {
1495 case 0:
1496 if (old_mode == mode)
1497 return 0; /* same rx-mode, no change */
1498 break;
1499 case VNET_API_ERROR_INVALID_INTERFACE:
1500 return clib_error_return (0, "invalid interface");
Stevenbd8a6112017-07-30 10:29:26 -07001501 case VNET_API_ERROR_INVALID_QUEUE:
1502 return clib_error_return (0, "invalid queue");
Stevene3a395c2017-05-09 16:19:50 -07001503 default:
1504 return clib_error_return (0, "unknown error");
1505 }
1506
1507 if (dev_class->rx_mode_change_function)
1508 {
1509 error = dev_class->rx_mode_change_function (vnm, hw_if_index, queue_id,
1510 mode);
1511 if (error)
1512 return (error);
1513 }
1514
1515 rv = vnet_hw_interface_set_rx_mode (vnm, hw_if_index, queue_id, mode);
1516 switch (rv)
1517 {
1518 case 0:
1519 break;
1520 case VNET_API_ERROR_UNSUPPORTED:
1521 return clib_error_return (0, "unsupported");
1522 case VNET_API_ERROR_INVALID_INTERFACE:
1523 return clib_error_return (0, "invalid interface");
Stevenbd8a6112017-07-30 10:29:26 -07001524 case VNET_API_ERROR_INVALID_QUEUE:
1525 return clib_error_return (0, "invalid queue");
Stevene3a395c2017-05-09 16:19:50 -07001526 default:
1527 return clib_error_return (0, "unknown error");
1528 }
1529
1530 return 0;
1531}
1532
Stevenad8015b2017-10-29 22:10:46 -07001533clib_error_t *
1534set_hw_interface_change_rx_mode (vnet_main_t * vnm, u32 hw_if_index,
1535 u8 queue_id_valid, u32 queue_id,
Damjan Marioneabd4242020-10-07 20:59:07 +02001536 vnet_hw_if_rx_mode mode)
Stevenad8015b2017-10-29 22:10:46 -07001537{
1538 clib_error_t *error = 0;
1539 vnet_hw_interface_t *hw;
1540 int i;
1541
1542 hw = vnet_get_hw_interface (vnm, hw_if_index);
1543
1544 if (queue_id_valid == 0)
1545 {
1546 for (i = 0; i < vec_len (hw->dq_runtime_index_by_queue); i++)
1547 {
1548 error = set_hw_interface_rx_mode (vnm, hw_if_index, i, mode);
1549 if (error)
1550 break;
1551 }
1552 hw->default_rx_mode = mode;
1553 }
1554 else
1555 error = set_hw_interface_rx_mode (vnm, hw_if_index, queue_id, mode);
1556
1557 return (error);
1558}
1559
Stevene3a395c2017-05-09 16:19:50 -07001560static clib_error_t *
Damjan Marion44036902017-04-28 12:29:15 +02001561set_interface_rx_mode (vlib_main_t * vm, unformat_input_t * input,
1562 vlib_cli_command_t * cmd)
1563{
1564 clib_error_t *error = 0;
1565 unformat_input_t _line_input, *line_input = &_line_input;
1566 vnet_main_t *vnm = vnet_get_main ();
Damjan Marion44036902017-04-28 12:29:15 +02001567 u32 hw_if_index = (u32) ~ 0;
1568 u32 queue_id = (u32) ~ 0;
Damjan Marioneabd4242020-10-07 20:59:07 +02001569 vnet_hw_if_rx_mode mode = VNET_HW_IF_RX_MODE_UNKNOWN;
Stevenad8015b2017-10-29 22:10:46 -07001570 u8 queue_id_valid = 0;
Dave Barach7be864a2016-11-28 11:41:35 -05001571
Damjan Marion44036902017-04-28 12:29:15 +02001572 if (!unformat_user (input, unformat_line_input, line_input))
1573 return 0;
1574
1575 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1576 {
1577 if (unformat
1578 (line_input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
1579 ;
1580 else if (unformat (line_input, "queue %d", &queue_id))
Stevenad8015b2017-10-29 22:10:46 -07001581 queue_id_valid = 1;
Damjan Marion44036902017-04-28 12:29:15 +02001582 else if (unformat (line_input, "polling"))
Damjan Marioneabd4242020-10-07 20:59:07 +02001583 mode = VNET_HW_IF_RX_MODE_POLLING;
Damjan Marion44036902017-04-28 12:29:15 +02001584 else if (unformat (line_input, "interrupt"))
Damjan Marioneabd4242020-10-07 20:59:07 +02001585 mode = VNET_HW_IF_RX_MODE_INTERRUPT;
Damjan Marion44036902017-04-28 12:29:15 +02001586 else if (unformat (line_input, "adaptive"))
Damjan Marioneabd4242020-10-07 20:59:07 +02001587 mode = VNET_HW_IF_RX_MODE_ADAPTIVE;
Damjan Marion44036902017-04-28 12:29:15 +02001588 else
1589 {
1590 error = clib_error_return (0, "parse error: '%U'",
1591 format_unformat_error, line_input);
1592 unformat_free (line_input);
1593 return error;
1594 }
1595 }
1596
1597 unformat_free (line_input);
1598
1599 if (hw_if_index == (u32) ~ 0)
1600 return clib_error_return (0, "please specify valid interface name");
1601
Damjan Marioneabd4242020-10-07 20:59:07 +02001602 if (mode == VNET_HW_IF_RX_MODE_UNKNOWN)
Damjan Marion44036902017-04-28 12:29:15 +02001603 return clib_error_return (0, "please specify valid rx-mode");
1604
Stevenad8015b2017-10-29 22:10:46 -07001605 error = set_hw_interface_change_rx_mode (vnm, hw_if_index, queue_id_valid,
1606 queue_id, mode);
Damjan Marion44036902017-04-28 12:29:15 +02001607
Stevene3a395c2017-05-09 16:19:50 -07001608 return (error);
Damjan Marion44036902017-04-28 12:29:15 +02001609}
1610
1611/*?
Billy McFalle9bac692017-08-11 14:05:11 -04001612 * This command is used to assign the RX packet processing mode (polling,
1613 * interrupt, adaptive) of the a given interface, and optionally a
1614 * given queue. If the '<em>queue</em>' is not provided, the '<em>mode</em>'
1615 * is applied to all queues of the interface. Not all interfaces support
1616 * all modes. To display the current rx-mode use the command
1617 * '<em>show interface rx-placement</em>'.
Damjan Marion44036902017-04-28 12:29:15 +02001618 *
1619 * @cliexpar
Billy McFalle9bac692017-08-11 14:05:11 -04001620 * Example of how to assign rx-mode to all queues on an interface:
1621 * @cliexcmd{set interface rx-mode VirtualEthernet0/0/12 polling}
1622 * Example of how to assign rx-mode to one queue of an interface:
1623 * @cliexcmd{set interface rx-mode VirtualEthernet0/0/12 queue 0 interrupt}
1624 * Example of how to display the rx-mode of all interfaces:
Damjan Marion44036902017-04-28 12:29:15 +02001625 * @cliexstart{show interface rx-placement}
1626 * Thread 1 (vpp_wk_0):
Billy McFalle9bac692017-08-11 14:05:11 -04001627 * node dpdk-input:
1628 * GigabitEthernet7/0/0 queue 0 (polling)
1629 * node vhost-user-input:
1630 * VirtualEthernet0/0/12 queue 0 (interrupt)
1631 * VirtualEthernet0/0/12 queue 2 (polling)
1632 * VirtualEthernet0/0/13 queue 0 (polling)
1633 * VirtualEthernet0/0/13 queue 2 (polling)
Damjan Marion44036902017-04-28 12:29:15 +02001634 * Thread 2 (vpp_wk_1):
Billy McFalle9bac692017-08-11 14:05:11 -04001635 * node dpdk-input:
1636 * GigabitEthernet7/0/1 queue 0 (polling)
1637 * node vhost-user-input:
1638 * VirtualEthernet0/0/12 queue 1 (polling)
1639 * VirtualEthernet0/0/12 queue 3 (polling)
1640 * VirtualEthernet0/0/13 queue 1 (polling)
1641 * VirtualEthernet0/0/13 queue 3 (polling)
Damjan Marion44036902017-04-28 12:29:15 +02001642 * @cliexend
Damjan Marion44036902017-04-28 12:29:15 +02001643?*/
1644/* *INDENT-OFF* */
Damjan Marionfe7d4a22018-04-13 19:43:39 +02001645VLIB_CLI_COMMAND (cmd_set_if_rx_mode,static) = {
Damjan Marion44036902017-04-28 12:29:15 +02001646 .path = "set interface rx-mode",
1647 .short_help = "set interface rx-mode <interface> [queue <n>] [polling | interrupt | adaptive]",
1648 .function = set_interface_rx_mode,
1649};
1650/* *INDENT-ON* */
1651
1652static clib_error_t *
1653show_interface_rx_placement_fn (vlib_main_t * vm, unformat_input_t * input,
1654 vlib_cli_command_t * cmd)
1655{
1656 u8 *s = 0;
1657 vnet_main_t *vnm = vnet_get_main ();
1658 vnet_device_input_runtime_t *rt;
1659 vnet_device_and_queue_t *dq;
1660 vlib_node_t *pn = vlib_get_node_by_name (vm, (u8 *) "device-input");
1661 uword si;
1662 int index = 0;
1663
1664 /* *INDENT-OFF* */
1665 foreach_vlib_main (({
1666 clib_bitmap_foreach (si, pn->sibling_bitmap,
1667 ({
1668 rt = vlib_node_get_runtime_data (this_vlib_main, si);
1669
1670 if (vec_len (rt->devices_and_queues))
1671 s = format (s, " node %U:\n", format_vlib_node_name, vm, si);
1672
1673 vec_foreach (dq, rt->devices_and_queues)
1674 {
Steven9d6d9892017-06-30 07:15:02 -07001675 vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm,
1676 dq->hw_if_index);
Damjan Marion44036902017-04-28 12:29:15 +02001677 s = format (s, " %U queue %u (%U)\n",
Steven9d6d9892017-06-30 07:15:02 -07001678 format_vnet_sw_if_index_name, vnm, hi->sw_if_index,
Damjan Marion44036902017-04-28 12:29:15 +02001679 dq->queue_id,
Damjan Marioneabd4242020-10-07 20:59:07 +02001680 format_vnet_hw_if_rx_mode, dq->mode);
Damjan Marion44036902017-04-28 12:29:15 +02001681 }
1682 }));
1683 if (vec_len (s) > 0)
1684 {
Steven84f36cb2018-09-26 10:44:54 -07001685 vlib_cli_output(vm, "Thread %u (%s):\n%v", index,
Damjan Marion44036902017-04-28 12:29:15 +02001686 vlib_worker_threads[index].name, s);
1687 vec_reset_length (s);
1688 }
1689 index++;
1690 }));
1691 /* *INDENT-ON* */
1692
1693 vec_free (s);
1694 return 0;
1695}
1696
Billy McFalle9bac692017-08-11 14:05:11 -04001697/*?
1698 * This command is used to display the interface and queue worker
1699 * thread placement.
1700 *
1701 * @cliexpar
1702 * Example of how to display the interface placement:
1703 * @cliexstart{show interface rx-placement}
1704 * Thread 1 (vpp_wk_0):
1705 * node dpdk-input:
1706 * GigabitEthernet7/0/0 queue 0 (polling)
1707 * node vhost-user-input:
1708 * VirtualEthernet0/0/12 queue 0 (polling)
1709 * VirtualEthernet0/0/12 queue 2 (polling)
1710 * VirtualEthernet0/0/13 queue 0 (polling)
1711 * VirtualEthernet0/0/13 queue 2 (polling)
1712 * Thread 2 (vpp_wk_1):
1713 * node dpdk-input:
1714 * GigabitEthernet7/0/1 queue 0 (polling)
1715 * node vhost-user-input:
1716 * VirtualEthernet0/0/12 queue 1 (polling)
1717 * VirtualEthernet0/0/12 queue 3 (polling)
1718 * VirtualEthernet0/0/13 queue 1 (polling)
1719 * VirtualEthernet0/0/13 queue 3 (polling)
1720 * @cliexend
1721?*/
Damjan Marion44036902017-04-28 12:29:15 +02001722/* *INDENT-OFF* */
1723VLIB_CLI_COMMAND (show_interface_rx_placement, static) = {
1724 .path = "show interface rx-placement",
1725 .short_help = "show interface rx-placement",
1726 .function = show_interface_rx_placement_fn,
1727};
1728/* *INDENT-ON* */
1729
Mohsin Kazmi54f7c512018-08-23 18:28:11 +02001730clib_error_t *
1731set_hw_interface_rx_placement (u32 hw_if_index, u32 queue_id,
1732 u32 thread_index, u8 is_main)
Damjan Marion44036902017-04-28 12:29:15 +02001733{
Damjan Marion44036902017-04-28 12:29:15 +02001734 vnet_main_t *vnm = vnet_get_main ();
1735 vnet_device_main_t *vdm = &vnet_device_main;
Mohsin Kazmi54f7c512018-08-23 18:28:11 +02001736 clib_error_t *error = 0;
Damjan Marioneabd4242020-10-07 20:59:07 +02001737 vnet_hw_if_rx_mode mode = VNET_HW_IF_RX_MODE_UNKNOWN;
Damjan Marion44036902017-04-28 12:29:15 +02001738 int rv;
1739
Mohsin Kazmi54f7c512018-08-23 18:28:11 +02001740 if (is_main)
1741 thread_index = 0;
1742 else
1743 thread_index += vdm->first_worker_thread_index;
Damjan Marion44036902017-04-28 12:29:15 +02001744
1745 if (thread_index > vdm->last_worker_thread_index)
1746 return clib_error_return (0,
1747 "please specify valid worker thread or main");
1748
1749 rv = vnet_hw_interface_get_rx_mode (vnm, hw_if_index, queue_id, &mode);
1750
1751 if (rv)
1752 return clib_error_return (0, "not found");
1753
1754 rv = vnet_hw_interface_unassign_rx_thread (vnm, hw_if_index, queue_id);
1755
1756 if (rv)
1757 return clib_error_return (0, "not found");
1758
1759 vnet_hw_interface_assign_rx_thread (vnm, hw_if_index, queue_id,
1760 thread_index);
1761 vnet_hw_interface_set_rx_mode (vnm, hw_if_index, queue_id, mode);
1762
Mohsin Kazmi54f7c512018-08-23 18:28:11 +02001763 return (error);
1764}
1765
1766static clib_error_t *
1767set_interface_rx_placement (vlib_main_t * vm, unformat_input_t * input,
1768 vlib_cli_command_t * cmd)
1769{
1770 clib_error_t *error = 0;
1771 unformat_input_t _line_input, *line_input = &_line_input;
1772 vnet_main_t *vnm = vnet_get_main ();
1773 u32 hw_if_index = (u32) ~ 0;
1774 u32 queue_id = (u32) 0;
1775 u32 thread_index = (u32) ~ 0;
1776 u8 is_main = 0;
1777
1778 if (!unformat_user (input, unformat_line_input, line_input))
1779 return 0;
1780
1781 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1782 {
1783 if (unformat
1784 (line_input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
1785 ;
1786 else if (unformat (line_input, "queue %d", &queue_id))
1787 ;
1788 else if (unformat (line_input, "main", &thread_index))
1789 is_main = 1;
1790 else if (unformat (line_input, "worker %d", &thread_index))
1791 ;
1792 else
1793 {
1794 error = clib_error_return (0, "parse error: '%U'",
1795 format_unformat_error, line_input);
1796 unformat_free (line_input);
1797 return error;
1798 }
1799 }
1800
1801 unformat_free (line_input);
1802
1803 if (hw_if_index == (u32) ~ 0)
1804 return clib_error_return (0, "please specify valid interface name");
1805
1806 error = set_hw_interface_rx_placement (hw_if_index, queue_id, thread_index,
1807 is_main);
1808
1809 return (error);
Damjan Marion44036902017-04-28 12:29:15 +02001810}
1811
1812/*?
1813 * This command is used to assign a given interface, and optionally a
1814 * given queue, to a different thread. If the '<em>queue</em>' is not provided,
Billy McFalle9bac692017-08-11 14:05:11 -04001815 * it defaults to 0. The '<em>worker</em>' parameter is zero based and the index
1816 * in the thread name, for example, 0 in the thread name '<em>vpp_wk_0</em>'.
Damjan Marion44036902017-04-28 12:29:15 +02001817 *
1818 * @cliexpar
1819 * Example of how to display the interface placement:
Billy McFalle9bac692017-08-11 14:05:11 -04001820 * @cliexstart{show interface rx-placement}
Damjan Marion44036902017-04-28 12:29:15 +02001821 * Thread 1 (vpp_wk_0):
Billy McFalle9bac692017-08-11 14:05:11 -04001822 * node dpdk-input:
1823 * GigabitEthernet7/0/0 queue 0 (polling)
1824 * node vhost-user-input:
1825 * VirtualEthernet0/0/12 queue 0 (polling)
1826 * VirtualEthernet0/0/12 queue 2 (polling)
1827 * VirtualEthernet0/0/13 queue 0 (polling)
1828 * VirtualEthernet0/0/13 queue 2 (polling)
Damjan Marion44036902017-04-28 12:29:15 +02001829 * Thread 2 (vpp_wk_1):
Billy McFalle9bac692017-08-11 14:05:11 -04001830 * node dpdk-input:
1831 * GigabitEthernet7/0/1 queue 0 (polling)
1832 * node vhost-user-input:
1833 * VirtualEthernet0/0/12 queue 1 (polling)
1834 * VirtualEthernet0/0/12 queue 3 (polling)
1835 * VirtualEthernet0/0/13 queue 1 (polling)
1836 * VirtualEthernet0/0/13 queue 3 (polling)
Damjan Marion44036902017-04-28 12:29:15 +02001837 * @cliexend
Billy McFalle9bac692017-08-11 14:05:11 -04001838 * Example of how to assign a interface and queue to a worker thread:
1839 * @cliexcmd{set interface rx-placement VirtualEthernet0/0/12 queue 1 worker 0}
1840 * Example of how to display the interface placement:
1841 * @cliexstart{show interface rx-placement}
1842 * Thread 1 (vpp_wk_0):
1843 * node dpdk-input:
1844 * GigabitEthernet7/0/0 queue 0 (polling)
1845 * node vhost-user-input:
1846 * VirtualEthernet0/0/12 queue 0 (polling)
1847 * VirtualEthernet0/0/12 queue 1 (polling)
1848 * VirtualEthernet0/0/12 queue 2 (polling)
1849 * VirtualEthernet0/0/13 queue 0 (polling)
1850 * VirtualEthernet0/0/13 queue 2 (polling)
1851 * Thread 2 (vpp_wk_1):
1852 * node dpdk-input:
1853 * GigabitEthernet7/0/1 queue 0 (polling)
1854 * node vhost-user-input:
1855 * VirtualEthernet0/0/12 queue 3 (polling)
1856 * VirtualEthernet0/0/13 queue 1 (polling)
1857 * VirtualEthernet0/0/13 queue 3 (polling)
1858 * @cliexend
Damjan Marion44036902017-04-28 12:29:15 +02001859?*/
1860/* *INDENT-OFF* */
1861VLIB_CLI_COMMAND (cmd_set_if_rx_placement,static) = {
1862 .path = "set interface rx-placement",
Billy McFalle9bac692017-08-11 14:05:11 -04001863 .short_help = "set interface rx-placement <interface> [queue <n>] "
Damjan Marion6f9ac652017-06-15 19:01:31 +02001864 "[worker <n> | main]",
Damjan Marion44036902017-04-28 12:29:15 +02001865 .function = set_interface_rx_placement,
Damjan Marion6f9ac652017-06-15 19:01:31 +02001866 .is_mp_safe = 1,
Damjan Marion44036902017-04-28 12:29:15 +02001867};
Damjan Marion44036902017-04-28 12:29:15 +02001868/* *INDENT-ON* */
Dave Barach5ecd5a52019-02-25 15:27:28 -05001869
Chenmin Sunc4665092020-07-06 08:20:39 +08001870clib_error_t *
1871set_interface_rss_queues (vlib_main_t * vm, u32 hw_if_index,
1872 clib_bitmap_t * bitmap)
1873{
1874 vnet_main_t *vnm = vnet_get_main ();
1875 vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1876
1877 return vnet_hw_interface_set_rss_queues (vnm, hi, bitmap);
1878}
1879
1880static clib_error_t *
1881set_interface_rss_queues_fn (vlib_main_t * vm,
1882 unformat_input_t * input,
1883 vlib_cli_command_t * cmd)
1884{
1885 clib_error_t *error = 0;
1886 unformat_input_t _line_input, *line_input = &_line_input;
1887 vnet_main_t *vnm = vnet_get_main ();
1888 u32 hw_if_index = (u32) ~ 0;
1889 clib_bitmap_t *bitmap = NULL;
1890
1891 if (!unformat_user (input, unformat_line_input, line_input))
1892 return 0;
1893
1894 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1895 {
1896 if (unformat
1897 (line_input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
1898 ;
1899 else
1900 if (unformat (line_input, "list %U", unformat_bitmap_list, &bitmap))
1901 ;
1902 else
1903 {
1904 error = clib_error_return (0, "parse error: '%U'",
1905 format_unformat_error, line_input);
1906 unformat_free (line_input);
1907 goto done;
1908 }
1909 }
1910
1911 unformat_free (line_input);
1912
1913 if (hw_if_index == (u32) ~ 0)
1914 {
1915 error = clib_error_return (0, "please specify valid interface name");
1916 goto done;
1917 }
1918
1919 if (bitmap == NULL)
1920 {
1921 error = clib_error_return (0, "please specify the valid rss queues");
1922 goto done;
1923 }
1924
1925 error = set_interface_rss_queues (vm, hw_if_index, bitmap);
1926
1927done:
1928 if (bitmap)
1929 clib_bitmap_free (bitmap);
1930
1931 return (error);
1932}
1933
1934/*?
1935 * This command is used to set the rss queues of a given interface
1936 * Not all the interfaces support this operation.
1937 * To display the current rss queues, use the command
1938 * '<em>show hardware-interfaces</em>'.
1939 *
1940 * @cliexpar
1941 * Example of how to set the rss queues to 0,2-5,7 of an interface:
1942 * @cliexstart{set interface rss queues VirtualFunctionEthernet18/1/0 list 0,2-5,7}
1943 * @cliexend
1944?*/
1945/* *INDENT-OFF* */
1946VLIB_CLI_COMMAND (cmd_set_interface_rss_queues,static) = {
1947 .path = "set interface rss queues",
1948 .short_help = "set interface rss queues <interface> <list <queue-list>>",
1949 .function = set_interface_rss_queues_fn,
1950};
1951/* *INDENT-ON* */
1952
Dave Barach33909772019-09-23 10:27:27 -04001953static u8 *
1954format_vnet_pcap (u8 * s, va_list * args)
1955{
1956 vnet_pcap_t *pp = va_arg (*args, vnet_pcap_t *);
1957 int type = va_arg (*args, int);
1958 int printed = 0;
1959
1960 if (type == 0)
1961 {
1962 if (pp->pcap_rx_enable)
1963 {
1964 s = format (s, "rx");
1965 printed = 1;
1966 }
1967 if (pp->pcap_tx_enable)
1968 {
1969 if (printed)
1970 s = format (s, " and ");
1971 s = format (s, "tx");
1972 printed = 1;
1973 }
1974 if (pp->pcap_drop_enable)
1975 {
1976 if (printed)
1977 s = format (s, " and ");
1978 s = format (s, "drop");
1979 printed = 1;
1980 }
1981 return s;
1982 }
1983 s = format (s, "unknown type %d!", type);
1984 return s;
1985}
1986
1987
Dave Barachb97641c2019-09-09 16:38:17 -04001988int
1989vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t * a)
1990{
1991 vlib_main_t *vm = vlib_get_main ();
Dave Barach33909772019-09-23 10:27:27 -04001992 vnet_pcap_t *pp = &vm->pcap;
Dave Barachb97641c2019-09-09 16:38:17 -04001993 pcap_main_t *pm = &pp->pcap_main;
Dave Barachf5667c32019-09-25 11:27:46 -04001994 vnet_classify_main_t *cm = &vnet_classify_main;
1995 vnet_classify_filter_set_t *set = 0;
Dave Barachb97641c2019-09-09 16:38:17 -04001996
1997 if (a->status)
1998 {
Dave Barach33909772019-09-23 10:27:27 -04001999 if (pp->pcap_rx_enable || pp->pcap_tx_enable || pp->pcap_drop_enable)
Dave Barachb97641c2019-09-09 16:38:17 -04002000 {
2001 vlib_cli_output
Dave Barach33909772019-09-23 10:27:27 -04002002 (vm, "pcap %U dispatch capture enabled: %d of %d pkts...",
2003 format_vnet_pcap, pp, 0 /* print type */ ,
Dave Barachb97641c2019-09-09 16:38:17 -04002004 pm->n_packets_captured, pm->n_packets_to_capture);
2005 vlib_cli_output (vm, "capture to file %s", pm->file_name);
2006 }
2007 else
Dave Barach33909772019-09-23 10:27:27 -04002008 vlib_cli_output (vm, "pcap dispatch capture disabled");
2009
Dave Barachb97641c2019-09-09 16:38:17 -04002010 return 0;
2011 }
2012
2013 /* Consistency checks */
2014
2015 /* Enable w/ capture already enabled not allowed */
Dave Barach33909772019-09-23 10:27:27 -04002016 if ((pp->pcap_rx_enable + pp->pcap_tx_enable + pp->pcap_drop_enable)
2017 && (a->rx_enable + a->tx_enable + a->drop_enable))
Dave Barachb97641c2019-09-09 16:38:17 -04002018 return VNET_API_ERROR_INVALID_VALUE;
2019
2020 /* Disable capture with capture already disabled, not interesting */
Dave Barach33909772019-09-23 10:27:27 -04002021 if (((pp->pcap_rx_enable + pp->pcap_tx_enable + pp->pcap_drop_enable) == 0)
2022 && ((a->rx_enable + a->tx_enable + a->drop_enable == 0)))
Dave Barachb97641c2019-09-09 16:38:17 -04002023 return VNET_API_ERROR_VALUE_EXIST;
2024
2025 /* Change number of packets to capture while capturing */
Dave Barach33909772019-09-23 10:27:27 -04002026 if ((pp->pcap_rx_enable + pp->pcap_tx_enable + pp->pcap_drop_enable)
2027 && (a->rx_enable + a->tx_enable + a->drop_enable)
Dave Barachb97641c2019-09-09 16:38:17 -04002028 && (pm->n_packets_to_capture != a->packets_to_capture))
2029 return VNET_API_ERROR_INVALID_VALUE_2;
2030
Dave Barachf5667c32019-09-25 11:27:46 -04002031 set = pool_elt_at_index (cm->filter_sets, cm->filter_set_by_sw_if_index[0]);
2032
Dave Barach33909772019-09-23 10:27:27 -04002033 /* Classify filter specified, but no classify filter configured */
Dave Barachf5667c32019-09-25 11:27:46 -04002034 if ((a->rx_enable + a->tx_enable + a->drop_enable) && a->filter &&
Dave Barach196fce22020-01-27 09:56:58 -05002035 (set->table_indices == 0 || set->table_indices[0] == ~0))
Dave Barach9137e542019-09-13 17:47:50 -04002036 return VNET_API_ERROR_NO_SUCH_LABEL;
2037
Dave Barach33909772019-09-23 10:27:27 -04002038 if (a->rx_enable + a->tx_enable + a->drop_enable)
Dave Barachb97641c2019-09-09 16:38:17 -04002039 {
Dave Barach586462f2020-08-05 16:12:35 -04002040 void *save_pcap_data;
2041
Dave Barach33909772019-09-23 10:27:27 -04002042 /* Sanity check max bytes per pkt */
2043 if (a->max_bytes_per_pkt < 32 || a->max_bytes_per_pkt > 9000)
2044 return VNET_API_ERROR_INVALID_MEMORY_SIZE;
2045
Dave Barachb97641c2019-09-09 16:38:17 -04002046 /* Clean up from previous run, if any */
Dave Barach586462f2020-08-05 16:12:35 -04002047 vec_reset_length (pm->pcap_data);
2048
2049 /* Throw away the data buffer? */
2050 if (a->free_data)
2051 vec_free (pm->pcap_data);
2052
2053 save_pcap_data = pm->pcap_data;
2054
Dave Barachb97641c2019-09-09 16:38:17 -04002055 memset (pm, 0, sizeof (*pm));
2056
Dave Barach586462f2020-08-05 16:12:35 -04002057 pm->pcap_data = save_pcap_data;
2058
Dave Barach11fb09e2020-08-06 12:10:09 -04002059 vec_validate_aligned (vnet_trace_placeholder, 2048,
2060 CLIB_CACHE_LINE_BYTES);
Dave Barachb97641c2019-09-09 16:38:17 -04002061 if (pm->lock == 0)
2062 clib_spinlock_init (&(pm->lock));
2063
2064 if (a->filename == 0)
Dave Barach33909772019-09-23 10:27:27 -04002065 {
2066 u8 *stem = 0;
2067
2068 if (a->rx_enable)
2069 stem = format (stem, "rx");
2070 if (a->tx_enable)
2071 stem = format (stem, "tx");
2072 if (a->drop_enable)
2073 stem = format (stem, "drop");
Benoît Ganne7d4a9972020-07-17 11:49:56 +02002074 a->filename = format (0, "/tmp/%v.pcap%c", stem, 0);
Dave Barach33909772019-09-23 10:27:27 -04002075 vec_free (stem);
2076 }
Dave Barachb97641c2019-09-09 16:38:17 -04002077
2078 pm->file_name = (char *) a->filename;
2079 pm->n_packets_captured = 0;
2080 pm->packet_type = PCAP_PACKET_TYPE_ethernet;
Dave Barach586462f2020-08-05 16:12:35 -04002081 /* Preallocate the data vector? */
2082 if (a->preallocate_data)
2083 {
2084 vec_validate
2085 (pm->pcap_data, a->packets_to_capture
2086 * ((sizeof (pcap_packet_header_t) + a->max_bytes_per_pkt)));
2087 vec_reset_length (pm->pcap_data);
2088 }
Dave Barachb97641c2019-09-09 16:38:17 -04002089 pm->n_packets_to_capture = a->packets_to_capture;
2090 pp->pcap_sw_if_index = a->sw_if_index;
Dave Barach9137e542019-09-13 17:47:50 -04002091 if (a->filter)
Dave Barachf5667c32019-09-25 11:27:46 -04002092 pp->filter_classify_table_index = set->table_indices[0];
Dave Barach9137e542019-09-13 17:47:50 -04002093 else
2094 pp->filter_classify_table_index = ~0;
Dave Barach33909772019-09-23 10:27:27 -04002095 pp->pcap_rx_enable = a->rx_enable;
2096 pp->pcap_tx_enable = a->tx_enable;
2097 pp->pcap_drop_enable = a->drop_enable;
2098 pp->max_bytes_per_pkt = a->max_bytes_per_pkt;
Dave Barachb97641c2019-09-09 16:38:17 -04002099 }
2100 else
2101 {
Dave Barach33909772019-09-23 10:27:27 -04002102 pp->pcap_rx_enable = 0;
2103 pp->pcap_tx_enable = 0;
2104 pp->pcap_drop_enable = 0;
Dave Barachf5667c32019-09-25 11:27:46 -04002105 pp->filter_classify_table_index = ~0;
Dave Barachb97641c2019-09-09 16:38:17 -04002106 if (pm->n_packets_captured)
2107 {
2108 clib_error_t *error;
2109 pm->n_packets_to_capture = pm->n_packets_captured;
2110 vlib_cli_output (vm, "Write %d packets to %s, and stop capture...",
2111 pm->n_packets_captured, pm->file_name);
2112 error = pcap_write (pm);
Andrew Yourtchenko4da15062019-09-11 14:14:43 +00002113 if (pm->flags & PCAP_MAIN_INIT_DONE)
Dave Barachb97641c2019-09-09 16:38:17 -04002114 pcap_close (pm);
2115 /* Report I/O errors... */
2116 if (error)
2117 {
2118 clib_error_report (error);
2119 return VNET_API_ERROR_SYSCALL_ERROR_1;
2120 }
Dave Barach586462f2020-08-05 16:12:35 -04002121 vec_free (pm->file_name);
2122 if (a->free_data)
2123 vec_free (pm->pcap_data);
Dave Barachb97641c2019-09-09 16:38:17 -04002124 return 0;
2125 }
2126 else
2127 return VNET_API_ERROR_NO_SUCH_ENTRY;
2128 }
2129
2130 return 0;
2131}
2132
2133static clib_error_t *
Dave Barach33909772019-09-23 10:27:27 -04002134pcap_trace_command_fn (vlib_main_t * vm,
2135 unformat_input_t * input, vlib_cli_command_t * cmd)
Dave Barach5ecd5a52019-02-25 15:27:28 -05002136{
Dave Barach5ecd5a52019-02-25 15:27:28 -05002137 unformat_input_t _line_input, *line_input = &_line_input;
Dave Barachb97641c2019-09-09 16:38:17 -04002138 vnet_pcap_dispatch_trace_args_t _a, *a = &_a;
Dave Barach5ecd5a52019-02-25 15:27:28 -05002139 vnet_main_t *vnm = vnet_get_main ();
Dave Barachb97641c2019-09-09 16:38:17 -04002140 u8 *filename = 0;
2141 u32 max = 1000;
Dave Barach33909772019-09-23 10:27:27 -04002142 u32 max_bytes_per_pkt = 512;
Dave Barachb97641c2019-09-09 16:38:17 -04002143 int rv;
Dave Barach33909772019-09-23 10:27:27 -04002144 int rx_enable = 0;
2145 int tx_enable = 0;
Dave Barach586462f2020-08-05 16:12:35 -04002146 int preallocate_data = 0;
Dave Barach33909772019-09-23 10:27:27 -04002147 int drop_enable = 0;
Dave Barachb97641c2019-09-09 16:38:17 -04002148 int status = 0;
Dave Barach9137e542019-09-13 17:47:50 -04002149 int filter = 0;
Dave Barach586462f2020-08-05 16:12:35 -04002150 int free_data = 0;
Dave Barach4330c462020-06-10 17:07:32 -04002151 u32 sw_if_index = 0; /* default: any interface */
Dave Barach5ecd5a52019-02-25 15:27:28 -05002152
2153 /* Get a line of input. */
2154 if (!unformat_user (input, unformat_line_input, line_input))
2155 return 0;
2156
2157 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2158 {
Dave Barach33909772019-09-23 10:27:27 -04002159 if (unformat (line_input, "rx"))
2160 rx_enable = 1;
2161 else if (unformat (line_input, "tx"))
2162 tx_enable = 1;
2163 else if (unformat (line_input, "drop"))
2164 drop_enable = 1;
2165 else if (unformat (line_input, "off"))
2166 rx_enable = tx_enable = drop_enable = 0;
2167 else if (unformat (line_input, "max-bytes-per-pkt %u",
2168 &max_bytes_per_pkt))
Dave Barachb97641c2019-09-09 16:38:17 -04002169 ;
2170 else if (unformat (line_input, "max %d", &max))
2171 ;
2172 else if (unformat (line_input, "packets-to-capture %d", &max))
2173 ;
2174 else if (unformat (line_input, "file %U", unformat_vlib_tmpfile,
2175 &filename))
2176 ;
2177 else if (unformat (line_input, "status %=", &status, 1))
2178 ;
2179 else if (unformat (line_input, "intfc %U",
2180 unformat_vnet_sw_interface, vnm, &sw_if_index))
2181 ;
Dave Barach586462f2020-08-05 16:12:35 -04002182 else if (unformat (line_input, "interface %U",
2183 unformat_vnet_sw_interface, vnm, &sw_if_index))
2184 ;
2185 else if (unformat (line_input, "preallocate-data %=",
2186 &preallocate_data, 1))
2187 ;
2188 else if (unformat (line_input, "free-data %=", &free_data, 1))
2189 ;
2190 else if (unformat (line_input, "intfc any")
2191 || unformat (line_input, "interface any"))
Dave Barachb97641c2019-09-09 16:38:17 -04002192 sw_if_index = 0;
Dave Barach9137e542019-09-13 17:47:50 -04002193 else if (unformat (line_input, "filter"))
2194 filter = 1;
Dave Barach5ecd5a52019-02-25 15:27:28 -05002195 else
2196 {
Dave Barachb97641c2019-09-09 16:38:17 -04002197 return clib_error_return (0, "unknown input `%U'",
2198 format_unformat_error, line_input);
Dave Barach5ecd5a52019-02-25 15:27:28 -05002199 }
2200 }
Dave Barachb97641c2019-09-09 16:38:17 -04002201
Dave Barach5ecd5a52019-02-25 15:27:28 -05002202 unformat_free (line_input);
2203
Dave Barachb97641c2019-09-09 16:38:17 -04002204 /* no need for memset (a, 0, sizeof (*a)), set all fields here. */
2205 a->filename = filename;
Dave Barach33909772019-09-23 10:27:27 -04002206 a->rx_enable = rx_enable;
2207 a->tx_enable = tx_enable;
Dave Barach586462f2020-08-05 16:12:35 -04002208 a->preallocate_data = preallocate_data;
2209 a->free_data = free_data;
Dave Barach33909772019-09-23 10:27:27 -04002210 a->drop_enable = drop_enable;
Dave Barachb97641c2019-09-09 16:38:17 -04002211 a->status = status;
2212 a->packets_to_capture = max;
Dave Barachb97641c2019-09-09 16:38:17 -04002213 a->sw_if_index = sw_if_index;
Dave Barach9137e542019-09-13 17:47:50 -04002214 a->filter = filter;
Dave Barach33909772019-09-23 10:27:27 -04002215 a->max_bytes_per_pkt = max_bytes_per_pkt;
Dave Barach5ecd5a52019-02-25 15:27:28 -05002216
Dave Barachb97641c2019-09-09 16:38:17 -04002217 rv = vnet_pcap_dispatch_trace_configure (a);
2218
2219 switch (rv)
Dave Barach5ecd5a52019-02-25 15:27:28 -05002220 {
Dave Barachb97641c2019-09-09 16:38:17 -04002221 case 0:
2222 break;
Dave Barach5ecd5a52019-02-25 15:27:28 -05002223
Dave Barachb97641c2019-09-09 16:38:17 -04002224 case VNET_API_ERROR_INVALID_VALUE:
2225 return clib_error_return (0, "dispatch trace already enabled...");
Dave Barach5ecd5a52019-02-25 15:27:28 -05002226
Dave Barachb97641c2019-09-09 16:38:17 -04002227 case VNET_API_ERROR_VALUE_EXIST:
2228 return clib_error_return (0, "dispatch trace already disabled...");
Dave Barach5ecd5a52019-02-25 15:27:28 -05002229
Dave Barachb97641c2019-09-09 16:38:17 -04002230 case VNET_API_ERROR_INVALID_VALUE_2:
2231 return clib_error_return
2232 (0, "can't change number of records to capture while tracing...");
2233
2234 case VNET_API_ERROR_SYSCALL_ERROR_1:
2235 return clib_error_return (0, "I/O writing trace capture...");
2236
2237 case VNET_API_ERROR_NO_SUCH_ENTRY:
2238 return clib_error_return (0, "No packets captured...");
2239
Dave Barach33909772019-09-23 10:27:27 -04002240 case VNET_API_ERROR_INVALID_MEMORY_SIZE:
2241 return clib_error_return (0,
2242 "Max bytes per pkt must be > 32, < 9000...");
2243
Dave Barach9137e542019-09-13 17:47:50 -04002244 case VNET_API_ERROR_NO_SUCH_LABEL:
2245 return clib_error_return
2246 (0, "No classify filter configured, see 'classify filter...'");
2247
Dave Barachb97641c2019-09-09 16:38:17 -04002248 default:
2249 vlib_cli_output (vm, "WARNING: trace configure returned %d", rv);
2250 break;
Dave Barach5ecd5a52019-02-25 15:27:28 -05002251 }
Dave Barachb97641c2019-09-09 16:38:17 -04002252 return 0;
Dave Barach5ecd5a52019-02-25 15:27:28 -05002253}
2254
Dave Barach5ecd5a52019-02-25 15:27:28 -05002255/*?
2256 * This command is used to start or stop a packet capture, or show
Dave Barach33909772019-09-23 10:27:27 -04002257 * the status of packet capture.
Dave Barach5ecd5a52019-02-25 15:27:28 -05002258 *
2259 * This command has the following optional parameters:
2260 *
Dave Barach33909772019-09-23 10:27:27 -04002261 *
2262 * - <b>rx</b> - Capture received packets
2263 *
2264 * - <b>tx</b> - Capture transmitted packets
2265 *
2266 * - <b>drop</b> - Capture dropped packets
2267 *
2268 * - <b>off</b> - Stop capturing packets, write results to the specified file
Dave Barach5ecd5a52019-02-25 15:27:28 -05002269 *
2270 * - <b>max <nn></b> - Depth of local buffer. Once '<em>nn</em>' number
2271 * of packets have been received, buffer is flushed to file. Once another
2272 * '<em>nn</em>' number of packets have been received, buffer is flushed
2273 * to file, overwriting previous write. If not entered, value defaults
2274 * to 100. Can only be updated if packet capture is off.
2275 *
Dave Barach33909772019-09-23 10:27:27 -04002276 * - <b>max-bytes-per-pkt <nnnn></b> - Maximum number of bytes to capture
2277 * for each packet. Must be >= 32, <= 9000.
2278 *
Dave Barach586462f2020-08-05 16:12:35 -04002279 * - <b>preallocate-data</b> - Preallocate the data buffer, to avoid
2280 * vector expansion delays during pcap capture
2281 *
2282 * - <b>free-data</b> - Free the data buffer. Ordinarily it's a feature
2283 * to retain the data buffer so this option is seldom used.
2284 *
Dave Barach33909772019-09-23 10:27:27 -04002285 * - <b>intfc <interface-name>|any</b> - Used to specify a given interface,
Dave Barach5ecd5a52019-02-25 15:27:28 -05002286 * or use '<em>any</em>' to run packet capture on all interfaces.
2287 * '<em>any</em>' is the default if not provided. Settings from a previous
2288 * packet capture are preserved, so '<em>any</em>' can be used to reset
2289 * the interface setting.
2290 *
Dave Barachf5667c32019-09-25 11:27:46 -04002291 * - <b>filter</b> - Use the pcap rx / tx / drop trace filter, which
2292 * must be configured. Use <b>classify filter pcap...</b> to configure the
2293 * filter. The filter will only be executed if the per-interface or
2294 * any-interface tests fail.
2295 *
Dave Barach5ecd5a52019-02-25 15:27:28 -05002296 * - <b>file <name></b> - Used to specify the output filename. The file will
2297 * be placed in the '<em>/tmp</em>' directory, so only the filename is
2298 * supported. Directory should not be entered. If file already exists, file
Dave Barach33909772019-09-23 10:27:27 -04002299 * will be overwritten. If no filename is provided, the file will be
2300 * named "/tmp/rx.pcap", "/tmp/tx.pcap", "/tmp/rxandtx.pcap", etc.
2301 * Can only be updated if packet capture is off.
Dave Barach5ecd5a52019-02-25 15:27:28 -05002302 *
2303 * - <b>status</b> - Displays the current status and configured attributes
2304 * associated with a packet capture. If packet capture is in progress,
2305 * '<em>status</em>' also will return the number of packets currently in
2306 * the local buffer. All additional attributes entered on command line
2307 * with '<em>status</em>' will be ignored and not applied.
2308 *
2309 * @cliexpar
2310 * Example of how to display the status of a tx packet capture when off:
Dave Barach33909772019-09-23 10:27:27 -04002311 * @cliexstart{pcap trace status}
Dave Barach5ecd5a52019-02-25 15:27:28 -05002312 * max is 100, for any interface to file /tmp/vpe.pcap
2313 * pcap tx capture is off...
2314 * @cliexend
2315 * Example of how to start a tx packet capture:
Dave Barach33909772019-09-23 10:27:27 -04002316 * @cliexstart{pcap trace tx max 35 intfc GigabitEthernet0/8/0 file vppTest.pcap}
Dave Barach5ecd5a52019-02-25 15:27:28 -05002317 * @cliexend
2318 * Example of how to display the status of a tx packet capture in progress:
Dave Barach33909772019-09-23 10:27:27 -04002319 * @cliexstart{pcap trace status}
Dave Barach5ecd5a52019-02-25 15:27:28 -05002320 * max is 35, for interface GigabitEthernet0/8/0 to file /tmp/vppTest.pcap
2321 * pcap tx capture is on: 20 of 35 pkts...
2322 * @cliexend
2323 * Example of how to stop a tx packet capture:
Dave Barach33909772019-09-23 10:27:27 -04002324 * @cliexstart{pcap trace off}
Dave Barach5ecd5a52019-02-25 15:27:28 -05002325 * captured 21 pkts...
2326 * saved to /tmp/vppTest.pcap...
2327 * @cliexend
2328?*/
2329/* *INDENT-OFF* */
2330
2331VLIB_CLI_COMMAND (pcap_tx_trace_command, static) = {
Dave Barach33909772019-09-23 10:27:27 -04002332 .path = "pcap trace",
Dave Barach5ecd5a52019-02-25 15:27:28 -05002333 .short_help =
Dave Barach586462f2020-08-05 16:12:35 -04002334 "pcap trace [rx] [tx] [drop] [off] [max <nn>] [intfc <interface>|any]\n"
2335 " [file <name>] [status] [max-bytes-per-pkt <nnnn>][filter]\n"
2336 " [preallocate-data][free-data]",
Dave Barach33909772019-09-23 10:27:27 -04002337 .function = pcap_trace_command_fn,
Dave Barach5ecd5a52019-02-25 15:27:28 -05002338};
2339/* *INDENT-ON* */
2340
Dave Barachba868bb2016-08-08 09:51:21 -04002341/*
2342 * fd.io coding-style-patch-verification: ON
2343 *
2344 * Local Variables:
2345 * eval: (c-set-style "gnu")
2346 * End:
2347 */