dpdk: Add support for Mellanox ConnectX-4 devices
[vpp.git] / vnet / vnet / unix / tap_api.c
1 /*
2  *------------------------------------------------------------------
3  * tap_api.c - vnet tap device driver API support
4  *
5  * Copyright (c) 2016 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/unix/tuntap.h>
28 #include <vnet/unix/tapcli.h>
29
30 #include <vnet/vnet_msg_enum.h>
31
32 #define vl_typedefs             /* define message structures */
33 #include <vnet/vnet_all_api_h.h>
34 #undef vl_typedefs
35
36 #define vl_endianfun            /* define message structures */
37 #include <vnet/vnet_all_api_h.h>
38 #undef vl_endianfun
39
40 /* instantiate all the print functions we know about */
41 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
42 #define vl_printfun
43 #include <vnet/vnet_all_api_h.h>
44 #undef vl_printfun
45
46 #include <vlibapi/api_helper_macros.h>
47
48 #define foreach_tap_api_msg                     \
49 _(TAP_CONNECT, tap_connect)                     \
50 _(TAP_MODIFY, tap_modify)                       \
51 _(TAP_DELETE, tap_delete)                       \
52 _(SW_INTERFACE_TAP_DUMP, sw_interface_tap_dump)
53
54 #define vl_msg_name_crc_list
55 #include <vnet/unix/tap.api.h>
56 #undef vl_msg_name_crc_list
57
58 /*
59  * WARNING: replicated pending api refactor completion
60  */
61 static void
62 send_sw_interface_flags_deleted (vpe_api_main_t * am,
63                                  unix_shared_memory_queue_t * q,
64                                  u32 sw_if_index)
65 {
66   vl_api_sw_interface_set_flags_t *mp;
67
68   mp = vl_msg_api_alloc (sizeof (*mp));
69   memset (mp, 0, sizeof (*mp));
70   mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_SET_FLAGS);
71   mp->sw_if_index = ntohl (sw_if_index);
72
73   mp->admin_up_down = 0;
74   mp->link_up_down = 0;
75   mp->deleted = 1;
76   vl_msg_api_send_shmem (q, (u8 *) & mp);
77 }
78
79 static void
80 vl_api_tap_connect_t_handler (vl_api_tap_connect_t * mp)
81 {
82   vlib_main_t *vm = vlib_get_main ();
83   int rv;
84   vl_api_tap_connect_reply_t *rmp;
85   vnet_main_t *vnm = vnet_get_main ();
86   unix_shared_memory_queue_t *q;
87   u32 sw_if_index = (u32) ~ 0;
88   u8 *tag;
89
90   rv = vnet_tap_connect_renumber (vm, mp->tap_name,
91                                   mp->use_random_mac ? 0 : mp->mac_address,
92                                   &sw_if_index, mp->renumber,
93                                   ntohl (mp->custom_dev_instance));
94
95   /* Add tag if supplied */
96   if (rv == 0 && mp->tag[0])
97     {
98       mp->tag[ARRAY_LEN (mp->tag) - 1] = 0;
99       tag = format (0, "%s%c", mp->tag, 0);
100       vnet_set_sw_interface_tag (vnm, tag, sw_if_index);
101     }
102
103   q = vl_api_client_index_to_input_queue (mp->client_index);
104   if (!q)
105     return;
106
107   rmp = vl_msg_api_alloc (sizeof (*rmp));
108   rmp->_vl_msg_id = ntohs (VL_API_TAP_CONNECT_REPLY);
109   rmp->context = mp->context;
110   rmp->retval = ntohl (rv);
111   rmp->sw_if_index = ntohl (sw_if_index);
112
113   vl_msg_api_send_shmem (q, (u8 *) & rmp);
114 }
115
116 static void
117 vl_api_tap_modify_t_handler (vl_api_tap_modify_t * mp)
118 {
119   int rv;
120   vl_api_tap_modify_reply_t *rmp;
121   unix_shared_memory_queue_t *q;
122   u32 sw_if_index = (u32) ~ 0;
123   vlib_main_t *vm = vlib_get_main ();
124
125   rv = vnet_tap_modify (vm, ntohl (mp->sw_if_index), mp->tap_name,
126                         mp->use_random_mac ? 0 : mp->mac_address,
127                         &sw_if_index, mp->renumber,
128                         ntohl (mp->custom_dev_instance));
129
130   q = vl_api_client_index_to_input_queue (mp->client_index);
131   if (!q)
132     return;
133
134   rmp = vl_msg_api_alloc (sizeof (*rmp));
135   rmp->_vl_msg_id = ntohs (VL_API_TAP_MODIFY_REPLY);
136   rmp->context = mp->context;
137   rmp->retval = ntohl (rv);
138   rmp->sw_if_index = ntohl (sw_if_index);
139
140   vl_msg_api_send_shmem (q, (u8 *) & rmp);
141 }
142
143 static void
144 vl_api_tap_delete_t_handler (vl_api_tap_delete_t * mp)
145 {
146   vlib_main_t *vm = vlib_get_main ();
147   int rv;
148   vpe_api_main_t *vam = &vpe_api_main;
149   vl_api_tap_delete_reply_t *rmp;
150   unix_shared_memory_queue_t *q;
151   u32 sw_if_index = ntohl (mp->sw_if_index);
152
153   rv = vnet_tap_delete (vm, sw_if_index);
154   if (!rv)
155     {
156       vnet_main_t *vnm = vnet_get_main ();
157       vnet_clear_sw_interface_tag (vnm, sw_if_index);
158     }
159
160   q = vl_api_client_index_to_input_queue (mp->client_index);
161   if (!q)
162     return;
163
164   rmp = vl_msg_api_alloc (sizeof (*rmp));
165   rmp->_vl_msg_id = ntohs (VL_API_TAP_DELETE_REPLY);
166   rmp->context = mp->context;
167   rmp->retval = ntohl (rv);
168
169   vl_msg_api_send_shmem (q, (u8 *) & rmp);
170
171   if (!rv)
172     send_sw_interface_flags_deleted (vam, q, sw_if_index);
173 }
174
175 static void
176 send_sw_interface_tap_details (vpe_api_main_t * am,
177                                unix_shared_memory_queue_t * q,
178                                tapcli_interface_details_t * tap_if,
179                                u32 context)
180 {
181   vl_api_sw_interface_tap_details_t *mp;
182   mp = vl_msg_api_alloc (sizeof (*mp));
183   memset (mp, 0, sizeof (*mp));
184   mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_TAP_DETAILS);
185   mp->sw_if_index = ntohl (tap_if->sw_if_index);
186   strncpy ((char *) mp->dev_name,
187            (char *) tap_if->dev_name, ARRAY_LEN (mp->dev_name) - 1);
188   mp->context = context;
189
190   vl_msg_api_send_shmem (q, (u8 *) & mp);
191 }
192
193 static void
194 vl_api_sw_interface_tap_dump_t_handler (vl_api_sw_interface_tap_dump_t * mp)
195 {
196   int rv = 0;
197   vpe_api_main_t *am = &vpe_api_main;
198   unix_shared_memory_queue_t *q;
199   tapcli_interface_details_t *tapifs = NULL;
200   tapcli_interface_details_t *tap_if = NULL;
201
202   q = vl_api_client_index_to_input_queue (mp->client_index);
203   if (q == 0)
204     return;
205
206   rv = vnet_tap_dump_ifs (&tapifs);
207   if (rv)
208     return;
209
210   vec_foreach (tap_if, tapifs)
211   {
212     send_sw_interface_tap_details (am, q, tap_if, mp->context);
213   }
214
215   vec_free (tapifs);
216 }
217
218 static void
219 setup_message_id_table (api_main_t * am)
220 {
221 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
222   foreach_vl_msg_name_crc_tap;
223 #undef _
224 }
225
226 static clib_error_t *
227 tap_api_hookup (vlib_main_t * vm)
228 {
229   api_main_t *am = &api_main;
230
231 #define _(N,n)                                                  \
232     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
233                            vl_api_##n##_t_handler,              \
234                            vl_noop_handler,                     \
235                            vl_api_##n##_t_endian,               \
236                            vl_api_##n##_t_print,                \
237                            sizeof(vl_api_##n##_t), 1);
238   foreach_tap_api_msg;
239 #undef _
240
241   /*
242    * Set up the (msg_name, crc, message-id) table
243    */
244   setup_message_id_table (am);
245
246   return 0;
247 }
248
249 VLIB_API_INIT_FUNCTION (tap_api_hookup);
250
251 /*
252  * fd.io coding-style-patch-verification: ON
253  *
254  * Local Variables:
255  * eval: (c-set-style "gnu")
256  * End:
257  */