linux-cp: A V2 variant of pair create API that returns the host
[vpp.git] / src / plugins / linux-cp / lcp_api.c
1 /*
2  * Copyright 2020 Rubicon Communications, LLC.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6
7 #include <sys/socket.h>
8 #include <linux/if.h>
9
10 #include <vnet/vnet.h>
11 #include <vnet/plugin/plugin.h>
12
13 #include <vlibapi/api.h>
14 #include <vlibmemory/api.h>
15 #include <vpp/app/version.h>
16 #include <vnet/format_fns.h>
17
18 #include <linux-cp/lcp_interface.h>
19 #include <linux-cp/lcp.api_enum.h>
20 #include <linux-cp/lcp.api_types.h>
21
22 static u16 lcp_msg_id_base;
23 #define REPLY_MSG_ID_BASE lcp_msg_id_base
24 #include <vlibapi/api_helper_macros.h>
25
26 static lip_host_type_t
27 api_decode_host_type (vl_api_lcp_itf_host_type_t type)
28 {
29   if (type == LCP_API_ITF_HOST_TUN)
30     return LCP_ITF_HOST_TUN;
31
32   return LCP_ITF_HOST_TAP;
33 }
34
35 static vl_api_lcp_itf_host_type_t
36 api_encode_host_type (lip_host_type_t type)
37 {
38   if (type == LCP_ITF_HOST_TUN)
39     return LCP_API_ITF_HOST_TUN;
40
41   return LCP_API_ITF_HOST_TAP;
42 }
43
44 void
45 lcp_set_auto_intf (u8 is_auto)
46 {
47   lcp_main_t *lcpm = &lcp_main;
48
49   lcpm->auto_intf = (is_auto != 0);
50 }
51
52 int
53 lcp_auto_intf (void)
54 {
55   lcp_main_t *lcpm = &lcp_main;
56
57   return lcpm->auto_intf;
58 }
59
60 static int
61 vl_api_lcp_itf_pair_add (u32 phy_sw_if_index, lip_host_type_t lip_host_type,
62                          u8 *mp_host_if_name, size_t sizeof_host_if_name,
63                          u8 *mp_namespace, size_t sizeof_mp_namespace,
64                          u32 *host_sw_if_index_p)
65 {
66   u8 *host_if_name, *netns;
67   int host_len, netns_len, rv;
68
69   host_if_name = netns = 0;
70
71   /* lcp_itf_pair_create expects vec of u8 */
72   host_len = clib_strnlen ((char *) mp_host_if_name, sizeof_host_if_name - 1);
73   vec_add (host_if_name, mp_host_if_name, host_len);
74   vec_add1 (host_if_name, 0);
75
76   netns_len = clib_strnlen ((char *) mp_namespace, sizeof_mp_namespace - 1);
77   vec_add (netns, mp_namespace, netns_len);
78   vec_add1 (netns, 0);
79
80   rv = lcp_itf_pair_create (phy_sw_if_index, host_if_name, lip_host_type,
81                             netns, host_sw_if_index_p);
82
83   vec_free (host_if_name);
84   vec_free (netns);
85
86   return rv;
87 }
88
89 static void
90 vl_api_lcp_itf_pair_add_del_t_handler (vl_api_lcp_itf_pair_add_del_t *mp)
91 {
92   u32 phy_sw_if_index;
93   vl_api_lcp_itf_pair_add_del_reply_t *rmp;
94   lip_host_type_t lip_host_type;
95   int rv;
96
97   if (!vnet_sw_if_index_is_api_valid (mp->sw_if_index))
98     {
99       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
100       goto bad_sw_if_index;
101     }
102
103   phy_sw_if_index = mp->sw_if_index;
104   lip_host_type = api_decode_host_type (mp->host_if_type);
105   if (mp->is_add)
106     {
107       rv =
108         vl_api_lcp_itf_pair_add (phy_sw_if_index, lip_host_type,
109                                  mp->host_if_name, sizeof (mp->host_if_name),
110                                  mp->namespace, sizeof (mp->namespace), NULL);
111     }
112   else
113     {
114       rv = lcp_itf_pair_delete (phy_sw_if_index);
115     }
116
117   BAD_SW_IF_INDEX_LABEL;
118   REPLY_MACRO (VL_API_LCP_ITF_PAIR_ADD_DEL_REPLY);
119 }
120
121 static void
122 vl_api_lcp_itf_pair_add_del_v2_t_handler (vl_api_lcp_itf_pair_add_del_v2_t *mp)
123 {
124   u32 phy_sw_if_index, host_sw_if_index = ~0;
125   vl_api_lcp_itf_pair_add_del_v2_reply_t *rmp;
126   lip_host_type_t lip_host_type;
127   int rv;
128
129   if (!vnet_sw_if_index_is_api_valid (mp->sw_if_index))
130     {
131       rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
132       goto bad_sw_if_index;
133     }
134
135   phy_sw_if_index = mp->sw_if_index;
136   lip_host_type = api_decode_host_type (mp->host_if_type);
137   if (mp->is_add)
138     {
139       rv = vl_api_lcp_itf_pair_add (phy_sw_if_index, lip_host_type,
140                                     mp->host_if_name,
141                                     sizeof (mp->host_if_name), mp->namespace,
142                                     sizeof (mp->namespace), &host_sw_if_index);
143     }
144   else
145     {
146       rv = lcp_itf_pair_delete (phy_sw_if_index);
147     }
148
149   BAD_SW_IF_INDEX_LABEL;
150   REPLY_MACRO2 (VL_API_LCP_ITF_PAIR_ADD_DEL_V2_REPLY,
151                 { rmp->host_sw_if_index = ntohl (host_sw_if_index); });
152 }
153
154 static void
155 send_lcp_itf_pair_details (index_t lipi, vl_api_registration_t *rp,
156                            u32 context)
157 {
158   vl_api_lcp_itf_pair_details_t *rmp;
159   lcp_itf_pair_t *lcp_pair = lcp_itf_pair_get (lipi);
160
161   REPLY_MACRO_DETAILS4 (
162     VL_API_LCP_ITF_PAIR_DETAILS, rp, context, ({
163       rmp->phy_sw_if_index = lcp_pair->lip_phy_sw_if_index;
164       rmp->host_sw_if_index = lcp_pair->lip_host_sw_if_index;
165       rmp->vif_index = lcp_pair->lip_vif_index;
166       rmp->host_if_type = api_encode_host_type (lcp_pair->lip_host_type);
167
168       memcpy_s (rmp->host_if_name, sizeof (rmp->host_if_name),
169                 lcp_pair->lip_host_name, vec_len (lcp_pair->lip_host_name));
170
171       clib_strncpy ((char *) rmp->namespace, (char *) lcp_pair->lip_namespace,
172                     vec_len (lcp_pair->lip_namespace));
173     }));
174 }
175
176 static void
177 vl_api_lcp_itf_pair_get_t_handler (vl_api_lcp_itf_pair_get_t *mp)
178 {
179   vl_api_lcp_itf_pair_get_reply_t *rmp;
180   i32 rv = 0;
181
182   REPLY_AND_DETAILS_MACRO (
183     VL_API_LCP_ITF_PAIR_GET_REPLY, lcp_itf_pair_pool,
184     ({ send_lcp_itf_pair_details (cursor, rp, mp->context); }));
185 }
186
187 static void
188 vl_api_lcp_default_ns_set_t_handler (vl_api_lcp_default_ns_set_t *mp)
189 {
190   vl_api_lcp_default_ns_set_reply_t *rmp;
191   int rv;
192
193   mp->namespace[LCP_NS_LEN - 1] = 0;
194   rv = lcp_set_default_ns (mp->namespace);
195
196   REPLY_MACRO (VL_API_LCP_DEFAULT_NS_SET_REPLY);
197 }
198
199 static void
200 vl_api_lcp_default_ns_get_t_handler (vl_api_lcp_default_ns_get_t *mp)
201 {
202   lcp_main_t *lcpm = &lcp_main;
203   vl_api_lcp_default_ns_get_reply_t *rmp;
204   vl_api_registration_t *reg;
205   char *ns;
206
207   reg = vl_api_client_index_to_registration (mp->client_index);
208   if (!reg)
209     return;
210
211   rmp = vl_msg_api_alloc (sizeof (*rmp));
212   clib_memset (rmp, 0, sizeof (*rmp));
213   rmp->_vl_msg_id = (VL_API_LCP_DEFAULT_NS_GET_REPLY + lcpm->msg_id_base);
214   rmp->context = mp->context;
215
216   ns = (char *) lcp_get_default_ns ();
217   if (ns)
218     clib_strncpy ((char *) rmp->namespace, ns, LCP_NS_LEN - 1);
219
220   vl_api_send_msg (reg, (u8 *) rmp);
221 }
222
223 static void
224 vl_api_lcp_itf_pair_replace_begin_t_handler (
225   vl_api_lcp_itf_pair_replace_begin_t *mp)
226 {
227   vl_api_lcp_itf_pair_replace_begin_reply_t *rmp;
228   int rv;
229
230   rv = lcp_itf_pair_replace_begin ();
231
232   REPLY_MACRO (VL_API_LCP_ITF_PAIR_REPLACE_BEGIN_REPLY);
233 }
234
235 static void
236 vl_api_lcp_itf_pair_replace_end_t_handler (
237   vl_api_lcp_itf_pair_replace_end_t *mp)
238 {
239   vl_api_lcp_itf_pair_replace_end_reply_t *rmp;
240   int rv = 0;
241
242   rv = lcp_itf_pair_replace_end ();
243
244   REPLY_MACRO (VL_API_LCP_ITF_PAIR_REPLACE_END_REPLY);
245 }
246
247 /*
248  * Set up the API message handling tables
249  */
250 #include <linux-cp/lcp.api.c>
251
252 static clib_error_t *
253 lcp_plugin_api_hookup (vlib_main_t *vm)
254 {
255   /* Ask for a correctly-sized block of API message decode slots */
256   lcp_msg_id_base = setup_message_id_table ();
257
258   return (NULL);
259 }
260
261 VLIB_INIT_FUNCTION (lcp_plugin_api_hookup);
262
263 #include <vpp/app/version.h>
264 VLIB_PLUGIN_REGISTER () = {
265   .version = VPP_BUILD_VER,
266   .description = "Linux Control Plane - Interface Mirror",
267   .default_disabled = 1,
268 };
269
270 /*
271  * fd.io coding-style-patch-verification: ON
272  *
273  * Local Variables:
274  * eval: (c-set-style "gnu")
275  * End:
276  */