blob: 163ce10a369be0d2406a478c601c017a5abb0a4e [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * Copyright (c) 2015 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#include <vnet/flow/flow_report.h>
Juraj Sloboda819ec6f2016-08-07 23:40:03 -070016#include <vnet/flow/flow_report_classify.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070017#include <vnet/api_errno.h>
18
Juraj Slobodaffa652a2016-08-07 23:43:42 -070019/* Common prefix of tcp and udp headers
20 * containing only source and destination port fields */
Swarup Nayak6bcac062017-11-26 23:11:40 +053021typedef struct
22{
Juraj Slobodaffa652a2016-08-07 23:43:42 -070023 u16 src_port, dst_port;
24} tcpudp_header_t;
Ed Warnickecb9cada2015-12-08 15:45:58 -070025
Juraj Sloboda819ec6f2016-08-07 23:40:03 -070026flow_report_classify_main_t flow_report_classify_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -070027
Swarup Nayak6bcac062017-11-26 23:11:40 +053028u8 *
29ipfix_classify_template_rewrite (flow_report_main_t * frm,
30 flow_report_t * fr,
31 ip4_address_t * collector_address,
32 ip4_address_t * src_address,
33 u16 collector_port)
Ed Warnickecb9cada2015-12-08 15:45:58 -070034{
Swarup Nayak6bcac062017-11-26 23:11:40 +053035 flow_report_classify_main_t *fcm = &flow_report_classify_main;
36 vnet_classify_table_t *tblp;
37 vnet_classify_main_t *vcm = &vnet_classify_main;
Juraj Slobodaffa652a2016-08-07 23:43:42 -070038 u32 flow_table_index = fr->opaque.as_uword;
Swarup Nayak6bcac062017-11-26 23:11:40 +053039 u8 *ip_start;
40 ip4_header_t *ip;
41 ip6_header_t *ip6;
42 tcpudp_header_t *tcpudp;
43 udp_header_t *udp;
44 ipfix_message_header_t *h;
45 ipfix_set_header_t *s;
46 ipfix_template_header_t *t;
47 ipfix_field_specifier_t *f;
48 ipfix_field_specifier_t *first_field;
49 u8 *rewrite = 0;
50 ip4_ipfix_template_packet_t *tp;
Ed Warnickecb9cada2015-12-08 15:45:58 -070051 u32 field_count = 0;
52 u32 field_index = 0;
Swarup Nayak6bcac062017-11-26 23:11:40 +053053 flow_report_stream_t *stream;
Juraj Slobodaffa652a2016-08-07 23:43:42 -070054 u8 ip_version;
55 u8 transport_protocol;
Swarup Nayak6bcac062017-11-26 23:11:40 +053056 u8 *virt_mask;
57 u8 *real_mask;
Juraj Slobodaffa652a2016-08-07 23:43:42 -070058
59 stream = &frm->streams[fr->stream_index];
60
Swarup Nayak6bcac062017-11-26 23:11:40 +053061 ipfix_classify_table_t *table = &fcm->tables[flow_table_index];
Juraj Slobodaffa652a2016-08-07 23:43:42 -070062
63 ip_version = table->ip_version;
64 transport_protocol = table->transport_protocol;
65
66 tblp = pool_elt_at_index (vcm->tables, table->classify_table_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -070067
Swarup Nayak6bcac062017-11-26 23:11:40 +053068 virt_mask = (u8 *) (tblp->mask - tblp->skip_n_vectors);
69 real_mask = (u8 *) (tblp->mask);
Ed Warnickecb9cada2015-12-08 15:45:58 -070070
Ed Warnickecb9cada2015-12-08 15:45:58 -070071 /* Determine field count */
Swarup Nayak6bcac062017-11-26 23:11:40 +053072 ip_start = virt_mask + sizeof (ethernet_header_t);
Juraj Sloboda50332f62016-08-22 07:02:11 -070073#define _(field,mask,item,length) \
74 if (((u8 *)&field >= real_mask) && (memcmp(&field, &mask, length) == 0)) \
75 { \
76 field_count++; \
77 \
78 fr->fields_to_send = clib_bitmap_set (fr->fields_to_send, \
79 field_index, 1); \
80 } \
Ed Warnickecb9cada2015-12-08 15:45:58 -070081 field_index++;
Ed Warnickecb9cada2015-12-08 15:45:58 -070082 foreach_ipfix_field;
83#undef _
Juraj Slobodaffa652a2016-08-07 23:43:42 -070084
Ed Warnickecb9cada2015-12-08 15:45:58 -070085 /* Add packetTotalCount manually */
86 field_count += 1;
87
88 /* $$$ enterprise fields, at some later date */
89
90 /* allocate rewrite space */
Swarup Nayak6bcac062017-11-26 23:11:40 +053091 vec_validate_aligned (rewrite,
92 sizeof (ip4_ipfix_template_packet_t)
93 + field_count * sizeof (ipfix_field_specifier_t) - 1,
94 CLIB_CACHE_LINE_BYTES);
Ed Warnickecb9cada2015-12-08 15:45:58 -070095
96 tp = (ip4_ipfix_template_packet_t *) rewrite;
Swarup Nayak6bcac062017-11-26 23:11:40 +053097 ip = (ip4_header_t *) & tp->ip4;
98 udp = (udp_header_t *) (ip + 1);
99 h = (ipfix_message_header_t *) (udp + 1);
100 s = (ipfix_set_header_t *) (h + 1);
101 t = (ipfix_template_header_t *) (s + 1);
102 first_field = f = (ipfix_field_specifier_t *) (t + 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700103
104 ip->ip_version_and_header_length = 0x45;
105 ip->ttl = 254;
106 ip->protocol = IP_PROTOCOL_UDP;
107 ip->src_address.as_u32 = src_address->as_u32;
108 ip->dst_address.as_u32 = collector_address->as_u32;
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700109 udp->src_port = clib_host_to_net_u16 (stream->src_port);
Juraj Sloboda5a49bb92016-07-07 03:23:15 -0700110 udp->dst_port = clib_host_to_net_u16 (collector_port);
Swarup Nayak6bcac062017-11-26 23:11:40 +0530111 udp->length = clib_host_to_net_u16 (vec_len (rewrite) - sizeof (*ip));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700112
Swarup Nayak6bcac062017-11-26 23:11:40 +0530113 /* FIXUP: message header export_time */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700114 /* FIXUP: message header sequence_number */
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700115 h->domain_id = clib_host_to_net_u32 (stream->domain_id);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700116
117 /* Take another trip through the mask and build the template */
Swarup Nayak6bcac062017-11-26 23:11:40 +0530118 ip_start = virt_mask + sizeof (ethernet_header_t);
Juraj Sloboda50332f62016-08-22 07:02:11 -0700119#define _(field,mask,item,length) \
120 if (((u8 *)&field >= real_mask) && (memcmp(&field, &mask, length) == 0)) \
121 { \
122 f->e_id_length = ipfix_e_id_length (0 /* enterprise */, \
123 item, length); \
124 f++; \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700125 }
126 foreach_ipfix_field;
127#undef _
128
129 /* Add packetTotalCount manually */
Swarup Nayak6bcac062017-11-26 23:11:40 +0530130 f->e_id_length =
131 ipfix_e_id_length (0 /* enterprise */ , packetTotalCount, 8);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700132 f++;
133
134 /* Back to the template packet... */
Swarup Nayak6bcac062017-11-26 23:11:40 +0530135 ip = (ip4_header_t *) & tp->ip4;
136 udp = (udp_header_t *) (ip + 1);
137
Ed Warnickecb9cada2015-12-08 15:45:58 -0700138 ASSERT (f - first_field);
139 /* Field count in this template */
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700140 t->id_count = ipfix_id_count (fr->template_id, f - first_field);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700141
Swarup Nayak6bcac062017-11-26 23:11:40 +0530142 /* set length in octets */
143 s->set_id_length =
144 ipfix_set_id_length (2 /* set_id */ , (u8 *) f - (u8 *) s);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700145
146 /* message length in octets */
Swarup Nayak6bcac062017-11-26 23:11:40 +0530147 h->version_length = version_length ((u8 *) f - (u8 *) h);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700148
Swarup Nayak6bcac062017-11-26 23:11:40 +0530149 ip->length = clib_host_to_net_u16 ((u8 *) f - (u8 *) ip);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700150 ip->checksum = ip4_header_checksum (ip);
151
152 return rewrite;
153}
154
Swarup Nayak6bcac062017-11-26 23:11:40 +0530155vlib_frame_t *
156ipfix_classify_send_flows (flow_report_main_t * frm,
157 flow_report_t * fr,
158 vlib_frame_t * f, u32 * to_next, u32 node_index)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700159{
Swarup Nayak6bcac062017-11-26 23:11:40 +0530160 flow_report_classify_main_t *fcm = &flow_report_classify_main;
161 vnet_classify_main_t *vcm = &vnet_classify_main;
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700162 u32 flow_table_index = fr->opaque.as_uword;
Swarup Nayak6bcac062017-11-26 23:11:40 +0530163 vnet_classify_table_t *t;
164 vnet_classify_bucket_t *b;
165 vnet_classify_entry_t *v, *save_v;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700166 vlib_buffer_t *b0 = 0;
167 u32 next_offset = 0;
Juraj Sloboda5a49bb92016-07-07 03:23:15 -0700168 u32 record_offset = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700169 u32 bi0 = ~0;
170 int i, j, k;
Swarup Nayak6bcac062017-11-26 23:11:40 +0530171 ip4_ipfix_template_packet_t *tp;
172 ipfix_message_header_t *h = 0;
173 ipfix_set_header_t *s = 0;
174 u8 *ip_start;
175 ip4_header_t *ip;
176 ip6_header_t *ip6;
177 tcpudp_header_t *tcpudp;
178 udp_header_t *udp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700179 int field_index;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700180 u32 records_this_buffer;
181 u16 new_l0, old_l0;
182 ip_csum_t sum0;
Swarup Nayak6bcac062017-11-26 23:11:40 +0530183 vlib_main_t *vm = frm->vlib_main;
184 flow_report_stream_t *stream;
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700185 u8 ip_version;
186 u8 transport_protocol;
Swarup Nayak6bcac062017-11-26 23:11:40 +0530187 u8 *virt_key;
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700188
189 stream = &frm->streams[fr->stream_index];
190
Swarup Nayak6bcac062017-11-26 23:11:40 +0530191 ipfix_classify_table_t *table = &fcm->tables[flow_table_index];
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700192
193 ip_version = table->ip_version;
194 transport_protocol = table->transport_protocol;
195
196 t = pool_elt_at_index (vcm->tables, table->classify_table_index);
Swarup Nayak6bcac062017-11-26 23:11:40 +0530197
Ed Warnickecb9cada2015-12-08 15:45:58 -0700198 while (__sync_lock_test_and_set (t->writer_lock, 1))
Swarup Nayak6bcac062017-11-26 23:11:40 +0530199 ;
200
Ed Warnickecb9cada2015-12-08 15:45:58 -0700201 for (i = 0; i < t->nbuckets; i++)
202 {
Swarup Nayak6bcac062017-11-26 23:11:40 +0530203 b = &t->buckets[i];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700204 if (b->offset == 0)
Swarup Nayak6bcac062017-11-26 23:11:40 +0530205 continue;
206
Ed Warnickecb9cada2015-12-08 15:45:58 -0700207 save_v = vnet_classify_get_entry (t, b->offset);
Swarup Nayak6bcac062017-11-26 23:11:40 +0530208 for (j = 0; j < (1 << b->log2_pages); j++)
209 {
210 for (k = 0; k < t->entries_per_page; k++)
211 {
212 v = vnet_classify_entry_at_index
213 (t, save_v, j * t->entries_per_page + k);
Juraj Sloboda0d2a8e72016-07-07 02:59:28 -0700214
Swarup Nayak6bcac062017-11-26 23:11:40 +0530215 if (vnet_classify_entry_is_free (v))
216 continue;
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700217
Swarup Nayak6bcac062017-11-26 23:11:40 +0530218 /* OK, we have something to send... */
219 if (PREDICT_FALSE (b0 == 0))
220 {
221 if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
222 goto flush;
223 b0 = vlib_get_buffer (vm, bi0);
224
225 u32 copy_len = sizeof (ip4_header_t) +
226 sizeof (udp_header_t) + sizeof (ipfix_message_header_t);
227 clib_memcpy (b0->data, fr->rewrite, copy_len);
228 b0->current_data = 0;
229 b0->current_length = copy_len;
230 b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
231 vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
232 vnet_buffer (b0)->sw_if_index[VLIB_TX] = frm->fib_index;
233
234 tp = vlib_buffer_get_current (b0);
235 ip = (ip4_header_t *) & tp->ip4;
236 udp = (udp_header_t *) (ip + 1);
237 h = (ipfix_message_header_t *) (udp + 1);
238 s = (ipfix_set_header_t *) (h + 1);
239
240 /* FIXUP: message header export_time */
241 h->export_time = (u32)
242 (((f64) frm->unix_time_0) +
243 (vlib_time_now (frm->vlib_main) - frm->vlib_time_0));
244 h->export_time = clib_host_to_net_u32 (h->export_time);
245
246 /* FIXUP: message header sequence_number */
247 h->sequence_number = stream->sequence_number;
248 h->sequence_number =
249 clib_host_to_net_u32 (h->sequence_number);
250
251 next_offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
252 record_offset = next_offset;
253 records_this_buffer = 0;
254 }
255
256 field_index = 0;
257 virt_key = (u8 *) (v->key - t->skip_n_vectors);
258 ip_start = virt_key + sizeof (ethernet_header_t);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700259#define _(field,mask,item,length) \
260 if (clib_bitmap_get (fr->fields_to_send, field_index)) \
261 { \
Damjan Marionf1213b82016-03-13 02:22:06 +0100262 clib_memcpy (b0->data + next_offset, &field, \
Ed Warnickecb9cada2015-12-08 15:45:58 -0700263 length); \
264 next_offset += length; \
265 } \
266 field_index++;
Swarup Nayak6bcac062017-11-26 23:11:40 +0530267 foreach_ipfix_field;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700268#undef _
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700269
Swarup Nayak6bcac062017-11-26 23:11:40 +0530270 /* Add packetTotalCount manually */
271 {
272 u64 packets = clib_host_to_net_u64 (v->hits);
273 clib_memcpy (b0->data + next_offset, &packets,
274 sizeof (packets));
275 next_offset += sizeof (packets);
276 }
277 records_this_buffer++;
278 stream->sequence_number++;
Juraj Sloboda5a49bb92016-07-07 03:23:15 -0700279
Swarup Nayak6bcac062017-11-26 23:11:40 +0530280 /* Next record will have the same size as this record */
281 u32 next_record_size = next_offset - record_offset;
282 record_offset = next_offset;
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700283
Swarup Nayak6bcac062017-11-26 23:11:40 +0530284 if (next_offset + next_record_size > frm->path_mtu)
285 {
286 s->set_id_length = ipfix_set_id_length (fr->template_id,
287 next_offset -
288 (sizeof (*ip) +
289 sizeof (*udp) +
290 sizeof (*h)));
291 h->version_length =
292 version_length (next_offset -
293 (sizeof (*ip) + sizeof (*udp)));
294 b0->current_length = next_offset;
295 b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700296
Swarup Nayak6bcac062017-11-26 23:11:40 +0530297 tp = vlib_buffer_get_current (b0);
298 ip = (ip4_header_t *) & tp->ip4;
299 udp = (udp_header_t *) (ip + 1);
Juraj Sloboda0d2a8e72016-07-07 02:59:28 -0700300
Swarup Nayak6bcac062017-11-26 23:11:40 +0530301 sum0 = ip->checksum;
302 old_l0 = ip->length;
303 new_l0 = clib_host_to_net_u16 ((u16) next_offset);
304
305 sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
306 length /* changed member */ );
307
308 ip->checksum = ip_csum_fold (sum0);
309 ip->length = new_l0;
310 udp->length =
311 clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
312
313 if (frm->udp_checksum)
314 {
315 /* RFC 7011 section 10.3.2. */
316 udp->checksum =
317 ip4_tcp_udp_compute_checksum (vm, b0, ip);
318 if (udp->checksum == 0)
319 udp->checksum = 0xffff;
320 }
321
322 ASSERT (ip->checksum == ip4_header_checksum (ip));
323
324 to_next[0] = bi0;
325 f->n_vectors++;
326 to_next++;
327
328 if (f->n_vectors == VLIB_FRAME_SIZE)
329 {
330 vlib_put_frame_to_node (vm, node_index, f);
331 f = vlib_get_frame_to_node (vm, node_index);
332 f->n_vectors = 0;
333 to_next = vlib_frame_vector_args (f);
334 }
335 b0 = 0;
336 bi0 = ~0;
337 }
338 }
339 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700340 }
Swarup Nayak6bcac062017-11-26 23:11:40 +0530341
342flush:
Ed Warnickecb9cada2015-12-08 15:45:58 -0700343 if (b0)
344 {
Swarup Nayak6bcac062017-11-26 23:11:40 +0530345 s->set_id_length = ipfix_set_id_length (fr->template_id,
346 next_offset -
347 (sizeof (*ip) + sizeof (*udp) +
348 sizeof (*h)));
349 h->version_length = version_length (next_offset -
350 (sizeof (*ip) + sizeof (*udp)));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700351 b0->current_length = next_offset;
352 b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
Swarup Nayak6bcac062017-11-26 23:11:40 +0530353
Ed Warnickecb9cada2015-12-08 15:45:58 -0700354 tp = vlib_buffer_get_current (b0);
Swarup Nayak6bcac062017-11-26 23:11:40 +0530355 ip = (ip4_header_t *) & tp->ip4;
356 udp = (udp_header_t *) (ip + 1);
357
Ed Warnickecb9cada2015-12-08 15:45:58 -0700358 sum0 = ip->checksum;
359 old_l0 = ip->length;
Swarup Nayak6bcac062017-11-26 23:11:40 +0530360 new_l0 = clib_host_to_net_u16 ((u16) next_offset);
361
Ed Warnickecb9cada2015-12-08 15:45:58 -0700362 sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
Swarup Nayak6bcac062017-11-26 23:11:40 +0530363 length /* changed member */ );
364
Ed Warnickecb9cada2015-12-08 15:45:58 -0700365 ip->checksum = ip_csum_fold (sum0);
366 ip->length = new_l0;
367 udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
368
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700369 if (frm->udp_checksum)
Swarup Nayak6bcac062017-11-26 23:11:40 +0530370 {
371 /* RFC 7011 section 10.3.2. */
372 udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
373 if (udp->checksum == 0)
374 udp->checksum = 0xffff;
375 }
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700376
Ed Warnickecb9cada2015-12-08 15:45:58 -0700377 ASSERT (ip->checksum == ip4_header_checksum (ip));
Swarup Nayak6bcac062017-11-26 23:11:40 +0530378
Ed Warnickecb9cada2015-12-08 15:45:58 -0700379 to_next[0] = bi0;
380 f->n_vectors++;
Swarup Nayak6bcac062017-11-26 23:11:40 +0530381
Ed Warnickecb9cada2015-12-08 15:45:58 -0700382 b0 = 0;
383 bi0 = ~0;
384 }
Swarup Nayak6bcac062017-11-26 23:11:40 +0530385
Ed Warnickecb9cada2015-12-08 15:45:58 -0700386 *(t->writer_lock) = 0;
387 return f;
388}
389
Ed Warnickecb9cada2015-12-08 15:45:58 -0700390static clib_error_t *
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700391ipfix_classify_table_add_del_command_fn (vlib_main_t * vm,
Swarup Nayak6bcac062017-11-26 23:11:40 +0530392 unformat_input_t * input,
393 vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700394{
Juraj Sloboda819ec6f2016-08-07 23:40:03 -0700395 flow_report_classify_main_t *fcm = &flow_report_classify_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700396 flow_report_main_t *frm = &flow_report_main;
397 vnet_flow_report_add_del_args_t args;
Swarup Nayak6bcac062017-11-26 23:11:40 +0530398 ipfix_classify_table_t *table;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700399 int rv;
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700400 int is_add = -1;
Juraj Sloboda24648ad2016-09-06 04:43:52 -0700401 u32 classify_table_index = ~0;
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700402 u8 ip_version = 0;
403 u8 transport_protocol = 255;
Swarup Nayak6bcac062017-11-26 23:11:40 +0530404 clib_error_t *error = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700405
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700406 if (fcm->src_port == 0)
407 clib_error_return (0, "call 'set ipfix classify stream' first");
408
Ed Warnickecb9cada2015-12-08 15:45:58 -0700409 memset (&args, 0, sizeof (args));
410
Swarup Nayak6bcac062017-11-26 23:11:40 +0530411 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
412 {
413 if (unformat (input, "add"))
414 is_add = 1;
415 else if (unformat (input, "del"))
416 is_add = 0;
417 else if (unformat (input, "%d", &classify_table_index))
418 ;
419 else if (unformat (input, "ip4"))
420 ip_version = 4;
421 else if (unformat (input, "ip6"))
422 ip_version = 6;
423 else if (unformat (input, "tcp"))
424 transport_protocol = 6;
425 else if (unformat (input, "udp"))
426 transport_protocol = 17;
427 else
428 return clib_error_return (0, "unknown input `%U'",
429 format_unformat_error, input);
430 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700431
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700432 if (is_add == -1)
433 return clib_error_return (0, "expecting: add|del");
434 if (classify_table_index == ~0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700435 return clib_error_return (0, "classifier table not specified");
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700436 if (ip_version == 0)
437 return clib_error_return (0, "IP version not specified");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700438
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700439 table = 0;
440 int i;
Swarup Nayak6bcac062017-11-26 23:11:40 +0530441 for (i = 0; i < vec_len (fcm->tables); i++)
442 if (ipfix_classify_table_index_valid (i))
443 if (fcm->tables[i].classify_table_index == classify_table_index)
444 {
445 table = &fcm->tables[i];
446 break;
447 }
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700448
Swarup Nayak6bcac062017-11-26 23:11:40 +0530449 if (is_add)
450 {
451 if (table)
452 return clib_error_return (0,
453 "Specified classifier table already used");
454 table = ipfix_classify_add_table ();
455 table->classify_table_index = classify_table_index;
456 }
457 else
458 {
459 if (!table)
460 return clib_error_return (0,
461 "Specified classifier table not registered");
462 }
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700463
464 table->ip_version = ip_version;
465 table->transport_protocol = transport_protocol;
466
467 args.opaque.as_uword = table - fcm->tables;
468 args.rewrite_callback = ipfix_classify_template_rewrite;
469 args.flow_data_callback = ipfix_classify_send_flows;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700470 args.is_add = is_add;
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700471 args.domain_id = fcm->domain_id;
472 args.src_port = fcm->src_port;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700473
Ole Troan5c749732017-03-13 13:39:52 +0100474 rv = vnet_flow_report_add_del (frm, &args, NULL);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700475
Swarup Nayak6bcac062017-11-26 23:11:40 +0530476 error = flow_report_add_del_error_to_clib_error (rv);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700477
Juraj Sloboda24648ad2016-09-06 04:43:52 -0700478 /* If deleting, or add failed */
479 if (is_add == 0 || (rv && is_add))
480 ipfix_classify_delete_table (table - fcm->tables);
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700481
Juraj Sloboda24648ad2016-09-06 04:43:52 -0700482 return error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700483}
484
Swarup Nayak6bcac062017-11-26 23:11:40 +0530485/* *INDENT-OFF* */
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700486VLIB_CLI_COMMAND (ipfix_classify_table_add_del_command, static) = {
487 .path = "ipfix classify table",
488 .short_help = "ipfix classify table add|del <table-index>",
489 .function = ipfix_classify_table_add_del_command_fn,
490};
Swarup Nayak6bcac062017-11-26 23:11:40 +0530491/* *INDENT-ON* */
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700492
493static clib_error_t *
494set_ipfix_classify_stream_command_fn (vlib_main_t * vm,
Swarup Nayak6bcac062017-11-26 23:11:40 +0530495 unformat_input_t * input,
496 vlib_cli_command_t * cmd)
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700497{
498 flow_report_classify_main_t *fcm = &flow_report_classify_main;
499 flow_report_main_t *frm = &flow_report_main;
500 u32 domain_id = 1;
501 u32 src_port = UDP_DST_PORT_ipfix;
502
Swarup Nayak6bcac062017-11-26 23:11:40 +0530503 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
504 {
505 if (unformat (input, "domain %d", &domain_id))
506 ;
507 else if (unformat (input, "src-port %d", &src_port))
508 ;
509 else
510 return clib_error_return (0, "unknown input `%U'",
511 format_unformat_error, input);
512 }
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700513
514 if (fcm->src_port != 0 &&
Swarup Nayak6bcac062017-11-26 23:11:40 +0530515 (fcm->domain_id != domain_id || fcm->src_port != (u16) src_port))
516 {
517 int rv = vnet_stream_change (frm, fcm->domain_id, fcm->src_port,
518 domain_id, (u16) src_port);
519 ASSERT (rv == 0);
520 }
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700521
522 fcm->domain_id = domain_id;
Swarup Nayak6bcac062017-11-26 23:11:40 +0530523 fcm->src_port = (u16) src_port;
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700524
525 return 0;
526}
527
Swarup Nayak6bcac062017-11-26 23:11:40 +0530528/* *INDENT-OFF* */
Juraj Slobodaffa652a2016-08-07 23:43:42 -0700529VLIB_CLI_COMMAND (set_ipfix_classify_stream_command, static) = {
530 .path = "set ipfix classify stream",
531 .short_help = "set ipfix classify stream"
532 "[domain <domain-id>] [src-port <src-port>]",
533 .function = set_ipfix_classify_stream_command_fn,
Ed Warnickecb9cada2015-12-08 15:45:58 -0700534};
Swarup Nayak6bcac062017-11-26 23:11:40 +0530535/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700536
537static clib_error_t *
Swarup Nayak6bcac062017-11-26 23:11:40 +0530538flow_report_classify_init (vlib_main_t * vm)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700539{
Swarup Nayak6bcac062017-11-26 23:11:40 +0530540 clib_error_t *error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700541
542 if ((error = vlib_call_init_function (vm, flow_report_init)))
543 return error;
544
545 return 0;
546}
547
Juraj Sloboda819ec6f2016-08-07 23:40:03 -0700548VLIB_INIT_FUNCTION (flow_report_classify_init);
Swarup Nayak6bcac062017-11-26 23:11:40 +0530549
550/*
551 * fd.io coding-style-patch-verification: ON
552 *
553 * Local Variables:
554 * eval: (c-set-style "gnu")
555 * End:
556 */