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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include <vnet/flow/flow_report.h>
17 #include <ioam/analyse/ioam_summary_export.h>
18 #include <vnet/api_errno.h>
19 #include <ioam/udp-ping/udp_ping.h>
21 #define UDP_PING_EXPORT_RECORD_SIZE 400
24 udp_ping_template_rewrite (flow_report_main_t * frm, flow_report_t * fr,
25 ip4_address_t * collector_address,
26 ip4_address_t * src_address, u16 collector_port)
28 return ioam_template_rewrite (frm, fr, collector_address,
29 src_address, collector_port);
33 udp_ping_send_flows (flow_report_main_t * frm, flow_report_t * fr,
34 vlib_frame_t * f, u32 * to_next, u32 node_index)
36 vlib_buffer_t *b0 = NULL;
40 ip4_ipfix_template_packet_t *tp;
41 ipfix_message_header_t *h;
42 ipfix_set_header_t *s = NULL;
45 u32 records_this_buffer;
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;
55 stream = &frm->streams[fr->stream_index];
56 data_len = vec_len (udp_ping_main.ip46_flow);
58 for (i = 0; i < data_len; i++)
60 if (pool_is_free_index (udp_ping_main.ip46_flow, i))
63 ip46_flow = pool_elt_at_index (udp_ping_main.ip46_flow, i);
65 for (src_port = ip46_flow->udp_data.start_src_port;
66 src_port <= ip46_flow->udp_data.end_src_port; src_port++)
68 for (dst_port = ip46_flow->udp_data.start_dst_port;
69 dst_port <= ip46_flow->udp_data.end_dst_port; dst_port++, j++)
71 stats = ip46_flow->udp_data.stats + j;
72 if (PREDICT_FALSE (b0 == NULL))
74 if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
78 b0 = vlib_get_buffer (vm, bi0);
79 memcpy (b0->data, fr->rewrite, vec_len (fr->rewrite));
81 b0->current_length = vec_len (fr->rewrite);
82 b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
83 vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
84 vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
86 tp = vlib_buffer_get_current (b0);
92 /* FIXUP: message header export_time */
93 h->export_time = clib_host_to_net_u32 (((u32) time (NULL)));
95 /* FIXUP: message header sequence_number */
96 h->sequence_number = stream->sequence_number++;
98 clib_host_to_net_u32 (h->sequence_number);
99 next_offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
100 records_this_buffer = 0;
103 next_offset = ioam_analyse_add_ipfix_record (fr,
104 &stats->analyse_data,
112 //u32 pak_sent = clib_host_to_net_u32(stats->pak_sent);
113 //memcpy (b0->data + next_offset, &pak_sent, sizeof(u32));
114 //next_offset += sizeof(u32);
116 records_this_buffer++;
118 /* Flush data if packet len is about to reach path mtu */
119 if (next_offset > (frm->path_mtu - UDP_PING_EXPORT_RECORD_SIZE))
121 b0->current_length = next_offset;
122 b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
123 tp = vlib_buffer_get_current (b0);
124 ip = (ip4_header_t *) & tp->ip4;
125 udp = (udp_header_t *) (ip + 1);
130 ipfix_set_id_length (IOAM_FLOW_TEMPLATE_ID,
131 next_offset - (sizeof (*ip) +
135 version_length (next_offset -
136 (sizeof (*ip) + sizeof (*udp)));
140 new_l0 = clib_host_to_net_u16 ((u16) next_offset);
141 sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
142 length /* changed member */ );
144 ip->checksum = ip_csum_fold (sum0);
147 clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
149 udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
150 if (udp->checksum == 0)
151 udp->checksum = 0xffff;
153 ASSERT (ip->checksum == ip4_header_checksum (ip));
159 if (f->n_vectors == VLIB_FRAME_SIZE)
161 vlib_put_frame_to_node (vm, node_index, f);
162 f = vlib_get_frame_to_node (vm, node_index);
164 to_next = vlib_frame_vector_args (f);
175 b0->current_length = next_offset;
176 b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
177 tp = vlib_buffer_get_current (b0);
178 ip = (ip4_header_t *) & tp->ip4;
179 udp = (udp_header_t *) (ip + 1);
183 s->set_id_length = ipfix_set_id_length (IOAM_FLOW_TEMPLATE_ID,
184 next_offset - (sizeof (*ip) +
188 version_length (next_offset - (sizeof (*ip) + sizeof (*udp)));
192 new_l0 = clib_host_to_net_u16 ((u16) next_offset);
193 sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
194 length /* changed member */ );
196 ip->checksum = ip_csum_fold (sum0);
198 udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
200 udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
201 if (udp->checksum == 0)
202 udp->checksum = 0xffff;
204 ASSERT (ip->checksum == ip4_header_checksum (ip));
210 if (f->n_vectors == VLIB_FRAME_SIZE)
212 vlib_put_frame_to_node (vm, node_index, f);
213 f = vlib_get_frame_to_node (vm, node_index);
215 to_next = vlib_frame_vector_args (f);
224 udp_ping_flow_create (u8 del)
226 vnet_flow_report_add_del_args_t args;
229 flow_report_main_t *frm = &flow_report_main;
231 args.rewrite_callback = udp_ping_template_rewrite;
232 args.flow_data_callback = udp_ping_send_flows;
233 del ? (args.is_add = 0) : (args.is_add = 1);
234 args.domain_id = domain_id;
236 rv = vnet_flow_report_add_del (frm, &args);
242 case VNET_API_ERROR_NO_SUCH_ENTRY:
243 return clib_error_return (0, "registration not found...");
245 return clib_error_return (0, "vnet_flow_report_add_del returned %d",
252 static clib_error_t *
253 set_udp_ping_export_command_fn (vlib_main_t * vm, unformat_input_t * input,
254 vlib_cli_command_t * cmd)
259 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
261 if (unformat (input, "export-ipfix"))
263 else if (unformat (input, "disable"))
270 (void) udp_ping_flow_create (0);
272 (void) udp_ping_flow_create (1);
278 VLIB_CLI_COMMAND (set_udp_ping_export_command, static) = {
279 .path = "set udp-ping export-ipfix",
280 .short_help = "set udp-ping export-ipfix [disable]",
281 .function = set_udp_ping_export_command_fn,
286 udp_ping_flow_report_init (vlib_main_t * vm)
290 if ((error = vlib_call_init_function (vm, flow_report_init)))
296 VLIB_INIT_FUNCTION (udp_ping_flow_report_init);
299 * fd.io coding-style-patch-verification: ON
302 * eval: (c-set-style "gnu")