Line data Source code
1 : /*
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>
27 : #include <vnet/ethernet/ethernet_types_api.h>
28 : #include <vnet/ip/ip_types_api.h>
29 : #include <vnet/devices/tap/tap.h>
30 :
31 : #include <vnet/format_fns.h>
32 : #include <vnet/devices/tap/tapv2.api_enum.h>
33 : #include <vnet/devices/tap/tapv2.api_types.h>
34 :
35 : #define REPLY_MSG_ID_BASE tap_main.msg_id_base
36 : #include <vlibapi/api_helper_macros.h>
37 :
38 : static void
39 0 : vl_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 0 : reg = vl_api_client_index_to_registration (mp->client_index);
45 0 : if (!reg)
46 0 : return;
47 :
48 0 : vnet_main_t *vnm = vnet_get_main ();
49 0 : vlib_main_t *vm = vlib_get_main ();
50 : vl_api_tap_create_v3_reply_t *rmp;
51 :
52 0 : tap_create_if_args_t _a, *ap = &_a;
53 :
54 0 : clib_memset (ap, 0, sizeof (*ap));
55 :
56 0 : ap->id = mp->id;
57 0 : if (!mp->use_random_mac)
58 : {
59 0 : mac_address_decode (mp->mac_address, &ap->mac_addr);
60 0 : ap->mac_addr_set = 1;
61 : }
62 0 : ap->rx_ring_sz = mp->rx_ring_sz;
63 0 : ap->tx_ring_sz = mp->tx_ring_sz;
64 0 : ap->sw_if_index = (u32) ~0;
65 0 : ap->num_rx_queues = clib_max (1, mp->num_rx_queues);
66 0 : ap->num_tx_queues = mp->num_tx_queues;
67 :
68 0 : if (mp->host_if_name_set)
69 0 : ap->host_if_name = format (0, "%s%c", mp->host_if_name, 0);
70 :
71 0 : if (mp->host_mac_addr_set)
72 : {
73 0 : mac_address_decode (mp->host_mac_addr, &ap->host_mac_addr);
74 : }
75 :
76 0 : if (mp->host_namespace_set)
77 0 : ap->host_namespace = format (0, "%s%c", mp->host_namespace, 0);
78 :
79 0 : if (mp->host_bridge_set)
80 0 : ap->host_bridge = format (0, "%s%c", mp->host_bridge, 0);
81 :
82 0 : if (mp->host_ip4_prefix_set)
83 : {
84 0 : ip4_address_decode (mp->host_ip4_prefix.address, &ap->host_ip4_addr);
85 0 : ap->host_ip4_prefix_len = mp->host_ip4_prefix.len;
86 : }
87 :
88 0 : if (mp->host_ip6_prefix_set)
89 : {
90 0 : ip6_address_decode (mp->host_ip6_prefix.address, &ap->host_ip6_addr);
91 0 : ap->host_ip6_prefix_len = mp->host_ip6_prefix.len;
92 : }
93 :
94 0 : if (mp->host_ip4_gw_set)
95 : {
96 0 : ip4_address_decode (mp->host_ip4_gw, &ap->host_ip4_gw);
97 0 : ap->host_ip4_gw_set = 1;
98 : }
99 :
100 0 : if (mp->host_ip6_gw_set)
101 : {
102 0 : ip6_address_decode (mp->host_ip6_gw, &ap->host_ip6_gw);
103 0 : ap->host_ip6_gw_set = 1;
104 : }
105 :
106 0 : if (mp->host_mtu_set)
107 : {
108 0 : ap->host_mtu_size = mp->host_mtu_size;
109 0 : ap->host_mtu_set = 1;
110 : }
111 :
112 0 : ap->tap_flags = mp->tap_flags;
113 :
114 0 : tap_create_if (vm, ap);
115 :
116 : /* If a tag was supplied... */
117 0 : if (vl_api_string_len (&mp->tag))
118 : {
119 0 : u8 *tag = vl_api_from_api_to_new_vec (mp, &mp->tag);
120 0 : vnet_set_sw_interface_tag (vnm, tag, ap->sw_if_index);
121 : }
122 :
123 0 : vec_free (ap->host_if_name);
124 0 : vec_free (ap->host_namespace);
125 0 : vec_free (ap->host_bridge);
126 :
127 0 : rv = ap->rv;
128 0 : REPLY_MACRO2_END (VL_API_TAP_CREATE_V3_REPLY,
129 : ({ rmp->sw_if_index = ap->sw_if_index; }));
130 : }
131 :
132 : static void
133 300 : vl_api_tap_create_v2_t_handler (vl_api_tap_create_v2_t * mp)
134 : {
135 : vl_api_registration_t *reg;
136 300 : reg = vl_api_client_index_to_registration (mp->client_index);
137 300 : if (!reg)
138 0 : return;
139 :
140 300 : vnet_main_t *vnm = vnet_get_main ();
141 300 : vlib_main_t *vm = vlib_get_main ();
142 : vl_api_tap_create_v2_reply_t *rmp;
143 :
144 300 : tap_create_if_args_t _a, *ap = &_a;
145 :
146 300 : clib_memset (ap, 0, sizeof (*ap));
147 :
148 300 : ap->id = ntohl (mp->id);
149 300 : if (!mp->use_random_mac)
150 : {
151 0 : mac_address_decode (mp->mac_address, &ap->mac_addr);
152 0 : ap->mac_addr_set = 1;
153 : }
154 300 : ap->rx_ring_sz = ntohs (mp->rx_ring_sz);
155 300 : ap->tx_ring_sz = ntohs (mp->tx_ring_sz);
156 300 : ap->sw_if_index = (u32) ~ 0;
157 300 : ap->num_rx_queues = 1;
158 300 : ap->num_tx_queues = 1;
159 :
160 300 : if (mp->num_rx_queues > 1)
161 0 : ap->num_rx_queues = mp->num_rx_queues;
162 :
163 300 : if (mp->host_if_name_set)
164 300 : ap->host_if_name = format (0, "%s%c", mp->host_if_name, 0);
165 :
166 300 : if (mp->host_mac_addr_set)
167 : {
168 0 : mac_address_decode (mp->host_mac_addr, &ap->host_mac_addr);
169 : }
170 :
171 300 : if (mp->host_namespace_set)
172 300 : ap->host_namespace = format (0, "%s%c", mp->host_namespace, 0);
173 :
174 300 : if (mp->host_bridge_set)
175 0 : ap->host_bridge = format (0, "%s%c", mp->host_bridge, 0);
176 :
177 300 : if (mp->host_ip4_prefix_set)
178 : {
179 150 : ip4_address_decode (mp->host_ip4_prefix.address, &ap->host_ip4_addr);
180 150 : ap->host_ip4_prefix_len = mp->host_ip4_prefix.len;
181 : }
182 :
183 300 : if (mp->host_ip6_prefix_set)
184 : {
185 150 : ip6_address_decode (mp->host_ip6_prefix.address, &ap->host_ip6_addr);
186 150 : ap->host_ip6_prefix_len = mp->host_ip6_prefix.len;
187 : }
188 :
189 300 : if (mp->host_ip4_gw_set)
190 : {
191 12 : ip4_address_decode (mp->host_ip4_gw, &ap->host_ip4_gw);
192 12 : ap->host_ip4_gw_set = 1;
193 : }
194 :
195 300 : if (mp->host_ip6_gw_set)
196 : {
197 12 : ip6_address_decode (mp->host_ip6_gw, &ap->host_ip6_gw);
198 12 : ap->host_ip6_gw_set = 1;
199 : }
200 :
201 300 : if (mp->host_mtu_set)
202 : {
203 0 : ap->host_mtu_size = ntohl (mp->host_mtu_size);
204 0 : ap->host_mtu_set = 1;
205 : }
206 :
207 : 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 :
226 300 : ap->tap_flags = ntohl (mp->tap_flags);
227 :
228 300 : tap_create_if (vm, ap);
229 :
230 :
231 : /* If a tag was supplied... */
232 300 : if (vl_api_string_len (&mp->tag))
233 : {
234 0 : u8 *tag = vl_api_from_api_to_new_vec (mp, &mp->tag);
235 0 : vnet_set_sw_interface_tag (vnm, tag, ap->sw_if_index);
236 : }
237 :
238 300 : rmp = vl_msg_api_alloc (sizeof (*rmp));
239 300 : rmp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_TAP_CREATE_V2_REPLY);
240 300 : rmp->context = mp->context;
241 300 : rmp->retval = ntohl (ap->rv);
242 300 : rmp->sw_if_index = ntohl (ap->sw_if_index);
243 :
244 300 : vl_api_send_msg (reg, (u8 *) rmp);
245 :
246 300 : vec_free (ap->host_if_name);
247 300 : vec_free (ap->host_namespace);
248 300 : vec_free (ap->host_bridge);
249 :
250 : }
251 :
252 : static void
253 552 : vl_api_tap_delete_v2_t_handler (vl_api_tap_delete_v2_t * mp)
254 : {
255 : vl_api_registration_t *reg;
256 552 : reg = vl_api_client_index_to_registration (mp->client_index);
257 552 : if (!reg)
258 0 : return;
259 :
260 552 : vnet_main_t *vnm = vnet_get_main ();
261 552 : vlib_main_t *vm = vlib_get_main ();
262 : int rv;
263 : vl_api_tap_delete_v2_reply_t *rmp;
264 :
265 552 : u32 sw_if_index = ntohl (mp->sw_if_index);
266 :
267 552 : rv = tap_delete_if (vm, sw_if_index);
268 :
269 552 : rmp = vl_msg_api_alloc (sizeof (*rmp));
270 552 : rmp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_TAP_DELETE_V2_REPLY);
271 552 : rmp->context = mp->context;
272 552 : rmp->retval = ntohl (rv);
273 :
274 552 : vl_api_send_msg (reg, (u8 *) rmp);
275 :
276 552 : if (!rv)
277 300 : vnet_clear_sw_interface_tag (vnm, sw_if_index);
278 : }
279 :
280 : static void
281 0 : tap_send_sw_interface_details (vpe_api_main_t * am,
282 : vl_api_registration_t * reg,
283 : tap_interface_details_t * tap_if, u32 context)
284 : {
285 : vl_api_sw_interface_tap_v2_details_t *mp;
286 0 : mp = vl_msg_api_alloc (sizeof (*mp));
287 0 : clib_memset (mp, 0, sizeof (*mp));
288 0 : mp->_vl_msg_id =
289 0 : htons (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_TAP_V2_DETAILS);
290 0 : mp->id = htonl (tap_if->id);
291 0 : mp->sw_if_index = htonl (tap_if->sw_if_index);
292 0 : mp->tap_flags = htonl (tap_if->tap_flags);
293 0 : 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)));
296 0 : mp->rx_ring_sz = htons (tap_if->rx_ring_sz);
297 0 : mp->tx_ring_sz = htons (tap_if->tx_ring_sz);
298 0 : mac_address_encode (&tap_if->host_mac_addr, mp->host_mac_addr);
299 0 : 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 0 : 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 0 : 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)));
308 0 : mp->host_mtu_size = htonl (tap_if->host_mtu_size);
309 0 : mac_address_encode (&tap_if->host_mac_addr, mp->host_mac_addr);
310 :
311 0 : if (tap_if->host_ip4_prefix_len)
312 0 : ip4_address_encode (&tap_if->host_ip4_addr, mp->host_ip4_prefix.address);
313 0 : mp->host_ip4_prefix.len = tap_if->host_ip4_prefix_len;
314 0 : if (tap_if->host_ip6_prefix_len)
315 0 : ip6_address_encode (&tap_if->host_ip6_addr, mp->host_ip6_prefix.address);
316 0 : mp->host_ip6_prefix.len = tap_if->host_ip6_prefix_len;
317 :
318 0 : mp->context = context;
319 0 : vl_api_send_msg (reg, (u8 *) mp);
320 0 : }
321 :
322 : static void
323 0 : vl_api_sw_interface_tap_v2_dump_t_handler (vl_api_sw_interface_tap_v2_dump_t *
324 : mp)
325 : {
326 : int rv;
327 0 : vpe_api_main_t *am = &vpe_api_main;
328 : vl_api_registration_t *reg;
329 0 : tap_interface_details_t *tapifs = NULL;
330 0 : tap_interface_details_t *tap_if = NULL;
331 : u32 filter_sw_if_index;
332 :
333 0 : reg = vl_api_client_index_to_registration (mp->client_index);
334 0 : if (!reg)
335 0 : return;
336 :
337 0 : filter_sw_if_index = htonl (mp->sw_if_index);
338 0 : if (mp->sw_if_index != ~0)
339 0 : VALIDATE_SW_IF_INDEX (mp);
340 :
341 0 : rv = tap_dump_ifs (&tapifs);
342 0 : if (rv)
343 0 : return;
344 :
345 0 : vec_foreach (tap_if, tapifs)
346 : {
347 0 : if ((filter_sw_if_index == ~0)
348 0 : || (tap_if->sw_if_index == filter_sw_if_index))
349 0 : tap_send_sw_interface_details (am, reg, tap_if, mp->context);
350 : }
351 0 : BAD_SW_IF_INDEX_LABEL;
352 0 : vec_free (tapifs);
353 : }
354 :
355 : #include <vnet/devices/tap/tapv2.api.c>
356 : static clib_error_t *
357 559 : tapv2_api_hookup (vlib_main_t * vm)
358 : {
359 : /*
360 : * Set up the (msg_name, crc, message-id) table
361 : */
362 559 : REPLY_MSG_ID_BASE = setup_message_id_table ();
363 :
364 559 : return 0;
365 : }
366 :
367 15679 : VLIB_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 : */
|