FD.io VPP  v21.01.1
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 #include <vnet/udp/udp_local.h>
24 
25 #include <vnet/interface.h>
26 #include <vnet/api_errno.h>
27 
28 #include <vnet/fib/fib_table.h>
31 
32 #include <vnet/vnet_msg_enum.h>
33 
34 #define vl_typedefs /* define message structures */
35 #include <vnet/vnet_all_api_h.h>
36 #undef vl_typedefs
37 
38 #define vl_endianfun /* define message structures */
39 #include <vnet/vnet_all_api_h.h>
40 #undef vl_endianfun
41 
42 /* instantiate all the print functions we know about */
43 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
44 #define vl_printfun
45 #include <vnet/vnet_all_api_h.h>
46 #undef vl_printfun
47 
49 
50 #define foreach_vpe_api_msg \
51 _(SET_IPFIX_EXPORTER, set_ipfix_exporter) \
52 _(IPFIX_EXPORTER_DUMP, ipfix_exporter_dump) \
53 _(SET_IPFIX_CLASSIFY_STREAM, set_ipfix_classify_stream) \
54 _(IPFIX_CLASSIFY_STREAM_DUMP, ipfix_classify_stream_dump) \
55 _(IPFIX_CLASSIFY_TABLE_ADD_DEL, ipfix_classify_table_add_del) \
56 _(IPFIX_CLASSIFY_TABLE_DUMP, ipfix_classify_table_dump) \
57 _(IPFIX_FLUSH, ipfix_flush)
58 
59 static void
61 {
65  vl_api_set_ipfix_exporter_reply_t *rmp;
66  ip4_address_t collector, src;
67  u16 collector_port = UDP_DST_PORT_ipfix;
68  u32 path_mtu;
69  u32 template_interval;
71  u32 fib_id;
72  u32 fib_index = ~0;
73  int rv = 0;
74 
76  if (!reg)
77  return;
78 
79  if (mp->src_address.af == ADDRESS_IP6
80  || mp->collector_address.af == ADDRESS_IP6)
81  {
82  rv = VNET_API_ERROR_UNIMPLEMENTED;
83  goto out;
84  }
85 
86  ip4_address_decode (mp->collector_address.un.ip4, &collector);
87  collector_port = ntohs (mp->collector_port);
88  if (collector_port == (u16) ~ 0)
89  collector_port = UDP_DST_PORT_ipfix;
90  ip4_address_decode (mp->src_address.un.ip4, &src);
91  fib_id = ntohl (mp->vrf_id);
92 
93  ip4_main_t *im = &ip4_main;
94  if (fib_id == ~0)
95  {
96  fib_index = ~0;
97  }
98  else
99  {
100  uword *p = hash_get (im->fib_index_by_table_id, fib_id);
101  if (!p)
102  {
103  rv = VNET_API_ERROR_NO_SUCH_FIB;
104  goto out;
105  }
106  fib_index = p[0];
107  }
108 
109  path_mtu = ntohl (mp->path_mtu);
110  if (path_mtu == ~0)
111  path_mtu = 512; // RFC 7011 section 10.3.3.
112  template_interval = ntohl (mp->template_interval);
113  if (template_interval == ~0)
114  template_interval = 20;
115  udp_checksum = mp->udp_checksum;
116 
117  if (collector.as_u32 != 0 && src.as_u32 == 0)
118  {
119  rv = VNET_API_ERROR_INVALID_VALUE;
120  goto out;
121  }
122 
123  if (path_mtu > 1450 /* vpp does not support fragmentation */ )
124  {
125  rv = VNET_API_ERROR_INVALID_VALUE;
126  goto out;
127  }
128 
129  if (path_mtu < 68)
130  {
131  rv = VNET_API_ERROR_INVALID_VALUE;
132  goto out;
133  }
134 
135  /* Reset report streams if we are reconfiguring IP addresses */
136  if (frm->ipfix_collector.as_u32 != collector.as_u32 ||
137  frm->src_address.as_u32 != src.as_u32 ||
138  frm->collector_port != collector_port)
140 
141  frm->ipfix_collector.as_u32 = collector.as_u32;
142  frm->collector_port = collector_port;
143  frm->src_address.as_u32 = src.as_u32;
144  frm->fib_index = fib_index;
145  frm->path_mtu = path_mtu;
146  frm->template_interval = template_interval;
147  frm->udp_checksum = udp_checksum;
148 
149  /* Turn on the flow reporting process */
151 
152 out:
153  REPLY_MACRO (VL_API_SET_IPFIX_EXPORTER_REPLY);
154 }
155 
156 static void
158 {
162  ip4_main_t *im = &ip4_main;
163  ip46_address_t collector = {.as_u64[0] = 0,.as_u64[1] = 0 };
164  ip46_address_t src = {.as_u64[0] = 0,.as_u64[1] = 0 };
165  u32 vrf_id;
166 
168  if (!reg)
169  return;
170 
171  rmp = vl_msg_api_alloc (sizeof (*rmp));
172  clib_memset (rmp, 0, sizeof (*rmp));
173  rmp->_vl_msg_id = ntohs (VL_API_IPFIX_EXPORTER_DETAILS);
174  rmp->context = mp->context;
175 
176  memcpy (&collector.ip4, &frm->ipfix_collector, sizeof (ip4_address_t));
178 
179  rmp->collector_port = htons (frm->collector_port);
180 
181  memcpy (&src.ip4, &frm->src_address, sizeof (ip4_address_t));
183 
184  if (frm->fib_index == ~0)
185  vrf_id = ~0;
186  else
187  vrf_id = im->fibs[frm->fib_index].ft_table_id;
188  rmp->vrf_id = htonl (vrf_id);
189  rmp->path_mtu = htonl (frm->path_mtu);
190  rmp->template_interval = htonl (frm->template_interval);
191  rmp->udp_checksum = (frm->udp_checksum != 0);
192 
193  vl_api_send_msg (reg, (u8 *) rmp);
194 }
195 
196 static void
199 {
200  vl_api_set_ipfix_classify_stream_reply_t *rmp;
203  u32 domain_id = 0;
204  u32 src_port = UDP_DST_PORT_ipfix;
205  int rv = 0;
206 
207  domain_id = ntohl (mp->domain_id);
208  src_port = ntohs (mp->src_port);
209 
210  if (fcm->src_port != 0 &&
211  (fcm->domain_id != domain_id || fcm->src_port != (u16) src_port))
212  {
213  int rv = vnet_stream_change (frm, fcm->domain_id, fcm->src_port,
214  domain_id, (u16) src_port);
215  ASSERT (rv == 0);
216  }
217 
218  fcm->domain_id = domain_id;
219  fcm->src_port = (u16) src_port;
220 
221  REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
222 }
223 
224 static void
227 {
231 
233  if (!reg)
234  return;
235 
236  rmp = vl_msg_api_alloc (sizeof (*rmp));
237  clib_memset (rmp, 0, sizeof (*rmp));
238  rmp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_STREAM_DETAILS);
239  rmp->context = mp->context;
240  rmp->domain_id = htonl (fcm->domain_id);
241  rmp->src_port = htons (fcm->src_port);
242 
243  vl_api_send_msg (reg, (u8 *) rmp);
244 }
245 
246 static void
249 {
250  vl_api_ipfix_classify_table_add_del_reply_t *rmp;
255  ipfix_classify_table_t *table;
256  int is_add;
258  u8 ip_version;
259  u8 transport_protocol;
260  int rv = 0;
261 
263  if (!reg)
264  return;
265 
266  classify_table_index = ntohl (mp->table_id);
267  ip_version = (mp->ip_version == ADDRESS_IP4) ? 4 : 6;
268  transport_protocol = mp->transport_protocol;
269  is_add = mp->is_add;
270 
271  if (fcm->src_port == 0)
272  {
273  /* call set_ipfix_classify_stream first */
274  rv = VNET_API_ERROR_UNSPECIFIED;
275  goto out;
276  }
277 
278  clib_memset (&args, 0, sizeof (args));
279 
280  table = 0;
281  int i;
282  for (i = 0; i < vec_len (fcm->tables); i++)
284  if (fcm->tables[i].classify_table_index == classify_table_index)
285  {
286  table = &fcm->tables[i];
287  break;
288  }
289 
290  if (is_add)
291  {
292  if (table)
293  {
294  rv = VNET_API_ERROR_VALUE_EXIST;
295  goto out;
296  }
297  table = ipfix_classify_add_table ();
299  }
300  else
301  {
302  if (!table)
303  {
304  rv = VNET_API_ERROR_NO_SUCH_ENTRY;
305  goto out;
306  }
307  }
308 
309  table->ip_version = ip_version;
310  table->transport_protocol = transport_protocol;
311 
312  args.opaque.as_uword = table - fcm->tables;
315  args.is_add = is_add;
316  args.domain_id = fcm->domain_id;
317  args.src_port = fcm->src_port;
318 
319  rv = vnet_flow_report_add_del (frm, &args, NULL);
320 
321  /* If deleting, or add failed */
322  if (is_add == 0 || (rv && is_add))
323  ipfix_classify_delete_table (table - fcm->tables);
324 
325 out:
326  REPLY_MACRO (VL_API_SET_IPFIX_CLASSIFY_STREAM_REPLY);
327 }
328 
329 static void
331  vl_api_registration_t * reg, u32 context)
332 {
335 
336  ipfix_classify_table_t *table = &fcm->tables[table_index];
337 
338  mp = vl_msg_api_alloc (sizeof (*mp));
339  clib_memset (mp, 0, sizeof (*mp));
340  mp->_vl_msg_id = ntohs (VL_API_IPFIX_CLASSIFY_TABLE_DETAILS);
341  mp->context = context;
342  mp->table_id = htonl (table->classify_table_index);
343  mp->ip_version = (table->ip_version == 4) ? ADDRESS_IP4 : ADDRESS_IP6;
345 
346  vl_api_send_msg (reg, (u8 *) mp);
347 }
348 
349 static void
352 {
355  u32 i;
356 
358  if (!reg)
359  return;
360 
361  for (i = 0; i < vec_len (fcm->tables); i++)
364 }
365 
366 static void
368 {
369  vl_api_ipfix_flush_reply_t *rmp;
372  int rv = 0;
373 
375  if (!reg)
376  return;
377 
378  /* poke the flow reporting process */
380  1 /* type_opaque */ , 0 /* data */ );
381 
382  REPLY_MACRO (VL_API_IPFIX_FLUSH_REPLY);
383 }
384 
385 /*
386  * flow_api_hookup
387  * Add vpe's API message handlers to the table.
388  * vlib has already mapped shared memory and
389  * added the client registration handlers.
390  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
391  */
392 #define vl_msg_name_crc_list
393 #include <vnet/vnet_all_api_h.h>
394 #undef vl_msg_name_crc_list
395 
396 static void
398 {
399 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
400  foreach_vl_msg_name_crc_ipfix_export;
401 #undef _
402 }
403 
404 static clib_error_t *
406 {
407  api_main_t *am = vlibapi_get_main ();
408 
409 #define _(N,n) \
410  vl_msg_api_set_handlers(VL_API_##N, #n, \
411  vl_api_##n##_t_handler, \
412  vl_noop_handler, \
413  vl_api_##n##_t_endian, \
414  vl_api_##n##_t_print, \
415  sizeof(vl_api_##n##_t), 1);
417 #undef _
418 
419  /*
420  * Set up the (msg_name, crc, message-id) table
421  */
423 
424  return 0;
425 }
426 
428 
429 /*
430  * fd.io coding-style-patch-verification: ON
431  *
432  * Local Variables:
433  * eval: (c-set-style "gnu")
434  * End:
435  */
IPFIX classify tables dump request.
vlib_node_registration_t flow_report_process_node
(constructor) VLIB_REGISTER_NODE (flow_report_process_node)
Definition: flow_report.c:327
u16 udp_checksum(udp_header_t *uh, u32 udp_len, void *ih, u8 version)
Definition: packets.c:116
#define ntohs(x)
Definition: af_xdp.bpf.c:29
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)
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:335
IPFIX exporter dump request.
vl_api_address_t src
Definition: gre.api:54
ip4_address_t src_address
Definition: flow_report.h:119
u32 vrf_id
Definition: nat44.api:1029
vlib_main_t * vm
Definition: in2out_ed.c:1580
void * vl_msg_api_alloc(int nbytes)
#define foreach_vpe_api_msg
Definition: flow_api.c:50
unsigned char u8
Definition: types.h:56
ip4_address_t ipfix_collector
Definition: flow_report.h:117
static void vl_api_set_ipfix_classify_stream_t_handler(vl_api_set_ipfix_classify_stream_t *mp)
Definition: flow_api.c:198
vnet_flow_rewrite_callback_t * rewrite_callback
Definition: flow_report.h:149
static void vl_api_ipfix_classify_stream_dump_t_handler(vl_api_ipfix_classify_stream_dump_t *mp)
Definition: flow_api.c:226
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:22
#define hash_get(h, key)
Definition: hash.h:249
static void send_ipfix_classify_table_details(u32 table_index, vl_api_registration_t *reg, u32 context)
Definition: flow_api.c:330
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:133
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:1015
unsigned short u16
Definition: types.h:57
#define REPLY_MACRO(t)
static clib_error_t * flow_api_hookup(vlib_main_t *vm)
Definition: flow_api.c:405
vl_api_address_t collector_address
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:227
An API client registration, only in vpp/vlib.
Definition: api_common.h:47
u32 classify_table_index
Definition: fib_types.api:68
vl_api_ip_port_and_mask_t src_port
Definition: flow_types.api:91
IPFIX classify stream configure request.
ipfix_classify_table_t * tables
u32 ft_table_id
Table ID (hash key) for this FIB.
Definition: fib_table.h:92
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
static vl_api_registration_t * vl_api_client_index_to_registration(u32 index)
Definition: api.h:79
static_always_inline ipfix_classify_table_t * ipfix_classify_add_table(void)
#define ASSERT(truth)
IPv4 main type.
Definition: ip4.h:107
static void vl_api_ipfix_flush_t_handler(vl_api_ipfix_flush_t *mp)
Definition: flow_api.c:367
void vnet_flow_reports_reset(flow_report_main_t *frm)
Definition: flow_report.c:436
static void vl_api_ipfix_classify_table_add_del_t_handler(vl_api_ipfix_classify_table_add_del_t *mp)
Definition: flow_api.c:248
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
vl_api_address_t src_address
VLIB_API_INIT_FUNCTION(hw_flow_api_hookup)
#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:468
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:155
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:220
static void vl_api_ipfix_exporter_dump_t_handler(vl_api_ipfix_exporter_dump_t *mp)
Definition: flow_api.c:157
vl_api_address_t collector_address
static api_main_t * vlibapi_get_main(void)
Definition: api_common.h:389
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1105
struct fib_table_t_ * fibs
Vector of FIBs.
Definition: ip4.h:112
static void vl_api_set_ipfix_exporter_t_handler(vl_api_set_ipfix_exporter_t *mp)
Definition: flow_api.c:60
vl_api_address_family_t ip_version
IPFIX classify stream dump request.
static void setup_message_id_table(api_main_t *am)
Definition: flow_api.c:397
static void vl_api_ipfix_classify_table_dump_t_handler(vl_api_ipfix_classify_table_dump_t *mp)
Definition: flow_api.c:351
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)