FD.io VPP  v21.01.1
Vector Packet Processing
udp_ping_export.c
Go to the documentation of this file.
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 
18 #include <vnet/api_errno.h>
19 #include <vnet/ip/ip4.h>
20 #include <vnet/udp/udp_local.h>
21 #include <ioam/udp-ping/udp_ping.h>
22 
23 #define UDP_PING_EXPORT_RECORD_SIZE 400
24 
25 static u8 *
27  ip4_address_t * collector_address,
28  ip4_address_t * src_address, u16 collector_port,
30  u32 n_elts, u32 * stream_index)
31 {
32  return ioam_template_rewrite (frm, fr, collector_address,
33  src_address, collector_port, elts, n_elts,
34  stream_index);
35 }
36 
37 static vlib_frame_t *
39  vlib_frame_t * f, u32 * to_next, u32 node_index)
40 {
41  vlib_buffer_t *b0 = NULL;
42  u32 next_offset = 0;
43  u32 bi0 = ~0;
44  int i, j;
47  ipfix_set_header_t *s = NULL;
49  udp_header_t *udp;
50  u32 records_this_buffer;
51  u16 new_l0, old_l0;
52  ip_csum_t sum0;
53  vlib_main_t *vm = frm->vlib_main;
54  flow_report_stream_t *stream;
55  udp_ping_flow_data *stats;
56  ip46_udp_ping_flow *ip46_flow;
58  u16 data_len;
59 
60  stream = &frm->streams[fr->stream_index];
61  data_len = vec_len (udp_ping_main.ip46_flow);
62 
63  for (i = 0; i < data_len; i++)
64  {
66  continue;
67 
68  ip46_flow = pool_elt_at_index (udp_ping_main.ip46_flow, i);
69  j = 0;
70  for (src_port = ip46_flow->udp_data.start_src_port;
71  src_port <= ip46_flow->udp_data.end_src_port; src_port++)
72  {
73  for (dst_port = ip46_flow->udp_data.start_dst_port;
74  dst_port <= ip46_flow->udp_data.end_dst_port; dst_port++, j++)
75  {
76  stats = ip46_flow->udp_data.stats + j;
77  if (PREDICT_FALSE (b0 == NULL))
78  {
79  if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
80  break;
81 
82 
83  b0 = vlib_get_buffer (vm, bi0);
84  memcpy (b0->data, fr->rewrite, vec_len (fr->rewrite));
85  b0->current_data = 0;
86  b0->current_length = vec_len (fr->rewrite);
87  b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
88  vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
89  vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
90 
91  tp = vlib_buffer_get_current (b0);
92  ip = &tp->ip4;
93  h = &tp->ipfix.h;
94  s = &tp->ipfix.s;
95 
96  /* FIXUP: message header export_time */
97  h->export_time = clib_host_to_net_u32 (((u32) time (NULL)));
98 
99  /* FIXUP: message header sequence_number */
100  h->sequence_number = stream->sequence_number++;
101  h->sequence_number =
102  clib_host_to_net_u32 (h->sequence_number);
103  next_offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
104  records_this_buffer = 0;
105  }
106 
107  next_offset = ioam_analyse_add_ipfix_record (fr,
108  &stats->analyse_data,
109  b0, next_offset,
110  &ip46_flow->
111  src.ip6,
112  &ip46_flow->
113  dst.ip6, src_port,
114  dst_port);
115 
116  //u32 pak_sent = clib_host_to_net_u32(stats->pak_sent);
117  //memcpy (b0->data + next_offset, &pak_sent, sizeof(u32));
118  //next_offset += sizeof(u32);
119 
120  records_this_buffer++;
121 
122  /* Flush data if packet len is about to reach path mtu */
123  if (next_offset > (frm->path_mtu - UDP_PING_EXPORT_RECORD_SIZE))
124  {
125  b0->current_length = next_offset;
126  b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
127  tp = vlib_buffer_get_current (b0);
128  ip = (ip4_header_t *) & tp->ip4;
129  udp = (udp_header_t *) (ip + 1);
130  h = &tp->ipfix.h;
131  s = &tp->ipfix.s;
132 
133  s->set_id_length =
135  next_offset - (sizeof (*ip) +
136  sizeof (*udp) +
137  sizeof (*h)));
138  h->version_length =
139  version_length (next_offset -
140  (sizeof (*ip) + sizeof (*udp)));
141 
142  sum0 = ip->checksum;
143  old_l0 = ip->length;
144  new_l0 = clib_host_to_net_u16 ((u16) next_offset);
145  sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
146  length /* changed member */ );
147 
148  ip->checksum = ip_csum_fold (sum0);
149  ip->length = new_l0;
150  udp->length =
151  clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
152 
153  udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
154  if (udp->checksum == 0)
155  udp->checksum = 0xffff;
156 
158 
159  to_next[0] = bi0;
160  f->n_vectors++;
161  to_next++;
162 
163  if (f->n_vectors == VLIB_FRAME_SIZE)
164  {
165  vlib_put_frame_to_node (vm, node_index, f);
166  f = vlib_get_frame_to_node (vm, node_index);
167  f->n_vectors = 0;
168  to_next = vlib_frame_vector_args (f);
169  }
170  b0 = 0;
171  bi0 = ~0;
172  }
173  }
174  }
175  }
176 
177  if (b0)
178  {
179  b0->current_length = next_offset;
180  b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
181  tp = vlib_buffer_get_current (b0);
182  ip = (ip4_header_t *) & tp->ip4;
183  udp = (udp_header_t *) (ip + 1);
184  h = &tp->ipfix.h;
185  s = &tp->ipfix.s;
186 
188  next_offset - (sizeof (*ip) +
189  sizeof (*udp) +
190  sizeof (*h)));
191  h->version_length =
192  version_length (next_offset - (sizeof (*ip) + sizeof (*udp)));
193 
194  sum0 = ip->checksum;
195  old_l0 = ip->length;
196  new_l0 = clib_host_to_net_u16 ((u16) next_offset);
197  sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
198  length /* changed member */ );
199 
200  ip->checksum = ip_csum_fold (sum0);
201  ip->length = new_l0;
202  udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
203 
204  udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
205  if (udp->checksum == 0)
206  udp->checksum = 0xffff;
207 
209 
210  to_next[0] = bi0;
211  f->n_vectors++;
212  to_next++;
213 
214  if (f->n_vectors == VLIB_FRAME_SIZE)
215  {
216  vlib_put_frame_to_node (vm, node_index, f);
217  f = vlib_get_frame_to_node (vm, node_index);
218  f->n_vectors = 0;
219  to_next = vlib_frame_vector_args (f);
220  }
221  b0 = 0;
222  bi0 = ~0;
223  }
224  return f;
225 }
226 
227 clib_error_t *
229 {
231  int rv;
232  u32 domain_id = 0;
234  u16 template_id;
235 
236  clib_memset (&args, 0, sizeof (args));
239  del ? (args.is_add = 0) : (args.is_add = 1);
240  args.domain_id = domain_id;
241  args.src_port = UDP_DST_PORT_ipfix;
242 
243  rv = vnet_flow_report_add_del (frm, &args, &template_id);
244 
245  switch (rv)
246  {
247  case 0:
248  break;
249  case VNET_API_ERROR_NO_SUCH_ENTRY:
250  return clib_error_return (0, "registration not found...");
251  default:
252  return clib_error_return (0, "vnet_flow_report_add_del returned %d",
253  rv);
254  }
255 
256  return 0;
257 }
258 
259 static clib_error_t *
261  vlib_cli_command_t * cmd)
262 {
263  //int rv;
264  int is_add = 1;
265 
267  {
268  if (unformat (input, "export-ipfix"))
269  is_add = 1;
270  else if (unformat (input, "disable"))
271  is_add = 0;
272  else
273  break;
274  }
275 
276  if (is_add)
277  (void) udp_ping_flow_create (0);
278  else
279  (void) udp_ping_flow_create (1);
280 
281  return 0;
282 }
283 
284 /* *INDENT-OFF* */
285 VLIB_CLI_COMMAND (set_udp_ping_export_command, static) = {
286  .path = "set udp-ping export-ipfix",
287  .short_help = "set udp-ping export-ipfix [disable]",
288  .function = set_udp_ping_export_command_fn,
289 };
290 /* *INDENT-ON* */
291 
292 clib_error_t *
294 {
295  return 0;
296 }
297 
298 /* *INDENT-OFF* */
300 {
301  .runs_after = VLIB_INITS ("flow_report_init"),
302 };
303 /* *INDENT-ON* */
304 
305 
306 /*
307  * fd.io coding-style-patch-verification: ON
308  *
309  * Local Variables:
310  * eval: (c-set-style "gnu")
311  * End:
312  */
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
ioam_analyser_data_t analyse_data
Analysed data.
Definition: udp_ping.h:44
u8 * ioam_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)
ip46_udp_ping_flow * ip46_flow
Vector od udp-ping data.
Definition: udp_ping.h:108
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:110
vl_api_ip_port_and_mask_t dst_port
Definition: flow_types.api:92
u16 start_dst_port
Defines start port of the dest port range.
Definition: udp_ping.h:73
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
u32 stream_index
Definition: flow_report.h:91
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
static vlib_frame_t * udp_ping_send_flows(flow_report_main_t *frm, flow_report_t *fr, vlib_frame_t *f, u32 *to_next, u32 node_index)
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
vl_api_address_t src
Definition: gre.api:54
uword ip_csum_t
Definition: ip_packet.h:246
vlib_main_t * vm
Definition: in2out_ed.c:1580
udp_ping_flow udp_data
Per flow data.
Definition: udp_ping.h:97
unsigned char u8
Definition: types.h:56
flow_report_stream_t * streams
Definition: flow_report.h:114
static uword ip4_header_checksum_is_valid(ip4_header_t *i)
Definition: ip4_packet.h:384
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
udp-ping data.
Definition: udp_ping.h:85
vnet_flow_rewrite_callback_t * rewrite_callback
Definition: flow_report.h:149
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:182
#define clib_error_return(e, args...)
Definition: error.h:99
static clib_error_t * set_udp_ping_export_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
u16 start_src_port
Defines start port of the src port range.
Definition: udp_ping.h:67
u16 ioam_analyse_add_ipfix_record(flow_report_t *fr, ioam_analyser_data_t *record, vlib_buffer_t *b0, u16 offset, ip6_address_t *src, ip6_address_t *dst, u16 src_port, u16 dst_port)
unsigned int u32
Definition: types.h:88
#define VLIB_FRAME_SIZE
Definition: node.h:378
flow_report_main_t flow_report_main
Definition: flow_report.c:22
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:546
udp_ping_main_t udp_ping_main
Definition: udp_ping_node.c:58
static __clib_warn_unused_result u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
Definition: buffer_funcs.h:677
u8 * rewrite
Definition: flow_report.h:89
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
u8 data_len
Definition: ikev2_types.api:24
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:216
vec_header_t h
Definition: buffer.c:322
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:233
#define PREDICT_FALSE(x)
Definition: clib.h:121
vl_api_address_union_t src_address
Definition: ip_types.api:122
vl_api_address_t dst
Definition: gre.api:55
static u32 version_length(u16 length)
Definition: ipfix_packet.h:33
vl_api_ip_port_and_mask_t src_port
Definition: flow_types.api:91
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
u16 n_vectors
Definition: node.h:397
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define IOAM_FLOW_TEMPLATE_ID
Definition: ioam_analyse.h:27
u8 data[]
Packet data.
Definition: buffer.h:181
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:298
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
#define ASSERT(truth)
vlib_main_t * vlib_main
Definition: flow_report.h:136
u16 ip4_tcp_udp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip4_header_t *ip0)
Definition: ip4_forward.c:1328
static u8 * udp_ping_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)
udp-ping session data.
Definition: udp_ping.h:28
char const int length
Definition: cJSON.h:163
ipfix_message_header_t h
Definition: ipfix_packet.h:192
static u32 ipfix_set_id_length(u16 set_id, u16 length)
Definition: ipfix_packet.h:121
Definition: defs.h:47
vl_api_address_t ip
Definition: l2.api:501
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
ipfix_template_packet_t ipfix
Definition: flow_report.h:46
VLIB buffer representation.
Definition: buffer.h:102
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:296
vnet_flow_data_callback_t * flow_data_callback
Definition: flow_report.h:148
#define vnet_buffer(b)
Definition: buffer.h:417
clib_error_t * udp_ping_flow_report_init(vlib_main_t *vm)
udp_ping_flow_data * stats
Ping statistics.
Definition: udp_ping.h:79
#define VLIB_INITS(...)
Definition: init.h:357
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:85
ipfix_set_header_t s
Definition: ipfix_packet.h:193
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:302
clib_error_t * udp_ping_flow_create(u8 del)
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
Definition: defs.h:46
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
#define UDP_PING_EXPORT_RECORD_SIZE