FD.io VPP  v20.01-48-g3e0dafb74
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 #include <vnet/ip/ip_types_api.h>
23 
24 #include <vnet/interface.h>
25 #include <vnet/api_errno.h>
26 
27 #include <vnet/fib/fib_table.h>
30 
31 #include <vnet/vnet_msg_enum.h>
32 
33 #define vl_typedefs /* define message structures */
34 #include <vnet/vnet_all_api_h.h>
35 #undef vl_typedefs
36 
37 #define vl_endianfun /* define message structures */
38 #include <vnet/vnet_all_api_h.h>
39 #undef vl_endianfun
40 
41 /* instantiate all the print functions we know about */
42 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
43 #define vl_printfun
44 #include <vnet/vnet_all_api_h.h>
45 #undef vl_printfun
46 
48 
49 #define foreach_vpe_api_msg \
50 _(SET_IPFIX_EXPORTER, set_ipfix_exporter) \
51 _(IPFIX_EXPORTER_DUMP, ipfix_exporter_dump) \
52 _(SET_IPFIX_CLASSIFY_STREAM, set_ipfix_classify_stream) \
53 _(IPFIX_CLASSIFY_STREAM_DUMP, ipfix_classify_stream_dump) \
54 _(IPFIX_CLASSIFY_TABLE_ADD_DEL, ipfix_classify_table_add_del) \
55 _(IPFIX_CLASSIFY_TABLE_DUMP, ipfix_classify_table_dump) \
56 _(IPFIX_FLUSH, ipfix_flush)
57 
58 static void
60 {
64  vl_api_set_ipfix_exporter_reply_t *rmp;
65  ip4_address_t collector, src;
66  u16 collector_port = UDP_DST_PORT_ipfix;
67  u32 path_mtu;
68  u32 template_interval;
70  u32 fib_id;
71  u32 fib_index = ~0;
72  int rv = 0;
73 
75  if (!reg)
76  return;
77 
78  if (mp->src_address.af == ADDRESS_IP6
79  || mp->collector_address.af == ADDRESS_IP6)
80  {
81  rv = VNET_API_ERROR_UNIMPLEMENTED;
82  goto out;
83  }
84 
85  ip4_address_decode (mp->collector_address.un.ip4, &collector);
86  collector_port = ntohs (mp->collector_port);
87  if (collector_port == (u16) ~ 0)
88  collector_port = UDP_DST_PORT_ipfix;
89  ip4_address_decode (mp->src_address.un.ip4, &src);
90  fib_id = ntohl (mp->vrf_id);
91 
92  ip4_main_t *im = &ip4_main;
93  if (fib_id == ~0)
94  {
95  fib_index = ~0;
96  }
97  else
98  {
99  uword *p = hash_get (im->fib_index_by_table_id, fib_id);
100  if (!p)
101  {
102  rv = VNET_API_ERROR_NO_SUCH_FIB;
103  goto out;
104  }
105  fib_index = p[0];
106  }
107 
108  path_mtu = ntohl (mp->path_mtu);
109  if (path_mtu == ~0)
110  path_mtu = 512; // RFC 7011 section 10.3.3.
111  template_interval = ntohl (mp->template_interval);
112  if (template_interval == ~0)
113  template_interval = 20;
114  udp_checksum = mp->udp_checksum;
115 
116  if (collector.as_u32 == 0)
117  {
118  rv = VNET_API_ERROR_INVALID_VALUE;
119  goto out;
120  }
121 
122  if (src.as_u32 == 0)
123  {
124  rv = VNET_API_ERROR_INVALID_VALUE;
125  goto out;
126  }
127 
128  if (path_mtu > 1450 /* vpp does not support fragmentation */ )
129  {
130  rv = VNET_API_ERROR_INVALID_VALUE;
131  goto out;
132  }
133 
134  if (path_mtu < 68)
135  {
136  rv = VNET_API_ERROR_INVALID_VALUE;
137  goto out;
138  }
139 
140  /* Reset report streams if we are reconfiguring IP addresses */
141  if (frm->ipfix_collector.as_u32 != collector.as_u32 ||
142  frm->src_address.as_u32 != src.as_u32 ||
143  frm->collector_port != collector_port)
145 
146  frm->ipfix_collector.as_u32 = collector.as_u32;
147  frm->collector_port = collector_port;
148  frm->src_address.as_u32 = src.as_u32;
149  frm->fib_index = fib_index;
150  frm->path_mtu = path_mtu;
151  frm->template_interval = template_interval;
152  frm->udp_checksum = udp_checksum;
153 
154  /* Turn on the flow reporting process */
156 
157 out:
158  REPLY_MACRO (VL_API_SET_IPFIX_EXPORTER_REPLY);
159 }
160 
161 static void
163 {
167  ip4_main_t *im = &ip4_main;
168  ip46_address_t collector = {.as_u64[0] = 0,.as_u64[1] = 0 };
169  ip46_address_t src = {.as_u64[0] = 0,.as_u64[1] = 0 };
170  u32 vrf_id;
171 
173  if (!reg)
174  return;
175 
176  rmp = vl_msg_api_alloc (sizeof (*rmp));
177  clib_memset (rmp, 0, sizeof (*rmp));
178  rmp->_vl_msg_id = ntohs (VL_API_IPFIX_EXPORTER_DETAILS);
179  rmp->context = mp->context;
180 
181  memcpy (&collector.ip4, &frm->ipfix_collector, sizeof (ip4_address_t));
183 
184  rmp->collector_port = htons (frm->collector_port);
185 
186  memcpy (&src.ip4, &frm->src_address, sizeof (ip4_address_t));
188 
189  if (frm->fib_index == ~0)
190  vrf_id = ~0;
191  else
192  vrf_id = im->fibs[frm->fib_index].ft_table_id;
193  rmp->vrf_id = htonl (vrf_id);
194  rmp->path_mtu = htonl (frm->path_mtu);
195  rmp->template_interval = htonl (frm->template_interval);
196  rmp->udp_checksum = (frm->udp_checksum != 0);
197 
198  vl_api_send_msg (reg, (u8 *) rmp);
199 }
200 
201 static void
204 {
205  vl_api_set_ipfix_classify_stream_reply_t *rmp;
208  u32 domain_id = 0;
209  u32 src_port = UDP_DST_PORT_ipfix;
210  int rv = 0;
211 
212  domain_id = ntohl (mp->domain_id);
213  src_port = ntohs (mp->src_port);
214 
215  if (fcm->src_port != 0 &&
216  (fcm->domain_id != domain_id || fcm->src_port != (u16) src_port))
217  {
218  int rv = vnet_stream_change (frm, fcm->domain_id, fcm->src_port,
219  domain_id, (u16) src_port);
220  ASSERT (rv == 0);
221  }
222 
223  fcm->domain_id = domain_id;
224  fcm->src_port = (u16) src_port;
225 
226  REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
227 }
228 
229 static void
232 {
236 
238  if (!reg)
239  return;
240 
241  rmp = vl_msg_api_alloc (sizeof (*rmp));
242  clib_memset (rmp, 0, sizeof (*rmp));
243  rmp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_STREAM_DETAILS);
244  rmp->context = mp->context;
245  rmp->domain_id = htonl (fcm->domain_id);
246  rmp->src_port = htons (fcm->src_port);
247 
248  vl_api_send_msg (reg, (u8 *) rmp);
249 }
250 
251 static void
254 {
255  vl_api_ipfix_classify_table_add_del_reply_t *rmp;
260  ipfix_classify_table_t *table;
261  int is_add;
263  u8 ip_version;
264  u8 transport_protocol;
265  int rv = 0;
266 
268  if (!reg)
269  return;
270 
271  classify_table_index = ntohl (mp->table_id);
272  ip_version = ntohl (mp->ip_version);
273  transport_protocol = ntohl (mp->transport_protocol);
274  is_add = mp->is_add;
275 
276  if (fcm->src_port == 0)
277  {
278  /* call set_ipfix_classify_stream first */
279  rv = VNET_API_ERROR_UNSPECIFIED;
280  goto out;
281  }
282 
283  clib_memset (&args, 0, sizeof (args));
284 
285  table = 0;
286  int i;
287  for (i = 0; i < vec_len (fcm->tables); i++)
289  if (fcm->tables[i].classify_table_index == classify_table_index)
290  {
291  table = &fcm->tables[i];
292  break;
293  }
294 
295  if (is_add)
296  {
297  if (table)
298  {
299  rv = VNET_API_ERROR_VALUE_EXIST;
300  goto out;
301  }
302  table = ipfix_classify_add_table ();
304  }
305  else
306  {
307  if (!table)
308  {
309  rv = VNET_API_ERROR_NO_SUCH_ENTRY;
310  goto out;
311  }
312  }
313 
314  table->ip_version = ip_version;
315  table->transport_protocol = transport_protocol;
316 
317  args.opaque.as_uword = table - fcm->tables;
320  args.is_add = is_add;
321  args.domain_id = fcm->domain_id;
322  args.src_port = fcm->src_port;
323 
324  rv = vnet_flow_report_add_del (frm, &args, NULL);
325 
326  /* If deleting, or add failed */
327  if (is_add == 0 || (rv && is_add))
328  ipfix_classify_delete_table (table - fcm->tables);
329 
330 out:
331  REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
332 }
333 
334 static void
336  vl_api_registration_t * reg, u32 context)
337 {
340 
341  ipfix_classify_table_t *table = &fcm->tables[table_index];
342 
343  mp = vl_msg_api_alloc (sizeof (*mp));
344  clib_memset (mp, 0, sizeof (*mp));
345  mp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_TABLE_DETAILS);
346  mp->context = context;
347  mp->table_id = htonl (table->classify_table_index);
348  mp->ip_version = htonl (table->ip_version);
349  mp->transport_protocol = htonl (table->transport_protocol);
350 
351  vl_api_send_msg (reg, (u8 *) mp);
352 }
353 
354 static void
357 {
360  u32 i;
361 
363  if (!reg)
364  return;
365 
366  for (i = 0; i < vec_len (fcm->tables); i++)
369 }
370 
371 static void
373 {
374  vl_api_ipfix_flush_reply_t *rmp;
377  int rv = 0;
378 
380  if (!reg)
381  return;
382 
383  /* poke the flow reporting process */
385  1 /* type_opaque */ , 0 /* data */ );
386 
387  REPLY_MACRO (VL_API_IPFIX_FLUSH_REPLY);
388 }
389 
390 /*
391  * flow_api_hookup
392  * Add vpe's API message handlers to the table.
393  * vlib has already mapped shared memory and
394  * added the client registration handlers.
395  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
396  */
397 #define vl_msg_name_crc_list
398 #include <vnet/vnet_all_api_h.h>
399 #undef vl_msg_name_crc_list
400 
401 static void
403 {
404 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
405  foreach_vl_msg_name_crc_ipfix_export;
406 #undef _
407 }
408 
409 static clib_error_t *
411 {
412  api_main_t *am = vlibapi_get_main ();
413 
414 #define _(N,n) \
415  vl_msg_api_set_handlers(VL_API_##N, #n, \
416  vl_api_##n##_t_handler, \
417  vl_noop_handler, \
418  vl_api_##n##_t_endian, \
419  vl_api_##n##_t_print, \
420  sizeof(vl_api_##n##_t), 1);
422 #undef _
423 
424  /*
425  * Set up the (msg_name, crc, message-id) table
426  */
428 
429  return 0;
430 }
431 
433 
434 /*
435  * fd.io coding-style-patch-verification: ON
436  *
437  * Local Variables:
438  * eval: (c-set-style "gnu")
439  * End:
440  */
IPFIX classify tables dump request.
static clib_error_t * flow_api_hookup(vlib_main_t *vm)
Definition: flow_api.c:410
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.
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static void vl_api_send_msg(vl_api_registration_t *rp, u8 *elem)
Definition: api.h:35
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:60
int i
ip4_address_t src_address
Definition: flow_report.h:119
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:356
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.
vl_api_address_family_t ip_version
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:402
vlib_main_t * vm
Definition: in2out_ed.c:1810
vl_api_address_t collector_address
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:225
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:253
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:59
u32 ft_table_id
Table ID (hash key) for this FIB.
Definition: fib_table.h:92
static void vl_api_set_ipfix_classify_stream_t_handler(vl_api_set_ipfix_classify_stream_t *mp)
Definition: flow_api.c:203
static vl_api_registration_t * vl_api_client_index_to_registration(u32 index)
Definition: api.h:57
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:162
#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:231
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
vl_api_address_t src_address
static void vl_api_ipfix_flush_t_handler(vl_api_ipfix_flush_t *mp)
Definition: flow_api.c:372
#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
void ip4_address_decode(const vl_api_ip4_address_t in, ip4_address_t *out)
Definition: ip_types_api.c:129
vnet_flow_data_callback_t * flow_data_callback
Definition: flow_report.h:148
void ip_address_encode(const ip46_address_t *in, ip46_type_t type, vl_api_address_t *out)
Definition: ip_types_api.c:178
vl_api_address_t collector_address
static api_main_t * vlibapi_get_main(void)
Definition: api_common.h:378
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1079
struct fib_table_t_ * fibs
Vector of FIBs.
Definition: ip4.h:110
vl_api_address_family_t ip_version
IPFIX classify stream dump request.
#define foreach_vpe_api_msg
Definition: flow_api.c:49
u32 vrf_id
Definition: nat.api:821
static void send_ipfix_classify_table_details(u32 table_index, vl_api_registration_t *reg, u32 context)
Definition: flow_api.c:335
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)