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;
50 vlib_main_t *vm = vlib_get_main ();
51 flow_report_stream_t *stream;
52 udp_ping_flow_data *stats;
53 ip46_udp_ping_flow *ip46_flow;
54 u16 src_port, dst_port;
57 stream = &exp->streams[fr->stream_index];
58 data_len = vec_len (udp_ping_main.ip46_flow);
60 for (i = 0; i < data_len; i++)
62 if (pool_is_free_index (udp_ping_main.ip46_flow, i))
65 ip46_flow = pool_elt_at_index (udp_ping_main.ip46_flow, i);
67 for (src_port = ip46_flow->udp_data.start_src_port;
68 src_port <= ip46_flow->udp_data.end_src_port; src_port++)
70 for (dst_port = ip46_flow->udp_data.start_dst_port;
71 dst_port <= ip46_flow->udp_data.end_dst_port; dst_port++, j++)
73 stats = ip46_flow->udp_data.stats + j;
74 if (PREDICT_FALSE (b0 == NULL))
76 if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
80 b0 = vlib_get_buffer (vm, bi0);
81 memcpy (b0->data, fr->rewrite, vec_len (fr->rewrite));
83 b0->current_length = vec_len (fr->rewrite);
84 b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
85 vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
86 vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
88 tp = vlib_buffer_get_current (b0);
93 /* FIXUP: message header export_time */
94 h->export_time = clib_host_to_net_u32 (((u32) time (NULL)));
96 /* FIXUP: message header sequence_number */
97 h->sequence_number = stream->sequence_number++;
99 clib_host_to_net_u32 (h->sequence_number);
100 next_offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
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 /* Flush data if packet len is about to reach path mtu */
117 if (next_offset > (exp->path_mtu - UDP_PING_EXPORT_RECORD_SIZE))
119 b0->current_length = next_offset;
120 b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
121 tp = vlib_buffer_get_current (b0);
122 ip = (ip4_header_t *) & tp->ip4;
123 udp = (udp_header_t *) (ip + 1);
128 ipfix_set_id_length (IOAM_FLOW_TEMPLATE_ID,
129 next_offset - (sizeof (*ip) +
133 version_length (next_offset -
134 (sizeof (*ip) + sizeof (*udp)));
138 new_l0 = clib_host_to_net_u16 ((u16) next_offset);
139 sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
140 length /* changed member */ );
142 ip->checksum = ip_csum_fold (sum0);
145 clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
147 udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
148 if (udp->checksum == 0)
149 udp->checksum = 0xffff;
151 ASSERT (ip4_header_checksum_is_valid (ip));
157 if (f->n_vectors == VLIB_FRAME_SIZE)
159 vlib_put_frame_to_node (vm, node_index, f);
160 f = vlib_get_frame_to_node (vm, node_index);
162 to_next = vlib_frame_vector_args (f);
173 b0->current_length = next_offset;
174 b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
175 tp = vlib_buffer_get_current (b0);
176 ip = (ip4_header_t *) & tp->ip4;
177 udp = (udp_header_t *) (ip + 1);
181 s->set_id_length = ipfix_set_id_length (IOAM_FLOW_TEMPLATE_ID,
182 next_offset - (sizeof (*ip) +
186 version_length (next_offset - (sizeof (*ip) + sizeof (*udp)));
190 new_l0 = clib_host_to_net_u16 ((u16) next_offset);
191 sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
192 length /* changed member */ );
194 ip->checksum = ip_csum_fold (sum0);
196 udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
198 udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
199 if (udp->checksum == 0)
200 udp->checksum = 0xffff;
202 ASSERT (ip4_header_checksum_is_valid (ip));
208 if (f->n_vectors == VLIB_FRAME_SIZE)
210 vlib_put_frame_to_node (vm, node_index, f);
211 f = vlib_get_frame_to_node (vm, node_index);
213 to_next = vlib_frame_vector_args (f);
222 udp_ping_flow_create (u8 del)
224 vnet_flow_report_add_del_args_t args;
227 ipfix_exporter_t *exp = &flow_report_main.exporters[0];
230 clib_memset (&args, 0, sizeof (args));
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;
235 args.src_port = UDP_DST_PORT_ipfix;
237 rv = vnet_flow_report_add_del (exp, &args, &template_id);
243 case VNET_API_ERROR_NO_SUCH_ENTRY:
244 return clib_error_return (0, "registration not found...");
246 return clib_error_return (0, "vnet_flow_report_add_del returned %d",
253 static clib_error_t *
254 set_udp_ping_export_command_fn (vlib_main_t * vm, unformat_input_t * input,
255 vlib_cli_command_t * cmd)
260 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
262 if (unformat (input, "export-ipfix"))
264 else if (unformat (input, "disable"))
271 (void) udp_ping_flow_create (0);
273 (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,
285 udp_ping_flow_report_init (vlib_main_t * vm)
290 VLIB_INIT_FUNCTION (udp_ping_flow_report_init) =
292 .runs_after = VLIB_INITS ("flow_report_init"),
297 * fd.io coding-style-patch-verification: ON
300 * eval: (c-set-style "gnu")