Line data Source code
1 : /*
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:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
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.
14 : */
15 :
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>
22 :
23 : #define UDP_PING_EXPORT_RECORD_SIZE 400
24 :
25 : static u8 *
26 0 : 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)
29 : {
30 0 : return ioam_template_rewrite (exp, fr, collector_port, elts, n_elts,
31 : stream_index);
32 : }
33 :
34 : static vlib_frame_t *
35 0 : 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,
37 : u32 node_index)
38 : {
39 0 : vlib_buffer_t *b0 = NULL;
40 0 : u32 next_offset = 0;
41 0 : u32 bi0 = ~0;
42 : int i, j;
43 : ip4_ipfix_template_packet_t *tp;
44 : ipfix_message_header_t *h;
45 0 : ipfix_set_header_t *s = NULL;
46 : ip4_header_t *ip;
47 : udp_header_t *udp;
48 : u16 new_l0, old_l0;
49 : ip_csum_t sum0;
50 0 : 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;
55 : u16 data_len;
56 :
57 0 : stream = &exp->streams[fr->stream_index];
58 0 : data_len = vec_len (udp_ping_main.ip46_flow);
59 :
60 0 : for (i = 0; i < data_len; i++)
61 : {
62 0 : if (pool_is_free_index (udp_ping_main.ip46_flow, i))
63 0 : continue;
64 :
65 0 : ip46_flow = pool_elt_at_index (udp_ping_main.ip46_flow, i);
66 0 : j = 0;
67 0 : for (src_port = ip46_flow->udp_data.start_src_port;
68 0 : src_port <= ip46_flow->udp_data.end_src_port; src_port++)
69 : {
70 0 : for (dst_port = ip46_flow->udp_data.start_dst_port;
71 0 : dst_port <= ip46_flow->udp_data.end_dst_port; dst_port++, j++)
72 : {
73 0 : stats = ip46_flow->udp_data.stats + j;
74 0 : if (PREDICT_FALSE (b0 == NULL))
75 : {
76 0 : if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
77 0 : break;
78 :
79 :
80 0 : b0 = vlib_get_buffer (vm, bi0);
81 0 : memcpy (b0->data, fr->rewrite, vec_len (fr->rewrite));
82 0 : b0->current_data = 0;
83 0 : b0->current_length = vec_len (fr->rewrite);
84 0 : b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
85 0 : vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
86 0 : vnet_buffer (b0)->sw_if_index[VLIB_TX] = ~0;
87 :
88 0 : tp = vlib_buffer_get_current (b0);
89 0 : ip = &tp->ip4;
90 0 : h = &tp->ipfix.h;
91 0 : s = &tp->ipfix.s;
92 :
93 : /* FIXUP: message header export_time */
94 0 : h->export_time = clib_host_to_net_u32 (((u32) time (NULL)));
95 :
96 : /* FIXUP: message header sequence_number */
97 0 : h->sequence_number = stream->sequence_number++;
98 0 : h->sequence_number =
99 0 : clib_host_to_net_u32 (h->sequence_number);
100 0 : next_offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
101 : }
102 :
103 0 : next_offset = ioam_analyse_add_ipfix_record (fr,
104 : &stats->analyse_data,
105 : b0, next_offset,
106 : &ip46_flow->
107 : src.ip6,
108 : &ip46_flow->
109 : dst.ip6, src_port,
110 : dst_port);
111 :
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);
115 :
116 : /* Flush data if packet len is about to reach path mtu */
117 0 : if (next_offset > (exp->path_mtu - UDP_PING_EXPORT_RECORD_SIZE))
118 : {
119 0 : b0->current_length = next_offset;
120 0 : b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
121 0 : tp = vlib_buffer_get_current (b0);
122 0 : ip = (ip4_header_t *) & tp->ip4;
123 0 : udp = (udp_header_t *) (ip + 1);
124 0 : h = &tp->ipfix.h;
125 0 : s = &tp->ipfix.s;
126 :
127 0 : s->set_id_length =
128 0 : ipfix_set_id_length (IOAM_FLOW_TEMPLATE_ID,
129 0 : next_offset - (sizeof (*ip) +
130 : sizeof (*udp) +
131 : sizeof (*h)));
132 0 : h->version_length =
133 0 : version_length (next_offset -
134 : (sizeof (*ip) + sizeof (*udp)));
135 :
136 0 : sum0 = ip->checksum;
137 0 : old_l0 = ip->length;
138 0 : new_l0 = clib_host_to_net_u16 ((u16) next_offset);
139 0 : sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
140 : length /* changed member */ );
141 :
142 0 : ip->checksum = ip_csum_fold (sum0);
143 0 : ip->length = new_l0;
144 0 : udp->length =
145 0 : clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
146 :
147 0 : udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
148 0 : if (udp->checksum == 0)
149 0 : udp->checksum = 0xffff;
150 :
151 0 : ASSERT (ip4_header_checksum_is_valid (ip));
152 :
153 0 : to_next[0] = bi0;
154 0 : f->n_vectors++;
155 0 : to_next++;
156 :
157 0 : if (f->n_vectors == VLIB_FRAME_SIZE)
158 : {
159 0 : vlib_put_frame_to_node (vm, node_index, f);
160 0 : f = vlib_get_frame_to_node (vm, node_index);
161 0 : f->n_vectors = 0;
162 0 : to_next = vlib_frame_vector_args (f);
163 : }
164 0 : b0 = 0;
165 0 : bi0 = ~0;
166 : }
167 : }
168 : }
169 : }
170 :
171 0 : if (b0)
172 : {
173 0 : b0->current_length = next_offset;
174 0 : b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
175 0 : tp = vlib_buffer_get_current (b0);
176 0 : ip = (ip4_header_t *) & tp->ip4;
177 0 : udp = (udp_header_t *) (ip + 1);
178 0 : h = &tp->ipfix.h;
179 0 : s = &tp->ipfix.s;
180 :
181 0 : s->set_id_length = ipfix_set_id_length (IOAM_FLOW_TEMPLATE_ID,
182 0 : next_offset - (sizeof (*ip) +
183 : sizeof (*udp) +
184 : sizeof (*h)));
185 0 : h->version_length =
186 0 : version_length (next_offset - (sizeof (*ip) + sizeof (*udp)));
187 :
188 0 : sum0 = ip->checksum;
189 0 : old_l0 = ip->length;
190 0 : new_l0 = clib_host_to_net_u16 ((u16) next_offset);
191 0 : sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
192 : length /* changed member */ );
193 :
194 0 : ip->checksum = ip_csum_fold (sum0);
195 0 : ip->length = new_l0;
196 0 : udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
197 :
198 0 : udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
199 0 : if (udp->checksum == 0)
200 0 : udp->checksum = 0xffff;
201 :
202 0 : ASSERT (ip4_header_checksum_is_valid (ip));
203 :
204 0 : to_next[0] = bi0;
205 0 : f->n_vectors++;
206 0 : to_next++;
207 :
208 0 : if (f->n_vectors == VLIB_FRAME_SIZE)
209 : {
210 0 : vlib_put_frame_to_node (vm, node_index, f);
211 0 : f = vlib_get_frame_to_node (vm, node_index);
212 0 : f->n_vectors = 0;
213 0 : to_next = vlib_frame_vector_args (f);
214 : }
215 0 : b0 = 0;
216 0 : bi0 = ~0;
217 : }
218 0 : return f;
219 : }
220 :
221 : clib_error_t *
222 0 : udp_ping_flow_create (u8 del)
223 : {
224 : vnet_flow_report_add_del_args_t args;
225 : int rv;
226 0 : u32 domain_id = 0;
227 0 : ipfix_exporter_t *exp = &flow_report_main.exporters[0];
228 : u16 template_id;
229 :
230 0 : clib_memset (&args, 0, sizeof (args));
231 0 : args.rewrite_callback = udp_ping_template_rewrite;
232 0 : args.flow_data_callback = udp_ping_send_flows;
233 0 : del ? (args.is_add = 0) : (args.is_add = 1);
234 0 : args.domain_id = domain_id;
235 0 : args.src_port = UDP_DST_PORT_ipfix;
236 :
237 0 : rv = vnet_flow_report_add_del (exp, &args, &template_id);
238 :
239 0 : switch (rv)
240 : {
241 0 : case 0:
242 0 : break;
243 0 : case VNET_API_ERROR_NO_SUCH_ENTRY:
244 0 : return clib_error_return (0, "registration not found...");
245 0 : default:
246 0 : return clib_error_return (0, "vnet_flow_report_add_del returned %d",
247 : rv);
248 : }
249 :
250 0 : return 0;
251 : }
252 :
253 : static clib_error_t *
254 0 : set_udp_ping_export_command_fn (vlib_main_t * vm, unformat_input_t * input,
255 : vlib_cli_command_t * cmd)
256 : {
257 : //int rv;
258 0 : int is_add = 1;
259 :
260 0 : while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
261 : {
262 0 : if (unformat (input, "export-ipfix"))
263 0 : is_add = 1;
264 0 : else if (unformat (input, "disable"))
265 0 : is_add = 0;
266 : else
267 0 : break;
268 : }
269 :
270 0 : if (is_add)
271 0 : (void) udp_ping_flow_create (0);
272 : else
273 0 : (void) udp_ping_flow_create (1);
274 :
275 0 : return 0;
276 : }
277 :
278 : /* *INDENT-OFF* */
279 176567 : VLIB_CLI_COMMAND (set_udp_ping_export_command, static) = {
280 : .path = "set udp-ping export-ipfix",
281 : .short_help = "set udp-ping export-ipfix [disable]",
282 : .function = set_udp_ping_export_command_fn,
283 : };
284 : /* *INDENT-ON* */
285 :
286 : clib_error_t *
287 559 : udp_ping_flow_report_init (vlib_main_t * vm)
288 : {
289 559 : return 0;
290 : }
291 :
292 : /* *INDENT-OFF* */
293 8399 : VLIB_INIT_FUNCTION (udp_ping_flow_report_init) =
294 : {
295 : .runs_after = VLIB_INITS ("flow_report_init"),
296 : };
297 : /* *INDENT-ON* */
298 :
299 :
300 : /*
301 : * fd.io coding-style-patch-verification: ON
302 : *
303 : * Local Variables:
304 : * eval: (c-set-style "gnu")
305 : * End:
306 : */
|