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