FIB: encode the label stack in the FIB path during table dump
[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   int msg_size = sizeof (*rmp);
76   unix_shared_memory_queue_t *q;
77
78   q = vl_api_client_index_to_input_queue (mp->client_index);
79   if (q == 0)
80     {
81       return;
82     }
83
84   rmp = vl_msg_api_alloc (msg_size);
85   clib_memset (rmp, 0, msg_size);
86   rmp->_vl_msg_id =
87     ntohs (VL_API_ABF_PLUGIN_GET_VERSION_REPLY + abf_base_msg_id);
88   rmp->context = mp->context;
89   rmp->major = htonl (ABF_PLUGIN_VERSION_MAJOR);
90   rmp->minor = htonl (ABF_PLUGIN_VERSION_MINOR);
91
92   vl_msg_api_send_shmem (q, (u8 *) & rmp);
93 }
94
95 static void
96 vl_api_abf_policy_add_del_t_handler (vl_api_abf_policy_add_del_t * mp)
97 {
98   vl_api_abf_policy_add_del_reply_t *rmp;
99   fib_route_path_t *paths = NULL, *path;
100   int rv = 0;
101   u8 pi;
102
103   vec_validate (paths, mp->policy.n_paths - 1);
104
105   for (pi = 0; pi < mp->policy.n_paths; pi++)
106     {
107       path = &paths[pi];
108       rv = fib_path_api_parse (&mp->policy.paths[pi], path);
109
110       if (0 != rv)
111         {
112           goto done;
113         }
114     }
115
116   if (mp->is_add)
117     {
118       abf_policy_update (ntohl (mp->policy.policy_id),
119                          ntohl (mp->policy.acl_index), paths);
120     }
121   else
122     {
123       abf_policy_delete (ntohl (mp->policy.policy_id), paths);
124     }
125 done:
126   vec_free (paths);
127
128   REPLY_MACRO (VL_API_ABF_POLICY_ADD_DEL_REPLY + abf_base_msg_id);
129 }
130
131 static void
132 vl_api_abf_itf_attach_add_del_t_handler (vl_api_abf_itf_attach_add_del_t * mp)
133 {
134   vl_api_abf_itf_attach_add_del_reply_t *rmp;
135   fib_protocol_t fproto = (mp->attach.is_ipv6 ?
136                            FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
137   int rv = 0;
138
139   if (mp->is_add)
140     {
141       abf_itf_attach (fproto,
142                       ntohl (mp->attach.policy_id),
143                       ntohl (mp->attach.priority),
144                       ntohl (mp->attach.sw_if_index));
145     }
146   else
147     {
148       abf_itf_detach (fproto,
149                       ntohl (mp->attach.policy_id),
150                       ntohl (mp->attach.sw_if_index));
151     }
152
153   REPLY_MACRO (VL_API_ABF_ITF_ATTACH_ADD_DEL_REPLY + abf_base_msg_id);
154 }
155
156 typedef struct abf_dump_walk_ctx_t_
157 {
158   unix_shared_memory_queue_t *q;
159   u32 context;
160 } abf_dump_walk_ctx_t;
161
162 static int
163 abf_policy_send_details (u32 api, void *args)
164 {
165   fib_route_path_encode_t *api_rpaths = NULL, *api_rpath;
166   vl_api_abf_policy_details_t *mp;
167   abf_dump_walk_ctx_t *ctx;
168   vl_api_fib_path_t *fp;
169   size_t msg_size;
170   abf_policy_t *ap;
171   u8 n_paths;
172
173   ctx = args;
174   ap = abf_policy_get (api);
175   n_paths = fib_path_list_get_n_paths (ap->ap_pl);
176   msg_size = sizeof (*mp) + sizeof (mp->policy.paths[0]) * n_paths;
177
178   mp = vl_msg_api_alloc (msg_size);
179   clib_memset (mp, 0, msg_size);
180   mp->_vl_msg_id = ntohs (VL_API_ABF_POLICY_DETAILS + abf_base_msg_id);
181
182   /* fill in the message */
183   mp->context = ctx->context;
184   mp->policy.n_paths = n_paths;
185   mp->policy.acl_index = htonl (ap->ap_acl);
186   mp->policy.policy_id = htonl (ap->ap_id);
187
188   fib_path_list_walk_w_ext (ap->ap_pl, NULL, fib_path_encode, &api_rpaths);
189
190   fp = mp->policy.paths;
191   vec_foreach (api_rpath, api_rpaths)
192   {
193     fib_api_path_encode (api_rpath, fp);
194     fp++;
195   }
196
197   vl_msg_api_send_shmem (ctx->q, (u8 *) & mp);
198
199   return (1);
200 }
201
202 static void
203 vl_api_abf_policy_dump_t_handler (vl_api_abf_policy_dump_t * mp)
204 {
205   unix_shared_memory_queue_t *q;
206
207   q = vl_api_client_index_to_input_queue (mp->client_index);
208   if (q == 0)
209     {
210       return;
211     }
212
213   abf_dump_walk_ctx_t ctx = {
214     .q = q,
215     .context = mp->context,
216   };
217
218   abf_policy_walk (abf_policy_send_details, &ctx);
219 }
220
221 static int
222 abf_itf_attach_send_details (u32 aiai, void *args)
223 {
224   vl_api_abf_itf_attach_details_t *mp;
225   abf_dump_walk_ctx_t *ctx;
226   abf_itf_attach_t *aia;
227   abf_policy_t *ap;
228
229   ctx = args;
230   aia = abf_itf_attach_get (aiai);
231   ap = abf_policy_get (aia->aia_abf);
232
233   mp = vl_msg_api_alloc (sizeof (*mp));
234   mp->_vl_msg_id = ntohs (VL_API_ABF_ITF_ATTACH_DETAILS + abf_base_msg_id);
235
236   mp->context = ctx->context;
237   mp->attach.policy_id = htonl (ap->ap_id);
238   mp->attach.sw_if_index = htonl (aia->aia_sw_if_index);
239   mp->attach.priority = htonl (aia->aia_prio);
240   mp->attach.is_ipv6 = (aia->aia_proto == FIB_PROTOCOL_IP6);
241
242   vl_msg_api_send_shmem (ctx->q, (u8 *) & mp);
243
244   return (1);
245 }
246
247 static void
248 vl_api_abf_itf_attach_dump_t_handler (vl_api_abf_itf_attach_dump_t * mp)
249 {
250   unix_shared_memory_queue_t *q;
251
252   q = vl_api_client_index_to_input_queue (mp->client_index);
253   if (q == 0)
254     {
255       return;
256     }
257
258   abf_dump_walk_ctx_t ctx = {
259     .q = q,
260     .context = mp->context,
261   };
262
263   abf_itf_attach_walk (abf_itf_attach_send_details, &ctx);
264 }
265
266 #define vl_msg_name_crc_list
267 #include <abf/abf_all_api_h.h>
268 #undef vl_msg_name_crc_list
269
270 /* Set up the API message handling tables */
271 static clib_error_t *
272 abf_plugin_api_hookup (vlib_main_t * vm)
273 {
274 #define _(N,n)                                                  \
275     vl_msg_api_set_handlers((VL_API_##N + abf_base_msg_id),     \
276                             #n,                                 \
277                             vl_api_##n##_t_handler,             \
278                             vl_noop_handler,                    \
279                             vl_api_##n##_t_endian,              \
280                             vl_api_##n##_t_print,               \
281                             sizeof(vl_api_##n##_t), 1);
282   foreach_abf_plugin_api_msg;
283 #undef _
284
285   return 0;
286 }
287
288 static void
289 setup_message_id_table (api_main_t * apim)
290 {
291 #define _(id,n,crc) \
292   vl_msg_api_add_msg_name_crc (apim, #n "_" #crc, id + abf_base_msg_id);
293   foreach_vl_msg_name_crc_abf;
294 #undef _
295 }
296
297 static clib_error_t *
298 abf_api_init (vlib_main_t * vm)
299 {
300   clib_error_t *error = 0;
301
302   u8 *name = format (0, "abf_%08x%c", api_version, 0);
303
304   /* Ask for a correctly-sized block of API message decode slots */
305   abf_base_msg_id = vl_msg_api_get_msg_ids ((char *) name,
306                                             VL_MSG_FIRST_AVAILABLE);
307
308   error = abf_plugin_api_hookup (vm);
309
310   /* Add our API messages to the global name_crc hash table */
311   setup_message_id_table (&api_main);
312
313   vec_free (name);
314
315   return error;
316 }
317
318 VLIB_INIT_FUNCTION (abf_api_init);
319
320 /* *INDENT-OFF* */
321 VLIB_PLUGIN_REGISTER () = {
322     .version = VPP_BUILD_VER,
323     .description = "ACL based Forwarding",
324 };
325 /* *INDENT-ON* */
326
327 /*
328  * fd.io coding-style-patch-verification: ON
329  *
330  * Local Variables:
331  * eval: (c-set-style "gnu")
332  * End:
333  */