blob: 9271f5b78c5076eb4fd762cefb7be2cd12507f88 [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>
Ed Warnickecb9cada2015-12-08 15:45:58 -070055
Dave Barachba868bb2016-08-08 09:51:21 -040056static int
57compare_interface_names (void *a1, void *a2)
Ed Warnickecb9cada2015-12-08 15:45:58 -070058{
Dave Barachba868bb2016-08-08 09:51:21 -040059 u32 *hi1 = a1;
60 u32 *hi2 = a2;
Ed Warnickecb9cada2015-12-08 15:45:58 -070061
Dave Barachba868bb2016-08-08 09:51:21 -040062 return vnet_hw_interface_compare (vnet_get_main (), *hi1, *hi2);
Ed Warnickecb9cada2015-12-08 15:45:58 -070063}
64
65static clib_error_t *
66show_or_clear_hw_interfaces (vlib_main_t * vm,
67 unformat_input_t * input,
68 vlib_cli_command_t * cmd)
69{
Dave Barachba868bb2016-08-08 09:51:21 -040070 clib_error_t *error = 0;
71 vnet_main_t *vnm = vnet_get_main ();
72 vnet_interface_main_t *im = &vnm->interface_main;
73 vnet_hw_interface_t *hi;
74 u32 hw_if_index, *hw_if_indices = 0;
John Lobcebbb92016-04-05 15:47:43 -040075 int i, verbose = -1, is_show, show_bond = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -070076
77 is_show = strstr (cmd->path, "show") != 0;
78 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
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700171/*?
Billy McFalle9bac692017-08-11 14:05:11 -0400172 * Display more detailed information about all or a list of given interfaces.
173 * The verboseness of the output can be controlled by the following optional
174 * parameters:
175 * - brief: Only show name, index and state (default for bonded interfaces).
176 * - verbose: Also display additional attributes (default for all other interfaces).
177 * - detail: Also display all remaining attributes and extended statistics.
178 *
179 * To limit the output of the command to bonded interfaces and their slave
180 * interfaces, use the '<em>bond</em>' optional parameter.
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700181 *
182 * @cliexpar
Billy McFalle9bac692017-08-11 14:05:11 -0400183 * Example of how to display default data for all interfaces:
184 * @cliexstart{show hardware-interfaces}
185 * Name Idx Link Hardware
186 * GigabitEthernet7/0/0 1 up GigabitEthernet7/0/0
187 * Ethernet address ec:f4:bb:c0:bc:fc
188 * Intel e1000
189 * carrier up full duplex speed 1000 mtu 9216
190 * rx queues 1, rx desc 1024, tx queues 3, tx desc 1024
191 * cpu socket 0
192 * GigabitEthernet7/0/1 2 up GigabitEthernet7/0/1
193 * Ethernet address ec:f4:bb:c0:bc:fd
194 * Intel e1000
195 * carrier up full duplex speed 1000 mtu 9216
196 * rx queues 1, rx desc 1024, tx queues 3, tx desc 1024
197 * cpu socket 0
198 * VirtualEthernet0/0/0 3 up VirtualEthernet0/0/0
199 * Ethernet address 02:fe:a5:a9:8b:8e
200 * VirtualEthernet0/0/1 4 up VirtualEthernet0/0/1
201 * Ethernet address 02:fe:c0:4e:3b:b0
202 * VirtualEthernet0/0/2 5 up VirtualEthernet0/0/2
203 * Ethernet address 02:fe:1f:73:92:81
204 * VirtualEthernet0/0/3 6 up VirtualEthernet0/0/3
205 * Ethernet address 02:fe:f2:25:c4:68
206 * local0 0 down local0
207 * local
208 * @cliexend
209 * Example of how to display '<em>verbose</em>' data for an interface by name and
210 * software index (where 2 is the software index):
211 * @cliexstart{show hardware-interfaces GigabitEthernet7/0/0 2 verbose}
212 * Name Idx Link Hardware
213 * GigabitEthernet7/0/0 1 up GigabitEthernet7/0/0
214 * Ethernet address ec:f4:bb:c0:bc:fc
215 * Intel e1000
216 * carrier up full duplex speed 1000 mtu 9216
217 * rx queues 1, rx desc 1024, tx queues 3, tx desc 1024
218 * cpu socket 0
219 * GigabitEthernet7/0/1 2 down GigabitEthernet7/0/1
220 * Ethernet address ec:f4:bb:c0:bc:fd
221 * Intel e1000
222 * carrier up full duplex speed 1000 mtu 9216
223 * rx queues 1, rx desc 1024, tx queues 3, tx desc 1024
224 * cpu socket 0
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700225 * @cliexend
226 ?*/
Billy McFalle9bac692017-08-11 14:05:11 -0400227/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700228VLIB_CLI_COMMAND (show_hw_interfaces_command, static) = {
229 .path = "show hardware-interfaces",
Billy McFalle9bac692017-08-11 14:05:11 -0400230 .short_help = "show hardware-interfaces [brief|verbose|detail] [bond] "
231 "[<interface> [<interface> [..]]] [<sw_idx> [<sw_idx> [..]]]",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700232 .function = show_or_clear_hw_interfaces,
233};
Dave Barachba868bb2016-08-08 09:51:21 -0400234/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700235
Billy McFalle9bac692017-08-11 14:05:11 -0400236
237/*?
238 * Clear the extended statistics for all or a list of given interfaces
239 * (statistics associated with the '<em>show hardware-interfaces</em>' command).
240 *
241 * @cliexpar
242 * Example of how to clear the extended statistics for all interfaces:
243 * @cliexcmd{clear hardware-interfaces}
244 * Example of how to clear the extended statistics for an interface by
245 * name and software index (where 2 is the software index):
246 * @cliexcmd{clear hardware-interfaces GigabitEthernet7/0/0 2}
247 ?*/
Dave Barachba868bb2016-08-08 09:51:21 -0400248/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700249VLIB_CLI_COMMAND (clear_hw_interface_counters_command, static) = {
250 .path = "clear hardware-interfaces",
Billy McFalle9bac692017-08-11 14:05:11 -0400251 .short_help = "clear hardware-interfaces "
252 "[<interface> [<interface> [..]]] [<sw_idx> [<sw_idx> [..]]]",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700253 .function = show_or_clear_hw_interfaces,
254};
Dave Barachba868bb2016-08-08 09:51:21 -0400255/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700256
Dave Barachba868bb2016-08-08 09:51:21 -0400257static int
258sw_interface_name_compare (void *a1, void *a2)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700259{
260 vnet_sw_interface_t *si1 = a1;
261 vnet_sw_interface_t *si2 = a2;
262
Dave Barachba868bb2016-08-08 09:51:21 -0400263 return vnet_sw_interface_compare (vnet_get_main (),
264 si1->sw_if_index, si2->sw_if_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700265}
266
267static clib_error_t *
268show_sw_interfaces (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400269 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700270{
Dave Barachba868bb2016-08-08 09:51:21 -0400271 clib_error_t *error = 0;
272 vnet_main_t *vnm = vnet_get_main ();
Dave Barach525c9d02018-05-26 10:48:55 -0400273 unformat_input_t _linput, *linput = &_linput;
Dave Barachba868bb2016-08-08 09:51:21 -0400274 vnet_interface_main_t *im = &vnm->interface_main;
275 vnet_sw_interface_t *si, *sorted_sis = 0;
Damjan Marion22311502016-10-28 20:30:15 +0200276 u32 sw_if_index = ~(u32) 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700277 u8 show_addresses = 0;
Damjan Marion22311502016-10-28 20:30:15 +0200278 u8 show_features = 0;
Dave Barach7be864a2016-11-28 11:41:35 -0500279 u8 show_tag = 0;
Dave Barach525c9d02018-05-26 10:48:55 -0400280 int verbose = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700281
Dave Barach525c9d02018-05-26 10:48:55 -0400282 /*
283 * Get a line of input. Won't work if the user typed
284 * "show interface" and nothing more.
285 */
286 if (unformat_user (input, unformat_line_input, linput))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700287 {
Dave Barach525c9d02018-05-26 10:48:55 -0400288 while (unformat_check_input (linput) != UNFORMAT_END_OF_INPUT)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700289 {
Dave Barach525c9d02018-05-26 10:48:55 -0400290 /* See if user wants to show specific interface */
291 if (unformat
292 (linput, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
293 {
294 si = pool_elt_at_index (im->sw_interfaces, sw_if_index);
295 vec_add1 (sorted_sis, si[0]);
296 }
297 else if (unformat (linput, "address") || unformat (linput, "addr"))
298 show_addresses = 1;
299 else if (unformat (linput, "features") || unformat (linput, "feat"))
300 show_features = 1;
301 else if (unformat (linput, "tag"))
302 show_tag = 1;
303 else if (unformat (linput, "verbose"))
304 verbose = 1;
305 else
306 {
307 error = clib_error_return (0, "unknown input `%U'",
308 format_unformat_error, linput);
309 goto done;
310 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700311 }
Dave Barach525c9d02018-05-26 10:48:55 -0400312 unformat_free (linput);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700313 }
Dave Barach7be864a2016-11-28 11:41:35 -0500314 if (show_features || show_tag)
Damjan Marion22311502016-10-28 20:30:15 +0200315 {
316 if (sw_if_index == ~(u32) 0)
317 return clib_error_return (0, "Interface not specified...");
Dave Barach7be864a2016-11-28 11:41:35 -0500318 }
Damjan Marion22311502016-10-28 20:30:15 +0200319
Dave Barach7be864a2016-11-28 11:41:35 -0500320 if (show_features)
321 {
Dave Barach525c9d02018-05-26 10:48:55 -0400322 vnet_interface_features_show (vm, sw_if_index, verbose);
Eyal Bari942402b2017-07-26 11:57:04 +0300323
324 l2_input_config_t *l2_input = l2input_intf_config (sw_if_index);
325 u32 fb = l2_input->feature_bitmap;
326 /* intf input features are masked by bridge domain */
327 if (l2_input->bridge)
328 fb &= l2input_bd_config (l2_input->bd_index)->feature_bitmap;
329 vlib_cli_output (vm, "\nl2-input:\n%U", format_l2_input_features, fb);
330
331 l2_output_config_t *l2_output = l2output_intf_config (sw_if_index);
332 vlib_cli_output (vm, "\nl2-output:");
333 if (l2_output->out_vtr_flag)
334 vlib_cli_output (vm, "%10s (%s)", "VTR", "--internal--");
335 vlib_cli_output (vm, "%U", format_l2_output_features,
336 l2_output->feature_bitmap);
Damjan Marion22311502016-10-28 20:30:15 +0200337 return 0;
338 }
Dave Barach7be864a2016-11-28 11:41:35 -0500339 if (show_tag)
340 {
341 u8 *tag;
342 tag = vnet_get_sw_interface_tag (vnm, sw_if_index);
343 vlib_cli_output (vm, "%U: %s",
344 format_vnet_sw_if_index_name, vnm, sw_if_index,
345 tag ? (char *) tag : "(none)");
346 return 0;
347 }
Damjan Marion22311502016-10-28 20:30:15 +0200348
Ed Warnickecb9cada2015-12-08 15:45:58 -0700349 if (!show_addresses)
Dave Barachba868bb2016-08-08 09:51:21 -0400350 vlib_cli_output (vm, "%U\n", format_vnet_sw_interface, vnm, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700351
Dave Barachba868bb2016-08-08 09:51:21 -0400352 if (vec_len (sorted_sis) == 0) /* Get all interfaces */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700353 {
354 /* Gather interfaces. */
Dave Barachba868bb2016-08-08 09:51:21 -0400355 sorted_sis =
356 vec_new (vnet_sw_interface_t, pool_elts (im->sw_interfaces));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700357 _vec_len (sorted_sis) = 0;
Dave Barach525c9d02018-05-26 10:48:55 -0400358 /* *INDENT-OFF* */
359 pool_foreach (si, im->sw_interfaces,
360 ({
361 int visible = vnet_swif_is_api_visible (si);
362 if (visible)
363 vec_add1 (sorted_sis, si[0]);}
364 ));
Ole Troand7231612018-06-07 10:17:57 +0200365 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700366 /* Sort by name. */
367 vec_sort_with_function (sorted_sis, sw_interface_name_compare);
368 }
369
370 if (show_addresses)
371 {
372 vec_foreach (si, sorted_sis)
Dave Barachba868bb2016-08-08 09:51:21 -0400373 {
Dave Barachba868bb2016-08-08 09:51:21 -0400374 ip4_main_t *im4 = &ip4_main;
375 ip6_main_t *im6 = &ip6_main;
376 ip_lookup_main_t *lm4 = &im4->lookup_main;
377 ip_lookup_main_t *lm6 = &im6->lookup_main;
378 ip_interface_address_t *ia = 0;
Dave Barachba868bb2016-08-08 09:51:21 -0400379 u32 fib_index4 = 0, fib_index6 = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700380
Dave Barachba868bb2016-08-08 09:51:21 -0400381 if (vec_len (im4->fib_index_by_sw_if_index) > si->sw_if_index)
382 fib_index4 = vec_elt (im4->fib_index_by_sw_if_index,
383 si->sw_if_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700384
Dave Barachba868bb2016-08-08 09:51:21 -0400385 if (vec_len (im6->fib_index_by_sw_if_index) > si->sw_if_index)
386 fib_index6 = vec_elt (im6->fib_index_by_sw_if_index,
387 si->sw_if_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700388
John Lo4478d8e2018-01-12 17:15:25 -0500389 ip4_fib_t *fib4 = ip4_fib_get (fib_index4);
390 ip6_fib_t *fib6 = ip6_fib_get (fib_index6);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700391
Dave Barachba868bb2016-08-08 09:51:21 -0400392 if (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)
393 vlib_cli_output
394 (vm, "%U (%s): \n unnumbered, use %U",
John Lo4478d8e2018-01-12 17:15:25 -0500395 format_vnet_sw_if_index_name, vnm, si->sw_if_index,
Dave Barachba868bb2016-08-08 09:51:21 -0400396 (si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? "up" : "dn",
397 format_vnet_sw_if_index_name, vnm, si->unnumbered_sw_if_index);
Dave Barachba868bb2016-08-08 09:51:21 -0400398 else
John Lo4478d8e2018-01-12 17:15:25 -0500399 vlib_cli_output
400 (vm, "%U (%s):",
401 format_vnet_sw_if_index_name, vnm, si->sw_if_index,
402 (si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ? "up" : "dn");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700403
Eyal Bari942402b2017-07-26 11:57:04 +0300404 /* Display any L2 info */
405 l2_input_config_t *l2_input = l2input_intf_config (si->sw_if_index);
406 if (l2_input->bridge)
Dave Barachba868bb2016-08-08 09:51:21 -0400407 {
John Lo4478d8e2018-01-12 17:15:25 -0500408 bd_main_t *bdm = &bd_main;
Eyal Bari942402b2017-07-26 11:57:04 +0300409 u32 bd_id = l2input_main.bd_configs[l2_input->bd_index].bd_id;
John Lo4478d8e2018-01-12 17:15:25 -0500410 vlib_cli_output (vm, " L2 bridge bd-id %d idx %d shg %d %s",
411 bd_id, bd_find_index (bdm, bd_id), l2_input->shg,
412 l2_input->bvi ? "bvi" : " ");
Dave Barachba868bb2016-08-08 09:51:21 -0400413 }
Eyal Bari942402b2017-07-26 11:57:04 +0300414 else if (l2_input->xconnect)
John Lo4478d8e2018-01-12 17:15:25 -0500415 vlib_cli_output (vm, " L2 xconnect %U",
416 format_vnet_sw_if_index_name, vnm,
417 l2_input->output_sw_if_index);
Dave Barachba868bb2016-08-08 09:51:21 -0400418
John Lo4478d8e2018-01-12 17:15:25 -0500419 /* *INDENT-OFF* */
Dave Barachba868bb2016-08-08 09:51:21 -0400420 /* Display any IP4 addressing info */
John Lo4478d8e2018-01-12 17:15:25 -0500421 foreach_ip_interface_address (lm4, ia, si->sw_if_index,
422 1 /* honor unnumbered */,
423 ({
424 ip4_address_t *r4 = ip_interface_address_get_address (lm4, ia);
425 if (fib4->table_id)
426 vlib_cli_output (vm, " L3 %U/%d ip4 table-id %d fib-idx %d",
427 format_ip4_address, r4, ia->address_length,
428 fib4->table_id,
429 ip4_fib_index_from_table_id (fib4->table_id));
430 else
431 vlib_cli_output (vm, " L3 %U/%d",
432 format_ip4_address, r4, ia->address_length);
433 }));
434 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700435
John Lo4478d8e2018-01-12 17:15:25 -0500436 /* *INDENT-OFF* */
Dave Barachba868bb2016-08-08 09:51:21 -0400437 /* Display any IP6 addressing info */
John Lo4478d8e2018-01-12 17:15:25 -0500438 foreach_ip_interface_address (lm6, ia, si->sw_if_index,
439 1 /* honor unnumbered */,
440 ({
441 ip6_address_t *r6 = ip_interface_address_get_address (lm6, ia);
442 if (fib6->table_id)
443 vlib_cli_output (vm, " L3 %U/%d ip6 table-id %d fib-idx %d",
444 format_ip6_address, r6, ia->address_length,
445 fib6->table_id,
446 ip6_fib_index_from_table_id (fib6->table_id));
447 else
448 vlib_cli_output (vm, " L3 %U/%d",
449 format_ip6_address, r6, ia->address_length);
450 }));
451 /* *INDENT-ON* */
Ole Troand7231612018-06-07 10:17:57 +0200452 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700453 }
Ole Troand7231612018-06-07 10:17:57 +0200454 else
455 {
456 vec_foreach (si, sorted_sis)
457 {
458 vlib_cli_output (vm, "%U\n", format_vnet_sw_interface, vnm, si);
459 }
460 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700461
Dave Barachba868bb2016-08-08 09:51:21 -0400462done:
Ole Troand7231612018-06-07 10:17:57 +0200463 vec_free (sorted_sis);
464 return error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700465}
466
Dave Barachba868bb2016-08-08 09:51:21 -0400467/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700468VLIB_CLI_COMMAND (show_sw_interfaces_command, static) = {
Dave Barach13ad1f02017-03-26 19:36:18 -0400469 .path = "show interface",
Dave Barach525c9d02018-05-26 10:48:55 -0400470 .short_help = "show interface [address|addr|features|feat] [<interface> [<interface> [..]]] [verbose]",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700471 .function = show_sw_interfaces,
472};
Dave Barachba868bb2016-08-08 09:51:21 -0400473/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700474
475/* Root of all interface commands. */
Dave Barachba868bb2016-08-08 09:51:21 -0400476/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700477VLIB_CLI_COMMAND (vnet_cli_interface_command, static) = {
478 .path = "interface",
479 .short_help = "Interface commands",
480};
Dave Barachba868bb2016-08-08 09:51:21 -0400481/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700482
Dave Barachba868bb2016-08-08 09:51:21 -0400483/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700484VLIB_CLI_COMMAND (vnet_cli_set_interface_command, static) = {
485 .path = "set interface",
486 .short_help = "Interface commands",
487};
Dave Barachba868bb2016-08-08 09:51:21 -0400488/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700489
490static clib_error_t *
491clear_interface_counters (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400492 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700493{
Dave Barachba868bb2016-08-08 09:51:21 -0400494 vnet_main_t *vnm = vnet_get_main ();
495 vnet_interface_main_t *im = &vnm->interface_main;
496 vlib_simple_counter_main_t *sm;
497 vlib_combined_counter_main_t *cm;
498 static vnet_main_t **my_vnet_mains;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700499 int i, j, n_counters;
500
501 vec_reset_length (my_vnet_mains);
Dave Barachba868bb2016-08-08 09:51:21 -0400502
Ed Warnickecb9cada2015-12-08 15:45:58 -0700503 for (i = 0; i < vec_len (vnet_mains); i++)
504 {
505 if (vnet_mains[i])
Dave Barachba868bb2016-08-08 09:51:21 -0400506 vec_add1 (my_vnet_mains, vnet_mains[i]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700507 }
508
509 if (vec_len (vnet_mains) == 0)
510 vec_add1 (my_vnet_mains, vnm);
511
512 n_counters = vec_len (im->combined_sw_if_counters);
513
514 for (j = 0; j < n_counters; j++)
515 {
Dave Barachba868bb2016-08-08 09:51:21 -0400516 for (i = 0; i < vec_len (my_vnet_mains); i++)
517 {
518 im = &my_vnet_mains[i]->interface_main;
519 cm = im->combined_sw_if_counters + j;
520 vlib_clear_combined_counters (cm);
521 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700522 }
523
524 n_counters = vec_len (im->sw_if_counters);
525
526 for (j = 0; j < n_counters; j++)
527 {
Dave Barachba868bb2016-08-08 09:51:21 -0400528 for (i = 0; i < vec_len (my_vnet_mains); i++)
529 {
530 im = &my_vnet_mains[i]->interface_main;
531 sm = im->sw_if_counters + j;
532 vlib_clear_simple_counters (sm);
533 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700534 }
535
536 return 0;
537}
538
Billy McFalle9bac692017-08-11 14:05:11 -0400539/*?
540 * Clear the statistics for all interfaces (statistics associated with the
541 * '<em>show interface</em>' command).
542 *
543 * @cliexpar
544 * Example of how to clear the statistics for all interfaces:
545 * @cliexcmd{clear interfaces}
546 ?*/
Dave Barachba868bb2016-08-08 09:51:21 -0400547/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700548VLIB_CLI_COMMAND (clear_interface_counters_command, static) = {
549 .path = "clear interfaces",
Billy McFalle9bac692017-08-11 14:05:11 -0400550 .short_help = "clear interfaces",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700551 .function = clear_interface_counters,
552};
Dave Barachba868bb2016-08-08 09:51:21 -0400553/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700554
Chris Luke16bcf7d2016-09-01 14:31:46 -0400555/**
556 * Parse subinterface names.
557 *
Dave Barachba868bb2016-08-08 09:51:21 -0400558 * The following subinterface syntax is supported. The first two are for
559 * backwards compatability:
560 *
561 * <intf-name> <id>
562 * - a subinterface with the name <intf-name>.<id>. The subinterface
563 * is a single dot1q vlan with vlan id <id> and exact-match semantics.
564 *
565 * <intf-name> <min_id>-<max_id>
566 * - a set of the above subinterfaces, repeating for each id
567 * in the range <min_id> to <max_id>
568 *
569 * In the following, exact-match semantics (i.e. the number of vlan tags on the
570 * packet must match the number of tags in the configuration) are used only if
571 * the keyword exact-match is present. Non-exact match is the default.
572 *
573 * <intf-name> <id> dot1q <outer_id> [exact-match]
574 * - a subinterface with the name <intf-name>.<id>. The subinterface
575 * is a single dot1q vlan with vlan id <outer_id>.
576 *
577 * <intf-name> <id> dot1q any [exact-match]
578 * - a subinterface with the name <intf-name>.<id>. The subinterface
579 * is a single dot1q vlan with any vlan id.
580 *
581 * <intf-name> <id> dot1q <outer_id> inner-dot1q <inner_id> [exact-match]
582 * - a subinterface with the name <intf-name>.<id>. The subinterface
583 * is a double dot1q vlan with outer vlan id <outer_id> and inner vlan id
584 * <inner_id>.
585 *
586 * <intf-name> <id> dot1q <outer_id> inner-dot1q any [exact-match]
587 * - a subinterface with the name <intf-name>.<id>. The subinterface
588 * is a double dot1q vlan with outer vlan id <id> and any inner vlan id.
589 *
590 * <intf-name> <id> dot1q any inner-dot1q any [exact-match]
591 *
592 * - a subinterface with the name <intf-name>.<id>. The subinterface
593 * is a double dot1q vlan with any outer vlan id and any inner vlan id.
594 *
595 * For each of the above CLI, there is a duplicate that uses the keyword
596 * "dot1ad" in place of the first "dot1q". These interfaces use ethertype
597 * 0x88ad in place of 0x8100 for the outer ethertype. Note that for double-
598 * tagged packets the inner ethertype is always 0x8100. Also note that
599 * the dot1q and dot1ad naming spaces are independent, so it is legal to
600 * have both "Gig3/0/0.1 dot1q 100" and "Gig3/0/0.2 dot1ad 100". For example:
601 *
602 * <intf-name> <id> dot1ad <outer_id> inner-dot1q <inner_id> [exact-match]
603 * - a subinterface with the name <intf-name>.<id>. The subinterface
604 * is a double dot1ad vlan with outer vlan id <outer_id> and inner vlan
605 * id <inner_id>.
606 *
607 * <intf-name> <id> untagged
608 * - a subinterface with the name <intf-name>.<id>. The subinterface
609 * has no vlan tags. Only one can be specified per interface.
610 *
611 * <intf-name> <id> default
612 * - a subinterface with the name <intf-name>.<id>. This is associated
613 * with a packet that did not match any other configured subinterface
614 * on this interface. Only one can be specified per interface.
615 */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700616
617static clib_error_t *
Dave Barachba868bb2016-08-08 09:51:21 -0400618parse_vlan_sub_interfaces (unformat_input_t * input,
619 vnet_sw_interface_t * template)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700620{
Dave Barachba868bb2016-08-08 09:51:21 -0400621 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700622 u32 inner_vlan, outer_vlan;
623
Dave Barachba868bb2016-08-08 09:51:21 -0400624 if (unformat (input, "any inner-dot1q any"))
625 {
626 template->sub.eth.flags.two_tags = 1;
627 template->sub.eth.flags.outer_vlan_id_any = 1;
628 template->sub.eth.flags.inner_vlan_id_any = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700629 }
Dave Barachba868bb2016-08-08 09:51:21 -0400630 else if (unformat (input, "any"))
631 {
632 template->sub.eth.flags.one_tag = 1;
633 template->sub.eth.flags.outer_vlan_id_any = 1;
634 }
635 else if (unformat (input, "%d inner-dot1q any", &outer_vlan))
636 {
637 template->sub.eth.flags.two_tags = 1;
638 template->sub.eth.flags.inner_vlan_id_any = 1;
639 template->sub.eth.outer_vlan_id = outer_vlan;
640 }
641 else if (unformat (input, "%d inner-dot1q %d", &outer_vlan, &inner_vlan))
642 {
643 template->sub.eth.flags.two_tags = 1;
644 template->sub.eth.outer_vlan_id = outer_vlan;
645 template->sub.eth.inner_vlan_id = inner_vlan;
646 }
647 else if (unformat (input, "%d", &outer_vlan))
648 {
649 template->sub.eth.flags.one_tag = 1;
650 template->sub.eth.outer_vlan_id = outer_vlan;
651 }
652 else
653 {
654 error = clib_error_return (0, "expected dot1q config, got `%U'",
655 format_unformat_error, input);
656 goto done;
657 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700658
Dave Barachba868bb2016-08-08 09:51:21 -0400659 if (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
660 {
661 if (unformat (input, "exact-match"))
662 {
663 template->sub.eth.flags.exact_match = 1;
664 }
665 }
666
667done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700668 return error;
669}
670
671static clib_error_t *
672create_sub_interfaces (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400673 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700674{
Dave Barachba868bb2016-08-08 09:51:21 -0400675 vnet_main_t *vnm = vnet_get_main ();
676 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700677 u32 hw_if_index, sw_if_index;
Dave Barachba868bb2016-08-08 09:51:21 -0400678 vnet_hw_interface_t *hi;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700679 u32 id, id_min, id_max;
680 vnet_sw_interface_t template;
681
682 hw_if_index = ~0;
Dave Barachba868bb2016-08-08 09:51:21 -0400683 if (!unformat_user (input, unformat_vnet_hw_interface, vnm, &hw_if_index))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700684 {
685 error = clib_error_return (0, "unknown interface `%U'",
686 format_unformat_error, input);
687 goto done;
688 }
689
690 memset (&template, 0, sizeof (template));
691 template.sub.eth.raw_flags = 0;
692
Dave Barachba868bb2016-08-08 09:51:21 -0400693 if (unformat (input, "%d default", &id_min))
694 {
695 id_max = id_min;
696 template.sub.eth.flags.default_sub = 1;
697 }
698 else if (unformat (input, "%d untagged", &id_min))
699 {
700 id_max = id_min;
701 template.sub.eth.flags.no_tags = 1;
702 template.sub.eth.flags.exact_match = 1;
703 }
704 else if (unformat (input, "%d dot1q", &id_min))
705 {
706 /* parse dot1q config */
707 id_max = id_min;
708 error = parse_vlan_sub_interfaces (input, &template);
709 if (error)
710 goto done;
711 }
712 else if (unformat (input, "%d dot1ad", &id_min))
713 {
714 /* parse dot1ad config */
715 id_max = id_min;
716 template.sub.eth.flags.dot1ad = 1;
717 error = parse_vlan_sub_interfaces (input, &template);
718 if (error)
719 goto done;
720 }
721 else if (unformat (input, "%d-%d", &id_min, &id_max))
722 {
723 template.sub.eth.flags.one_tag = 1;
Dave Barachba868bb2016-08-08 09:51:21 -0400724 template.sub.eth.flags.exact_match = 1;
725 if (id_min > id_max)
726 goto id_error;
727 }
728 else if (unformat (input, "%d", &id_min))
729 {
730 id_max = id_min;
731 template.sub.eth.flags.one_tag = 1;
732 template.sub.eth.outer_vlan_id = id_min;
733 template.sub.eth.flags.exact_match = 1;
734 }
735 else
736 {
Ed Warnickecb9cada2015-12-08 15:45:58 -0700737 id_error:
738 error = clib_error_return (0, "expected ID or ID MIN-MAX, got `%U'",
739 format_unformat_error, input);
740 goto done;
Dave Barachba868bb2016-08-08 09:51:21 -0400741 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700742
743 hi = vnet_get_hw_interface (vnm, hw_if_index);
John Lobcebbb92016-04-05 15:47:43 -0400744
Dave Barachba868bb2016-08-08 09:51:21 -0400745 if (hi->bond_info == VNET_HW_INTERFACE_BOND_INFO_SLAVE)
746 {
747 error =
748 clib_error_return (0,
749 "not allowed as %v belong to a BondEthernet interface",
750 hi->name);
751 goto done;
752 }
John Lobcebbb92016-04-05 15:47:43 -0400753
Ed Warnickecb9cada2015-12-08 15:45:58 -0700754 for (id = id_min; id <= id_max; id++)
755 {
Dave Barachba868bb2016-08-08 09:51:21 -0400756 uword *p;
757 vnet_interface_main_t *im = &vnm->interface_main;
758 u64 sup_and_sub_key = ((u64) (hi->sw_if_index) << 32) | (u64) id;
759 u64 *kp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700760
761 p = hash_get_mem (im->sw_if_index_by_sup_and_sub, &sup_and_sub_key);
762 if (p)
Dave Barachba868bb2016-08-08 09:51:21 -0400763 {
764 if (CLIB_DEBUG > 0)
765 clib_warning ("sup sw_if_index %d, sub id %d already exists\n",
766 hi->sw_if_index, id);
767 continue;
768 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700769
770 kp = clib_mem_alloc (sizeof (*kp));
771 *kp = sup_and_sub_key;
772
773 template.type = VNET_SW_INTERFACE_TYPE_SUB;
Eyal Baric5b13602016-11-24 19:42:43 +0200774 template.flood_class = VNET_FLOOD_CLASS_NORMAL;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700775 template.sup_sw_if_index = hi->sw_if_index;
776 template.sub.id = id;
Eyal Baria4509cf2016-09-26 09:24:09 +0300777 if (id_min < id_max)
778 template.sub.eth.outer_vlan_id = id;
779
Ed Warnickecb9cada2015-12-08 15:45:58 -0700780 error = vnet_create_sw_interface (vnm, &template, &sw_if_index);
Dave Barachba868bb2016-08-08 09:51:21 -0400781 if (error)
782 goto done;
Dave Barach16ad6ae2016-07-28 17:55:30 -0400783
Ed Warnickecb9cada2015-12-08 15:45:58 -0700784 hash_set (hi->sub_interface_sw_if_index_by_id, id, sw_if_index);
785 hash_set_mem (im->sw_if_index_by_sup_and_sub, kp, sw_if_index);
Dave Barachba868bb2016-08-08 09:51:21 -0400786 vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name,
787 vnet_get_main (), sw_if_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700788 }
789
Dave Barachba868bb2016-08-08 09:51:21 -0400790done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700791 return error;
792}
793
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700794/*?
Billy McFalle9bac692017-08-11 14:05:11 -0400795 * This command is used to add VLAN IDs to interfaces, also known as subinterfaces.
796 * The primary input to this command is the '<em>interface</em>' and '<em>subId</em>'
797 * (subinterface Id) parameters. If no additional VLAN ID is provide, the VLAN ID is
798 * assumed to be the '<em>subId</em>'. The VLAN ID and '<em>subId</em>' can be different,
799 * but this is not recommended.
800 *
801 * This command has several variations:
802 * - <b>create sub-interfaces <interface> <subId></b> - Create a subinterface to
803 * process packets with a given 802.1q VLAN ID (same value as the '<em>subId</em>').
804 *
805 * - <b>create sub-interfaces <interface> <subId> default</b> - Adding the
806 * '<em>default</em>' parameter indicates that packets with VLAN IDs that do not
807 * match any other subinterfaces should be sent to this subinterface.
808 *
809 * - <b>create sub-interfaces <interface> <subId> untagged</b> - Adding the
810 * '<em>untagged</em>' parameter indicates that packets no VLAN IDs should be sent
811 * to this subinterface.
812 *
813 * - <b>create sub-interfaces <interface> <subId>-<subId></b> - Create a range of
814 * subinterfaces to handle a range of VLAN IDs.
815 *
816 * - <b>create sub-interfaces <interface> <subId> dot1q|dot1ad <vlanId>|any [exact-match]</b> -
817 * Use this command to specify the outer VLAN ID, to either be explicited or to make the
818 * VLAN ID different from the '<em>subId</em>'.
819 *
820 * - <b>create sub-interfaces <interface> <subId> dot1q|dot1ad <vlanId>|any inner-dot1q
821 * <vlanId>|any [exact-match]</b> - Use this command to specify the outer VLAN ID and
822 * the innner VLAN ID.
823 *
824 * When '<em>dot1q</em>' or '<em>dot1ad</em>' is explictly entered, subinterfaces
825 * can be configured as either exact-match or non-exact match. Non-exact match is the CLI
826 * default. If '<em>exact-match</em>' is specified, packets must have the same number of
827 * VLAN tags as the configuration. For non-exact-match, packets must at least that number
828 * of tags. L3 (routed) interfaces must be configured as exact-match. L2 interfaces are
829 * typically configured as non-exact-match. If '<em>dot1q</em>' or '<em>dot1ad</em>' is NOT
830 * entered, then the default behavior is exact-match.
831 *
832 * Use the '<em>show interface</em>' command to display all subinterfaces.
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700833 *
834 * @cliexpar
Billy McFalle9bac692017-08-11 14:05:11 -0400835 * @parblock
836 * Example of how to create a VLAN subinterface 11 to process packets on 802.1q VLAN ID 11:
837 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 11}
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700838 *
Billy McFalle9bac692017-08-11 14:05:11 -0400839 * The previous example is shorthand and is equivalent to:
840 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 11 dot1q 11 exact-match}
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700841 *
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700842 *
Billy McFalle9bac692017-08-11 14:05:11 -0400843 * Example of how to create a subinterface number that is different from the VLAN ID:
844 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 11 dot1q 100}
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700845 *
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700846 *
Billy McFalle9bac692017-08-11 14:05:11 -0400847 * Examples of how to create q-in-q and q-in-any subinterfaces:
848 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 11 dot1q 100 inner-dot1q 200}
849 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 12 dot1q 100 inner-dot1q any}
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700850 *
Billy McFalle9bac692017-08-11 14:05:11 -0400851 * Examples of how to create dot1ad interfaces:
852 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 11 dot1ad 11}
853 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 12 dot1ad 100 inner-dot1q 200}
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700854 *
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700855 *
Billy McFalle9bac692017-08-11 14:05:11 -0400856 * Examples of '<em>exact-match</em>' versus non-exact match. A packet with
857 * outer VLAN 100 and inner VLAN 200 would match this interface, because the default
858 * is non-exact match:
859 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 5 dot1q 100}
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700860 *
Billy McFalle9bac692017-08-11 14:05:11 -0400861 * However, the same packet would NOT match this interface because '<em>exact-match</em>'
862 * is specified and only one VLAN is configured, but packet contains two VLANs:
863 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 5 dot1q 100 exact-match}
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 * Example of how to created a subinterface to process untagged packets:
867 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 5 untagged}
868 *
869 * Example of how to created a subinterface to process any packet with a VLAN ID that
870 * does not match any other subinterface:
871 * @cliexcmd{create sub-interfaces GigabitEthernet2/0/0 7 default}
872 *
873 * When subinterfaces are created, they are in the down state. Example of how to
874 * enable a newly created subinterface:
875 * @cliexcmd{set interface GigabitEthernet2/0/0.7 up}
876 * @endparblock
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700877 ?*/
Billy McFalle9bac692017-08-11 14:05:11 -0400878/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700879VLIB_CLI_COMMAND (create_sub_interfaces_command, static) = {
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700880 .path = "create sub-interfaces",
Billy McFalle9bac692017-08-11 14:05:11 -0400881 .short_help = "create sub-interfaces <interface> "
882 "{<subId> [default|untagged]} | "
883 "{<subId>-<subId>} | "
884 "{<subId> dot1q|dot1ad <vlanId>|any [inner-dot1q <vlanId>|any] [exact-match]}",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700885 .function = create_sub_interfaces,
886};
Dave Barachba868bb2016-08-08 09:51:21 -0400887/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700888
889static clib_error_t *
890set_state (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400891 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700892{
Dave Barachba868bb2016-08-08 09:51:21 -0400893 vnet_main_t *vnm = vnet_get_main ();
894 clib_error_t *error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700895 u32 sw_if_index, flags;
896
897 sw_if_index = ~0;
Dave Barachba868bb2016-08-08 09:51:21 -0400898 if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700899 {
900 error = clib_error_return (0, "unknown interface `%U'",
901 format_unformat_error, input);
902 goto done;
903 }
904
Dave Barachba868bb2016-08-08 09:51:21 -0400905 if (!unformat (input, "%U", unformat_vnet_sw_interface_flags, &flags))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700906 {
907 error = clib_error_return (0, "unknown flags `%U'",
908 format_unformat_error, input);
909 goto done;
910 }
911
912 error = vnet_sw_interface_set_flags (vnm, sw_if_index, flags);
913 if (error)
914 goto done;
915
Dave Barachba868bb2016-08-08 09:51:21 -0400916done:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700917 return error;
918}
919
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700920
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700921/*?
Billy McFalle9bac692017-08-11 14:05:11 -0400922 * This command is used to change the admin state (up/down) of an interface.
923 *
924 * If an interface is down, the optional '<em>punt</em>' flag can also be set.
925 * The '<em>punt</em>' flag implies the interface is disabled for forwarding
926 * but punt all traffic to slow-path. Use the '<em>enable</em>' flag to clear
927 * '<em>punt</em>' flag (interface is still down).
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700928 *
929 * @cliexpar
Billy McFalle9bac692017-08-11 14:05:11 -0400930 * Example of how to configure the admin state of an interface to '<em>up</em?':
931 * @cliexcmd{set interface state GigabitEthernet2/0/0 up}
932 * Example of how to configure the admin state of an interface to '<em>down</em?':
933 * @cliexcmd{set interface state GigabitEthernet2/0/0 down}
Keith Burns (alagalah)6ef7bb92016-09-10 14:55:04 -0700934 ?*/
Billy McFalle9bac692017-08-11 14:05:11 -0400935/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700936VLIB_CLI_COMMAND (set_state_command, static) = {
937 .path = "set interface state",
Billy McFalle9bac692017-08-11 14:05:11 -0400938 .short_help = "set interface state <interface> [up|down|punt|enable]",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700939 .function = set_state,
940};
Dave Barachba868bb2016-08-08 09:51:21 -0400941/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700942
943static clib_error_t *
944set_unnumbered (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400945 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700946{
Dave Barachba868bb2016-08-08 09:51:21 -0400947 vnet_main_t *vnm = vnet_get_main ();
Neale Ranns2ae2bc52018-03-16 03:22:39 -0700948 u32 unnumbered_sw_if_index = ~0;
949 u32 inherit_from_sw_if_index = ~0;
950 int enable = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700951
Igor Mikhailov (imichail)ab3e42b2016-09-25 15:11:53 -0700952 if (unformat (input, "%U use %U",
953 unformat_vnet_sw_interface, vnm, &unnumbered_sw_if_index,
954 unformat_vnet_sw_interface, vnm, &inherit_from_sw_if_index))
Neale Ranns2ae2bc52018-03-16 03:22:39 -0700955 enable = 1;
Igor Mikhailov (imichail)ab3e42b2016-09-25 15:11:53 -0700956 else if (unformat (input, "del %U",
957 unformat_vnet_sw_interface, vnm,
958 &unnumbered_sw_if_index))
Neale Ranns2ae2bc52018-03-16 03:22:39 -0700959 enable = 0;
Igor Mikhailov (imichail)ab3e42b2016-09-25 15:11:53 -0700960 else
961 return clib_error_return (0, "parse error '%U'",
962 format_unformat_error, input);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700963
Neale Ranns2ae2bc52018-03-16 03:22:39 -0700964 if (~0 == unnumbered_sw_if_index)
965 return clib_error_return (0, "Specify the unnumbered interface");
966 if (enable && ~0 == inherit_from_sw_if_index)
967 return clib_error_return (0, "When enabling unnumberered specify the"
968 " IP enabled interface that it uses");
Neale Ranns898273f2017-03-18 02:57:38 -0700969
Neale Ranns2ae2bc52018-03-16 03:22:39 -0700970 vnet_sw_interface_update_unnumbered (unnumbered_sw_if_index,
971 inherit_from_sw_if_index, enable);
Neale Ranns898273f2017-03-18 02:57:38 -0700972
Neale Ranns2ae2bc52018-03-16 03:22:39 -0700973 return (NULL);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700974}
975
Dave Barachba868bb2016-08-08 09:51:21 -0400976/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700977VLIB_CLI_COMMAND (set_unnumbered_command, static) = {
978 .path = "set interface unnumbered",
Billy McFalle9bac692017-08-11 14:05:11 -0400979 .short_help = "set interface unnumbered [<interface> use <interface> | del <interface>]",
Ed Warnickecb9cada2015-12-08 15:45:58 -0700980 .function = set_unnumbered,
981};
Dave Barachba868bb2016-08-08 09:51:21 -0400982/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700983
984
985
986static clib_error_t *
987set_hw_class (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -0400988 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700989{
Dave Barachba868bb2016-08-08 09:51:21 -0400990 vnet_main_t *vnm = vnet_get_main ();
991 vnet_interface_main_t *im = &vnm->interface_main;
992 clib_error_t *error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700993 u32 hw_if_index, hw_class_index;
994
995 hw_if_index = ~0;
Dave Barachba868bb2016-08-08 09:51:21 -0400996 if (!unformat_user (input, unformat_vnet_hw_interface, vnm, &hw_if_index))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700997 {
998 error = clib_error_return (0, "unknown hardware interface `%U'",
999 format_unformat_error, input);
1000 goto done;
1001 }
1002
Dave Barachba868bb2016-08-08 09:51:21 -04001003 if (!unformat_user (input, unformat_hash_string,
1004 im->hw_interface_class_by_name, &hw_class_index))
Ed Warnickecb9cada2015-12-08 15:45:58 -07001005 {
1006 error = clib_error_return (0, "unknown hardware class `%U'",
1007 format_unformat_error, input);
1008 goto done;
1009 }
1010
1011 error = vnet_hw_interface_set_class (vnm, hw_if_index, hw_class_index);
1012 if (error)
1013 goto done;
1014
Dave Barachba868bb2016-08-08 09:51:21 -04001015done:
Ed Warnickecb9cada2015-12-08 15:45:58 -07001016 return error;
1017}
1018
Dave Barachba868bb2016-08-08 09:51:21 -04001019/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001020VLIB_CLI_COMMAND (set_hw_class_command, static) = {
1021 .path = "set interface hw-class",
1022 .short_help = "Set interface hardware class",
1023 .function = set_hw_class,
1024};
Dave Barachba868bb2016-08-08 09:51:21 -04001025/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001026
Dave Barachba868bb2016-08-08 09:51:21 -04001027static clib_error_t *
1028vnet_interface_cli_init (vlib_main_t * vm)
1029{
1030 return 0;
1031}
Ed Warnickecb9cada2015-12-08 15:45:58 -07001032
1033VLIB_INIT_FUNCTION (vnet_interface_cli_init);
1034
Dave Barachba868bb2016-08-08 09:51:21 -04001035static clib_error_t *
Ed Warnickecb9cada2015-12-08 15:45:58 -07001036renumber_interface_command_fn (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -04001037 unformat_input_t * input,
1038 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001039{
1040 u32 hw_if_index;
1041 u32 new_dev_instance;
Dave Barachba868bb2016-08-08 09:51:21 -04001042 vnet_main_t *vnm = vnet_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -07001043 int rv;
1044
Dave Barachba868bb2016-08-08 09:51:21 -04001045 if (!unformat_user (input, unformat_vnet_hw_interface, vnm, &hw_if_index))
Ed Warnickecb9cada2015-12-08 15:45:58 -07001046 return clib_error_return (0, "unknown hardware interface `%U'",
Dave Barachba868bb2016-08-08 09:51:21 -04001047 format_unformat_error, input);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001048
Dave Barachba868bb2016-08-08 09:51:21 -04001049 if (!unformat (input, "%d", &new_dev_instance))
Ed Warnickecb9cada2015-12-08 15:45:58 -07001050 return clib_error_return (0, "new dev instance missing");
1051
1052 rv = vnet_interface_name_renumber (hw_if_index, new_dev_instance);
1053
1054 switch (rv)
1055 {
1056 case 0:
1057 break;
1058
1059 default:
1060 return clib_error_return (0, "vnet_interface_name_renumber returned %d",
Dave Barachba868bb2016-08-08 09:51:21 -04001061 rv);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001062
1063 }
1064
1065 return 0;
1066}
1067
1068
Dave Barachba868bb2016-08-08 09:51:21 -04001069/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001070VLIB_CLI_COMMAND (renumber_interface_command, static) = {
1071 .path = "renumber interface",
Billy McFalle9bac692017-08-11 14:05:11 -04001072 .short_help = "renumber interface <interface> <new-dev-instance>",
Ed Warnickecb9cada2015-12-08 15:45:58 -07001073 .function = renumber_interface_command_fn,
1074};
Dave Barachba868bb2016-08-08 09:51:21 -04001075/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -07001076
Damjan Marion8358ff92016-04-15 14:26:00 +02001077static clib_error_t *
1078promiscuous_cmd (vlib_main_t * vm,
Dave Barachba868bb2016-08-08 09:51:21 -04001079 unformat_input_t * input, vlib_cli_command_t * cmd)
Damjan Marion8358ff92016-04-15 14:26:00 +02001080{
Dave Barachba868bb2016-08-08 09:51:21 -04001081 vnet_main_t *vnm = vnet_get_main ();
Damjan Marion8358ff92016-04-15 14:26:00 +02001082 u32 hw_if_index;
1083 u32 flags = ETHERNET_INTERFACE_FLAG_ACCEPT_ALL;
Dave Barachba868bb2016-08-08 09:51:21 -04001084 ethernet_main_t *em = &ethernet_main;
1085 ethernet_interface_t *eif;
Damjan Marion8358ff92016-04-15 14:26:00 +02001086
1087 if (unformat (input, "on %U",
Dave Barachba868bb2016-08-08 09:51:21 -04001088 unformat_vnet_hw_interface, vnm, &hw_if_index))
Damjan Marion8358ff92016-04-15 14:26:00 +02001089 ;
1090 else if (unformat (input, "off %U",
Dave Barachba868bb2016-08-08 09:51:21 -04001091 unformat_ethernet_interface, vnm, &hw_if_index))
Damjan Marion8358ff92016-04-15 14:26:00 +02001092 flags = 0;
1093 else
1094 return clib_error_return (0, "unknown input `%U'",
Dave Barachba868bb2016-08-08 09:51:21 -04001095 format_unformat_error, input);
Damjan Marion8358ff92016-04-15 14:26:00 +02001096
1097 eif = ethernet_get_interface (em, hw_if_index);
1098 if (!eif)
1099 return clib_error_return (0, "not supported");
1100
1101 ethernet_set_flags (vnm, hw_if_index, flags);
1102 return 0;
1103}
1104
Dave Barachba868bb2016-08-08 09:51:21 -04001105/* *INDENT-OFF* */
Damjan Marion8358ff92016-04-15 14:26:00 +02001106VLIB_CLI_COMMAND (set_interface_promiscuous_cmd, static) = {
1107 .path = "set interface promiscuous",
Billy McFalle9bac692017-08-11 14:05:11 -04001108 .short_help = "set interface promiscuous [on|off] <interface>",
Damjan Marion8358ff92016-04-15 14:26:00 +02001109 .function = promiscuous_cmd,
1110};
Dave Barachba868bb2016-08-08 09:51:21 -04001111/* *INDENT-ON* */
Damjan Marion8358ff92016-04-15 14:26:00 +02001112
1113static clib_error_t *
1114mtu_cmd (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
1115{
Dave Barachba868bb2016-08-08 09:51:21 -04001116 vnet_main_t *vnm = vnet_get_main ();
Ole Troand7231612018-06-07 10:17:57 +02001117 u32 hw_if_index, sw_if_index, mtu;
Damjan Marionfe7d4a22018-04-13 19:43:39 +02001118 ethernet_main_t *em = &ethernet_main;
Ole Troand7231612018-06-07 10:17:57 +02001119 u32 mtus[VNET_N_MTU] = { 0, 0, 0, 0 };
Damjan Marion8358ff92016-04-15 14:26:00 +02001120
Damjan Marionfe7d4a22018-04-13 19:43:39 +02001121 if (unformat (input, "%d %U", &mtu,
1122 unformat_vnet_hw_interface, vnm, &hw_if_index))
Damjan Marion8358ff92016-04-15 14:26:00 +02001123 {
Ole Troand7231612018-06-07 10:17:57 +02001124 /*
1125 * Change physical MTU on interface. Only supported for Ethernet
1126 * interfaces
1127 */
Damjan Marionfe7d4a22018-04-13 19:43:39 +02001128 vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
1129 ethernet_interface_t *eif = ethernet_get_interface (em, hw_if_index);
1130
1131 if (!eif)
1132 return clib_error_return (0, "not supported");
1133
1134 if (mtu < hi->min_supported_packet_bytes)
1135 return clib_error_return (0, "Invalid mtu (%d): "
1136 "must be >= min pkt bytes (%d)", mtu,
1137 hi->min_supported_packet_bytes);
1138
1139 if (mtu > hi->max_supported_packet_bytes)
1140 return clib_error_return (0, "Invalid mtu (%d): must be <= (%d)", mtu,
1141 hi->max_supported_packet_bytes);
1142
1143 vnet_hw_interface_set_mtu (vnm, hw_if_index, mtu);
Ole Troand7231612018-06-07 10:17:57 +02001144 goto done;
Damjan Marion8358ff92016-04-15 14:26:00 +02001145 }
Ole Troand7231612018-06-07 10:17:57 +02001146 else if (unformat (input, "packet %d %U", &mtu,
1147 unformat_vnet_sw_interface, vnm, &sw_if_index))
1148 /* Set default packet MTU (including L3 header */
1149 mtus[VNET_MTU_L3] = mtu;
1150 else if (unformat (input, "ip4 %d %U", &mtu,
1151 unformat_vnet_sw_interface, vnm, &sw_if_index))
1152 mtus[VNET_MTU_IP4] = mtu;
1153 else if (unformat (input, "ip6 %d %U", &mtu,
1154 unformat_vnet_sw_interface, vnm, &sw_if_index))
1155 mtus[VNET_MTU_IP6] = mtu;
1156 else if (unformat (input, "mpls %d %U", &mtu,
1157 unformat_vnet_sw_interface, vnm, &sw_if_index))
1158 mtus[VNET_MTU_MPLS] = mtu;
Damjan Marion8358ff92016-04-15 14:26:00 +02001159 else
Damjan Marionfe7d4a22018-04-13 19:43:39 +02001160 return clib_error_return (0, "unknown input `%U'",
1161 format_unformat_error, input);
Ole Troand7231612018-06-07 10:17:57 +02001162
1163 vnet_sw_interface_set_protocol_mtu (vnm, sw_if_index, mtus);
1164
1165done:
Damjan Marion8358ff92016-04-15 14:26:00 +02001166 return 0;
1167}
1168
Dave Barachba868bb2016-08-08 09:51:21 -04001169/* *INDENT-OFF* */
Damjan Marion8358ff92016-04-15 14:26:00 +02001170VLIB_CLI_COMMAND (set_interface_mtu_cmd, static) = {
1171 .path = "set interface mtu",
Ole Troand7231612018-06-07 10:17:57 +02001172 .short_help = "set interface mtu [packet|ip4|ip6|mpls] <value> <interface>",
Damjan Marion8358ff92016-04-15 14:26:00 +02001173 .function = mtu_cmd,
1174};
Dave Barachba868bb2016-08-08 09:51:21 -04001175/* *INDENT-ON* */
Damjan Marion8358ff92016-04-15 14:26:00 +02001176
Pavel Kotucekc631f2d2016-09-26 10:40:02 +02001177static clib_error_t *
1178set_interface_mac_address (vlib_main_t * vm, unformat_input_t * input,
1179 vlib_cli_command_t * cmd)
1180{
1181 vnet_main_t *vnm = vnet_get_main ();
Neale Rannsd867a7c2017-10-04 02:29:07 -07001182 vnet_sw_interface_t *si = NULL;
Pavel Kotucekc631f2d2016-09-26 10:40:02 +02001183 clib_error_t *error = 0;
1184 u32 sw_if_index = ~0;
John Lo62fcc0a2017-10-31 14:31:10 -04001185 u8 mac[6] = { 0 };
Pavel Kotucekc631f2d2016-09-26 10:40:02 +02001186
1187 if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
1188 {
1189 error = clib_error_return (0, "unknown interface `%U'",
1190 format_unformat_error, input);
1191 goto done;
1192 }
John Lo62fcc0a2017-10-31 14:31:10 -04001193 if (!unformat_user (input, unformat_ethernet_address, mac))
Pavel Kotucekc631f2d2016-09-26 10:40:02 +02001194 {
1195 error = clib_error_return (0, "expected mac address `%U'",
1196 format_unformat_error, input);
1197 goto done;
1198 }
Neale Rannsd867a7c2017-10-04 02:29:07 -07001199 si = vnet_get_sw_interface (vnm, sw_if_index);
1200 error = vnet_hw_interface_change_mac_address (vnm, si->hw_if_index, mac);
Pavel Kotucekc631f2d2016-09-26 10:40:02 +02001201done:
1202 return error;
1203}
1204
1205/*?
1206 * The '<em>set interface mac address </em>' command allows to set MAC address of given interface.
1207 * In case of NIC interfaces the one has to support MAC address change. A side effect of MAC address
1208 * change are changes of MAC addresses in FIB tables (ipv4 and ipv6).
1209 *
1210 * @cliexpar
1211 * @parblock
1212 * Example of how to change MAC Address of interface:
1213 * @cliexcmd{set interface mac address GigabitEthernet0/8/0 aa:bb:cc:dd:ee:01}
1214 * @cliexcmd{set interface mac address host-vpp0 aa:bb:cc:dd:ee:02}
1215 * @cliexcmd{set interface mac address tap-0 aa:bb:cc:dd:ee:03}
1216 * @cliexcmd{set interface mac address pg0 aa:bb:cc:dd:ee:04}
1217 * @endparblock
1218?*/
1219/* *INDENT-OFF* */
1220VLIB_CLI_COMMAND (set_interface_mac_address_cmd, static) = {
1221 .path = "set interface mac address",
Billy McFalle9bac692017-08-11 14:05:11 -04001222 .short_help = "set interface mac address <interface> <mac-address>",
Pavel Kotucekc631f2d2016-09-26 10:40:02 +02001223 .function = set_interface_mac_address,
1224};
1225/* *INDENT-ON* */
1226
Dave Barach7be864a2016-11-28 11:41:35 -05001227static clib_error_t *
1228set_tag (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd)
1229{
1230 vnet_main_t *vnm = vnet_get_main ();
1231 u32 sw_if_index = ~0;
1232 u8 *tag = 0;
1233
1234 if (!unformat (input, "%U %s", unformat_vnet_sw_interface,
1235 vnm, &sw_if_index, &tag))
1236 return clib_error_return (0, "unknown input `%U'",
1237 format_unformat_error, input);
1238
1239 vnet_set_sw_interface_tag (vnm, tag, sw_if_index);
1240
1241 return 0;
1242}
1243
1244/* *INDENT-OFF* */
1245VLIB_CLI_COMMAND (set_tag_command, static) = {
1246 .path = "set interface tag",
Billy McFalle9bac692017-08-11 14:05:11 -04001247 .short_help = "set interface tag <interface> <tag>",
Dave Barach7be864a2016-11-28 11:41:35 -05001248 .function = set_tag,
1249};
1250/* *INDENT-ON* */
1251
1252static clib_error_t *
1253clear_tag (vlib_main_t * vm, unformat_input_t * input,
1254 vlib_cli_command_t * cmd)
1255{
1256 vnet_main_t *vnm = vnet_get_main ();
1257 u32 sw_if_index = ~0;
1258
1259 if (!unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
1260 return clib_error_return (0, "unknown input `%U'",
1261 format_unformat_error, input);
1262
1263 vnet_clear_sw_interface_tag (vnm, sw_if_index);
1264
1265 return 0;
1266}
1267
1268/* *INDENT-OFF* */
1269VLIB_CLI_COMMAND (clear_tag_command, static) = {
1270 .path = "clear interface tag",
Billy McFalle9bac692017-08-11 14:05:11 -04001271 .short_help = "clear interface tag <interface>",
Dave Barach7be864a2016-11-28 11:41:35 -05001272 .function = clear_tag,
1273};
1274/* *INDENT-ON* */
1275
Damjan Marion44036902017-04-28 12:29:15 +02001276static clib_error_t *
Neale Ranns1855b8e2018-07-11 10:31:26 -07001277set_ip_directed_broadcast (vlib_main_t * vm,
1278 unformat_input_t * input, vlib_cli_command_t * cmd)
1279{
1280 vnet_main_t *vnm = vnet_get_main ();
1281 u32 sw_if_index = ~0;
1282 u8 enable = 0;
1283
1284 if (!unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index));
1285 else if (unformat (input, "enable"))
1286 enable = 1;
1287 else if (unformat (input, "disable"))
1288 enable = 0;
1289 else
1290 return clib_error_return (0, "unknown input: `%U'",
1291 format_unformat_error, input);
1292
1293 if (~0 == sw_if_index)
1294 return clib_error_return (0, "specify an interface: `%U'",
1295 format_unformat_error, input);
1296
1297 vnet_sw_interface_ip_directed_broadcast (vnm, sw_if_index, enable);
1298
1299 return 0;
1300}
1301
1302/*?
1303 * This command is used to enable/disable IP directed broadcast
1304 * If directed broadcast is enabled a packet sent to the interface's
1305 * subnet broadcast address will be sent L2 broadcast on the interface,
1306 * otherwise it is dropped.
1307 ?*/
1308/* *INDENT-OFF* */
1309VLIB_CLI_COMMAND (set_ip_directed_broadcast_command, static) = {
1310 .path = "set interface ip directed-broadcast",
1311 .short_help = "set interface enable <interface> <enable|disable>",
1312 .function = set_ip_directed_broadcast,
1313};
1314/* *INDENT-ON* */
1315
1316static clib_error_t *
Stevene3a395c2017-05-09 16:19:50 -07001317set_hw_interface_rx_mode (vnet_main_t * vnm, u32 hw_if_index,
1318 u32 queue_id, vnet_hw_interface_rx_mode mode)
1319{
1320 vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
1321 vnet_device_class_t *dev_class =
1322 vnet_get_device_class (vnm, hw->dev_class_index);
1323 clib_error_t *error;
1324 vnet_hw_interface_rx_mode old_mode;
1325 int rv;
1326
Damjan Marion4e53a0d2017-06-21 14:29:44 +02001327 if (mode == VNET_HW_INTERFACE_RX_MODE_DEFAULT)
1328 mode = hw->default_rx_mode;
1329
Stevene3a395c2017-05-09 16:19:50 -07001330 rv = vnet_hw_interface_get_rx_mode (vnm, hw_if_index, queue_id, &old_mode);
1331 switch (rv)
1332 {
1333 case 0:
1334 if (old_mode == mode)
1335 return 0; /* same rx-mode, no change */
1336 break;
1337 case VNET_API_ERROR_INVALID_INTERFACE:
1338 return clib_error_return (0, "invalid interface");
Stevenbd8a6112017-07-30 10:29:26 -07001339 case VNET_API_ERROR_INVALID_QUEUE:
1340 return clib_error_return (0, "invalid queue");
Stevene3a395c2017-05-09 16:19:50 -07001341 default:
1342 return clib_error_return (0, "unknown error");
1343 }
1344
1345 if (dev_class->rx_mode_change_function)
1346 {
1347 error = dev_class->rx_mode_change_function (vnm, hw_if_index, queue_id,
1348 mode);
1349 if (error)
1350 return (error);
1351 }
1352
1353 rv = vnet_hw_interface_set_rx_mode (vnm, hw_if_index, queue_id, mode);
1354 switch (rv)
1355 {
1356 case 0:
1357 break;
1358 case VNET_API_ERROR_UNSUPPORTED:
1359 return clib_error_return (0, "unsupported");
1360 case VNET_API_ERROR_INVALID_INTERFACE:
1361 return clib_error_return (0, "invalid interface");
Stevenbd8a6112017-07-30 10:29:26 -07001362 case VNET_API_ERROR_INVALID_QUEUE:
1363 return clib_error_return (0, "invalid queue");
Stevene3a395c2017-05-09 16:19:50 -07001364 default:
1365 return clib_error_return (0, "unknown error");
1366 }
1367
1368 return 0;
1369}
1370
Stevenad8015b2017-10-29 22:10:46 -07001371clib_error_t *
1372set_hw_interface_change_rx_mode (vnet_main_t * vnm, u32 hw_if_index,
1373 u8 queue_id_valid, u32 queue_id,
1374 vnet_hw_interface_rx_mode mode)
1375{
1376 clib_error_t *error = 0;
1377 vnet_hw_interface_t *hw;
1378 int i;
1379
1380 hw = vnet_get_hw_interface (vnm, hw_if_index);
1381
1382 if (queue_id_valid == 0)
1383 {
1384 for (i = 0; i < vec_len (hw->dq_runtime_index_by_queue); i++)
1385 {
1386 error = set_hw_interface_rx_mode (vnm, hw_if_index, i, mode);
1387 if (error)
1388 break;
1389 }
1390 hw->default_rx_mode = mode;
1391 }
1392 else
1393 error = set_hw_interface_rx_mode (vnm, hw_if_index, queue_id, mode);
1394
1395 return (error);
1396}
1397
Stevene3a395c2017-05-09 16:19:50 -07001398static clib_error_t *
Damjan Marion44036902017-04-28 12:29:15 +02001399set_interface_rx_mode (vlib_main_t * vm, unformat_input_t * input,
1400 vlib_cli_command_t * cmd)
1401{
1402 clib_error_t *error = 0;
1403 unformat_input_t _line_input, *line_input = &_line_input;
1404 vnet_main_t *vnm = vnet_get_main ();
Damjan Marion44036902017-04-28 12:29:15 +02001405 u32 hw_if_index = (u32) ~ 0;
1406 u32 queue_id = (u32) ~ 0;
1407 vnet_hw_interface_rx_mode mode = VNET_HW_INTERFACE_RX_MODE_UNKNOWN;
Stevenad8015b2017-10-29 22:10:46 -07001408 u8 queue_id_valid = 0;
Dave Barach7be864a2016-11-28 11:41:35 -05001409
Damjan Marion44036902017-04-28 12:29:15 +02001410 if (!unformat_user (input, unformat_line_input, line_input))
1411 return 0;
1412
1413 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1414 {
1415 if (unformat
1416 (line_input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
1417 ;
1418 else if (unformat (line_input, "queue %d", &queue_id))
Stevenad8015b2017-10-29 22:10:46 -07001419 queue_id_valid = 1;
Damjan Marion44036902017-04-28 12:29:15 +02001420 else if (unformat (line_input, "polling"))
1421 mode = VNET_HW_INTERFACE_RX_MODE_POLLING;
1422 else if (unformat (line_input, "interrupt"))
1423 mode = VNET_HW_INTERFACE_RX_MODE_INTERRUPT;
1424 else if (unformat (line_input, "adaptive"))
1425 mode = VNET_HW_INTERFACE_RX_MODE_ADAPTIVE;
1426 else
1427 {
1428 error = clib_error_return (0, "parse error: '%U'",
1429 format_unformat_error, line_input);
1430 unformat_free (line_input);
1431 return error;
1432 }
1433 }
1434
1435 unformat_free (line_input);
1436
1437 if (hw_if_index == (u32) ~ 0)
1438 return clib_error_return (0, "please specify valid interface name");
1439
1440 if (mode == VNET_HW_INTERFACE_RX_MODE_UNKNOWN)
1441 return clib_error_return (0, "please specify valid rx-mode");
1442
Stevenad8015b2017-10-29 22:10:46 -07001443 error = set_hw_interface_change_rx_mode (vnm, hw_if_index, queue_id_valid,
1444 queue_id, mode);
Damjan Marion44036902017-04-28 12:29:15 +02001445
Stevene3a395c2017-05-09 16:19:50 -07001446 return (error);
Damjan Marion44036902017-04-28 12:29:15 +02001447}
1448
1449/*?
Billy McFalle9bac692017-08-11 14:05:11 -04001450 * This command is used to assign the RX packet processing mode (polling,
1451 * interrupt, adaptive) of the a given interface, and optionally a
1452 * given queue. If the '<em>queue</em>' is not provided, the '<em>mode</em>'
1453 * is applied to all queues of the interface. Not all interfaces support
1454 * all modes. To display the current rx-mode use the command
1455 * '<em>show interface rx-placement</em>'.
Damjan Marion44036902017-04-28 12:29:15 +02001456 *
1457 * @cliexpar
Billy McFalle9bac692017-08-11 14:05:11 -04001458 * Example of how to assign rx-mode to all queues on an interface:
1459 * @cliexcmd{set interface rx-mode VirtualEthernet0/0/12 polling}
1460 * Example of how to assign rx-mode to one queue of an interface:
1461 * @cliexcmd{set interface rx-mode VirtualEthernet0/0/12 queue 0 interrupt}
1462 * Example of how to display the rx-mode of all interfaces:
Damjan Marion44036902017-04-28 12:29:15 +02001463 * @cliexstart{show interface rx-placement}
1464 * Thread 1 (vpp_wk_0):
Billy McFalle9bac692017-08-11 14:05:11 -04001465 * node dpdk-input:
1466 * GigabitEthernet7/0/0 queue 0 (polling)
1467 * node vhost-user-input:
1468 * VirtualEthernet0/0/12 queue 0 (interrupt)
1469 * VirtualEthernet0/0/12 queue 2 (polling)
1470 * VirtualEthernet0/0/13 queue 0 (polling)
1471 * VirtualEthernet0/0/13 queue 2 (polling)
Damjan Marion44036902017-04-28 12:29:15 +02001472 * Thread 2 (vpp_wk_1):
Billy McFalle9bac692017-08-11 14:05:11 -04001473 * node dpdk-input:
1474 * GigabitEthernet7/0/1 queue 0 (polling)
1475 * node vhost-user-input:
1476 * VirtualEthernet0/0/12 queue 1 (polling)
1477 * VirtualEthernet0/0/12 queue 3 (polling)
1478 * VirtualEthernet0/0/13 queue 1 (polling)
1479 * VirtualEthernet0/0/13 queue 3 (polling)
Damjan Marion44036902017-04-28 12:29:15 +02001480 * @cliexend
Damjan Marion44036902017-04-28 12:29:15 +02001481?*/
1482/* *INDENT-OFF* */
Damjan Marionfe7d4a22018-04-13 19:43:39 +02001483VLIB_CLI_COMMAND (cmd_set_if_rx_mode,static) = {
Damjan Marion44036902017-04-28 12:29:15 +02001484 .path = "set interface rx-mode",
1485 .short_help = "set interface rx-mode <interface> [queue <n>] [polling | interrupt | adaptive]",
1486 .function = set_interface_rx_mode,
1487};
1488/* *INDENT-ON* */
1489
1490static clib_error_t *
1491show_interface_rx_placement_fn (vlib_main_t * vm, unformat_input_t * input,
1492 vlib_cli_command_t * cmd)
1493{
1494 u8 *s = 0;
1495 vnet_main_t *vnm = vnet_get_main ();
1496 vnet_device_input_runtime_t *rt;
1497 vnet_device_and_queue_t *dq;
1498 vlib_node_t *pn = vlib_get_node_by_name (vm, (u8 *) "device-input");
1499 uword si;
1500 int index = 0;
1501
1502 /* *INDENT-OFF* */
1503 foreach_vlib_main (({
1504 clib_bitmap_foreach (si, pn->sibling_bitmap,
1505 ({
1506 rt = vlib_node_get_runtime_data (this_vlib_main, si);
1507
1508 if (vec_len (rt->devices_and_queues))
1509 s = format (s, " node %U:\n", format_vlib_node_name, vm, si);
1510
1511 vec_foreach (dq, rt->devices_and_queues)
1512 {
Steven9d6d9892017-06-30 07:15:02 -07001513 vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm,
1514 dq->hw_if_index);
Damjan Marion44036902017-04-28 12:29:15 +02001515 s = format (s, " %U queue %u (%U)\n",
Steven9d6d9892017-06-30 07:15:02 -07001516 format_vnet_sw_if_index_name, vnm, hi->sw_if_index,
Damjan Marion44036902017-04-28 12:29:15 +02001517 dq->queue_id,
1518 format_vnet_hw_interface_rx_mode, dq->mode);
1519 }
1520 }));
1521 if (vec_len (s) > 0)
1522 {
1523 vlib_cli_output(vm, "Thread %u (%v):\n%v", index,
1524 vlib_worker_threads[index].name, s);
1525 vec_reset_length (s);
1526 }
1527 index++;
1528 }));
1529 /* *INDENT-ON* */
1530
1531 vec_free (s);
1532 return 0;
1533}
1534
Billy McFalle9bac692017-08-11 14:05:11 -04001535/*?
1536 * This command is used to display the interface and queue worker
1537 * thread placement.
1538 *
1539 * @cliexpar
1540 * Example of how to display the interface placement:
1541 * @cliexstart{show interface rx-placement}
1542 * Thread 1 (vpp_wk_0):
1543 * node dpdk-input:
1544 * GigabitEthernet7/0/0 queue 0 (polling)
1545 * node vhost-user-input:
1546 * VirtualEthernet0/0/12 queue 0 (polling)
1547 * VirtualEthernet0/0/12 queue 2 (polling)
1548 * VirtualEthernet0/0/13 queue 0 (polling)
1549 * VirtualEthernet0/0/13 queue 2 (polling)
1550 * Thread 2 (vpp_wk_1):
1551 * node dpdk-input:
1552 * GigabitEthernet7/0/1 queue 0 (polling)
1553 * node vhost-user-input:
1554 * VirtualEthernet0/0/12 queue 1 (polling)
1555 * VirtualEthernet0/0/12 queue 3 (polling)
1556 * VirtualEthernet0/0/13 queue 1 (polling)
1557 * VirtualEthernet0/0/13 queue 3 (polling)
1558 * @cliexend
1559?*/
Damjan Marion44036902017-04-28 12:29:15 +02001560/* *INDENT-OFF* */
1561VLIB_CLI_COMMAND (show_interface_rx_placement, static) = {
1562 .path = "show interface rx-placement",
1563 .short_help = "show interface rx-placement",
1564 .function = show_interface_rx_placement_fn,
1565};
1566/* *INDENT-ON* */
1567
Mohsin Kazmi54f7c512018-08-23 18:28:11 +02001568clib_error_t *
1569set_hw_interface_rx_placement (u32 hw_if_index, u32 queue_id,
1570 u32 thread_index, u8 is_main)
Damjan Marion44036902017-04-28 12:29:15 +02001571{
Damjan Marion44036902017-04-28 12:29:15 +02001572 vnet_main_t *vnm = vnet_get_main ();
1573 vnet_device_main_t *vdm = &vnet_device_main;
Mohsin Kazmi54f7c512018-08-23 18:28:11 +02001574 clib_error_t *error = 0;
1575 vnet_hw_interface_rx_mode mode = VNET_HW_INTERFACE_RX_MODE_UNKNOWN;
Damjan Marion44036902017-04-28 12:29:15 +02001576 int rv;
1577
Mohsin Kazmi54f7c512018-08-23 18:28:11 +02001578 if (is_main)
1579 thread_index = 0;
1580 else
1581 thread_index += vdm->first_worker_thread_index;
Damjan Marion44036902017-04-28 12:29:15 +02001582
1583 if (thread_index > vdm->last_worker_thread_index)
1584 return clib_error_return (0,
1585 "please specify valid worker thread or main");
1586
1587 rv = vnet_hw_interface_get_rx_mode (vnm, hw_if_index, queue_id, &mode);
1588
1589 if (rv)
1590 return clib_error_return (0, "not found");
1591
1592 rv = vnet_hw_interface_unassign_rx_thread (vnm, hw_if_index, queue_id);
1593
1594 if (rv)
1595 return clib_error_return (0, "not found");
1596
1597 vnet_hw_interface_assign_rx_thread (vnm, hw_if_index, queue_id,
1598 thread_index);
1599 vnet_hw_interface_set_rx_mode (vnm, hw_if_index, queue_id, mode);
1600
Mohsin Kazmi54f7c512018-08-23 18:28:11 +02001601 return (error);
1602}
1603
1604static clib_error_t *
1605set_interface_rx_placement (vlib_main_t * vm, unformat_input_t * input,
1606 vlib_cli_command_t * cmd)
1607{
1608 clib_error_t *error = 0;
1609 unformat_input_t _line_input, *line_input = &_line_input;
1610 vnet_main_t *vnm = vnet_get_main ();
1611 u32 hw_if_index = (u32) ~ 0;
1612 u32 queue_id = (u32) 0;
1613 u32 thread_index = (u32) ~ 0;
1614 u8 is_main = 0;
1615
1616 if (!unformat_user (input, unformat_line_input, line_input))
1617 return 0;
1618
1619 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1620 {
1621 if (unformat
1622 (line_input, "%U", unformat_vnet_hw_interface, vnm, &hw_if_index))
1623 ;
1624 else if (unformat (line_input, "queue %d", &queue_id))
1625 ;
1626 else if (unformat (line_input, "main", &thread_index))
1627 is_main = 1;
1628 else if (unformat (line_input, "worker %d", &thread_index))
1629 ;
1630 else
1631 {
1632 error = clib_error_return (0, "parse error: '%U'",
1633 format_unformat_error, line_input);
1634 unformat_free (line_input);
1635 return error;
1636 }
1637 }
1638
1639 unformat_free (line_input);
1640
1641 if (hw_if_index == (u32) ~ 0)
1642 return clib_error_return (0, "please specify valid interface name");
1643
1644 error = set_hw_interface_rx_placement (hw_if_index, queue_id, thread_index,
1645 is_main);
1646
1647 return (error);
Damjan Marion44036902017-04-28 12:29:15 +02001648}
1649
1650/*?
1651 * This command is used to assign a given interface, and optionally a
1652 * given queue, to a different thread. If the '<em>queue</em>' is not provided,
Billy McFalle9bac692017-08-11 14:05:11 -04001653 * it defaults to 0. The '<em>worker</em>' parameter is zero based and the index
1654 * in the thread name, for example, 0 in the thread name '<em>vpp_wk_0</em>'.
Damjan Marion44036902017-04-28 12:29:15 +02001655 *
1656 * @cliexpar
1657 * Example of how to display the interface placement:
Billy McFalle9bac692017-08-11 14:05:11 -04001658 * @cliexstart{show interface rx-placement}
Damjan Marion44036902017-04-28 12:29:15 +02001659 * Thread 1 (vpp_wk_0):
Billy McFalle9bac692017-08-11 14:05:11 -04001660 * node dpdk-input:
1661 * GigabitEthernet7/0/0 queue 0 (polling)
1662 * node vhost-user-input:
1663 * VirtualEthernet0/0/12 queue 0 (polling)
1664 * VirtualEthernet0/0/12 queue 2 (polling)
1665 * VirtualEthernet0/0/13 queue 0 (polling)
1666 * VirtualEthernet0/0/13 queue 2 (polling)
Damjan Marion44036902017-04-28 12:29:15 +02001667 * Thread 2 (vpp_wk_1):
Billy McFalle9bac692017-08-11 14:05:11 -04001668 * node dpdk-input:
1669 * GigabitEthernet7/0/1 queue 0 (polling)
1670 * node vhost-user-input:
1671 * VirtualEthernet0/0/12 queue 1 (polling)
1672 * VirtualEthernet0/0/12 queue 3 (polling)
1673 * VirtualEthernet0/0/13 queue 1 (polling)
1674 * VirtualEthernet0/0/13 queue 3 (polling)
Damjan Marion44036902017-04-28 12:29:15 +02001675 * @cliexend
Billy McFalle9bac692017-08-11 14:05:11 -04001676 * Example of how to assign a interface and queue to a worker thread:
1677 * @cliexcmd{set interface rx-placement VirtualEthernet0/0/12 queue 1 worker 0}
1678 * Example of how to display the interface placement:
1679 * @cliexstart{show interface rx-placement}
1680 * Thread 1 (vpp_wk_0):
1681 * node dpdk-input:
1682 * GigabitEthernet7/0/0 queue 0 (polling)
1683 * node vhost-user-input:
1684 * VirtualEthernet0/0/12 queue 0 (polling)
1685 * VirtualEthernet0/0/12 queue 1 (polling)
1686 * VirtualEthernet0/0/12 queue 2 (polling)
1687 * VirtualEthernet0/0/13 queue 0 (polling)
1688 * VirtualEthernet0/0/13 queue 2 (polling)
1689 * Thread 2 (vpp_wk_1):
1690 * node dpdk-input:
1691 * GigabitEthernet7/0/1 queue 0 (polling)
1692 * node vhost-user-input:
1693 * VirtualEthernet0/0/12 queue 3 (polling)
1694 * VirtualEthernet0/0/13 queue 1 (polling)
1695 * VirtualEthernet0/0/13 queue 3 (polling)
1696 * @cliexend
Damjan Marion44036902017-04-28 12:29:15 +02001697?*/
1698/* *INDENT-OFF* */
1699VLIB_CLI_COMMAND (cmd_set_if_rx_placement,static) = {
1700 .path = "set interface rx-placement",
Billy McFalle9bac692017-08-11 14:05:11 -04001701 .short_help = "set interface rx-placement <interface> [queue <n>] "
Damjan Marion6f9ac652017-06-15 19:01:31 +02001702 "[worker <n> | main]",
Damjan Marion44036902017-04-28 12:29:15 +02001703 .function = set_interface_rx_placement,
Damjan Marion6f9ac652017-06-15 19:01:31 +02001704 .is_mp_safe = 1,
Damjan Marion44036902017-04-28 12:29:15 +02001705};
Damjan Marion44036902017-04-28 12:29:15 +02001706/* *INDENT-ON* */
Dave Barachba868bb2016-08-08 09:51:21 -04001707/*
1708 * fd.io coding-style-patch-verification: ON
1709 *
1710 * Local Variables:
1711 * eval: (c-set-style "gnu")
1712 * End:
1713 */