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 ip4_address_t *collector_address,
28 ip4_address_t *src_address, u16 collector_port,
29 ipfix_report_element_t *elts, u32 n_elts,
32 return ioam_template_rewrite (exp, fr, collector_address, src_address,
33 collector_port, elts, n_elts, stream_index);
37 udp_ping_send_flows (flow_report_main_t *frm, ipfix_exporter_t *exp,
38 flow_report_t *fr, vlib_frame_t *f, u32 *to_next,
41 vlib_buffer_t *b0 = NULL;
45 ip4_ipfix_template_packet_t *tp;
46 ipfix_message_header_t *h;
47 ipfix_set_header_t *s = NULL;
50 u32 records_this_buffer;
53 vlib_main_t *vm = vlib_get_main ();
54 flow_report_stream_t *stream;
55 udp_ping_flow_data *stats;
56 ip46_udp_ping_flow *ip46_flow;
57 u16 src_port, dst_port;
60 stream = &exp->streams[fr->stream_index];
61 data_len = vec_len (udp_ping_main.ip46_flow);
63 for (i = 0; i < data_len; i++)
65 if (pool_is_free_index (udp_ping_main.ip46_flow, i))
68 ip46_flow = pool_elt_at_index (udp_ping_main.ip46_flow, i);
70 for (src_port = ip46_flow->udp_data.start_src_port;
71 src_port <= ip46_flow->udp_data.end_src_port; src_port++)
73 for (dst_port = ip46_flow->udp_data.start_dst_port;
74 dst_port <= ip46_flow->udp_data.end_dst_port; dst_port++, j++)
76 stats = ip46_flow->udp_data.stats + j;
77 if (PREDICT_FALSE (b0 == NULL))
79 if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
83 b0 = vlib_get_buffer (vm, bi0);
84 memcpy (b0->data, fr->rewrite, vec_len (fr->rewrite));
86 b0->current_length = vec_len (fr->rewrite);
87 b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
88 vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
89 vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
91 tp = vlib_buffer_get_current (b0);
96 /* FIXUP: message header export_time */
97 h->export_time = clib_host_to_net_u32 (((u32) time (NULL)));
99 /* FIXUP: message header sequence_number */
100 h->sequence_number = stream->sequence_number++;
102 clib_host_to_net_u32 (h->sequence_number);
103 next_offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
104 records_this_buffer = 0;
107 next_offset = ioam_analyse_add_ipfix_record (fr,
108 &stats->analyse_data,
116 //u32 pak_sent = clib_host_to_net_u32(stats->pak_sent);
117 //memcpy (b0->data + next_offset, &pak_sent, sizeof(u32));
118 //next_offset += sizeof(u32);
120 records_this_buffer++;
122 /* Flush data if packet len is about to reach path mtu */
123 if (next_offset > (exp->path_mtu - UDP_PING_EXPORT_RECORD_SIZE))
125 b0->current_length = next_offset;
126 b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
127 tp = vlib_buffer_get_current (b0);
128 ip = (ip4_header_t *) & tp->ip4;
129 udp = (udp_header_t *) (ip + 1);
134 ipfix_set_id_length (IOAM_FLOW_TEMPLATE_ID,
135 next_offset - (sizeof (*ip) +
139 version_length (next_offset -
140 (sizeof (*ip) + sizeof (*udp)));
144 new_l0 = clib_host_to_net_u16 ((u16) next_offset);
145 sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
146 length /* changed member */ );
148 ip->checksum = ip_csum_fold (sum0);
151 clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
153 udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
154 if (udp->checksum == 0)
155 udp->checksum = 0xffff;
157 ASSERT (ip4_header_checksum_is_valid (ip));
163 if (f->n_vectors == VLIB_FRAME_SIZE)
165 vlib_put_frame_to_node (vm, node_index, f);
166 f = vlib_get_frame_to_node (vm, node_index);
168 to_next = vlib_frame_vector_args (f);
179 b0->current_length = next_offset;
180 b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
181 tp = vlib_buffer_get_current (b0);
182 ip = (ip4_header_t *) & tp->ip4;
183 udp = (udp_header_t *) (ip + 1);
187 s->set_id_length = ipfix_set_id_length (IOAM_FLOW_TEMPLATE_ID,
188 next_offset - (sizeof (*ip) +
192 version_length (next_offset - (sizeof (*ip) + sizeof (*udp)));
196 new_l0 = clib_host_to_net_u16 ((u16) next_offset);
197 sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
198 length /* changed member */ );
200 ip->checksum = ip_csum_fold (sum0);
202 udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
204 udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
205 if (udp->checksum == 0)
206 udp->checksum = 0xffff;
208 ASSERT (ip4_header_checksum_is_valid (ip));
214 if (f->n_vectors == VLIB_FRAME_SIZE)
216 vlib_put_frame_to_node (vm, node_index, f);
217 f = vlib_get_frame_to_node (vm, node_index);
219 to_next = vlib_frame_vector_args (f);
228 udp_ping_flow_create (u8 del)
230 vnet_flow_report_add_del_args_t args;
233 ipfix_exporter_t *exp = &flow_report_main.exporters[0];
236 clib_memset (&args, 0, sizeof (args));
237 args.rewrite_callback = udp_ping_template_rewrite;
238 args.flow_data_callback = udp_ping_send_flows;
239 del ? (args.is_add = 0) : (args.is_add = 1);
240 args.domain_id = domain_id;
241 args.src_port = UDP_DST_PORT_ipfix;
243 rv = vnet_flow_report_add_del (exp, &args, &template_id);
249 case VNET_API_ERROR_NO_SUCH_ENTRY:
250 return clib_error_return (0, "registration not found...");
252 return clib_error_return (0, "vnet_flow_report_add_del returned %d",
259 static clib_error_t *
260 set_udp_ping_export_command_fn (vlib_main_t * vm, unformat_input_t * input,
261 vlib_cli_command_t * cmd)
266 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
268 if (unformat (input, "export-ipfix"))
270 else if (unformat (input, "disable"))
277 (void) udp_ping_flow_create (0);
279 (void) udp_ping_flow_create (1);
285 VLIB_CLI_COMMAND (set_udp_ping_export_command, static) = {
286 .path = "set udp-ping export-ipfix",
287 .short_help = "set udp-ping export-ipfix [disable]",
288 .function = set_udp_ping_export_command_fn,
293 udp_ping_flow_report_init (vlib_main_t * vm)
299 VLIB_INIT_FUNCTION (udp_ping_flow_report_init) =
301 .runs_after = VLIB_INITS ("flow_report_init"),
307 * fd.io coding-style-patch-verification: ON
310 * eval: (c-set-style "gnu")