build-data: Common makefile for NXP DPAA1/DPAA2 platforms
[vpp.git] / src / vnet / flow / flow_api.c
1 /*
2  *------------------------------------------------------------------
3  * flow_api.c - flow api
4  *
5  * Copyright (c) 2016 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19
20 #include <vnet/vnet.h>
21 #include <vlibmemory/api.h>
22
23 #include <vnet/interface.h>
24 #include <vnet/api_errno.h>
25
26 #include <vnet/fib/fib_table.h>
27 #include <vnet/flow/flow_report.h>
28 #include <vnet/flow/flow_report_classify.h>
29
30 #include <vnet/vnet_msg_enum.h>
31
32 #define vl_typedefs             /* define message structures */
33 #include <vnet/vnet_all_api_h.h>
34 #undef vl_typedefs
35
36 #define vl_endianfun            /* define message structures */
37 #include <vnet/vnet_all_api_h.h>
38 #undef vl_endianfun
39
40 /* instantiate all the print functions we know about */
41 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
42 #define vl_printfun
43 #include <vnet/vnet_all_api_h.h>
44 #undef vl_printfun
45
46 #include <vlibapi/api_helper_macros.h>
47
48 #define foreach_vpe_api_msg                                             \
49 _(SET_IPFIX_EXPORTER, set_ipfix_exporter)                               \
50 _(IPFIX_EXPORTER_DUMP, ipfix_exporter_dump)                             \
51 _(SET_IPFIX_CLASSIFY_STREAM, set_ipfix_classify_stream)                 \
52 _(IPFIX_CLASSIFY_STREAM_DUMP, ipfix_classify_stream_dump)               \
53 _(IPFIX_CLASSIFY_TABLE_ADD_DEL, ipfix_classify_table_add_del)           \
54 _(IPFIX_CLASSIFY_TABLE_DUMP, ipfix_classify_table_dump)
55
56 static void
57 vl_api_set_ipfix_exporter_t_handler (vl_api_set_ipfix_exporter_t * mp)
58 {
59   vlib_main_t *vm = vlib_get_main ();
60   flow_report_main_t *frm = &flow_report_main;
61   vl_api_set_ipfix_exporter_reply_t *rmp;
62   ip4_address_t collector, src;
63   u16 collector_port = UDP_DST_PORT_ipfix;
64   u32 path_mtu;
65   u32 template_interval;
66   u8 udp_checksum;
67   u32 fib_id;
68   u32 fib_index = ~0;
69   int rv = 0;
70
71   memcpy (collector.data, mp->collector_address, sizeof (collector.data));
72   collector_port = ntohs (mp->collector_port);
73   if (collector_port == (u16) ~ 0)
74     collector_port = UDP_DST_PORT_ipfix;
75   memcpy (src.data, mp->src_address, sizeof (src.data));
76   fib_id = ntohl (mp->vrf_id);
77
78   ip4_main_t *im = &ip4_main;
79   if (fib_id == ~0)
80     {
81       fib_index = ~0;
82     }
83   else
84     {
85       uword *p = hash_get (im->fib_index_by_table_id, fib_id);
86       if (!p)
87         {
88           rv = VNET_API_ERROR_NO_SUCH_FIB;
89           goto out;
90         }
91       fib_index = p[0];
92     }
93
94   path_mtu = ntohl (mp->path_mtu);
95   if (path_mtu == ~0)
96     path_mtu = 512;             // RFC 7011 section 10.3.3.
97   template_interval = ntohl (mp->template_interval);
98   if (template_interval == ~0)
99     template_interval = 20;
100   udp_checksum = mp->udp_checksum;
101
102   if (collector.as_u32 == 0)
103     {
104       rv = VNET_API_ERROR_INVALID_VALUE;
105       goto out;
106     }
107
108   if (src.as_u32 == 0)
109     {
110       rv = VNET_API_ERROR_INVALID_VALUE;
111       goto out;
112     }
113
114   if (path_mtu > 1450 /* vpp does not support fragmentation */ )
115     {
116       rv = VNET_API_ERROR_INVALID_VALUE;
117       goto out;
118     }
119
120   if (path_mtu < 68)
121     {
122       rv = VNET_API_ERROR_INVALID_VALUE;
123       goto out;
124     }
125
126   /* Reset report streams if we are reconfiguring IP addresses */
127   if (frm->ipfix_collector.as_u32 != collector.as_u32 ||
128       frm->src_address.as_u32 != src.as_u32 ||
129       frm->collector_port != collector_port)
130     vnet_flow_reports_reset (frm);
131
132   frm->ipfix_collector.as_u32 = collector.as_u32;
133   frm->collector_port = collector_port;
134   frm->src_address.as_u32 = src.as_u32;
135   frm->fib_index = fib_index;
136   frm->path_mtu = path_mtu;
137   frm->template_interval = template_interval;
138   frm->udp_checksum = udp_checksum;
139
140   /* Turn on the flow reporting process */
141   vlib_process_signal_event (vm, flow_report_process_node.index, 1, 0);
142
143 out:
144   REPLY_MACRO (VL_API_SET_IPFIX_EXPORTER_REPLY);
145 }
146
147 static void
148 vl_api_ipfix_exporter_dump_t_handler (vl_api_ipfix_exporter_dump_t * mp)
149 {
150   flow_report_main_t *frm = &flow_report_main;
151   vl_api_registration_t *reg;
152   vl_api_ipfix_exporter_details_t *rmp;
153   ip4_main_t *im = &ip4_main;
154   u32 vrf_id;
155
156   reg = vl_api_client_index_to_registration (mp->client_index);
157   if (!reg)
158     return;;
159
160   rmp = vl_msg_api_alloc (sizeof (*rmp));
161   memset (rmp, 0, sizeof (*rmp));
162   rmp->_vl_msg_id = ntohs (VL_API_IPFIX_EXPORTER_DETAILS);
163   rmp->context = mp->context;
164   memcpy (rmp->collector_address, frm->ipfix_collector.data,
165           sizeof (frm->ipfix_collector.data));
166   rmp->collector_port = htons (frm->collector_port);
167   memcpy (rmp->src_address, frm->src_address.data,
168           sizeof (frm->src_address.data));
169   if (frm->fib_index == ~0)
170     vrf_id = ~0;
171   else
172     vrf_id = im->fibs[frm->fib_index].ft_table_id;
173   rmp->vrf_id = htonl (vrf_id);
174   rmp->path_mtu = htonl (frm->path_mtu);
175   rmp->template_interval = htonl (frm->template_interval);
176   rmp->udp_checksum = (frm->udp_checksum != 0);
177
178   vl_api_send_msg (reg, (u8 *) rmp);
179 }
180
181 static void
182   vl_api_set_ipfix_classify_stream_t_handler
183   (vl_api_set_ipfix_classify_stream_t * mp)
184 {
185   vl_api_set_ipfix_classify_stream_reply_t *rmp;
186   flow_report_classify_main_t *fcm = &flow_report_classify_main;
187   flow_report_main_t *frm = &flow_report_main;
188   u32 domain_id = 0;
189   u32 src_port = UDP_DST_PORT_ipfix;
190   int rv = 0;
191
192   domain_id = ntohl (mp->domain_id);
193   src_port = ntohs (mp->src_port);
194
195   if (fcm->src_port != 0 &&
196       (fcm->domain_id != domain_id || fcm->src_port != (u16) src_port))
197     {
198       int rv = vnet_stream_change (frm, fcm->domain_id, fcm->src_port,
199                                    domain_id, (u16) src_port);
200       ASSERT (rv == 0);
201     }
202
203   fcm->domain_id = domain_id;
204   fcm->src_port = (u16) src_port;
205
206   REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
207 }
208
209 static void
210   vl_api_ipfix_classify_stream_dump_t_handler
211   (vl_api_ipfix_classify_stream_dump_t * mp)
212 {
213   flow_report_classify_main_t *fcm = &flow_report_classify_main;
214   vl_api_registration_t *reg;
215   vl_api_ipfix_classify_stream_details_t *rmp;
216
217   reg = vl_api_client_index_to_registration (mp->client_index);
218   if (!reg)
219     return;
220
221   rmp = vl_msg_api_alloc (sizeof (*rmp));
222   memset (rmp, 0, sizeof (*rmp));
223   rmp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_STREAM_DETAILS);
224   rmp->context = mp->context;
225   rmp->domain_id = htonl (fcm->domain_id);
226   rmp->src_port = htons (fcm->src_port);
227
228   vl_api_send_msg (reg, (u8 *) rmp);
229 }
230
231 static void
232   vl_api_ipfix_classify_table_add_del_t_handler
233   (vl_api_ipfix_classify_table_add_del_t * mp)
234 {
235   vl_api_ipfix_classify_table_add_del_reply_t *rmp;
236   flow_report_classify_main_t *fcm = &flow_report_classify_main;
237   flow_report_main_t *frm = &flow_report_main;
238   vnet_flow_report_add_del_args_t args;
239   ipfix_classify_table_t *table;
240   int is_add;
241   u32 classify_table_index;
242   u8 ip_version;
243   u8 transport_protocol;
244   int rv = 0;
245
246   classify_table_index = ntohl (mp->table_id);
247   ip_version = mp->ip_version;
248   transport_protocol = mp->transport_protocol;
249   is_add = mp->is_add;
250
251   if (fcm->src_port == 0)
252     {
253       /* call set_ipfix_classify_stream first */
254       rv = VNET_API_ERROR_UNSPECIFIED;
255       goto out;
256     }
257
258   memset (&args, 0, sizeof (args));
259
260   table = 0;
261   int i;
262   for (i = 0; i < vec_len (fcm->tables); i++)
263     if (ipfix_classify_table_index_valid (i))
264       if (fcm->tables[i].classify_table_index == classify_table_index)
265         {
266           table = &fcm->tables[i];
267           break;
268         }
269
270   if (is_add)
271     {
272       if (table)
273         {
274           rv = VNET_API_ERROR_VALUE_EXIST;
275           goto out;
276         }
277       table = ipfix_classify_add_table ();
278       table->classify_table_index = classify_table_index;
279     }
280   else
281     {
282       if (!table)
283         {
284           rv = VNET_API_ERROR_NO_SUCH_ENTRY;
285           goto out;
286         }
287     }
288
289   table->ip_version = ip_version;
290   table->transport_protocol = transport_protocol;
291
292   args.opaque.as_uword = table - fcm->tables;
293   args.rewrite_callback = ipfix_classify_template_rewrite;
294   args.flow_data_callback = ipfix_classify_send_flows;
295   args.is_add = is_add;
296   args.domain_id = fcm->domain_id;
297   args.src_port = fcm->src_port;
298
299   rv = vnet_flow_report_add_del (frm, &args, NULL);
300
301   /* If deleting, or add failed */
302   if (is_add == 0 || (rv && is_add))
303     ipfix_classify_delete_table (table - fcm->tables);
304
305 out:
306   REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
307 }
308
309 static void
310 send_ipfix_classify_table_details (u32 table_index,
311                                    vl_api_registration_t * reg, u32 context)
312 {
313   flow_report_classify_main_t *fcm = &flow_report_classify_main;
314   vl_api_ipfix_classify_table_details_t *mp;
315
316   ipfix_classify_table_t *table = &fcm->tables[table_index];
317
318   mp = vl_msg_api_alloc (sizeof (*mp));
319   memset (mp, 0, sizeof (*mp));
320   mp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_TABLE_DETAILS);
321   mp->context = context;
322   mp->table_id = htonl (table->classify_table_index);
323   mp->ip_version = table->ip_version;
324   mp->transport_protocol = table->transport_protocol;
325
326   vl_api_send_msg (reg, (u8 *) mp);
327 }
328
329 static void
330   vl_api_ipfix_classify_table_dump_t_handler
331   (vl_api_ipfix_classify_table_dump_t * mp)
332 {
333   flow_report_classify_main_t *fcm = &flow_report_classify_main;
334   vl_api_registration_t *reg;
335   u32 i;
336
337   reg = vl_api_client_index_to_registration (mp->client_index);
338   if (!reg)
339     return;
340
341   for (i = 0; i < vec_len (fcm->tables); i++)
342     if (ipfix_classify_table_index_valid (i))
343       send_ipfix_classify_table_details (i, reg, mp->context);
344 }
345
346 /*
347  * flow_api_hookup
348  * Add vpe's API message handlers to the table.
349  * vlib has alread mapped shared memory and
350  * added the client registration handlers.
351  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
352  */
353 #define vl_msg_name_crc_list
354 #include <vnet/vnet_all_api_h.h>
355 #undef vl_msg_name_crc_list
356
357 static void
358 setup_message_id_table (api_main_t * am)
359 {
360 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
361   foreach_vl_msg_name_crc_flow;
362 #undef _
363 }
364
365 static clib_error_t *
366 flow_api_hookup (vlib_main_t * vm)
367 {
368   api_main_t *am = &api_main;
369
370 #define _(N,n)                                                  \
371     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
372                            vl_api_##n##_t_handler,              \
373                            vl_noop_handler,                     \
374                            vl_api_##n##_t_endian,               \
375                            vl_api_##n##_t_print,                \
376                            sizeof(vl_api_##n##_t), 1);
377   foreach_vpe_api_msg;
378 #undef _
379
380   /*
381    * Set up the (msg_name, crc, message-id) table
382    */
383   setup_message_id_table (am);
384
385   return 0;
386 }
387
388 VLIB_API_INIT_FUNCTION (flow_api_hookup);
389
390 /*
391  * fd.io coding-style-patch-verification: ON
392  *
393  * Local Variables:
394  * eval: (c-set-style "gnu")
395  * End:
396  */