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