blob: ab4189ab60773e8718ce958b81cdd252245ea1c5 [file] [log] [blame]
Damjan Marion8389fb92017-10-13 18:29:53 +02001/*
2 *------------------------------------------------------------------
3 * tap_api.c - vnet tap device driver API support
4 *
5 * Copyright (c) 2017 Cisco and/or its affiliates.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *------------------------------------------------------------------
18 */
19
20#include <vnet/vnet.h>
21#include <vlibmemory/api.h>
22
23#include <vnet/interface.h>
24#include <vnet/api_errno.h>
25#include <vnet/ethernet/ethernet.h>
26#include <vnet/ip/ip.h>
Jakub Grajciar5de4fb72019-09-03 10:40:01 +020027#include <vnet/ethernet/ethernet_types_api.h>
28#include <vnet/ip/ip_types_api.h>
Damjan Marionc99b4cd2017-12-04 15:25:58 +010029#include <vnet/devices/tap/tap.h>
Damjan Marion8389fb92017-10-13 18:29:53 +020030
Filip Tehlar3808ec02021-06-22 12:03:55 +000031#include <vnet/format_fns.h>
32#include <vnet/devices/tap/tapv2.api_enum.h>
33#include <vnet/devices/tap/tapv2.api_types.h>
34
Mohsin Kazmib21fd4b2021-09-22 20:03:28 +000035#define REPLY_MSG_ID_BASE tap_main.msg_id_base
Filip Tehlar3808ec02021-06-22 12:03:55 +000036#include <vlibapi/api_helper_macros.h>
37
Damjan Marion8389fb92017-10-13 18:29:53 +020038static void
Nathan Skrzypczak40edaf62021-12-15 18:45:59 +010039vl_api_tap_create_v3_t_handler (vl_api_tap_create_v3_t *mp)
40{
41 vl_api_registration_t *reg;
42 int rv;
43
44 reg = vl_api_client_index_to_registration (mp->client_index);
45 if (!reg)
46 return;
47
48 vnet_main_t *vnm = vnet_get_main ();
49 vlib_main_t *vm = vlib_get_main ();
50 vl_api_tap_create_v3_reply_t *rmp;
51
52 tap_create_if_args_t _a, *ap = &_a;
53
54 clib_memset (ap, 0, sizeof (*ap));
55
56 ap->id = mp->id;
57 if (!mp->use_random_mac)
58 {
59 mac_address_decode (mp->mac_address, &ap->mac_addr);
60 ap->mac_addr_set = 1;
61 }
62 ap->rx_ring_sz = mp->rx_ring_sz;
63 ap->tx_ring_sz = mp->tx_ring_sz;
64 ap->sw_if_index = (u32) ~0;
65 ap->num_rx_queues = clib_max (1, mp->num_rx_queues);
66 ap->num_tx_queues = mp->num_tx_queues;
67
68 if (mp->host_if_name_set)
69 ap->host_if_name = format (0, "%s%c", mp->host_if_name, 0);
70
71 if (mp->host_mac_addr_set)
72 {
73 mac_address_decode (mp->host_mac_addr, &ap->host_mac_addr);
74 }
75
76 if (mp->host_namespace_set)
77 ap->host_namespace = format (0, "%s%c", mp->host_namespace, 0);
78
79 if (mp->host_bridge_set)
80 ap->host_bridge = format (0, "%s%c", mp->host_bridge, 0);
81
82 if (mp->host_ip4_prefix_set)
83 {
84 ip4_address_decode (mp->host_ip4_prefix.address, &ap->host_ip4_addr);
85 ap->host_ip4_prefix_len = mp->host_ip4_prefix.len;
86 }
87
88 if (mp->host_ip6_prefix_set)
89 {
90 ip6_address_decode (mp->host_ip6_prefix.address, &ap->host_ip6_addr);
91 ap->host_ip6_prefix_len = mp->host_ip6_prefix.len;
92 }
93
94 if (mp->host_ip4_gw_set)
95 {
96 ip4_address_decode (mp->host_ip4_gw, &ap->host_ip4_gw);
97 ap->host_ip4_gw_set = 1;
98 }
99
100 if (mp->host_ip6_gw_set)
101 {
102 ip6_address_decode (mp->host_ip6_gw, &ap->host_ip6_gw);
103 ap->host_ip6_gw_set = 1;
104 }
105
106 if (mp->host_mtu_set)
107 {
108 ap->host_mtu_size = mp->host_mtu_size;
109 ap->host_mtu_set = 1;
110 }
111
112 ap->tap_flags = mp->tap_flags;
113
114 tap_create_if (vm, ap);
115
116 /* If a tag was supplied... */
117 if (vl_api_string_len (&mp->tag))
118 {
119 u8 *tag = vl_api_from_api_to_new_vec (mp, &mp->tag);
120 vnet_set_sw_interface_tag (vnm, tag, ap->sw_if_index);
121 }
122
123 vec_free (ap->host_if_name);
124 vec_free (ap->host_namespace);
125 vec_free (ap->host_bridge);
126
127 rv = ap->rv;
128 REPLY_MACRO2_END (VL_API_TAP_CREATE_V3_REPLY,
129 ({ rmp->sw_if_index = ap->sw_if_index; }));
130}
131
132static void
Damjan Marion8389fb92017-10-13 18:29:53 +0200133vl_api_tap_create_v2_t_handler (vl_api_tap_create_v2_t * mp)
134{
Paul Vinciguerra44d06912019-10-30 01:53:25 +0000135 vl_api_registration_t *reg;
136 reg = vl_api_client_index_to_registration (mp->client_index);
137 if (!reg)
138 return;
139
Jerome Tollet0b061112018-06-04 16:40:26 +0100140 vnet_main_t *vnm = vnet_get_main ();
Damjan Marion8389fb92017-10-13 18:29:53 +0200141 vlib_main_t *vm = vlib_get_main ();
Damjan Marion8389fb92017-10-13 18:29:53 +0200142 vl_api_tap_create_v2_reply_t *rmp;
Paul Vinciguerra44d06912019-10-30 01:53:25 +0000143
Damjan Marion8389fb92017-10-13 18:29:53 +0200144 tap_create_if_args_t _a, *ap = &_a;
145
Dave Barachb7b92992018-10-17 10:38:51 -0400146 clib_memset (ap, 0, sizeof (*ap));
Damjan Marion8389fb92017-10-13 18:29:53 +0200147
Steven9e635692018-03-01 09:36:01 -0800148 ap->id = ntohl (mp->id);
Damjan Marion8389fb92017-10-13 18:29:53 +0200149 if (!mp->use_random_mac)
150 {
Jakub Grajciar5de4fb72019-09-03 10:40:01 +0200151 mac_address_decode (mp->mac_address, &ap->mac_addr);
Damjan Marion2df39092017-12-04 20:03:37 +0100152 ap->mac_addr_set = 1;
Damjan Marion8389fb92017-10-13 18:29:53 +0200153 }
Milan Lenco2aef64f2017-12-05 12:18:15 +0100154 ap->rx_ring_sz = ntohs (mp->rx_ring_sz);
155 ap->tx_ring_sz = ntohs (mp->tx_ring_sz);
Damjan Marion8389fb92017-10-13 18:29:53 +0200156 ap->sw_if_index = (u32) ~ 0;
Mohsin Kazmi9f32b6a2020-02-14 12:09:04 +0000157 ap->num_rx_queues = 1;
Nathan Skrzypczak40edaf62021-12-15 18:45:59 +0100158 ap->num_tx_queues = 1;
Damjan Marion8389fb92017-10-13 18:29:53 +0200159
Mohsin Kazmi9f32b6a2020-02-14 12:09:04 +0000160 if (mp->num_rx_queues > 1)
161 ap->num_rx_queues = mp->num_rx_queues;
Jakub Grajciar5de4fb72019-09-03 10:40:01 +0200162
Damjan Marion2df39092017-12-04 20:03:37 +0100163 if (mp->host_if_name_set)
Mohsin Kazmi784bbcc2020-10-21 18:32:59 +0200164 ap->host_if_name = format (0, "%s%c", mp->host_if_name, 0);
Damjan Marion2df39092017-12-04 20:03:37 +0100165
166 if (mp->host_mac_addr_set)
167 {
Jakub Grajciar5de4fb72019-09-03 10:40:01 +0200168 mac_address_decode (mp->host_mac_addr, &ap->host_mac_addr);
Damjan Marion2df39092017-12-04 20:03:37 +0100169 }
170
Damjan Marion91c6ef72017-12-01 13:34:24 +0100171 if (mp->host_namespace_set)
Mohsin Kazmi784bbcc2020-10-21 18:32:59 +0200172 ap->host_namespace = format (0, "%s%c", mp->host_namespace, 0);
Damjan Marion91c6ef72017-12-01 13:34:24 +0100173
174 if (mp->host_bridge_set)
Mohsin Kazmi784bbcc2020-10-21 18:32:59 +0200175 ap->host_bridge = format (0, "%s%c", mp->host_bridge, 0);
Damjan Marion91c6ef72017-12-01 13:34:24 +0100176
Jakub Grajciar5de4fb72019-09-03 10:40:01 +0200177 if (mp->host_ip4_prefix_set)
Damjan Marion91c6ef72017-12-01 13:34:24 +0100178 {
Jakub Grajciar5de4fb72019-09-03 10:40:01 +0200179 ip4_address_decode (mp->host_ip4_prefix.address, &ap->host_ip4_addr);
180 ap->host_ip4_prefix_len = mp->host_ip4_prefix.len;
Damjan Marion91c6ef72017-12-01 13:34:24 +0100181 }
182
Jakub Grajciar5de4fb72019-09-03 10:40:01 +0200183 if (mp->host_ip6_prefix_set)
Damjan Marion91c6ef72017-12-01 13:34:24 +0100184 {
Jakub Grajciar5de4fb72019-09-03 10:40:01 +0200185 ip6_address_decode (mp->host_ip6_prefix.address, &ap->host_ip6_addr);
186 ap->host_ip6_prefix_len = mp->host_ip6_prefix.len;
Damjan Marion91c6ef72017-12-01 13:34:24 +0100187 }
188
Damjan Marion7866c452018-01-18 13:35:11 +0100189 if (mp->host_ip4_gw_set)
190 {
Jakub Grajciar5de4fb72019-09-03 10:40:01 +0200191 ip4_address_decode (mp->host_ip4_gw, &ap->host_ip4_gw);
Damjan Marion7866c452018-01-18 13:35:11 +0100192 ap->host_ip4_gw_set = 1;
193 }
194
195 if (mp->host_ip6_gw_set)
196 {
Jakub Grajciar5de4fb72019-09-03 10:40:01 +0200197 ip6_address_decode (mp->host_ip6_gw, &ap->host_ip6_gw);
Damjan Marion7866c452018-01-18 13:35:11 +0100198 ap->host_ip6_gw_set = 1;
199 }
200
Mohsin Kazmi97d54ed2019-06-10 11:20:15 +0200201 if (mp->host_mtu_set)
202 {
203 ap->host_mtu_size = ntohl (mp->host_mtu_size);
204 ap->host_mtu_set = 1;
205 }
206
Mohsin Kazmia1a22462020-09-02 11:59:37 +0000207 STATIC_ASSERT (((int) TAP_API_FLAG_GSO == (int) TAP_FLAG_GSO),
208 "tap gso api flag mismatch");
209 STATIC_ASSERT (((int) TAP_API_FLAG_CSUM_OFFLOAD ==
210 (int) TAP_FLAG_CSUM_OFFLOAD),
211 "tap checksum offload api flag mismatch");
212 STATIC_ASSERT (((int) TAP_API_FLAG_PERSIST == (int) TAP_FLAG_PERSIST),
213 "tap persist api flag mismatch");
214 STATIC_ASSERT (((int) TAP_API_FLAG_ATTACH == (int) TAP_FLAG_ATTACH),
215 "tap attach api flag mismatch");
216 STATIC_ASSERT (((int) TAP_API_FLAG_TUN == (int) TAP_FLAG_TUN),
217 "tap tun api flag mismatch");
218 STATIC_ASSERT (((int) TAP_API_FLAG_GRO_COALESCE ==
219 (int) TAP_FLAG_GRO_COALESCE),
220 "tap gro coalesce api flag mismatch");
221 STATIC_ASSERT (((int) TAP_API_FLAG_PACKED == (int) TAP_FLAG_PACKED),
222 "tap packed api flag mismatch");
223 STATIC_ASSERT (((int) TAP_API_FLAG_IN_ORDER ==
224 (int) TAP_FLAG_IN_ORDER), "tap in-order api flag mismatch");
225
Andrew Yourtchenko754f24b2019-01-07 20:56:46 +0100226 ap->tap_flags = ntohl (mp->tap_flags);
227
Damjan Marion91c6ef72017-12-01 13:34:24 +0100228 tap_create_if (vm, ap);
Damjan Marion8389fb92017-10-13 18:29:53 +0200229
Damjan Marion8389fb92017-10-13 18:29:53 +0200230
Jerome Tollet0b061112018-06-04 16:40:26 +0100231 /* If a tag was supplied... */
Jakub Grajciar5de4fb72019-09-03 10:40:01 +0200232 if (vl_api_string_len (&mp->tag))
Jerome Tollet0b061112018-06-04 16:40:26 +0100233 {
Dave Barach77841402020-04-29 17:04:10 -0400234 u8 *tag = vl_api_from_api_to_new_vec (mp, &mp->tag);
Jerome Tollet0b061112018-06-04 16:40:26 +0100235 vnet_set_sw_interface_tag (vnm, tag, ap->sw_if_index);
236 }
237
Damjan Marion8389fb92017-10-13 18:29:53 +0200238 rmp = vl_msg_api_alloc (sizeof (*rmp));
Filip Tehlar3808ec02021-06-22 12:03:55 +0000239 rmp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_TAP_CREATE_V2_REPLY);
Damjan Marion8389fb92017-10-13 18:29:53 +0200240 rmp->context = mp->context;
Damjan Marion91c6ef72017-12-01 13:34:24 +0100241 rmp->retval = ntohl (ap->rv);
Damjan Marion8389fb92017-10-13 18:29:53 +0200242 rmp->sw_if_index = ntohl (ap->sw_if_index);
243
Florin Coras6c4dae22018-01-09 06:39:23 -0800244 vl_api_send_msg (reg, (u8 *) rmp);
Mohsin Kazmi784bbcc2020-10-21 18:32:59 +0200245
246 vec_free (ap->host_if_name);
247 vec_free (ap->host_namespace);
248 vec_free (ap->host_bridge);
249
Damjan Marion8389fb92017-10-13 18:29:53 +0200250}
251
252static void
Damjan Marion8389fb92017-10-13 18:29:53 +0200253vl_api_tap_delete_v2_t_handler (vl_api_tap_delete_v2_t * mp)
254{
Paul Vinciguerra44d06912019-10-30 01:53:25 +0000255 vl_api_registration_t *reg;
256 reg = vl_api_client_index_to_registration (mp->client_index);
257 if (!reg)
258 return;
259
Jerome Tollet0b061112018-06-04 16:40:26 +0100260 vnet_main_t *vnm = vnet_get_main ();
Damjan Marion8389fb92017-10-13 18:29:53 +0200261 vlib_main_t *vm = vlib_get_main ();
262 int rv;
Damjan Marion8389fb92017-10-13 18:29:53 +0200263 vl_api_tap_delete_v2_reply_t *rmp;
Paul Vinciguerra44d06912019-10-30 01:53:25 +0000264
Damjan Marion8389fb92017-10-13 18:29:53 +0200265 u32 sw_if_index = ntohl (mp->sw_if_index);
266
267 rv = tap_delete_if (vm, sw_if_index);
268
Damjan Marion8389fb92017-10-13 18:29:53 +0200269 rmp = vl_msg_api_alloc (sizeof (*rmp));
Filip Tehlar3808ec02021-06-22 12:03:55 +0000270 rmp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_TAP_DELETE_V2_REPLY);
Damjan Marion8389fb92017-10-13 18:29:53 +0200271 rmp->context = mp->context;
272 rmp->retval = ntohl (rv);
273
Florin Coras6c4dae22018-01-09 06:39:23 -0800274 vl_api_send_msg (reg, (u8 *) rmp);
Damjan Marion8389fb92017-10-13 18:29:53 +0200275
276 if (!rv)
Ole Troan2e1c8962019-04-10 09:44:23 +0200277 vnet_clear_sw_interface_tag (vnm, sw_if_index);
Damjan Marion8389fb92017-10-13 18:29:53 +0200278}
279
280static void
281tap_send_sw_interface_details (vpe_api_main_t * am,
Florin Coras6c4dae22018-01-09 06:39:23 -0800282 vl_api_registration_t * reg,
Damjan Marion8389fb92017-10-13 18:29:53 +0200283 tap_interface_details_t * tap_if, u32 context)
284{
285 vl_api_sw_interface_tap_v2_details_t *mp;
286 mp = vl_msg_api_alloc (sizeof (*mp));
Dave Barachb7b92992018-10-17 10:38:51 -0400287 clib_memset (mp, 0, sizeof (*mp));
Filip Tehlar3808ec02021-06-22 12:03:55 +0000288 mp->_vl_msg_id =
289 htons (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_TAP_V2_DETAILS);
Milan Lenco73e7f422017-12-14 10:04:25 +0100290 mp->id = htonl (tap_if->id);
291 mp->sw_if_index = htonl (tap_if->sw_if_index);
Andrew Yourtchenko754f24b2019-01-07 20:56:46 +0100292 mp->tap_flags = htonl (tap_if->tap_flags);
Damjan Marion8389fb92017-10-13 18:29:53 +0200293 clib_memcpy (mp->dev_name, tap_if->dev_name,
294 MIN (ARRAY_LEN (mp->dev_name) - 1,
295 strlen ((const char *) tap_if->dev_name)));
Milan Lenco73e7f422017-12-14 10:04:25 +0100296 mp->rx_ring_sz = htons (tap_if->rx_ring_sz);
297 mp->tx_ring_sz = htons (tap_if->tx_ring_sz);
Jakub Grajciar5de4fb72019-09-03 10:40:01 +0200298 mac_address_encode (&tap_if->host_mac_addr, mp->host_mac_addr);
Milan Lenco73e7f422017-12-14 10:04:25 +0100299 clib_memcpy (mp->host_if_name, tap_if->host_if_name,
300 MIN (ARRAY_LEN (mp->host_if_name) - 1,
301 strlen ((const char *) tap_if->host_if_name)));
302 clib_memcpy (mp->host_namespace, tap_if->host_namespace,
303 MIN (ARRAY_LEN (mp->host_namespace) - 1,
304 strlen ((const char *) tap_if->host_namespace)));
305 clib_memcpy (mp->host_bridge, tap_if->host_bridge,
306 MIN (ARRAY_LEN (mp->host_bridge) - 1,
307 strlen ((const char *) tap_if->host_bridge)));
Mohsin Kazmi97d54ed2019-06-10 11:20:15 +0200308 mp->host_mtu_size = htonl (tap_if->host_mtu_size);
Jakub Grajciar5de4fb72019-09-03 10:40:01 +0200309 mac_address_encode (&tap_if->host_mac_addr, mp->host_mac_addr);
310
Milan Lenco73e7f422017-12-14 10:04:25 +0100311 if (tap_if->host_ip4_prefix_len)
Jakub Grajciar5de4fb72019-09-03 10:40:01 +0200312 ip4_address_encode (&tap_if->host_ip4_addr, mp->host_ip4_prefix.address);
313 mp->host_ip4_prefix.len = tap_if->host_ip4_prefix_len;
Milan Lenco73e7f422017-12-14 10:04:25 +0100314 if (tap_if->host_ip6_prefix_len)
Jakub Grajciar5de4fb72019-09-03 10:40:01 +0200315 ip6_address_encode (&tap_if->host_ip6_addr, mp->host_ip6_prefix.address);
316 mp->host_ip6_prefix.len = tap_if->host_ip6_prefix_len;
Damjan Marion8389fb92017-10-13 18:29:53 +0200317
Milan Lenco73e7f422017-12-14 10:04:25 +0100318 mp->context = context;
Florin Coras6c4dae22018-01-09 06:39:23 -0800319 vl_api_send_msg (reg, (u8 *) mp);
Damjan Marion8389fb92017-10-13 18:29:53 +0200320}
321
322static void
323vl_api_sw_interface_tap_v2_dump_t_handler (vl_api_sw_interface_tap_v2_dump_t *
324 mp)
325{
326 int rv;
327 vpe_api_main_t *am = &vpe_api_main;
Florin Coras6c4dae22018-01-09 06:39:23 -0800328 vl_api_registration_t *reg;
Damjan Marion8389fb92017-10-13 18:29:53 +0200329 tap_interface_details_t *tapifs = NULL;
330 tap_interface_details_t *tap_if = NULL;
Jakub Grajciar5de4fb72019-09-03 10:40:01 +0200331 u32 filter_sw_if_index;
Damjan Marion8389fb92017-10-13 18:29:53 +0200332
Florin Coras6c4dae22018-01-09 06:39:23 -0800333 reg = vl_api_client_index_to_registration (mp->client_index);
334 if (!reg)
Damjan Marion8389fb92017-10-13 18:29:53 +0200335 return;
336
Jakub Grajciar5de4fb72019-09-03 10:40:01 +0200337 filter_sw_if_index = htonl (mp->sw_if_index);
Paul Vinciguerra073d74d2020-04-27 01:12:48 -0400338 if (mp->sw_if_index != ~0)
339 VALIDATE_SW_IF_INDEX (mp);
Jakub Grajciar5de4fb72019-09-03 10:40:01 +0200340
Damjan Marion8389fb92017-10-13 18:29:53 +0200341 rv = tap_dump_ifs (&tapifs);
342 if (rv)
343 return;
344
345 vec_foreach (tap_if, tapifs)
346 {
Paul Vinciguerra073d74d2020-04-27 01:12:48 -0400347 if ((filter_sw_if_index == ~0)
348 || (tap_if->sw_if_index == filter_sw_if_index))
349 tap_send_sw_interface_details (am, reg, tap_if, mp->context);
Damjan Marion8389fb92017-10-13 18:29:53 +0200350 }
Paul Vinciguerra073d74d2020-04-27 01:12:48 -0400351 BAD_SW_IF_INDEX_LABEL;
Damjan Marion8389fb92017-10-13 18:29:53 +0200352 vec_free (tapifs);
353}
354
Filip Tehlar3808ec02021-06-22 12:03:55 +0000355#include <vnet/devices/tap/tapv2.api.c>
Damjan Marion8389fb92017-10-13 18:29:53 +0200356static clib_error_t *
357tapv2_api_hookup (vlib_main_t * vm)
358{
Damjan Marion8389fb92017-10-13 18:29:53 +0200359 /*
360 * Set up the (msg_name, crc, message-id) table
361 */
Filip Tehlar3808ec02021-06-22 12:03:55 +0000362 REPLY_MSG_ID_BASE = setup_message_id_table ();
Damjan Marion8389fb92017-10-13 18:29:53 +0200363
364 return 0;
365}
366
367VLIB_API_INIT_FUNCTION (tapv2_api_hookup);
368
369/*
370 * fd.io coding-style-patch-verification: ON
371 *
372 * Local Variables:
373 * eval: (c-set-style "gnu")
374 * End:
375 */