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/ipfix-export/flow_report.h>
17 #include <ioam/analyse/ioam_summary_export.h>
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>
23 #define UDP_PING_EXPORT_RECORD_SIZE 400
26 udp_ping_template_rewrite (ipfix_exporter_t *exp, flow_report_t *fr,
27 u16 collector_port, ipfix_report_element_t *elts,
28 u32 n_elts, u32 *stream_index)
30 return ioam_template_rewrite (exp, fr, collector_port, elts, n_elts,
35 udp_ping_send_flows (flow_report_main_t *frm, ipfix_exporter_t *exp,
36 flow_report_t *fr, vlib_frame_t *f, u32 *to_next,
39 vlib_buffer_t *b0 = NULL;
43 ip4_ipfix_template_packet_t *tp;
44 ipfix_message_header_t *h;
45 ipfix_set_header_t *s = NULL;
48 u32 records_this_buffer;
51 vlib_main_t *vm = vlib_get_main ();
52 flow_report_stream_t *stream;
53 udp_ping_flow_data *stats;
54 ip46_udp_ping_flow *ip46_flow;
55 u16 src_port, dst_port;
58 stream = &exp->streams[fr->stream_index];
59 data_len = vec_len (udp_ping_main.ip46_flow);
61 for (i = 0; i < data_len; i++)
63 if (pool_is_free_index (udp_ping_main.ip46_flow, i))
66 ip46_flow = pool_elt_at_index (udp_ping_main.ip46_flow, i);
68 for (src_port = ip46_flow->udp_data.start_src_port;
69 src_port <= ip46_flow->udp_data.end_src_port; src_port++)
71 for (dst_port = ip46_flow->udp_data.start_dst_port;
72 dst_port <= ip46_flow->udp_data.end_dst_port; dst_port++, j++)
74 stats = ip46_flow->udp_data.stats + j;
75 if (PREDICT_FALSE (b0 == NULL))
77 if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
81 b0 = vlib_get_buffer (vm, bi0);
82 memcpy (b0->data, fr->rewrite, vec_len (fr->rewrite));
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;
89 tp = vlib_buffer_get_current (b0);
94 /* FIXUP: message header export_time */
95 h->export_time = clib_host_to_net_u32 (((u32) time (NULL)));
97 /* FIXUP: message header sequence_number */
98 h->sequence_number = stream->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;
105 next_offset = ioam_analyse_add_ipfix_record (fr,
106 &stats->analyse_data,
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);
118 records_this_buffer++;
120 /* Flush data if packet len is about to reach path mtu */
121 if (next_offset > (exp->path_mtu - UDP_PING_EXPORT_RECORD_SIZE))
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);
132 ipfix_set_id_length (IOAM_FLOW_TEMPLATE_ID,
133 next_offset - (sizeof (*ip) +
137 version_length (next_offset -
138 (sizeof (*ip) + sizeof (*udp)));
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 */ );
146 ip->checksum = ip_csum_fold (sum0);
149 clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
151 udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
152 if (udp->checksum == 0)
153 udp->checksum = 0xffff;
155 ASSERT (ip4_header_checksum_is_valid (ip));
161 if (f->n_vectors == VLIB_FRAME_SIZE)
163 vlib_put_frame_to_node (vm, node_index, f);
164 f = vlib_get_frame_to_node (vm, node_index);
166 to_next = vlib_frame_vector_args (f);
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);
185 s->set_id_length = ipfix_set_id_length (IOAM_FLOW_TEMPLATE_ID,
186 next_offset - (sizeof (*ip) +
190 version_length (next_offset - (sizeof (*ip) + sizeof (*udp)));
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 */ );
198 ip->checksum = ip_csum_fold (sum0);
200 udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
202 udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
203 if (udp->checksum == 0)
204 udp->checksum = 0xffff;
206 ASSERT (ip4_header_checksum_is_valid (ip));
212 if (f->n_vectors == VLIB_FRAME_SIZE)
214 vlib_put_frame_to_node (vm, node_index, f);
215 f = vlib_get_frame_to_node (vm, node_index);
217 to_next = vlib_frame_vector_args (f);
226 udp_ping_flow_create (u8 del)
228 vnet_flow_report_add_del_args_t args;
231 ipfix_exporter_t *exp = &flow_report_main.exporters[0];
234 clib_memset (&args, 0, sizeof (args));
235 args.rewrite_callback = udp_ping_template_rewrite;
236 args.flow_data_callback = udp_ping_send_flows;
237 del ? (args.is_add = 0) : (args.is_add = 1);
238 args.domain_id = domain_id;
239 args.src_port = UDP_DST_PORT_ipfix;
241 rv = vnet_flow_report_add_del (exp, &args, &template_id);
247 case VNET_API_ERROR_NO_SUCH_ENTRY:
248 return clib_error_return (0, "registration not found...");
250 return clib_error_return (0, "vnet_flow_report_add_del returned %d",
257 static clib_error_t *
258 set_udp_ping_export_command_fn (vlib_main_t * vm, unformat_input_t * input,
259 vlib_cli_command_t * cmd)
264 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
266 if (unformat (input, "export-ipfix"))
268 else if (unformat (input, "disable"))
275 (void) udp_ping_flow_create (0);
277 (void) udp_ping_flow_create (1);
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,
291 udp_ping_flow_report_init (vlib_main_t * vm)
297 VLIB_INIT_FUNCTION (udp_ping_flow_report_init) =
299 .runs_after = VLIB_INITS ("flow_report_init"),
305 * fd.io coding-style-patch-verification: ON
308 * eval: (c-set-style "gnu")