misc: fix issues reported by clang-15
[vpp.git] / src / plugins / ioam / udp-ping / udp_ping_export.c
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 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   return ioam_template_rewrite (exp, fr, collector_port, elts, n_elts,
31                                 stream_index);
32 }
33
34 static vlib_frame_t *
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,
37                      u32 node_index)
38 {
39   vlib_buffer_t *b0 = NULL;
40   u32 next_offset = 0;
41   u32 bi0 = ~0;
42   int i, j;
43   ip4_ipfix_template_packet_t *tp;
44   ipfix_message_header_t *h;
45   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   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   stream = &exp->streams[fr->stream_index];
58   data_len = vec_len (udp_ping_main.ip46_flow);
59
60   for (i = 0; i < data_len; i++)
61     {
62       if (pool_is_free_index (udp_ping_main.ip46_flow, i))
63         continue;
64
65       ip46_flow = pool_elt_at_index (udp_ping_main.ip46_flow, i);
66       j = 0;
67       for (src_port = ip46_flow->udp_data.start_src_port;
68            src_port <= ip46_flow->udp_data.end_src_port; src_port++)
69         {
70           for (dst_port = ip46_flow->udp_data.start_dst_port;
71                dst_port <= ip46_flow->udp_data.end_dst_port; dst_port++, j++)
72             {
73               stats = ip46_flow->udp_data.stats + j;
74               if (PREDICT_FALSE (b0 == NULL))
75                 {
76                   if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
77                     break;
78
79
80                   b0 = vlib_get_buffer (vm, bi0);
81                   memcpy (b0->data, fr->rewrite, vec_len (fr->rewrite));
82                   b0->current_data = 0;
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;
87
88                   tp = vlib_buffer_get_current (b0);
89                   ip = &tp->ip4;
90                   h = &tp->ipfix.h;
91                   s = &tp->ipfix.s;
92
93                   /* FIXUP: message header export_time */
94                   h->export_time = clib_host_to_net_u32 (((u32) time (NULL)));
95
96                   /* FIXUP: message header sequence_number */
97                   h->sequence_number = stream->sequence_number++;
98                   h->sequence_number =
99                     clib_host_to_net_u32 (h->sequence_number);
100                   next_offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
101                 }
102
103               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               if (next_offset > (exp->path_mtu - UDP_PING_EXPORT_RECORD_SIZE))
118                 {
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);
124                   h = &tp->ipfix.h;
125                   s = &tp->ipfix.s;
126
127                   s->set_id_length =
128                     ipfix_set_id_length (IOAM_FLOW_TEMPLATE_ID,
129                                          next_offset - (sizeof (*ip) +
130                                                         sizeof (*udp) +
131                                                         sizeof (*h)));
132                   h->version_length =
133                     version_length (next_offset -
134                                     (sizeof (*ip) + sizeof (*udp)));
135
136                   sum0 = ip->checksum;
137                   old_l0 = ip->length;
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 */ );
141
142                   ip->checksum = ip_csum_fold (sum0);
143                   ip->length = new_l0;
144                   udp->length =
145                     clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
146
147                   udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
148                   if (udp->checksum == 0)
149                     udp->checksum = 0xffff;
150
151                   ASSERT (ip4_header_checksum_is_valid (ip));
152
153                   to_next[0] = bi0;
154                   f->n_vectors++;
155                   to_next++;
156
157                   if (f->n_vectors == VLIB_FRAME_SIZE)
158                     {
159                       vlib_put_frame_to_node (vm, node_index, f);
160                       f = vlib_get_frame_to_node (vm, node_index);
161                       f->n_vectors = 0;
162                       to_next = vlib_frame_vector_args (f);
163                     }
164                   b0 = 0;
165                   bi0 = ~0;
166                 }
167             }
168         }
169     }
170
171   if (b0)
172     {
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);
178       h = &tp->ipfix.h;
179       s = &tp->ipfix.s;
180
181       s->set_id_length = ipfix_set_id_length (IOAM_FLOW_TEMPLATE_ID,
182                                               next_offset - (sizeof (*ip) +
183                                                              sizeof (*udp) +
184                                                              sizeof (*h)));
185       h->version_length =
186         version_length (next_offset - (sizeof (*ip) + sizeof (*udp)));
187
188       sum0 = ip->checksum;
189       old_l0 = ip->length;
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 */ );
193
194       ip->checksum = ip_csum_fold (sum0);
195       ip->length = new_l0;
196       udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
197
198       udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
199       if (udp->checksum == 0)
200         udp->checksum = 0xffff;
201
202       ASSERT (ip4_header_checksum_is_valid (ip));
203
204       to_next[0] = bi0;
205       f->n_vectors++;
206       to_next++;
207
208       if (f->n_vectors == VLIB_FRAME_SIZE)
209         {
210           vlib_put_frame_to_node (vm, node_index, f);
211           f = vlib_get_frame_to_node (vm, node_index);
212           f->n_vectors = 0;
213           to_next = vlib_frame_vector_args (f);
214         }
215       b0 = 0;
216       bi0 = ~0;
217     }
218   return f;
219 }
220
221 clib_error_t *
222 udp_ping_flow_create (u8 del)
223 {
224   vnet_flow_report_add_del_args_t args;
225   int rv;
226   u32 domain_id = 0;
227   ipfix_exporter_t *exp = &flow_report_main.exporters[0];
228   u16 template_id;
229
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;
236
237   rv = vnet_flow_report_add_del (exp, &args, &template_id);
238
239   switch (rv)
240     {
241     case 0:
242       break;
243     case VNET_API_ERROR_NO_SUCH_ENTRY:
244       return clib_error_return (0, "registration not found...");
245     default:
246       return clib_error_return (0, "vnet_flow_report_add_del returned %d",
247                                 rv);
248     }
249
250   return 0;
251 }
252
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)
256 {
257   //int rv;
258   int is_add = 1;
259
260   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
261     {
262       if (unformat (input, "export-ipfix"))
263         is_add = 1;
264       else if (unformat (input, "disable"))
265         is_add = 0;
266       else
267         break;
268     }
269
270   if (is_add)
271     (void) udp_ping_flow_create (0);
272   else
273     (void) udp_ping_flow_create (1);
274
275   return 0;
276 }
277
278 /* *INDENT-OFF* */
279 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 udp_ping_flow_report_init (vlib_main_t * vm)
288 {
289   return 0;
290 }
291
292 /* *INDENT-OFF* */
293 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  */