222e1f4e11619a4cc3051a14d0eca540715ac21a
[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 <vnet/format_fns.h>
33 #include <abf/abf.api_enum.h>
34 #include <abf/abf.api_types.h>
35
36 /**
37  * Base message ID for the plugin
38  */
39 static u32 abf_base_msg_id;
40
41 #define REPLY_MSG_ID_BASE (abf_base_msg_id)
42 #include <vlibapi/api_helper_macros.h>
43
44 static void
45 vl_api_abf_plugin_get_version_t_handler (vl_api_abf_plugin_get_version_t * mp)
46 {
47   vl_api_abf_plugin_get_version_reply_t *rmp;
48   vl_api_registration_t *rp;
49
50   rp = vl_api_client_index_to_registration (mp->client_index);
51   if (rp == 0)
52     return;
53
54   rmp = vl_msg_api_alloc (sizeof (*rmp));
55   rmp->_vl_msg_id =
56     ntohs (VL_API_ABF_PLUGIN_GET_VERSION_REPLY + abf_base_msg_id);
57   rmp->context = mp->context;
58   rmp->major = htonl (ABF_PLUGIN_VERSION_MAJOR);
59   rmp->minor = htonl (ABF_PLUGIN_VERSION_MINOR);
60
61   vl_api_send_msg (rp, (u8 *) rmp);
62 }
63
64 static void
65 vl_api_abf_policy_add_del_t_handler (vl_api_abf_policy_add_del_t * mp)
66 {
67   vl_api_abf_policy_add_del_reply_t *rmp;
68   fib_route_path_t *paths = NULL, *path;
69   int rv = 0;
70   u8 pi;
71
72   if (mp->policy.n_paths == 0)
73     {
74       rv = VNET_API_ERROR_INVALID_VALUE;
75       goto done;
76     }
77
78   vec_validate (paths, mp->policy.n_paths - 1);
79
80   for (pi = 0; pi < mp->policy.n_paths; pi++)
81     {
82       path = &paths[pi];
83       rv = fib_api_path_decode (&mp->policy.paths[pi], path);
84
85       if (0 != rv)
86         {
87           goto done;
88         }
89     }
90
91   if (mp->is_add)
92     {
93       rv = abf_policy_update (ntohl (mp->policy.policy_id),
94                               ntohl (mp->policy.acl_index), paths);
95     }
96   else
97     {
98       rv = abf_policy_delete (ntohl (mp->policy.policy_id), paths);
99     }
100 done:
101   vec_free (paths);
102
103   REPLY_MACRO (VL_API_ABF_POLICY_ADD_DEL_REPLY);
104 }
105
106 static void
107 vl_api_abf_itf_attach_add_del_t_handler (vl_api_abf_itf_attach_add_del_t * mp)
108 {
109   vl_api_abf_itf_attach_add_del_reply_t *rmp;
110   fib_protocol_t fproto = (mp->attach.is_ipv6 ?
111                            FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
112   int rv = 0;
113
114   if (mp->is_add)
115     {
116       abf_itf_attach (fproto,
117                       ntohl (mp->attach.policy_id),
118                       ntohl (mp->attach.priority),
119                       ntohl (mp->attach.sw_if_index));
120     }
121   else
122     {
123       abf_itf_detach (fproto,
124                       ntohl (mp->attach.policy_id),
125                       ntohl (mp->attach.sw_if_index));
126     }
127
128   REPLY_MACRO (VL_API_ABF_ITF_ATTACH_ADD_DEL_REPLY);
129 }
130
131 typedef struct abf_dump_walk_ctx_t_
132 {
133   vl_api_registration_t *rp;
134   u32 context;
135 } abf_dump_walk_ctx_t;
136
137 static int
138 abf_policy_send_details (u32 api, void *args)
139 {
140   fib_path_encode_ctx_t walk_ctx = {
141     .rpaths = NULL,
142   };
143   vl_api_abf_policy_details_t *mp;
144   abf_dump_walk_ctx_t *ctx;
145   fib_route_path_t *rpath;
146   vl_api_fib_path_t *fp;
147   size_t msg_size;
148   abf_policy_t *ap;
149   u8 n_paths;
150
151   ctx = args;
152   ap = abf_policy_get (api);
153   n_paths = fib_path_list_get_n_paths (ap->ap_pl);
154   msg_size = sizeof (*mp) + sizeof (mp->policy.paths[0]) * n_paths;
155
156   mp = vl_msg_api_alloc (msg_size);
157   clib_memset (mp, 0, msg_size);
158   mp->_vl_msg_id = ntohs (VL_API_ABF_POLICY_DETAILS + abf_base_msg_id);
159
160   /* fill in the message */
161   mp->context = ctx->context;
162   mp->policy.n_paths = n_paths;
163   mp->policy.acl_index = htonl (ap->ap_acl);
164   mp->policy.policy_id = htonl (ap->ap_id);
165
166   fib_path_list_walk_w_ext (ap->ap_pl, NULL, fib_path_encode, &walk_ctx);
167
168   fp = mp->policy.paths;
169   vec_foreach (rpath, walk_ctx.rpaths)
170   {
171     fib_api_path_encode (rpath, fp);
172     fp++;
173   }
174
175   vl_api_send_msg (ctx->rp, (u8 *) mp);
176
177   vec_free (walk_ctx.rpaths);
178
179   return (1);
180 }
181
182 static void
183 vl_api_abf_policy_dump_t_handler (vl_api_abf_policy_dump_t * mp)
184 {
185   vl_api_registration_t *rp;
186
187   rp = vl_api_client_index_to_registration (mp->client_index);
188   if (rp == 0)
189     return;
190
191   abf_dump_walk_ctx_t ctx = {
192     .rp = rp,
193     .context = mp->context,
194   };
195
196   abf_policy_walk (abf_policy_send_details, &ctx);
197 }
198
199 static int
200 abf_itf_attach_send_details (u32 aiai, void *args)
201 {
202   vl_api_abf_itf_attach_details_t *mp;
203   abf_dump_walk_ctx_t *ctx;
204   abf_itf_attach_t *aia;
205   abf_policy_t *ap;
206
207   ctx = args;
208   aia = abf_itf_attach_get (aiai);
209   ap = abf_policy_get (aia->aia_abf);
210
211   mp = vl_msg_api_alloc (sizeof (*mp));
212   mp->_vl_msg_id = ntohs (VL_API_ABF_ITF_ATTACH_DETAILS + abf_base_msg_id);
213
214   mp->context = ctx->context;
215   mp->attach.policy_id = htonl (ap->ap_id);
216   mp->attach.sw_if_index = htonl (aia->aia_sw_if_index);
217   mp->attach.priority = htonl (aia->aia_prio);
218   mp->attach.is_ipv6 = (aia->aia_proto == FIB_PROTOCOL_IP6);
219
220   vl_api_send_msg (ctx->rp, (u8 *) mp);
221
222   return (1);
223 }
224
225 static void
226 vl_api_abf_itf_attach_dump_t_handler (vl_api_abf_itf_attach_dump_t * mp)
227 {
228   vl_api_registration_t *rp;
229
230   rp = vl_api_client_index_to_registration (mp->client_index);
231   if (rp == 0)
232     return;
233
234   abf_dump_walk_ctx_t ctx = {
235     .rp = rp,
236     .context = mp->context,
237   };
238
239   abf_itf_attach_walk (abf_itf_attach_send_details, &ctx);
240 }
241
242 #include <abf/abf.api.c>
243
244 static clib_error_t *
245 abf_api_init (vlib_main_t * vm)
246 {
247   /* Ask for a correctly-sized block of API message decode slots */
248   abf_base_msg_id = setup_message_id_table ();
249
250   return 0;
251 }
252
253 VLIB_INIT_FUNCTION (abf_api_init);
254
255 /* *INDENT-OFF* */
256 VLIB_PLUGIN_REGISTER () = {
257     .version = VPP_BUILD_VER,
258     .description = "Access Control List (ACL) Based Forwarding",
259 };
260 /* *INDENT-ON* */
261
262 /*
263  * fd.io coding-style-patch-verification: ON
264  *
265  * Local Variables:
266  * eval: (c-set-style "gnu")
267  * End:
268  */