FD.io VPP  v19.08-27-gf4dcae4
Vector Packet Processing
flow_api.c
Go to the documentation of this file.
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>
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 
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 _(IPFIX_FLUSH, ipfix_flush)
56 
57 static void
59 {
63  vl_api_set_ipfix_exporter_reply_t *rmp;
64  ip4_address_t collector, src;
65  u16 collector_port = UDP_DST_PORT_ipfix;
66  u32 path_mtu;
67  u32 template_interval;
69  u32 fib_id;
70  u32 fib_index = ~0;
71  int rv = 0;
72 
74  if (!reg)
75  return;
76 
77  memcpy (collector.data, mp->collector_address, sizeof (collector.data));
78  collector_port = ntohs (mp->collector_port);
79  if (collector_port == (u16) ~ 0)
80  collector_port = UDP_DST_PORT_ipfix;
81  memcpy (src.data, mp->src_address, sizeof (src.data));
82  fib_id = ntohl (mp->vrf_id);
83 
84  ip4_main_t *im = &ip4_main;
85  if (fib_id == ~0)
86  {
87  fib_index = ~0;
88  }
89  else
90  {
91  uword *p = hash_get (im->fib_index_by_table_id, fib_id);
92  if (!p)
93  {
94  rv = VNET_API_ERROR_NO_SUCH_FIB;
95  goto out;
96  }
97  fib_index = p[0];
98  }
99 
100  path_mtu = ntohl (mp->path_mtu);
101  if (path_mtu == ~0)
102  path_mtu = 512; // RFC 7011 section 10.3.3.
103  template_interval = ntohl (mp->template_interval);
104  if (template_interval == ~0)
105  template_interval = 20;
106  udp_checksum = mp->udp_checksum;
107 
108  if (collector.as_u32 == 0)
109  {
110  rv = VNET_API_ERROR_INVALID_VALUE;
111  goto out;
112  }
113 
114  if (src.as_u32 == 0)
115  {
116  rv = VNET_API_ERROR_INVALID_VALUE;
117  goto out;
118  }
119 
120  if (path_mtu > 1450 /* vpp does not support fragmentation */ )
121  {
122  rv = VNET_API_ERROR_INVALID_VALUE;
123  goto out;
124  }
125 
126  if (path_mtu < 68)
127  {
128  rv = VNET_API_ERROR_INVALID_VALUE;
129  goto out;
130  }
131 
132  /* Reset report streams if we are reconfiguring IP addresses */
133  if (frm->ipfix_collector.as_u32 != collector.as_u32 ||
134  frm->src_address.as_u32 != src.as_u32 ||
135  frm->collector_port != collector_port)
137 
138  frm->ipfix_collector.as_u32 = collector.as_u32;
139  frm->collector_port = collector_port;
140  frm->src_address.as_u32 = src.as_u32;
141  frm->fib_index = fib_index;
142  frm->path_mtu = path_mtu;
143  frm->template_interval = template_interval;
144  frm->udp_checksum = udp_checksum;
145 
146  /* Turn on the flow reporting process */
148 
149 out:
150  REPLY_MACRO (VL_API_SET_IPFIX_EXPORTER_REPLY);
151 }
152 
153 static void
155 {
159  ip4_main_t *im = &ip4_main;
160  u32 vrf_id;
161 
163  if (!reg)
164  return;
165 
166  rmp = vl_msg_api_alloc (sizeof (*rmp));
167  clib_memset (rmp, 0, sizeof (*rmp));
168  rmp->_vl_msg_id = ntohs (VL_API_IPFIX_EXPORTER_DETAILS);
169  rmp->context = mp->context;
170  memcpy (rmp->collector_address, frm->ipfix_collector.data,
171  sizeof (frm->ipfix_collector.data));
172  rmp->collector_port = htons (frm->collector_port);
173  memcpy (rmp->src_address, frm->src_address.data,
174  sizeof (frm->src_address.data));
175  if (frm->fib_index == ~0)
176  vrf_id = ~0;
177  else
178  vrf_id = im->fibs[frm->fib_index].ft_table_id;
179  rmp->vrf_id = htonl (vrf_id);
180  rmp->path_mtu = htonl (frm->path_mtu);
181  rmp->template_interval = htonl (frm->template_interval);
182  rmp->udp_checksum = (frm->udp_checksum != 0);
183 
184  vl_api_send_msg (reg, (u8 *) rmp);
185 }
186 
187 static void
190 {
191  vl_api_set_ipfix_classify_stream_reply_t *rmp;
194  u32 domain_id = 0;
195  u32 src_port = UDP_DST_PORT_ipfix;
196  int rv = 0;
197 
198  domain_id = ntohl (mp->domain_id);
199  src_port = ntohs (mp->src_port);
200 
201  if (fcm->src_port != 0 &&
202  (fcm->domain_id != domain_id || fcm->src_port != (u16) src_port))
203  {
204  int rv = vnet_stream_change (frm, fcm->domain_id, fcm->src_port,
205  domain_id, (u16) src_port);
206  ASSERT (rv == 0);
207  }
208 
209  fcm->domain_id = domain_id;
210  fcm->src_port = (u16) src_port;
211 
212  REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
213 }
214 
215 static void
218 {
222 
224  if (!reg)
225  return;
226 
227  rmp = vl_msg_api_alloc (sizeof (*rmp));
228  clib_memset (rmp, 0, sizeof (*rmp));
229  rmp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_STREAM_DETAILS);
230  rmp->context = mp->context;
231  rmp->domain_id = htonl (fcm->domain_id);
232  rmp->src_port = htons (fcm->src_port);
233 
234  vl_api_send_msg (reg, (u8 *) rmp);
235 }
236 
237 static void
240 {
241  vl_api_ipfix_classify_table_add_del_reply_t *rmp;
246  ipfix_classify_table_t *table;
247  int is_add;
249  u8 ip_version;
250  u8 transport_protocol;
251  int rv = 0;
252 
254  if (!reg)
255  return;
256 
257  classify_table_index = ntohl (mp->table_id);
258  ip_version = mp->ip_version;
259  transport_protocol = mp->transport_protocol;
260  is_add = mp->is_add;
261 
262  if (fcm->src_port == 0)
263  {
264  /* call set_ipfix_classify_stream first */
265  rv = VNET_API_ERROR_UNSPECIFIED;
266  goto out;
267  }
268 
269  clib_memset (&args, 0, sizeof (args));
270 
271  table = 0;
272  int i;
273  for (i = 0; i < vec_len (fcm->tables); i++)
275  if (fcm->tables[i].classify_table_index == classify_table_index)
276  {
277  table = &fcm->tables[i];
278  break;
279  }
280 
281  if (is_add)
282  {
283  if (table)
284  {
285  rv = VNET_API_ERROR_VALUE_EXIST;
286  goto out;
287  }
288  table = ipfix_classify_add_table ();
290  }
291  else
292  {
293  if (!table)
294  {
295  rv = VNET_API_ERROR_NO_SUCH_ENTRY;
296  goto out;
297  }
298  }
299 
300  table->ip_version = ip_version;
301  table->transport_protocol = transport_protocol;
302 
303  args.opaque.as_uword = table - fcm->tables;
306  args.is_add = is_add;
307  args.domain_id = fcm->domain_id;
308  args.src_port = fcm->src_port;
309 
310  rv = vnet_flow_report_add_del (frm, &args, NULL);
311 
312  /* If deleting, or add failed */
313  if (is_add == 0 || (rv && is_add))
314  ipfix_classify_delete_table (table - fcm->tables);
315 
316 out:
317  REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
318 }
319 
320 static void
323 {
326 
327  ipfix_classify_table_t *table = &fcm->tables[table_index];
328 
329  mp = vl_msg_api_alloc (sizeof (*mp));
330  clib_memset (mp, 0, sizeof (*mp));
331  mp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_TABLE_DETAILS);
332  mp->context = context;
333  mp->table_id = htonl (table->classify_table_index);
334  mp->ip_version = table->ip_version;
336 
337  vl_api_send_msg (reg, (u8 *) mp);
338 }
339 
340 static void
343 {
346  u32 i;
347 
349  if (!reg)
350  return;
351 
352  for (i = 0; i < vec_len (fcm->tables); i++)
355 }
356 
357 static void
359 {
360  vl_api_ipfix_flush_reply_t *rmp;
363  int rv = 0;
364 
366  if (!reg)
367  return;
368 
369  /* poke the flow reporting process */
371  1 /* type_opaque */ , 0 /* data */ );
372 
373  REPLY_MACRO (VL_API_IPFIX_FLUSH_REPLY);
374 }
375 
376 /*
377  * flow_api_hookup
378  * Add vpe's API message handlers to the table.
379  * vlib has already mapped shared memory and
380  * added the client registration handlers.
381  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
382  */
383 #define vl_msg_name_crc_list
384 #include <vnet/vnet_all_api_h.h>
385 #undef vl_msg_name_crc_list
386 
387 static void
389 {
390 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
391  foreach_vl_msg_name_crc_ipfix_export;
392 #undef _
393 }
394 
395 static clib_error_t *
397 {
398  api_main_t *am = &api_main;
399 
400 #define _(N,n) \
401  vl_msg_api_set_handlers(VL_API_##N, #n, \
402  vl_api_##n##_t_handler, \
403  vl_noop_handler, \
404  vl_api_##n##_t_endian, \
405  vl_api_##n##_t_print, \
406  sizeof(vl_api_##n##_t), 1);
408 #undef _
409 
410  /*
411  * Set up the (msg_name, crc, message-id) table
412  */
414 
415  return 0;
416 }
417 
419 
420 /*
421  * fd.io coding-style-patch-verification: ON
422  *
423  * Local Variables:
424  * eval: (c-set-style "gnu")
425  * End:
426  */
IPFIX classify tables dump request.
static clib_error_t * flow_api_hookup(vlib_main_t *vm)
Definition: flow_api.c:396
vlib_node_registration_t flow_report_process_node
(constructor) VLIB_REGISTER_NODE (flow_report_process_node)
Definition: flow_report.c:326
u16 udp_checksum(udp_header_t *uh, u32 udp_len, void *ih, u8 version)
Definition: packets.c:114
static_always_inline void ipfix_classify_delete_table(u32 index)
uword as_uword
Definition: flow_report.h:74
static_always_inline u8 ipfix_classify_table_index_valid(u32 index)
#define NULL
Definition: clib.h:58
Reply to IPFIX classify tables dump request.
static void vl_api_send_msg(vl_api_registration_t *rp, u8 *elem)
Definition: api.h:34
int vnet_flow_report_add_del(flow_report_main_t *frm, vnet_flow_report_add_del_args_t *a, u16 *template_id)
Definition: flow_report.c:334
IPFIX exporter dump request.
vl_api_address_t src
Definition: gre.api:51
int i
ip4_address_t src_address
Definition: flow_report.h:119
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
void * vl_msg_api_alloc(int nbytes)
unsigned char u8
Definition: types.h:56
ip4_address_t ipfix_collector
Definition: flow_report.h:117
u16 src_port
Definition: udp.api:41
static void vl_api_ipfix_classify_table_dump_t_handler(vl_api_ipfix_classify_table_dump_t *mp)
Definition: flow_api.c:342
vnet_flow_rewrite_callback_t * rewrite_callback
Definition: flow_report.h:149
unsigned int u32
Definition: types.h:88
Reply to IPFIX exporter dump request.
flow_report_main_t flow_report_main
Definition: flow_report.c:21
#define hash_get(h, key)
Definition: hash.h:249
flow_report_classify_main_t flow_report_classify_main
uword * fib_index_by_table_id
Hash table mapping table id to fib index.
Definition: ip4.h:131
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:934
unsigned short u16
Definition: types.h:57
#define REPLY_MACRO(t)
static void setup_message_id_table(api_main_t *am)
Definition: flow_api.c:388
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:203
An API client registration, only in vpp/vlib.
Definition: api_common.h:46
u32 classify_table_index
Definition: fib_types.api:68
IPFIX classify stream configure request.
static void vl_api_ipfix_classify_table_add_del_t_handler(vl_api_ipfix_classify_table_add_del_t *mp)
Definition: flow_api.c:239
ipfix_classify_table_t * tables
static void vl_api_set_ipfix_exporter_t_handler(vl_api_set_ipfix_exporter_t *mp)
Definition: flow_api.c:58
u32 ft_table_id
Table ID (hash key) for this FIB.
Definition: fib_table.h:89
vlib_main_t * vm
Definition: buffer.c:312
static void vl_api_set_ipfix_classify_stream_t_handler(vl_api_set_ipfix_classify_stream_t *mp)
Definition: flow_api.c:189
static vl_api_registration_t * vl_api_client_index_to_registration(u32 index)
Definition: api.h:56
static_always_inline ipfix_classify_table_t * ipfix_classify_add_table(void)
static void vl_api_ipfix_exporter_dump_t_handler(vl_api_ipfix_exporter_dump_t *mp)
Definition: flow_api.c:154
#define ASSERT(truth)
IPv4 main type.
Definition: ip4.h:105
static void vl_api_ipfix_classify_stream_dump_t_handler(vl_api_ipfix_classify_stream_dump_t *mp)
Definition: flow_api.c:217
void vnet_flow_reports_reset(flow_report_main_t *frm)
Definition: flow_report.c:435
VLIB_API_INIT_FUNCTION(flow_api_hookup)
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static void vl_api_ipfix_flush_t_handler(vl_api_ipfix_flush_t *mp)
Definition: flow_api.c:358
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
Reply to IPFIX classify stream dump request.
int vnet_stream_change(flow_report_main_t *frm, u32 old_domain_id, u16 old_src_port, u32 new_domain_id, u16 new_src_port)
Definition: flow_report.c:467
Configure IPFIX exporter process request.
u64 uword
Definition: types.h:112
vnet_flow_data_callback_t * flow_data_callback
Definition: flow_report.h:148
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:921
struct fib_table_t_ * fibs
Vector of FIBs.
Definition: ip4.h:110
IPFIX classify stream dump request.
#define foreach_vpe_api_msg
Definition: flow_api.c:48
u32 context
Definition: gre.api:45
api_main_t api_main
Definition: api_shared.c:35
static void send_ipfix_classify_table_details(u32 table_index, vl_api_registration_t *reg, u32 context)
Definition: flow_api.c:321
vlib_frame_t * ipfix_classify_send_flows(flow_report_main_t *frm, flow_report_t *fr, vlib_frame_t *f, u32 *to_next, u32 node_index)
IPFIX add or delete classifier table request.
u8 * ipfix_classify_template_rewrite(flow_report_main_t *frm, flow_report_t *fr, ip4_address_t *collector_address, ip4_address_t *src_address, u16 collector_port, ipfix_report_element_t *elts, u32 n_elts, u32 *stream_index)