Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 1 | /* |
| 2 | *------------------------------------------------------------------ |
| 3 | * Copyright (c) 2016 Cisco and/or its affiliates. |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at: |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | *------------------------------------------------------------------ |
| 16 | */ |
Matus Fabian | 82e29c4 | 2016-05-11 04:49:46 -0700 | [diff] [blame] | 17 | #include <stdint.h> |
| 18 | #include <net/if.h> |
| 19 | #include <sys/ioctl.h> |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 20 | |
| 21 | #include <vlib/vlib.h> |
| 22 | #include <vlib/unix/unix.h> |
| 23 | #include <vnet/ethernet/ethernet.h> |
| 24 | |
Matus Fabian | 82e29c4 | 2016-05-11 04:49:46 -0700 | [diff] [blame] | 25 | #include <vnet/devices/netmap/net_netmap.h> |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 26 | #include <vnet/devices/netmap/netmap.h> |
| 27 | |
| 28 | static clib_error_t * |
| 29 | netmap_create_command_fn (vlib_main_t * vm, unformat_input_t * input, |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 30 | vlib_cli_command_t * cmd) |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 31 | { |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 32 | unformat_input_t _line_input, *line_input = &_line_input; |
| 33 | u8 *host_if_name = NULL; |
| 34 | u8 hwaddr[6]; |
| 35 | u8 *hw_addr_ptr = 0; |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 36 | int r; |
| 37 | u8 is_pipe = 0; |
| 38 | u8 is_master = 0; |
Pierre Pfister | 78ea9c2 | 2016-05-23 12:51:54 +0100 | [diff] [blame] | 39 | u32 sw_if_index = ~0; |
Billy McFall | a9a20e7 | 2017-02-15 11:39:12 -0500 | [diff] [blame] | 40 | clib_error_t *error = NULL; |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 41 | |
| 42 | /* Get a line of input. */ |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 43 | if (!unformat_user (input, unformat_line_input, line_input)) |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 44 | return 0; |
| 45 | |
| 46 | while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) |
| 47 | { |
| 48 | if (unformat (line_input, "name %s", &host_if_name)) |
| 49 | ; |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 50 | else |
| 51 | if (unformat |
| 52 | (line_input, "hw-addr %U", unformat_ethernet_address, hwaddr)) |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 53 | hw_addr_ptr = hwaddr; |
| 54 | else if (unformat (line_input, "pipe")) |
| 55 | is_pipe = 1; |
| 56 | else if (unformat (line_input, "master")) |
| 57 | is_master = 1; |
| 58 | else if (unformat (line_input, "slave")) |
| 59 | is_master = 0; |
| 60 | else |
Billy McFall | a9a20e7 | 2017-02-15 11:39:12 -0500 | [diff] [blame] | 61 | { |
| 62 | error = clib_error_return (0, "unknown input `%U'", |
| 63 | format_unformat_error, line_input); |
| 64 | goto done; |
| 65 | } |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 66 | } |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 67 | |
| 68 | if (host_if_name == NULL) |
Billy McFall | a9a20e7 | 2017-02-15 11:39:12 -0500 | [diff] [blame] | 69 | { |
| 70 | error = clib_error_return (0, "missing host interface name"); |
| 71 | goto done; |
| 72 | } |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 73 | |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 74 | r = |
| 75 | netmap_create_if (vm, host_if_name, hw_addr_ptr, is_pipe, is_master, |
| 76 | &sw_if_index); |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 77 | |
| 78 | if (r == VNET_API_ERROR_SYSCALL_ERROR_1) |
Billy McFall | a9a20e7 | 2017-02-15 11:39:12 -0500 | [diff] [blame] | 79 | { |
| 80 | error = clib_error_return (0, "%s (errno %d)", strerror (errno), errno); |
| 81 | goto done; |
| 82 | } |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 83 | |
| 84 | if (r == VNET_API_ERROR_INVALID_INTERFACE) |
Billy McFall | a9a20e7 | 2017-02-15 11:39:12 -0500 | [diff] [blame] | 85 | { |
| 86 | error = clib_error_return (0, "Invalid interface name"); |
| 87 | goto done; |
| 88 | } |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 89 | |
| 90 | if (r == VNET_API_ERROR_SUBIF_ALREADY_EXISTS) |
Billy McFall | a9a20e7 | 2017-02-15 11:39:12 -0500 | [diff] [blame] | 91 | { |
| 92 | error = clib_error_return (0, "Interface already exists"); |
| 93 | goto done; |
| 94 | } |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 95 | |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 96 | vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main (), |
| 97 | sw_if_index); |
Billy McFall | a9a20e7 | 2017-02-15 11:39:12 -0500 | [diff] [blame] | 98 | |
| 99 | done: |
| 100 | unformat_free (line_input); |
| 101 | |
| 102 | return error; |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 103 | } |
| 104 | |
Billy McFall | 2d0b6e3 | 2017-01-11 08:44:52 -0500 | [diff] [blame] | 105 | /*? |
| 106 | * '<em>netmap</em>' is a framework for very fast packet I/O from userspace. |
| 107 | * '<em>VALE</em>' is an equally fast in-kernel software switch using the |
| 108 | * netmap API. '<em>netmap</em>' includes '<em>netmap pipes</em>', a shared |
| 109 | * memory packet transport channel. Together, they provide a high speed |
| 110 | * user-space interface that allows VPP to patch into a linux namespace, a |
| 111 | * linux container, or a physical NIC without the use of DPDK. Netmap/VALE |
| 112 | * generates the '<em>netmap.ko</em>' kernel module that needs to be loaded |
| 113 | * before netmap interfaces can be created. |
| 114 | * - https://github.com/luigirizzo/netmap - Netmap/VALE repo. |
| 115 | * - https://github.com/vpp-dev/netmap - VPP development package for Netmap/VALE, |
| 116 | * which is a snapshot of the Netmap/VALE repo with minor changes to work |
| 117 | * with containers and modified kernel drivers to work with NICs. |
| 118 | * |
| 119 | * Create a netmap interface that will attach to a linux interface. |
| 120 | * The interface must already exist. Once created, a new netmap interface |
| 121 | * will exist in VPP with the name '<em>netmap-<ifname></em>', where |
| 122 | * '<em><ifname></em>' takes one of two forms: |
| 123 | * - <b>ifname</b> - Linux interface to bind too. |
| 124 | * - <b>valeXXX:YYY</b> - |
| 125 | * - Where '<em>valeXXX</em>' is an arbitrary name for a VALE |
| 126 | * interface that must start with '<em>vale</em>' and is less |
| 127 | * than 16 characters. |
| 128 | * - Where '<em>YYY</em>' is an existing linux namespace. |
| 129 | * |
| 130 | * This command has the following optional parameters: |
| 131 | * |
| 132 | * - <b>hw-addr <mac-addr></b> - Optional ethernet address, can be in either |
| 133 | * X:X:X:X:X:X unix or X.X.X cisco format. |
| 134 | * |
| 135 | * - <b>pipe</b> - Optional flag to indicate that a '<em>netmap pipe</em>' |
| 136 | * instance should be created. |
| 137 | * |
| 138 | * - <b>master | slave</b> - Optional flag to indicate whether VPP should |
| 139 | * be the master or slave of the '<em>netmap pipe</em>'. Only considered |
| 140 | * if '<em>pipe</em>' is entered. Defaults to '<em>slave</em>' if not entered. |
| 141 | * |
| 142 | * @cliexpar |
| 143 | * Example of how to create a netmap interface tied to the linux |
| 144 | * namespace '<em>vpp1</em>': |
| 145 | * @cliexstart{create netmap name vale00:vpp1 hw-addr 02:FE:3F:34:15:9B pipe master} |
| 146 | * netmap-vale00:vpp1 |
| 147 | * @cliexend |
| 148 | * Once the netmap interface is created, enable the interface using: |
| 149 | * @cliexcmd{set interface state netmap-vale00:vpp1 up} |
| 150 | ?*/ |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 151 | /* *INDENT-OFF* */ |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 152 | VLIB_CLI_COMMAND (netmap_create_command, static) = { |
| 153 | .path = "create netmap", |
Billy McFall | 2d0b6e3 | 2017-01-11 08:44:52 -0500 | [diff] [blame] | 154 | .short_help = "create netmap name <ifname>|valeXXX:YYY " |
| 155 | "[hw-addr <mac-addr>] [pipe] [master|slave]", |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 156 | .function = netmap_create_command_fn, |
| 157 | }; |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 158 | /* *INDENT-ON* */ |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 159 | |
| 160 | static clib_error_t * |
| 161 | netmap_delete_command_fn (vlib_main_t * vm, unformat_input_t * input, |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 162 | vlib_cli_command_t * cmd) |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 163 | { |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 164 | unformat_input_t _line_input, *line_input = &_line_input; |
| 165 | u8 *host_if_name = NULL; |
Billy McFall | a9a20e7 | 2017-02-15 11:39:12 -0500 | [diff] [blame] | 166 | clib_error_t *error = NULL; |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 167 | |
| 168 | /* Get a line of input. */ |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 169 | if (!unformat_user (input, unformat_line_input, line_input)) |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 170 | return 0; |
| 171 | |
| 172 | while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) |
| 173 | { |
| 174 | if (unformat (line_input, "name %s", &host_if_name)) |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 175 | ; |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 176 | else |
Billy McFall | a9a20e7 | 2017-02-15 11:39:12 -0500 | [diff] [blame] | 177 | { |
| 178 | error = clib_error_return (0, "unknown input `%U'", |
| 179 | format_unformat_error, line_input); |
| 180 | goto done; |
| 181 | } |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 182 | } |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 183 | |
| 184 | if (host_if_name == NULL) |
Billy McFall | a9a20e7 | 2017-02-15 11:39:12 -0500 | [diff] [blame] | 185 | { |
| 186 | error = clib_error_return (0, "missing host interface name"); |
| 187 | goto done; |
| 188 | } |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 189 | |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 190 | netmap_delete_if (vm, host_if_name); |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 191 | |
Billy McFall | a9a20e7 | 2017-02-15 11:39:12 -0500 | [diff] [blame] | 192 | done: |
| 193 | unformat_free (line_input); |
| 194 | |
| 195 | return error; |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 196 | } |
| 197 | |
Billy McFall | 2d0b6e3 | 2017-01-11 08:44:52 -0500 | [diff] [blame] | 198 | /*? |
| 199 | * Delete a netmap interface. Use the '<em><ifname></em>' to identify |
| 200 | * the netmap interface to be deleted. In VPP, netmap interfaces are |
| 201 | * named as '<em>netmap-<ifname></em>', where '<em><ifname></em>' |
| 202 | * takes one of two forms: |
| 203 | * - <b>ifname</b> - Linux interface to bind too. |
| 204 | * - <b>valeXXX:YYY</b> - |
| 205 | * - Where '<em>valeXXX</em>' is an arbitrary name for a VALE |
| 206 | * interface that must start with '<em>vale</em>' and is less |
| 207 | * than 16 characters. |
| 208 | * - Where '<em>YYY</em>' is an existing linux namespace. |
| 209 | * |
| 210 | * @cliexpar |
| 211 | * Example of how to delete a netmap interface named '<em>netmap-vale00:vpp1</em>': |
| 212 | * @cliexcmd{delete netmap name vale00:vpp1} |
| 213 | ?*/ |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 214 | /* *INDENT-OFF* */ |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 215 | VLIB_CLI_COMMAND (netmap_delete_command, static) = { |
| 216 | .path = "delete netmap", |
Billy McFall | 2d0b6e3 | 2017-01-11 08:44:52 -0500 | [diff] [blame] | 217 | .short_help = "delete netmap name <ifname>|valeXXX:YYY", |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 218 | .function = netmap_delete_command_fn, |
| 219 | }; |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 220 | /* *INDENT-ON* */ |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 221 | |
| 222 | clib_error_t * |
| 223 | netmap_cli_init (vlib_main_t * vm) |
| 224 | { |
| 225 | return 0; |
| 226 | } |
| 227 | |
| 228 | VLIB_INIT_FUNCTION (netmap_cli_init); |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 229 | |
| 230 | /* |
| 231 | * fd.io coding-style-patch-verification: ON |
| 232 | * |
| 233 | * Local Variables: |
| 234 | * eval: (c-set-style "gnu") |
| 235 | * End: |
| 236 | */ |