3fd73d7995f416a426bdcf1fabe230a244a270ab
[vpp.git] / src / vnet / bonding / bond_api.c
1 /*
2  *------------------------------------------------------------------
3  * bond_api.c - vnet bonding 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/ethernet/ethernet_types_api.h>
27 #include <vnet/bonding/node.h>
28
29 #include <vnet/format_fns.h>
30 #include <vnet/bonding/bond.api_enum.h>
31 #include <vnet/bonding/bond.api_types.h>
32
33 #define REPLY_MSG_ID_BASE msg_id_base
34 #include <vlibapi/api_helper_macros.h>
35
36 static u16 msg_id_base;
37
38 static void
39 vl_api_bond_delete_t_handler (vl_api_bond_delete_t * mp)
40 {
41   vlib_main_t *vm = vlib_get_main ();
42   int rv;
43   vl_api_bond_delete_reply_t *rmp;
44   u32 sw_if_index = ntohl (mp->sw_if_index);
45
46   rv = bond_delete_if (vm, sw_if_index);
47
48   REPLY_MACRO (VL_API_BOND_DELETE_REPLY);
49 }
50
51 static void
52 vl_api_bond_create_t_handler (vl_api_bond_create_t * mp)
53 {
54   vlib_main_t *vm = vlib_get_main ();
55   vl_api_bond_create_reply_t *rmp;
56   bond_create_if_args_t _a, *ap = &_a;
57
58   clib_memset (ap, 0, sizeof (*ap));
59
60   ap->id = ntohl (mp->id);
61
62   if (mp->use_custom_mac)
63     {
64       mac_address_decode (mp->mac_address, (mac_address_t *) ap->hw_addr);
65       ap->hw_addr_set = 1;
66     }
67
68   ap->mode = ntohl (mp->mode);
69   ap->lb = ntohl (mp->lb);
70   ap->numa_only = mp->numa_only;
71   bond_create_if (vm, ap);
72
73   int rv = ap->rv;
74
75   /* *INDENT-OFF* */
76   REPLY_MACRO2(VL_API_BOND_CREATE_REPLY,
77   ({
78     rmp->sw_if_index = ntohl (ap->sw_if_index);
79   }));
80   /* *INDENT-ON* */
81 }
82
83 static void
84 vl_api_bond_create2_t_handler (vl_api_bond_create2_t * mp)
85 {
86   vlib_main_t *vm = vlib_get_main ();
87   vl_api_bond_create2_reply_t *rmp;
88   bond_create_if_args_t _a, *ap = &_a;
89
90   clib_memset (ap, 0, sizeof (*ap));
91
92   ap->id = ntohl (mp->id);
93
94   if (mp->use_custom_mac)
95     {
96       mac_address_decode (mp->mac_address, (mac_address_t *) ap->hw_addr);
97       ap->hw_addr_set = 1;
98     }
99
100   ap->mode = ntohl (mp->mode);
101   ap->lb = ntohl (mp->lb);
102   ap->numa_only = mp->numa_only;
103   ap->gso = mp->enable_gso;
104   bond_create_if (vm, ap);
105
106   int rv = ap->rv;
107
108   /* *INDENT-OFF* */
109   REPLY_MACRO2(VL_API_BOND_CREATE2_REPLY,
110   ({
111     rmp->sw_if_index = ntohl (ap->sw_if_index);
112   }));
113   /* *INDENT-ON* */
114 }
115
116 static void
117 vl_api_bond_add_member_t_handler (vl_api_bond_add_member_t * mp)
118 {
119   vlib_main_t *vm = vlib_get_main ();
120   vl_api_bond_add_member_reply_t *rmp;
121   bond_add_member_args_t _a, *ap = &_a;
122   int rv = 0;
123
124   clib_memset (ap, 0, sizeof (*ap));
125
126   ap->group = ntohl (mp->bond_sw_if_index);
127   VALIDATE_SW_IF_INDEX (mp);
128   ap->member = ntohl (mp->sw_if_index);
129   ap->is_passive = mp->is_passive;
130   ap->is_long_timeout = mp->is_long_timeout;
131
132   bond_add_member (vm, ap);
133   rv = ap->rv;
134
135   BAD_SW_IF_INDEX_LABEL;
136   REPLY_MACRO (VL_API_BOND_ADD_MEMBER_REPLY);
137 }
138
139 static void
140 vl_api_bond_enslave_t_handler (vl_api_bond_enslave_t * mp)
141 {
142   vlib_main_t *vm = vlib_get_main ();
143   vl_api_bond_enslave_reply_t *rmp;
144   bond_add_member_args_t _a, *ap = &_a;
145   int rv = 0;
146
147   clib_memset (ap, 0, sizeof (*ap));
148
149   ap->group = ntohl (mp->bond_sw_if_index);
150   VALIDATE_SW_IF_INDEX (mp);
151   ap->member = ntohl (mp->sw_if_index);
152   ap->is_passive = mp->is_passive;
153   ap->is_long_timeout = mp->is_long_timeout;
154
155   bond_add_member (vm, ap);
156   rv = ap->rv;
157
158   BAD_SW_IF_INDEX_LABEL;
159   REPLY_MACRO (VL_API_BOND_ENSLAVE_REPLY);
160 }
161
162 static void
163   vl_api_sw_interface_set_bond_weight_t_handler
164   (vl_api_sw_interface_set_bond_weight_t * mp)
165 {
166   vlib_main_t *vm = vlib_get_main ();
167   bond_set_intf_weight_args_t _a, *ap = &_a;
168   vl_api_sw_interface_set_bond_weight_reply_t *rmp;
169   int rv = 0;
170
171   clib_memset (ap, 0, sizeof (*ap));
172
173   ap->sw_if_index = ntohl (mp->sw_if_index);
174   ap->weight = ntohl (mp->weight);
175
176   bond_set_intf_weight (vm, ap);
177   rv = ap->rv;
178
179   REPLY_MACRO (VL_API_SW_INTERFACE_SET_BOND_WEIGHT_REPLY);
180 }
181
182 static void
183 vl_api_bond_detach_slave_t_handler (vl_api_bond_detach_slave_t * mp)
184 {
185   vlib_main_t *vm = vlib_get_main ();
186   vl_api_bond_detach_slave_reply_t *rmp;
187   bond_detach_member_args_t _a, *ap = &_a;
188   int rv = 0;
189
190   clib_memset (ap, 0, sizeof (*ap));
191
192   ap->member = ntohl (mp->sw_if_index);
193   bond_detach_member (vm, ap);
194   rv = ap->rv;
195
196   REPLY_MACRO (VL_API_BOND_DETACH_SLAVE_REPLY);
197 }
198
199 static void
200 vl_api_bond_detach_member_t_handler (vl_api_bond_detach_member_t * mp)
201 {
202   vlib_main_t *vm = vlib_get_main ();
203   vl_api_bond_detach_member_reply_t *rmp;
204   bond_detach_member_args_t _a, *ap = &_a;
205   int rv = 0;
206
207   clib_memset (ap, 0, sizeof (*ap));
208
209   ap->member = ntohl (mp->sw_if_index);
210   bond_detach_member (vm, ap);
211   rv = ap->rv;
212
213   REPLY_MACRO (VL_API_BOND_DETACH_MEMBER_REPLY);
214 }
215
216 static void
217 bond_send_sw_interface_details (vpe_api_main_t * am,
218                                 vl_api_registration_t * reg,
219                                 bond_interface_details_t * bond_if,
220                                 u32 context)
221 {
222   vl_api_sw_interface_bond_details_t *mp;
223
224   mp = vl_msg_api_alloc (sizeof (*mp));
225   clib_memset (mp, 0, sizeof (*mp));
226   mp->_vl_msg_id =
227     htons (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_BOND_DETAILS);
228   mp->sw_if_index = htonl (bond_if->sw_if_index);
229   mp->id = htonl (bond_if->id);
230   clib_memcpy (mp->interface_name, bond_if->interface_name,
231                MIN (ARRAY_LEN (mp->interface_name) - 1,
232                     strlen ((const char *) bond_if->interface_name)));
233   mp->mode = htonl (bond_if->mode);
234   mp->lb = htonl (bond_if->lb);
235   mp->numa_only = bond_if->numa_only;
236   mp->active_slaves = htonl (bond_if->active_members);
237   mp->slaves = htonl (bond_if->members);
238
239   mp->context = context;
240   vl_api_send_msg (reg, (u8 *) mp);
241 }
242
243 static void
244 vl_api_sw_interface_bond_dump_t_handler (vl_api_sw_interface_bond_dump_t * mp)
245 {
246   int rv;
247   vpe_api_main_t *am = &vpe_api_main;
248   vl_api_registration_t *reg;
249   bond_interface_details_t *bondifs = NULL;
250   bond_interface_details_t *bond_if = NULL;
251
252   reg = vl_api_client_index_to_registration (mp->client_index);
253   if (!reg)
254     return;
255
256   rv = bond_dump_ifs (&bondifs);
257   if (rv)
258     return;
259
260   vec_foreach (bond_if, bondifs)
261   {
262     bond_send_sw_interface_details (am, reg, bond_if, mp->context);
263   }
264
265   vec_free (bondifs);
266 }
267
268 static void
269 bond_send_sw_bond_interface_details (vpe_api_main_t * am,
270                                      vl_api_registration_t * reg,
271                                      bond_interface_details_t * bond_if,
272                                      u32 context)
273 {
274   vl_api_sw_bond_interface_details_t *mp;
275
276   mp = vl_msg_api_alloc (sizeof (*mp));
277   clib_memset (mp, 0, sizeof (*mp));
278   mp->_vl_msg_id =
279     htons (REPLY_MSG_ID_BASE + VL_API_SW_BOND_INTERFACE_DETAILS);
280   mp->sw_if_index = htonl (bond_if->sw_if_index);
281   mp->id = htonl (bond_if->id);
282   clib_memcpy (mp->interface_name, bond_if->interface_name,
283                MIN (ARRAY_LEN (mp->interface_name) - 1,
284                     strlen ((const char *) bond_if->interface_name)));
285   mp->mode = htonl (bond_if->mode);
286   mp->lb = htonl (bond_if->lb);
287   mp->numa_only = bond_if->numa_only;
288   mp->active_members = htonl (bond_if->active_members);
289   mp->members = htonl (bond_if->members);
290
291   mp->context = context;
292   vl_api_send_msg (reg, (u8 *) mp);
293 }
294
295 static void
296 vl_api_sw_bond_interface_dump_t_handler (vl_api_sw_bond_interface_dump_t * mp)
297 {
298   int rv;
299   vpe_api_main_t *am = &vpe_api_main;
300   vl_api_registration_t *reg;
301   bond_interface_details_t *bondifs = NULL;
302   bond_interface_details_t *bond_if = NULL;
303   u32 filter_sw_if_index;
304
305   reg = vl_api_client_index_to_registration (mp->client_index);
306   if (!reg)
307     return;
308
309   filter_sw_if_index = htonl (mp->sw_if_index);
310   if (filter_sw_if_index != ~0)
311     VALIDATE_SW_IF_INDEX (mp);
312
313   rv = bond_dump_ifs (&bondifs);
314   if (rv)
315     return;
316
317   vec_foreach (bond_if, bondifs)
318   {
319     if ((filter_sw_if_index == ~0) ||
320         (bond_if->sw_if_index == filter_sw_if_index))
321       bond_send_sw_bond_interface_details (am, reg, bond_if, mp->context);
322   }
323
324   BAD_SW_IF_INDEX_LABEL;
325   vec_free (bondifs);
326 }
327
328 static void
329 bond_send_sw_member_interface_details (vpe_api_main_t * am,
330                                        vl_api_registration_t * reg,
331                                        member_interface_details_t * member_if,
332                                        u32 context)
333 {
334   vl_api_sw_interface_slave_details_t *mp;
335
336   mp = vl_msg_api_alloc (sizeof (*mp));
337   clib_memset (mp, 0, sizeof (*mp));
338   mp->_vl_msg_id =
339     htons (REPLY_MSG_ID_BASE + VL_API_SW_INTERFACE_SLAVE_DETAILS);
340   mp->sw_if_index = htonl (member_if->sw_if_index);
341   clib_memcpy (mp->interface_name, member_if->interface_name,
342                MIN (ARRAY_LEN (mp->interface_name) - 1,
343                     strlen ((const char *) member_if->interface_name)));
344   mp->is_passive = member_if->is_passive;
345   mp->is_long_timeout = member_if->is_long_timeout;
346   mp->is_local_numa = member_if->is_local_numa;
347   mp->weight = htonl (member_if->weight);
348
349   mp->context = context;
350   vl_api_send_msg (reg, (u8 *) mp);
351 }
352
353 static void
354 vl_api_sw_interface_slave_dump_t_handler (vl_api_sw_interface_slave_dump_t *
355                                           mp)
356 {
357   int rv;
358   vpe_api_main_t *am = &vpe_api_main;
359   vl_api_registration_t *reg;
360   member_interface_details_t *memberifs = NULL;
361   member_interface_details_t *member_if = NULL;
362
363   reg = vl_api_client_index_to_registration (mp->client_index);
364   if (!reg)
365     return;
366
367   rv = bond_dump_member_ifs (&memberifs, ntohl (mp->sw_if_index));
368   if (rv)
369     return;
370
371   vec_foreach (member_if, memberifs)
372   {
373     bond_send_sw_member_interface_details (am, reg, member_if, mp->context);
374   }
375
376   vec_free (memberifs);
377 }
378
379 static void
380 bond_send_member_interface_details (vpe_api_main_t * am,
381                                     vl_api_registration_t * reg,
382                                     member_interface_details_t * member_if,
383                                     u32 context)
384 {
385   vl_api_sw_member_interface_details_t *mp;
386
387   mp = vl_msg_api_alloc (sizeof (*mp));
388   clib_memset (mp, 0, sizeof (*mp));
389   mp->_vl_msg_id =
390     htons (REPLY_MSG_ID_BASE + VL_API_SW_MEMBER_INTERFACE_DETAILS);
391   mp->sw_if_index = htonl (member_if->sw_if_index);
392   clib_memcpy (mp->interface_name, member_if->interface_name,
393                MIN (ARRAY_LEN (mp->interface_name) - 1,
394                     strlen ((const char *) member_if->interface_name)));
395   mp->is_passive = member_if->is_passive;
396   mp->is_long_timeout = member_if->is_long_timeout;
397   mp->is_local_numa = member_if->is_local_numa;
398   mp->weight = htonl (member_if->weight);
399
400   mp->context = context;
401   vl_api_send_msg (reg, (u8 *) mp);
402 }
403
404 static void
405 vl_api_sw_member_interface_dump_t_handler (vl_api_sw_member_interface_dump_t *
406                                            mp)
407 {
408   int rv;
409   vpe_api_main_t *am = &vpe_api_main;
410   vl_api_registration_t *reg;
411   member_interface_details_t *memberifs = NULL;
412   member_interface_details_t *member_if = NULL;
413
414   reg = vl_api_client_index_to_registration (mp->client_index);
415   if (!reg)
416     return;
417
418   rv = bond_dump_member_ifs (&memberifs, ntohl (mp->sw_if_index));
419   if (rv)
420     return;
421
422   vec_foreach (member_if, memberifs)
423   {
424     bond_send_member_interface_details (am, reg, member_if, mp->context);
425   }
426
427   vec_free (memberifs);
428 }
429
430 #include <vnet/bonding/bond.api.c>
431 static clib_error_t *
432 bond_api_hookup (vlib_main_t * vm)
433 {
434   /*
435    * Set up the (msg_name, crc, message-id) table
436    */
437   REPLY_MSG_ID_BASE = setup_message_id_table ();
438
439   return 0;
440 }
441
442 VLIB_API_INIT_FUNCTION (bond_api_hookup);
443
444 /*
445  * fd.io coding-style-patch-verification: ON
446  *
447  * Local Variables:
448  * eval: (c-set-style "gnu")
449  * End:
450  */