abf_api.c revision 1d1985de
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 */
58static 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
71static void
72vl_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
91static void
92vl_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_path_api_parse (&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    }
121done:
122  vec_free (paths);
123
124  REPLY_MACRO (VL_API_ABF_POLICY_ADD_DEL_REPLY + abf_base_msg_id);
125}
126
127static void
128vl_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
152typedef struct abf_dump_walk_ctx_t_
153{
154  vl_api_registration_t *rp;
155  u32 context;
156} abf_dump_walk_ctx_t;
157
158static int
159abf_policy_send_details (u32 api, void *args)
160{
161  fib_route_path_encode_t *api_rpaths = NULL, *api_rpath;
162  vl_api_abf_policy_details_t *mp;
163  abf_dump_walk_ctx_t *ctx;
164  vl_api_fib_path_t *fp;
165  size_t msg_size;
166  abf_policy_t *ap;
167  u8 n_paths;
168
169  ctx = args;
170  ap = abf_policy_get (api);
171  n_paths = fib_path_list_get_n_paths (ap->ap_pl);
172  msg_size = sizeof (*mp) + sizeof (mp->policy.paths[0]) * n_paths;
173
174  mp = vl_msg_api_alloc (msg_size);
175  clib_memset (mp, 0, msg_size);
176  mp->_vl_msg_id = ntohs (VL_API_ABF_POLICY_DETAILS + abf_base_msg_id);
177
178  /* fill in the message */
179  mp->context = ctx->context;
180  mp->policy.n_paths = n_paths;
181  mp->policy.acl_index = htonl (ap->ap_acl);
182  mp->policy.policy_id = htonl (ap->ap_id);
183
184  fib_path_list_walk_w_ext (ap->ap_pl, NULL, fib_path_encode, &api_rpaths);
185
186  fp = mp->policy.paths;
187  vec_foreach (api_rpath, api_rpaths)
188  {
189    fib_api_path_encode (api_rpath, fp);
190    fp++;
191  }
192
193  vl_api_send_msg (ctx->rp, (u8 *) mp);
194
195  return (1);
196}
197
198static void
199vl_api_abf_policy_dump_t_handler (vl_api_abf_policy_dump_t * mp)
200{
201  vl_api_registration_t *rp;
202
203  rp = vl_api_client_index_to_registration (mp->client_index);
204  if (rp == 0)
205    return;
206
207  abf_dump_walk_ctx_t ctx = {
208    .rp = rp,
209    .context = mp->context,
210  };
211
212  abf_policy_walk (abf_policy_send_details, &ctx);
213}
214
215static int
216abf_itf_attach_send_details (u32 aiai, void *args)
217{
218  vl_api_abf_itf_attach_details_t *mp;
219  abf_dump_walk_ctx_t *ctx;
220  abf_itf_attach_t *aia;
221  abf_policy_t *ap;
222
223  ctx = args;
224  aia = abf_itf_attach_get (aiai);
225  ap = abf_policy_get (aia->aia_abf);
226
227  mp = vl_msg_api_alloc (sizeof (*mp));
228  mp->_vl_msg_id = ntohs (VL_API_ABF_ITF_ATTACH_DETAILS + abf_base_msg_id);
229
230  mp->context = ctx->context;
231  mp->attach.policy_id = htonl (ap->ap_id);
232  mp->attach.sw_if_index = htonl (aia->aia_sw_if_index);
233  mp->attach.priority = htonl (aia->aia_prio);
234  mp->attach.is_ipv6 = (aia->aia_proto == FIB_PROTOCOL_IP6);
235
236  vl_api_send_msg (ctx->rp, (u8 *) mp);
237
238  return (1);
239}
240
241static void
242vl_api_abf_itf_attach_dump_t_handler (vl_api_abf_itf_attach_dump_t * mp)
243{
244  vl_api_registration_t *rp;
245
246  rp = vl_api_client_index_to_registration (mp->client_index);
247  if (rp == 0)
248    return;
249
250  abf_dump_walk_ctx_t ctx = {
251    .rp = rp,
252    .context = mp->context,
253  };
254
255  abf_itf_attach_walk (abf_itf_attach_send_details, &ctx);
256}
257
258#define vl_msg_name_crc_list
259#include <abf/abf_all_api_h.h>
260#undef vl_msg_name_crc_list
261
262/* Set up the API message handling tables */
263static clib_error_t *
264abf_plugin_api_hookup (vlib_main_t * vm)
265{
266#define _(N,n)                                                  \
267    vl_msg_api_set_handlers((VL_API_##N + abf_base_msg_id),     \
268                            #n,					\
269                            vl_api_##n##_t_handler,             \
270                            vl_noop_handler,                    \
271                            vl_api_##n##_t_endian,              \
272                            vl_api_##n##_t_print,               \
273                            sizeof(vl_api_##n##_t), 1);
274  foreach_abf_plugin_api_msg;
275#undef _
276
277  return 0;
278}
279
280static void
281setup_message_id_table (api_main_t * apim)
282{
283#define _(id,n,crc) \
284  vl_msg_api_add_msg_name_crc (apim, #n "_" #crc, id + abf_base_msg_id);
285  foreach_vl_msg_name_crc_abf;
286#undef _
287}
288
289static clib_error_t *
290abf_api_init (vlib_main_t * vm)
291{
292  clib_error_t *error = 0;
293
294  u8 *name = format (0, "abf_%08x%c", api_version, 0);
295
296  /* Ask for a correctly-sized block of API message decode slots */
297  abf_base_msg_id = vl_msg_api_get_msg_ids ((char *) name,
298					    VL_MSG_FIRST_AVAILABLE);
299
300  error = abf_plugin_api_hookup (vm);
301
302  /* Add our API messages to the global name_crc hash table */
303  setup_message_id_table (&api_main);
304
305  vec_free (name);
306
307  return error;
308}
309
310VLIB_INIT_FUNCTION (abf_api_init);
311
312/* *INDENT-OFF* */
313VLIB_PLUGIN_REGISTER () = {
314    .version = VPP_BUILD_VER,
315    .description = "Access Control List (ACL) Based Forwarding",
316};
317/* *INDENT-ON* */
318
319/*
320 * fd.io coding-style-patch-verification: ON
321 *
322 * Local Variables:
323 * eval: (c-set-style "gnu")
324 * End:
325 */
326