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);
91 /* FIXUP: message header export_time */
92 h->export_time = clib_host_to_net_u32 (((u32) time (NULL)));
94 /* FIXUP: message header sequence_number */
95 h->sequence_number = stream->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;
102 next_offset = ioam_analyse_add_ipfix_record (fr,
103 &stats->analyse_data,
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);
115 records_this_buffer++;
117 /* Flush data if packet len is about to reach path mtu */
118 if (next_offset > (frm->path_mtu - UDP_PING_EXPORT_RECORD_SIZE))
120 b0->current_length = next_offset;
121 b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
122 tp = vlib_buffer_get_current (b0);
123 ip = (ip4_header_t *) & tp->ip4;
124 udp = (udp_header_t *) (ip + 1);
129 ipfix_set_id_length (IOAM_FLOW_TEMPLATE_ID,
130 next_offset - (sizeof (*ip) +
134 version_length (next_offset -
135 (sizeof (*ip) + sizeof (*udp)));
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 */ );
143 ip->checksum = ip_csum_fold (sum0);
146 clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
148 udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
149 if (udp->checksum == 0)
150 udp->checksum = 0xffff;
152 ASSERT (ip->checksum == ip4_header_checksum (ip));
158 if (f->n_vectors == VLIB_FRAME_SIZE)
160 vlib_put_frame_to_node (vm, node_index, f);
161 f = vlib_get_frame_to_node (vm, node_index);
163 to_next = vlib_frame_vector_args (f);
174 b0->current_length = next_offset;
175 b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
176 tp = vlib_buffer_get_current (b0);
177 ip = (ip4_header_t *) & tp->ip4;
178 udp = (udp_header_t *) (ip + 1);
182 s->set_id_length = ipfix_set_id_length (IOAM_FLOW_TEMPLATE_ID,
183 next_offset - (sizeof (*ip) +
187 version_length (next_offset - (sizeof (*ip) + sizeof (*udp)));
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 */ );
195 ip->checksum = ip_csum_fold (sum0);
197 udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
199 udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
200 if (udp->checksum == 0)
201 udp->checksum = 0xffff;
203 ASSERT (ip->checksum == ip4_header_checksum (ip));
209 if (f->n_vectors == VLIB_FRAME_SIZE)
211 vlib_put_frame_to_node (vm, node_index, f);
212 f = vlib_get_frame_to_node (vm, node_index);
214 to_next = vlib_frame_vector_args (f);
223 udp_ping_flow_create (u8 del)
225 vnet_flow_report_add_del_args_t args;
228 flow_report_main_t *frm = &flow_report_main;
231 memset (&args, 0, sizeof (args));
232 args.rewrite_callback = udp_ping_template_rewrite;
233 args.flow_data_callback = udp_ping_send_flows;
234 del ? (args.is_add = 0) : (args.is_add = 1);
235 args.domain_id = domain_id;
236 args.src_port = UDP_DST_PORT_ipfix;
238 rv = vnet_flow_report_add_del (frm, &args, &template_id);
244 case VNET_API_ERROR_NO_SUCH_ENTRY:
245 return clib_error_return (0, "registration not found...");
247 return clib_error_return (0, "vnet_flow_report_add_del returned %d",
254 static clib_error_t *
255 set_udp_ping_export_command_fn (vlib_main_t * vm, unformat_input_t * input,
256 vlib_cli_command_t * cmd)
261 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
263 if (unformat (input, "export-ipfix"))
265 else if (unformat (input, "disable"))
272 (void) udp_ping_flow_create (0);
274 (void) udp_ping_flow_create (1);
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,
288 udp_ping_flow_report_init (vlib_main_t * vm)
292 if ((error = vlib_call_init_function (vm, flow_report_init)))
298 VLIB_INIT_FUNCTION (udp_ping_flow_report_init);
301 * fd.io coding-style-patch-verification: ON
304 * eval: (c-set-style "gnu")