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; |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 40 | |
| 41 | /* Get a line of input. */ |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 42 | if (!unformat_user (input, unformat_line_input, line_input)) |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 43 | return 0; |
| 44 | |
| 45 | while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) |
| 46 | { |
| 47 | if (unformat (line_input, "name %s", &host_if_name)) |
| 48 | ; |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 49 | else |
| 50 | if (unformat |
| 51 | (line_input, "hw-addr %U", unformat_ethernet_address, hwaddr)) |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 52 | hw_addr_ptr = hwaddr; |
| 53 | else if (unformat (line_input, "pipe")) |
| 54 | is_pipe = 1; |
| 55 | else if (unformat (line_input, "master")) |
| 56 | is_master = 1; |
| 57 | else if (unformat (line_input, "slave")) |
| 58 | is_master = 0; |
| 59 | else |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 60 | return clib_error_return (0, "unknown input `%U'", |
| 61 | format_unformat_error, input); |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 62 | } |
| 63 | unformat_free (line_input); |
| 64 | |
| 65 | if (host_if_name == NULL) |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 66 | return clib_error_return (0, "missing host interface name"); |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 67 | |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 68 | r = |
| 69 | netmap_create_if (vm, host_if_name, hw_addr_ptr, is_pipe, is_master, |
| 70 | &sw_if_index); |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 71 | |
| 72 | if (r == VNET_API_ERROR_SYSCALL_ERROR_1) |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 73 | return clib_error_return (0, "%s (errno %d)", strerror (errno), errno); |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 74 | |
| 75 | if (r == VNET_API_ERROR_INVALID_INTERFACE) |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 76 | return clib_error_return (0, "Invalid interface name"); |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 77 | |
| 78 | if (r == VNET_API_ERROR_SUBIF_ALREADY_EXISTS) |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 79 | return clib_error_return (0, "Interface already exists"); |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 80 | |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 81 | vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main (), |
| 82 | sw_if_index); |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 83 | return 0; |
| 84 | } |
| 85 | |
Billy McFall | 2d0b6e3 | 2017-01-11 08:44:52 -0500 | [diff] [blame] | 86 | /*? |
| 87 | * '<em>netmap</em>' is a framework for very fast packet I/O from userspace. |
| 88 | * '<em>VALE</em>' is an equally fast in-kernel software switch using the |
| 89 | * netmap API. '<em>netmap</em>' includes '<em>netmap pipes</em>', a shared |
| 90 | * memory packet transport channel. Together, they provide a high speed |
| 91 | * user-space interface that allows VPP to patch into a linux namespace, a |
| 92 | * linux container, or a physical NIC without the use of DPDK. Netmap/VALE |
| 93 | * generates the '<em>netmap.ko</em>' kernel module that needs to be loaded |
| 94 | * before netmap interfaces can be created. |
| 95 | * - https://github.com/luigirizzo/netmap - Netmap/VALE repo. |
| 96 | * - https://github.com/vpp-dev/netmap - VPP development package for Netmap/VALE, |
| 97 | * which is a snapshot of the Netmap/VALE repo with minor changes to work |
| 98 | * with containers and modified kernel drivers to work with NICs. |
| 99 | * |
| 100 | * Create a netmap interface that will attach to a linux interface. |
| 101 | * The interface must already exist. Once created, a new netmap interface |
| 102 | * will exist in VPP with the name '<em>netmap-<ifname></em>', where |
| 103 | * '<em><ifname></em>' takes one of two forms: |
| 104 | * - <b>ifname</b> - Linux interface to bind too. |
| 105 | * - <b>valeXXX:YYY</b> - |
| 106 | * - Where '<em>valeXXX</em>' is an arbitrary name for a VALE |
| 107 | * interface that must start with '<em>vale</em>' and is less |
| 108 | * than 16 characters. |
| 109 | * - Where '<em>YYY</em>' is an existing linux namespace. |
| 110 | * |
| 111 | * This command has the following optional parameters: |
| 112 | * |
| 113 | * - <b>hw-addr <mac-addr></b> - Optional ethernet address, can be in either |
| 114 | * X:X:X:X:X:X unix or X.X.X cisco format. |
| 115 | * |
| 116 | * - <b>pipe</b> - Optional flag to indicate that a '<em>netmap pipe</em>' |
| 117 | * instance should be created. |
| 118 | * |
| 119 | * - <b>master | slave</b> - Optional flag to indicate whether VPP should |
| 120 | * be the master or slave of the '<em>netmap pipe</em>'. Only considered |
| 121 | * if '<em>pipe</em>' is entered. Defaults to '<em>slave</em>' if not entered. |
| 122 | * |
| 123 | * @cliexpar |
| 124 | * Example of how to create a netmap interface tied to the linux |
| 125 | * namespace '<em>vpp1</em>': |
| 126 | * @cliexstart{create netmap name vale00:vpp1 hw-addr 02:FE:3F:34:15:9B pipe master} |
| 127 | * netmap-vale00:vpp1 |
| 128 | * @cliexend |
| 129 | * Once the netmap interface is created, enable the interface using: |
| 130 | * @cliexcmd{set interface state netmap-vale00:vpp1 up} |
| 131 | ?*/ |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 132 | /* *INDENT-OFF* */ |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 133 | VLIB_CLI_COMMAND (netmap_create_command, static) = { |
| 134 | .path = "create netmap", |
Billy McFall | 2d0b6e3 | 2017-01-11 08:44:52 -0500 | [diff] [blame] | 135 | .short_help = "create netmap name <ifname>|valeXXX:YYY " |
| 136 | "[hw-addr <mac-addr>] [pipe] [master|slave]", |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 137 | .function = netmap_create_command_fn, |
| 138 | }; |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 139 | /* *INDENT-ON* */ |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 140 | |
| 141 | static clib_error_t * |
| 142 | netmap_delete_command_fn (vlib_main_t * vm, unformat_input_t * input, |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 143 | vlib_cli_command_t * cmd) |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 144 | { |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 145 | unformat_input_t _line_input, *line_input = &_line_input; |
| 146 | u8 *host_if_name = NULL; |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 147 | |
| 148 | /* Get a line of input. */ |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 149 | if (!unformat_user (input, unformat_line_input, line_input)) |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 150 | return 0; |
| 151 | |
| 152 | while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) |
| 153 | { |
| 154 | if (unformat (line_input, "name %s", &host_if_name)) |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 155 | ; |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 156 | else |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 157 | return clib_error_return (0, "unknown input `%U'", |
| 158 | format_unformat_error, input); |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 159 | } |
| 160 | unformat_free (line_input); |
| 161 | |
| 162 | if (host_if_name == NULL) |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 163 | return clib_error_return (0, "missing host interface name"); |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 164 | |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 165 | netmap_delete_if (vm, host_if_name); |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 166 | |
| 167 | return 0; |
| 168 | } |
| 169 | |
Billy McFall | 2d0b6e3 | 2017-01-11 08:44:52 -0500 | [diff] [blame] | 170 | /*? |
| 171 | * Delete a netmap interface. Use the '<em><ifname></em>' to identify |
| 172 | * the netmap interface to be deleted. In VPP, netmap interfaces are |
| 173 | * named as '<em>netmap-<ifname></em>', where '<em><ifname></em>' |
| 174 | * takes one of two forms: |
| 175 | * - <b>ifname</b> - Linux interface to bind too. |
| 176 | * - <b>valeXXX:YYY</b> - |
| 177 | * - Where '<em>valeXXX</em>' is an arbitrary name for a VALE |
| 178 | * interface that must start with '<em>vale</em>' and is less |
| 179 | * than 16 characters. |
| 180 | * - Where '<em>YYY</em>' is an existing linux namespace. |
| 181 | * |
| 182 | * @cliexpar |
| 183 | * Example of how to delete a netmap interface named '<em>netmap-vale00:vpp1</em>': |
| 184 | * @cliexcmd{delete netmap name vale00:vpp1} |
| 185 | ?*/ |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 186 | /* *INDENT-OFF* */ |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 187 | VLIB_CLI_COMMAND (netmap_delete_command, static) = { |
| 188 | .path = "delete netmap", |
Billy McFall | 2d0b6e3 | 2017-01-11 08:44:52 -0500 | [diff] [blame] | 189 | .short_help = "delete netmap name <ifname>|valeXXX:YYY", |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 190 | .function = netmap_delete_command_fn, |
| 191 | }; |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 192 | /* *INDENT-ON* */ |
Damjan Marion | 108c731 | 2016-04-20 05:04:20 +0200 | [diff] [blame] | 193 | |
| 194 | clib_error_t * |
| 195 | netmap_cli_init (vlib_main_t * vm) |
| 196 | { |
| 197 | return 0; |
| 198 | } |
| 199 | |
| 200 | VLIB_INIT_FUNCTION (netmap_cli_init); |
Damjan Marion | 00a9dca | 2016-08-17 17:05:46 +0200 | [diff] [blame] | 201 | |
| 202 | /* |
| 203 | * fd.io coding-style-patch-verification: ON |
| 204 | * |
| 205 | * Local Variables: |
| 206 | * eval: (c-set-style "gnu") |
| 207 | * End: |
| 208 | */ |