fib: fib api updates
[vpp.git] / src / plugins / abf / abf_api.c
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <stddef.h>
17
18 #include <vnet/vnet.h>
19 #include <vnet/plugin/plugin.h>
20 #include <abf/abf_policy.h>
21 #include <abf/abf_itf_attach.h>
22 #include <vnet/mpls/mpls_types.h>
23 #include <vnet/fib/fib_path_list.h>
24 #include <vnet/fib/fib_api.h>
25
26 #include <vpp/app/version.h>
27
28 #include <vlibapi/api.h>
29 #include <vlibmemory/api.h>
30
31 /* define message IDs */
32 #include <abf/abf_msg_enum.h>
33
34 /* define message structures */
35 #define vl_typedefs
36 #include <abf/abf_all_api_h.h>
37 #undef vl_typedefs
38
39 /* define generated endian-swappers */
40 #define vl_endianfun
41 #include <abf/abf_all_api_h.h>
42 #undef vl_endianfun
43
44 /* instantiate all the print functions we know about */
45 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
46 #define vl_printfun
47 #include <abf/abf_all_api_h.h>
48 #undef vl_printfun
49
50 /* Get the API version number */
51 #define vl_api_version(n,v) static u32 api_version=(v);
52 #include <abf/abf_all_api_h.h>
53 #undef vl_api_version
54
55 /**
56  * Base message ID fot the plugin
57  */
58 static u32 abf_base_msg_id;
59
60 #include <vlibapi/api_helper_macros.h>
61
62 /* List of message types that this plugin understands */
63
64 #define foreach_abf_plugin_api_msg                    \
65 _(ABF_PLUGIN_GET_VERSION, abf_plugin_get_version)     \
66 _(ABF_POLICY_ADD_DEL, abf_policy_add_del)             \
67 _(ABF_POLICY_DUMP, abf_policy_dump)                   \
68 _(ABF_ITF_ATTACH_ADD_DEL, abf_itf_attach_add_del)     \
69 _(ABF_ITF_ATTACH_DUMP, abf_itf_attach_dump)
70
71 static void
72 vl_api_abf_plugin_get_version_t_handler (vl_api_abf_plugin_get_version_t * mp)
73 {
74   vl_api_abf_plugin_get_version_reply_t *rmp;
75   vl_api_registration_t *rp;
76
77   rp = vl_api_client_index_to_registration (mp->client_index);
78   if (rp == 0)
79     return;
80
81   rmp = vl_msg_api_alloc (sizeof (*rmp));
82   rmp->_vl_msg_id =
83     ntohs (VL_API_ABF_PLUGIN_GET_VERSION_REPLY + abf_base_msg_id);
84   rmp->context = mp->context;
85   rmp->major = htonl (ABF_PLUGIN_VERSION_MAJOR);
86   rmp->minor = htonl (ABF_PLUGIN_VERSION_MINOR);
87
88   vl_api_send_msg (rp, (u8 *) rmp);
89 }
90
91 static void
92 vl_api_abf_policy_add_del_t_handler (vl_api_abf_policy_add_del_t * mp)
93 {
94   vl_api_abf_policy_add_del_reply_t *rmp;
95   fib_route_path_t *paths = NULL, *path;
96   int rv = 0;
97   u8 pi;
98
99   vec_validate (paths, mp->policy.n_paths - 1);
100
101   for (pi = 0; pi < mp->policy.n_paths; pi++)
102     {
103       path = &paths[pi];
104       rv = fib_api_path_decode (&mp->policy.paths[pi], path);
105
106       if (0 != rv)
107         {
108           goto done;
109         }
110     }
111
112   if (mp->is_add)
113     {
114       rv = abf_policy_update (ntohl (mp->policy.policy_id),
115                               ntohl (mp->policy.acl_index), paths);
116     }
117   else
118     {
119       rv = abf_policy_delete (ntohl (mp->policy.policy_id), paths);
120     }
121 done:
122   vec_free (paths);
123
124   REPLY_MACRO (VL_API_ABF_POLICY_ADD_DEL_REPLY + abf_base_msg_id);
125 }
126
127 static void
128 vl_api_abf_itf_attach_add_del_t_handler (vl_api_abf_itf_attach_add_del_t * mp)
129 {
130   vl_api_abf_itf_attach_add_del_reply_t *rmp;
131   fib_protocol_t fproto = (mp->attach.is_ipv6 ?
132                            FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
133   int rv = 0;
134
135   if (mp->is_add)
136     {
137       abf_itf_attach (fproto,
138                       ntohl (mp->attach.policy_id),
139                       ntohl (mp->attach.priority),
140                       ntohl (mp->attach.sw_if_index));
141     }
142   else
143     {
144       abf_itf_detach (fproto,
145                       ntohl (mp->attach.policy_id),
146                       ntohl (mp->attach.sw_if_index));
147     }
148
149   REPLY_MACRO (VL_API_ABF_ITF_ATTACH_ADD_DEL_REPLY + abf_base_msg_id);
150 }
151
152 typedef struct abf_dump_walk_ctx_t_
153 {
154   vl_api_registration_t *rp;
155   u32 context;
156 } abf_dump_walk_ctx_t;
157
158 static int
159 abf_policy_send_details (u32 api, void *args)
160 {
161   fib_path_encode_ctx_t walk_ctx = {
162     .rpaths = NULL,
163   };
164   vl_api_abf_policy_details_t *mp;
165   abf_dump_walk_ctx_t *ctx;
166   fib_route_path_t *rpath;
167   vl_api_fib_path_t *fp;
168   size_t msg_size;
169   abf_policy_t *ap;
170   u8 n_paths;
171
172   ctx = args;
173   ap = abf_policy_get (api);
174   n_paths = fib_path_list_get_n_paths (ap->ap_pl);
175   msg_size = sizeof (*mp) + sizeof (mp->policy.paths[0]) * n_paths;
176
177   mp = vl_msg_api_alloc (msg_size);
178   clib_memset (mp, 0, msg_size);
179   mp->_vl_msg_id = ntohs (VL_API_ABF_POLICY_DETAILS + abf_base_msg_id);
180
181   /* fill in the message */
182   mp->context = ctx->context;
183   mp->policy.n_paths = n_paths;
184   mp->policy.acl_index = htonl (ap->ap_acl);
185   mp->policy.policy_id = htonl (ap->ap_id);
186
187   fib_path_list_walk_w_ext (ap->ap_pl, NULL, fib_path_encode, &walk_ctx);
188
189   fp = mp->policy.paths;
190   vec_foreach (rpath, walk_ctx.rpaths)
191   {
192     fib_api_path_encode (rpath, fp);
193     fp++;
194   }
195
196   vl_api_send_msg (ctx->rp, (u8 *) mp);
197
198   vec_free (walk_ctx.rpaths);
199
200   return (1);
201 }
202
203 static void
204 vl_api_abf_policy_dump_t_handler (vl_api_abf_policy_dump_t * mp)
205 {
206   vl_api_registration_t *rp;
207
208   rp = vl_api_client_index_to_registration (mp->client_index);
209   if (rp == 0)
210     return;
211
212   abf_dump_walk_ctx_t ctx = {
213     .rp = rp,
214     .context = mp->context,
215   };
216
217   abf_policy_walk (abf_policy_send_details, &ctx);
218 }
219
220 static int
221 abf_itf_attach_send_details (u32 aiai, void *args)
222 {
223   vl_api_abf_itf_attach_details_t *mp;
224   abf_dump_walk_ctx_t *ctx;
225   abf_itf_attach_t *aia;
226   abf_policy_t *ap;
227
228   ctx = args;
229   aia = abf_itf_attach_get (aiai);
230   ap = abf_policy_get (aia->aia_abf);
231
232   mp = vl_msg_api_alloc (sizeof (*mp));
233   mp->_vl_msg_id = ntohs (VL_API_ABF_ITF_ATTACH_DETAILS + abf_base_msg_id);
234
235   mp->context = ctx->context;
236   mp->attach.policy_id = htonl (ap->ap_id);
237   mp->attach.sw_if_index = htonl (aia->aia_sw_if_index);
238   mp->attach.priority = htonl (aia->aia_prio);
239   mp->attach.is_ipv6 = (aia->aia_proto == FIB_PROTOCOL_IP6);
240
241   vl_api_send_msg (ctx->rp, (u8 *) mp);
242
243   return (1);
244 }
245
246 static void
247 vl_api_abf_itf_attach_dump_t_handler (vl_api_abf_itf_attach_dump_t * mp)
248 {
249   vl_api_registration_t *rp;
250
251   rp = vl_api_client_index_to_registration (mp->client_index);
252   if (rp == 0)
253     return;
254
255   abf_dump_walk_ctx_t ctx = {
256     .rp = rp,
257     .context = mp->context,
258   };
259
260   abf_itf_attach_walk (abf_itf_attach_send_details, &ctx);
261 }
262
263 #define vl_msg_name_crc_list
264 #include <abf/abf_all_api_h.h>
265 #undef vl_msg_name_crc_list
266
267 /* Set up the API message handling tables */
268 static clib_error_t *
269 abf_plugin_api_hookup (vlib_main_t * vm)
270 {
271 #define _(N,n)                                                  \
272     vl_msg_api_set_handlers((VL_API_##N + abf_base_msg_id),     \
273                             #n,                                 \
274                             vl_api_##n##_t_handler,             \
275                             vl_noop_handler,                    \
276                             vl_api_##n##_t_endian,              \
277                             vl_api_##n##_t_print,               \
278                             sizeof(vl_api_##n##_t), 1);
279   foreach_abf_plugin_api_msg;
280 #undef _
281
282   return 0;
283 }
284
285 static void
286 setup_message_id_table (api_main_t * apim)
287 {
288 #define _(id,n,crc) \
289   vl_msg_api_add_msg_name_crc (apim, #n "_" #crc, id + abf_base_msg_id);
290   foreach_vl_msg_name_crc_abf;
291 #undef _
292 }
293
294 static clib_error_t *
295 abf_api_init (vlib_main_t * vm)
296 {
297   clib_error_t *error = 0;
298
299   u8 *name = format (0, "abf_%08x%c", api_version, 0);
300
301   /* Ask for a correctly-sized block of API message decode slots */
302   abf_base_msg_id = vl_msg_api_get_msg_ids ((char *) name,
303                                             VL_MSG_FIRST_AVAILABLE);
304
305   error = abf_plugin_api_hookup (vm);
306
307   /* Add our API messages to the global name_crc hash table */
308   setup_message_id_table (&api_main);
309
310   vec_free (name);
311
312   return error;
313 }
314
315 VLIB_INIT_FUNCTION (abf_api_init);
316
317 /* *INDENT-OFF* */
318 VLIB_PLUGIN_REGISTER () = {
319     .version = VPP_BUILD_VER,
320     .description = "Access Control List (ACL) Based Forwarding",
321 };
322 /* *INDENT-ON* */
323
324 /*
325  * fd.io coding-style-patch-verification: ON
326  *
327  * Local Variables:
328  * eval: (c-set-style "gnu")
329  * End:
330  */