Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 1 | /* |
| 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 Sloboda | 819ec6f | 2016-08-07 23:40:03 -0700 | [diff] [blame] | 16 | #include <vnet/flow/flow_report_classify.h> |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 17 | #include <vnet/api_errno.h> |
| 18 | |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 19 | /* Common prefix of tcp and udp headers |
| 20 | * containing only source and destination port fields */ |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 21 | typedef struct |
| 22 | { |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 23 | u16 src_port, dst_port; |
| 24 | } tcpudp_header_t; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 25 | |
Juraj Sloboda | 819ec6f | 2016-08-07 23:40:03 -0700 | [diff] [blame] | 26 | flow_report_classify_main_t flow_report_classify_main; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 27 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 28 | u8 * |
| 29 | ipfix_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 Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 34 | { |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 35 | 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 Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 38 | u32 flow_table_index = fr->opaque.as_uword; |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 39 | 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 Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 51 | u32 field_count = 0; |
| 52 | u32 field_index = 0; |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 53 | flow_report_stream_t *stream; |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 54 | u8 ip_version; |
| 55 | u8 transport_protocol; |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 56 | u8 *virt_mask; |
| 57 | u8 *real_mask; |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 58 | |
| 59 | stream = &frm->streams[fr->stream_index]; |
| 60 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 61 | ipfix_classify_table_t *table = &fcm->tables[flow_table_index]; |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 62 | |
| 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 Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 67 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 68 | virt_mask = (u8 *) (tblp->mask - tblp->skip_n_vectors); |
| 69 | real_mask = (u8 *) (tblp->mask); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 70 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 71 | /* Determine field count */ |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 72 | ip_start = virt_mask + sizeof (ethernet_header_t); |
Juraj Sloboda | 50332f6 | 2016-08-22 07:02:11 -0700 | [diff] [blame] | 73 | #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 Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 81 | field_index++; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 82 | foreach_ipfix_field; |
| 83 | #undef _ |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 84 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 85 | /* Add packetTotalCount manually */ |
| 86 | field_count += 1; |
| 87 | |
| 88 | /* $$$ enterprise fields, at some later date */ |
| 89 | |
| 90 | /* allocate rewrite space */ |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 91 | 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 Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 95 | |
| 96 | tp = (ip4_ipfix_template_packet_t *) rewrite; |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 97 | 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 Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 103 | |
| 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 Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 109 | udp->src_port = clib_host_to_net_u16 (stream->src_port); |
Juraj Sloboda | 5a49bb9 | 2016-07-07 03:23:15 -0700 | [diff] [blame] | 110 | udp->dst_port = clib_host_to_net_u16 (collector_port); |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 111 | udp->length = clib_host_to_net_u16 (vec_len (rewrite) - sizeof (*ip)); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 112 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 113 | /* FIXUP: message header export_time */ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 114 | /* FIXUP: message header sequence_number */ |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 115 | h->domain_id = clib_host_to_net_u32 (stream->domain_id); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 116 | |
| 117 | /* Take another trip through the mask and build the template */ |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 118 | ip_start = virt_mask + sizeof (ethernet_header_t); |
Juraj Sloboda | 50332f6 | 2016-08-22 07:02:11 -0700 | [diff] [blame] | 119 | #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 Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 125 | } |
| 126 | foreach_ipfix_field; |
| 127 | #undef _ |
| 128 | |
| 129 | /* Add packetTotalCount manually */ |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 130 | f->e_id_length = |
| 131 | ipfix_e_id_length (0 /* enterprise */ , packetTotalCount, 8); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 132 | f++; |
| 133 | |
| 134 | /* Back to the template packet... */ |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 135 | ip = (ip4_header_t *) & tp->ip4; |
| 136 | udp = (udp_header_t *) (ip + 1); |
| 137 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 138 | ASSERT (f - first_field); |
| 139 | /* Field count in this template */ |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 140 | t->id_count = ipfix_id_count (fr->template_id, f - first_field); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 141 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 142 | /* set length in octets */ |
| 143 | s->set_id_length = |
| 144 | ipfix_set_id_length (2 /* set_id */ , (u8 *) f - (u8 *) s); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 145 | |
| 146 | /* message length in octets */ |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 147 | h->version_length = version_length ((u8 *) f - (u8 *) h); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 148 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 149 | ip->length = clib_host_to_net_u16 ((u8 *) f - (u8 *) ip); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 150 | ip->checksum = ip4_header_checksum (ip); |
| 151 | |
| 152 | return rewrite; |
| 153 | } |
| 154 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 155 | vlib_frame_t * |
| 156 | ipfix_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 Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 159 | { |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 160 | flow_report_classify_main_t *fcm = &flow_report_classify_main; |
| 161 | vnet_classify_main_t *vcm = &vnet_classify_main; |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 162 | u32 flow_table_index = fr->opaque.as_uword; |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 163 | vnet_classify_table_t *t; |
| 164 | vnet_classify_bucket_t *b; |
| 165 | vnet_classify_entry_t *v, *save_v; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 166 | vlib_buffer_t *b0 = 0; |
| 167 | u32 next_offset = 0; |
Juraj Sloboda | 5a49bb9 | 2016-07-07 03:23:15 -0700 | [diff] [blame] | 168 | u32 record_offset = 0; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 169 | u32 bi0 = ~0; |
| 170 | int i, j, k; |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 171 | 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 Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 179 | int field_index; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 180 | u32 records_this_buffer; |
| 181 | u16 new_l0, old_l0; |
| 182 | ip_csum_t sum0; |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 183 | vlib_main_t *vm = frm->vlib_main; |
| 184 | flow_report_stream_t *stream; |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 185 | u8 ip_version; |
| 186 | u8 transport_protocol; |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 187 | u8 *virt_key; |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 188 | |
| 189 | stream = &frm->streams[fr->stream_index]; |
| 190 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 191 | ipfix_classify_table_t *table = &fcm->tables[flow_table_index]; |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 192 | |
| 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 Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 197 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 198 | while (__sync_lock_test_and_set (t->writer_lock, 1)) |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 199 | ; |
| 200 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 201 | for (i = 0; i < t->nbuckets; i++) |
| 202 | { |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 203 | b = &t->buckets[i]; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 204 | if (b->offset == 0) |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 205 | continue; |
| 206 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 207 | save_v = vnet_classify_get_entry (t, b->offset); |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 208 | 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 Sloboda | 0d2a8e7 | 2016-07-07 02:59:28 -0700 | [diff] [blame] | 214 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 215 | if (vnet_classify_entry_is_free (v)) |
| 216 | continue; |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 217 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 218 | /* 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 Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 259 | #define _(field,mask,item,length) \ |
| 260 | if (clib_bitmap_get (fr->fields_to_send, field_index)) \ |
| 261 | { \ |
Damjan Marion | f1213b8 | 2016-03-13 02:22:06 +0100 | [diff] [blame] | 262 | clib_memcpy (b0->data + next_offset, &field, \ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 263 | length); \ |
| 264 | next_offset += length; \ |
| 265 | } \ |
| 266 | field_index++; |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 267 | foreach_ipfix_field; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 268 | #undef _ |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 269 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 270 | /* 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 Sloboda | 5a49bb9 | 2016-07-07 03:23:15 -0700 | [diff] [blame] | 279 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 280 | /* 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 Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 283 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 284 | 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 Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 296 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 297 | tp = vlib_buffer_get_current (b0); |
| 298 | ip = (ip4_header_t *) & tp->ip4; |
| 299 | udp = (udp_header_t *) (ip + 1); |
Juraj Sloboda | 0d2a8e7 | 2016-07-07 02:59:28 -0700 | [diff] [blame] | 300 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 301 | 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 Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 340 | } |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 341 | |
| 342 | flush: |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 343 | if (b0) |
| 344 | { |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 345 | 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 Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 351 | b0->current_length = next_offset; |
| 352 | b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID; |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 353 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 354 | tp = vlib_buffer_get_current (b0); |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 355 | ip = (ip4_header_t *) & tp->ip4; |
| 356 | udp = (udp_header_t *) (ip + 1); |
| 357 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 358 | sum0 = ip->checksum; |
| 359 | old_l0 = ip->length; |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 360 | new_l0 = clib_host_to_net_u16 ((u16) next_offset); |
| 361 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 362 | sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t, |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 363 | length /* changed member */ ); |
| 364 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 365 | 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 Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 369 | if (frm->udp_checksum) |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 370 | { |
| 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 Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 376 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 377 | ASSERT (ip->checksum == ip4_header_checksum (ip)); |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 378 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 379 | to_next[0] = bi0; |
| 380 | f->n_vectors++; |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 381 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 382 | b0 = 0; |
| 383 | bi0 = ~0; |
| 384 | } |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 385 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 386 | *(t->writer_lock) = 0; |
| 387 | return f; |
| 388 | } |
| 389 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 390 | static clib_error_t * |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 391 | ipfix_classify_table_add_del_command_fn (vlib_main_t * vm, |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 392 | unformat_input_t * input, |
| 393 | vlib_cli_command_t * cmd) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 394 | { |
Juraj Sloboda | 819ec6f | 2016-08-07 23:40:03 -0700 | [diff] [blame] | 395 | flow_report_classify_main_t *fcm = &flow_report_classify_main; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 396 | flow_report_main_t *frm = &flow_report_main; |
| 397 | vnet_flow_report_add_del_args_t args; |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 398 | ipfix_classify_table_t *table; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 399 | int rv; |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 400 | int is_add = -1; |
Juraj Sloboda | 24648ad | 2016-09-06 04:43:52 -0700 | [diff] [blame] | 401 | u32 classify_table_index = ~0; |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 402 | u8 ip_version = 0; |
| 403 | u8 transport_protocol = 255; |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 404 | clib_error_t *error = 0; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 405 | |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 406 | if (fcm->src_port == 0) |
| 407 | clib_error_return (0, "call 'set ipfix classify stream' first"); |
| 408 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 409 | memset (&args, 0, sizeof (args)); |
| 410 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 411 | 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 Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 431 | |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 432 | if (is_add == -1) |
| 433 | return clib_error_return (0, "expecting: add|del"); |
| 434 | if (classify_table_index == ~0) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 435 | return clib_error_return (0, "classifier table not specified"); |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 436 | if (ip_version == 0) |
| 437 | return clib_error_return (0, "IP version not specified"); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 438 | |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 439 | table = 0; |
| 440 | int i; |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 441 | 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 Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 448 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 449 | 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 Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 463 | |
| 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 Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 470 | args.is_add = is_add; |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 471 | args.domain_id = fcm->domain_id; |
| 472 | args.src_port = fcm->src_port; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 473 | |
Ole Troan | 5c74973 | 2017-03-13 13:39:52 +0100 | [diff] [blame] | 474 | rv = vnet_flow_report_add_del (frm, &args, NULL); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 475 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 476 | error = flow_report_add_del_error_to_clib_error (rv); |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 477 | |
Juraj Sloboda | 24648ad | 2016-09-06 04:43:52 -0700 | [diff] [blame] | 478 | /* If deleting, or add failed */ |
| 479 | if (is_add == 0 || (rv && is_add)) |
| 480 | ipfix_classify_delete_table (table - fcm->tables); |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 481 | |
Juraj Sloboda | 24648ad | 2016-09-06 04:43:52 -0700 | [diff] [blame] | 482 | return error; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 483 | } |
| 484 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 485 | /* *INDENT-OFF* */ |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 486 | VLIB_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 Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 491 | /* *INDENT-ON* */ |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 492 | |
| 493 | static clib_error_t * |
| 494 | set_ipfix_classify_stream_command_fn (vlib_main_t * vm, |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 495 | unformat_input_t * input, |
| 496 | vlib_cli_command_t * cmd) |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 497 | { |
| 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 Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 503 | 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 Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 513 | |
| 514 | if (fcm->src_port != 0 && |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 515 | (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 Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 521 | |
| 522 | fcm->domain_id = domain_id; |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 523 | fcm->src_port = (u16) src_port; |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 524 | |
| 525 | return 0; |
| 526 | } |
| 527 | |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 528 | /* *INDENT-OFF* */ |
Juraj Sloboda | ffa652a | 2016-08-07 23:43:42 -0700 | [diff] [blame] | 529 | VLIB_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 Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 534 | }; |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 535 | /* *INDENT-ON* */ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 536 | |
| 537 | static clib_error_t * |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 538 | flow_report_classify_init (vlib_main_t * vm) |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 539 | { |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 540 | clib_error_t *error; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 541 | |
| 542 | if ((error = vlib_call_init_function (vm, flow_report_init))) |
| 543 | return error; |
| 544 | |
| 545 | return 0; |
| 546 | } |
| 547 | |
Juraj Sloboda | 819ec6f | 2016-08-07 23:40:03 -0700 | [diff] [blame] | 548 | VLIB_INIT_FUNCTION (flow_report_classify_init); |
Swarup Nayak | 6bcac06 | 2017-11-26 23:11:40 +0530 | [diff] [blame] | 549 | |
| 550 | /* |
| 551 | * fd.io coding-style-patch-verification: ON |
| 552 | * |
| 553 | * Local Variables: |
| 554 | * eval: (c-set-style "gnu") |
| 555 | * End: |
| 556 | */ |