LCOV - code coverage report
Current view: top level - vnet/ipfix-export - flow_report_classify.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 6 256 2.3 %
Date: 2023-10-26 01:39:38 Functions: 7 11 63.6 %

          Line data    Source code
       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/ipfix-export/flow_report.h>
      16             : #include <vnet/ipfix-export/flow_report_classify.h>
      17             : #include <vnet/api_errno.h>
      18             : #include <vnet/classify/vnet_classify.h>
      19             : #include <vnet/ip/ip4.h>
      20             : #include <vnet/udp/udp_local.h>
      21             : 
      22             : /* Common prefix of tcp and udp headers
      23             :  * containing only source and destination port fields */
      24             : typedef struct
      25             : {
      26             :   u16 src_port, dst_port;
      27             : } tcpudp_header_t;
      28             : 
      29             : flow_report_classify_main_t flow_report_classify_main;
      30             : 
      31             : u8 *
      32           0 : ipfix_classify_template_rewrite (ipfix_exporter_t *exp, flow_report_t *fr,
      33             :                                  u16 collector_port,
      34             :                                  ipfix_report_element_t *elts, u32 n_elts,
      35             :                                  u32 *stream_index)
      36             : {
      37           0 :   flow_report_classify_main_t *fcm = &flow_report_classify_main;
      38             :   vnet_classify_table_t *tblp;
      39           0 :   vnet_classify_main_t *vcm = &vnet_classify_main;
      40           0 :   u32 flow_table_index = fr->opaque.as_uword;
      41             :   u8 *ip_start;
      42             :   ip4_header_t *ip;
      43             :   ip6_header_t *ip6;
      44             :   tcpudp_header_t *tcpudp;
      45             :   udp_header_t *udp;
      46             :   ipfix_message_header_t *h;
      47             :   ipfix_set_header_t *s;
      48             :   ipfix_template_header_t *t;
      49             :   ipfix_field_specifier_t *f;
      50             :   ipfix_field_specifier_t *first_field;
      51           0 :   u8 *rewrite = 0;
      52             :   ip4_ipfix_template_packet_t *tp;
      53           0 :   u32 field_count = 0;
      54           0 :   u32 field_index = 0;
      55             :   flow_report_stream_t *stream;
      56             :   u8 ip_version;
      57             :   u8 transport_protocol;
      58             :   u8 *virt_mask;
      59             :   u8 *real_mask;
      60             : 
      61           0 :   stream = &exp->streams[fr->stream_index];
      62             : 
      63           0 :   ipfix_classify_table_t *table = &fcm->tables[flow_table_index];
      64             : 
      65           0 :   ip_version = table->ip_version;
      66           0 :   transport_protocol = table->transport_protocol;
      67             : 
      68           0 :   tblp = pool_elt_at_index (vcm->tables, table->classify_table_index);
      69             : 
      70           0 :   virt_mask = (u8 *) (tblp->mask - tblp->skip_n_vectors);
      71           0 :   real_mask = (u8 *) (tblp->mask);
      72             : 
      73             :   /* Determine field count */
      74           0 :   ip_start = virt_mask + sizeof (ethernet_header_t);
      75             : #define _(field,mask,item,length)                                             \
      76             :   if (((u8 *)&field >= real_mask) && (memcmp(&field, &mask, length) == 0))    \
      77             :     {                                                                         \
      78             :       field_count++;                                                          \
      79             :                                                                               \
      80             :       fr->fields_to_send = clib_bitmap_set (fr->fields_to_send,               \
      81             :                                             field_index, 1);                  \
      82             :     }                                                                         \
      83             :   field_index++;
      84           0 :   foreach_ipfix_field;
      85             : #undef _
      86             : 
      87             :   /* Add packetTotalCount manually */
      88           0 :   field_count += 1;
      89             : 
      90             :   /* $$$ enterprise fields, at some later date */
      91             : 
      92             :   /* allocate rewrite space */
      93           0 :   vec_validate_aligned (rewrite,
      94             :                         sizeof (ip4_ipfix_template_packet_t)
      95             :                         + field_count * sizeof (ipfix_field_specifier_t) - 1,
      96             :                         CLIB_CACHE_LINE_BYTES);
      97             : 
      98           0 :   tp = (ip4_ipfix_template_packet_t *) rewrite;
      99           0 :   ip = (ip4_header_t *) & tp->ip4;
     100           0 :   udp = (udp_header_t *) (ip + 1);
     101           0 :   h = (ipfix_message_header_t *) (udp + 1);
     102           0 :   s = (ipfix_set_header_t *) (h + 1);
     103           0 :   t = (ipfix_template_header_t *) (s + 1);
     104           0 :   first_field = f = (ipfix_field_specifier_t *) (t + 1);
     105             : 
     106           0 :   ip->ip_version_and_header_length = 0x45;
     107           0 :   ip->ttl = 254;
     108           0 :   ip->protocol = IP_PROTOCOL_UDP;
     109           0 :   ip->src_address.as_u32 = exp->src_address.ip.ip4.as_u32;
     110           0 :   ip->dst_address.as_u32 = exp->ipfix_collector.ip.ip4.as_u32;
     111           0 :   udp->src_port = clib_host_to_net_u16 (stream->src_port);
     112           0 :   udp->dst_port = clib_host_to_net_u16 (collector_port);
     113           0 :   udp->length = clib_host_to_net_u16 (vec_len (rewrite) - sizeof (*ip));
     114             : 
     115             :   /* FIXUP: message header export_time */
     116             :   /* FIXUP: message header sequence_number */
     117           0 :   h->domain_id = clib_host_to_net_u32 (stream->domain_id);
     118             : 
     119             :   /* Take another trip through the mask and build the template */
     120           0 :   ip_start = virt_mask + sizeof (ethernet_header_t);
     121             : #define _(field,mask,item,length)                                             \
     122             :   if (((u8 *)&field >= real_mask) && (memcmp(&field, &mask, length) == 0))    \
     123             :     {                                                                         \
     124             :       f->e_id_length = ipfix_e_id_length (0 /* enterprise */,                 \
     125             :                                           item, length);                      \
     126             :       f++;                                                                    \
     127             :     }
     128           0 :   foreach_ipfix_field;
     129             : #undef _
     130             : 
     131             :   /* Add packetTotalCount manually */
     132           0 :   f->e_id_length =
     133           0 :     ipfix_e_id_length (0 /* enterprise */ , packetTotalCount, 8);
     134           0 :   f++;
     135             : 
     136             :   /* Back to the template packet... */
     137           0 :   ip = (ip4_header_t *) & tp->ip4;
     138           0 :   udp = (udp_header_t *) (ip + 1);
     139             : 
     140           0 :   ASSERT (f - first_field);
     141             :   /* Field count in this template */
     142           0 :   t->id_count = ipfix_id_count (fr->template_id, f - first_field);
     143             : 
     144             :   /* set length in octets */
     145           0 :   s->set_id_length =
     146           0 :     ipfix_set_id_length (2 /* set_id */ , (u8 *) f - (u8 *) s);
     147             : 
     148             :   /* message length in octets */
     149           0 :   h->version_length = version_length ((u8 *) f - (u8 *) h);
     150             : 
     151           0 :   ip->length = clib_host_to_net_u16 ((u8 *) f - (u8 *) ip);
     152           0 :   ip->checksum = ip4_header_checksum (ip);
     153             : 
     154           0 :   return rewrite;
     155             : }
     156             : 
     157             : vlib_frame_t *
     158           0 : ipfix_classify_send_flows (flow_report_main_t *frm, ipfix_exporter_t *exp,
     159             :                            flow_report_t *fr, vlib_frame_t *f, u32 *to_next,
     160             :                            u32 node_index)
     161             : {
     162           0 :   flow_report_classify_main_t *fcm = &flow_report_classify_main;
     163           0 :   vnet_classify_main_t *vcm = &vnet_classify_main;
     164           0 :   u32 flow_table_index = fr->opaque.as_uword;
     165             :   vnet_classify_table_t *t;
     166             :   vnet_classify_bucket_t *b;
     167             :   vnet_classify_entry_t *v, *save_v;
     168           0 :   vlib_buffer_t *b0 = 0;
     169           0 :   u32 next_offset = 0;
     170           0 :   u32 record_offset = 0;
     171           0 :   u32 bi0 = ~0;
     172             :   int i, j, k;
     173             :   ip4_ipfix_template_packet_t *tp;
     174           0 :   ipfix_message_header_t *h = 0;
     175           0 :   ipfix_set_header_t *s = 0;
     176             :   u8 *ip_start;
     177             :   ip4_header_t *ip;
     178             :   ip6_header_t *ip6;
     179             :   tcpudp_header_t *tcpudp;
     180             :   udp_header_t *udp;
     181             :   int field_index;
     182             :   u16 new_l0, old_l0;
     183             :   ip_csum_t sum0;
     184           0 :   vlib_main_t *vm = frm->vlib_main;
     185             :   flow_report_stream_t *stream;
     186             :   u8 ip_version;
     187             :   u8 transport_protocol;
     188             :   u8 *virt_key;
     189             : 
     190           0 :   stream = &exp->streams[fr->stream_index];
     191             : 
     192           0 :   ipfix_classify_table_t *table = &fcm->tables[flow_table_index];
     193             : 
     194           0 :   ip_version = table->ip_version;
     195           0 :   transport_protocol = table->transport_protocol;
     196             : 
     197           0 :   t = pool_elt_at_index (vcm->tables, table->classify_table_index);
     198             : 
     199           0 :   clib_spinlock_lock (&t->writer_lock);
     200             : 
     201           0 :   for (i = 0; i < t->nbuckets; i++)
     202             :     {
     203           0 :       b = &t->buckets[i];
     204           0 :       if (b->offset == 0)
     205           0 :         continue;
     206             : 
     207           0 :       save_v = vnet_classify_get_entry (t, b->offset);
     208           0 :       for (j = 0; j < (1 << b->log2_pages); j++)
     209             :         {
     210           0 :           for (k = 0; k < t->entries_per_page; k++)
     211             :             {
     212           0 :               v = vnet_classify_entry_at_index
     213           0 :                 (t, save_v, j * t->entries_per_page + k);
     214             : 
     215           0 :               if (vnet_classify_entry_is_free (v))
     216           0 :                 continue;
     217             : 
     218             :               /* OK, we have something to send... */
     219           0 :               if (PREDICT_FALSE (b0 == 0))
     220             :                 {
     221           0 :                   if (vlib_buffer_alloc (vm, &bi0, 1) != 1)
     222           0 :                     goto flush;
     223           0 :                   b0 = vlib_get_buffer (vm, bi0);
     224             : 
     225           0 :                   u32 copy_len = sizeof (ip4_header_t) +
     226             :                     sizeof (udp_header_t) + sizeof (ipfix_message_header_t);
     227           0 :                   clib_memcpy_fast (b0->data, fr->rewrite, copy_len);
     228           0 :                   b0->current_data = 0;
     229           0 :                   b0->current_length = copy_len;
     230           0 :                   b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
     231           0 :                   vnet_buffer (b0)->sw_if_index[VLIB_RX] = 0;
     232           0 :                   vnet_buffer (b0)->sw_if_index[VLIB_TX] = exp->fib_index;
     233             : 
     234           0 :                   tp = vlib_buffer_get_current (b0);
     235           0 :                   ip = (ip4_header_t *) & tp->ip4;
     236           0 :                   udp = (udp_header_t *) (ip + 1);
     237           0 :                   h = (ipfix_message_header_t *) (udp + 1);
     238           0 :                   s = (ipfix_set_header_t *) (h + 1);
     239             : 
     240             :                   /* FIXUP: message header export_time */
     241           0 :                   h->export_time = (u32)
     242           0 :                     (((f64) frm->unix_time_0) +
     243           0 :                      (vlib_time_now (frm->vlib_main) - frm->vlib_time_0));
     244           0 :                   h->export_time = clib_host_to_net_u32 (h->export_time);
     245             : 
     246             :                   /* FIXUP: message header sequence_number */
     247           0 :                   h->sequence_number = stream->sequence_number;
     248           0 :                   h->sequence_number =
     249           0 :                     clib_host_to_net_u32 (h->sequence_number);
     250             : 
     251           0 :                   next_offset = (u32) (((u8 *) (s + 1)) - (u8 *) tp);
     252           0 :                   record_offset = next_offset;
     253             :                 }
     254             : 
     255           0 :               field_index = 0;
     256           0 :               virt_key = (u8 *) (v->key - t->skip_n_vectors);
     257           0 :               ip_start = virt_key + sizeof (ethernet_header_t);
     258             : #define _(field,mask,item,length)                                       \
     259             :               if (clib_bitmap_get (fr->fields_to_send, field_index))    \
     260             :                 {                                                       \
     261             :                   clib_memcpy_fast (b0->data + next_offset, &field,          \
     262             :                           length);                                      \
     263             :                   next_offset += length;                                \
     264             :                 }                                                       \
     265             :               field_index++;
     266           0 :               foreach_ipfix_field;
     267             : #undef _
     268             : 
     269             :               /* Add packetTotalCount manually */
     270             :               {
     271           0 :                 u64 packets = clib_host_to_net_u64 (v->hits);
     272           0 :                 clib_memcpy_fast (b0->data + next_offset, &packets,
     273             :                                   sizeof (packets));
     274           0 :                 next_offset += sizeof (packets);
     275             :               }
     276           0 :               stream->sequence_number++;
     277             : 
     278             :               /* Next record will have the same size as this record */
     279           0 :               u32 next_record_size = next_offset - record_offset;
     280           0 :               record_offset = next_offset;
     281             : 
     282           0 :               if (next_offset + next_record_size > exp->path_mtu)
     283             :                 {
     284           0 :                   s->set_id_length = ipfix_set_id_length (fr->template_id,
     285           0 :                                                           next_offset -
     286             :                                                           (sizeof (*ip) +
     287             :                                                            sizeof (*udp) +
     288             :                                                            sizeof (*h)));
     289           0 :                   h->version_length =
     290           0 :                     version_length (next_offset -
     291             :                                     (sizeof (*ip) + sizeof (*udp)));
     292           0 :                   b0->current_length = next_offset;
     293           0 :                   b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
     294             : 
     295           0 :                   tp = vlib_buffer_get_current (b0);
     296           0 :                   ip = (ip4_header_t *) & tp->ip4;
     297           0 :                   udp = (udp_header_t *) (ip + 1);
     298             : 
     299           0 :                   sum0 = ip->checksum;
     300           0 :                   old_l0 = ip->length;
     301           0 :                   new_l0 = clib_host_to_net_u16 ((u16) next_offset);
     302             : 
     303           0 :                   sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
     304             :                                          length /* changed member */ );
     305             : 
     306           0 :                   ip->checksum = ip_csum_fold (sum0);
     307           0 :                   ip->length = new_l0;
     308           0 :                   udp->length =
     309           0 :                     clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
     310             : 
     311           0 :                   if (exp->udp_checksum)
     312             :                     {
     313             :                       /* RFC 7011 section 10.3.2. */
     314           0 :                       udp->checksum =
     315           0 :                         ip4_tcp_udp_compute_checksum (vm, b0, ip);
     316           0 :                       if (udp->checksum == 0)
     317           0 :                         udp->checksum = 0xffff;
     318             :                     }
     319             : 
     320           0 :                   ASSERT (ip4_header_checksum_is_valid (ip));
     321             : 
     322           0 :                   to_next[0] = bi0;
     323           0 :                   f->n_vectors++;
     324           0 :                   to_next++;
     325             : 
     326           0 :                   if (f->n_vectors == VLIB_FRAME_SIZE)
     327             :                     {
     328           0 :                       vlib_put_frame_to_node (vm, node_index, f);
     329           0 :                       f = vlib_get_frame_to_node (vm, node_index);
     330           0 :                       f->n_vectors = 0;
     331           0 :                       to_next = vlib_frame_vector_args (f);
     332             :                     }
     333           0 :                   b0 = 0;
     334           0 :                   bi0 = ~0;
     335             :                 }
     336             :             }
     337             :         }
     338             :     }
     339             : 
     340           0 : flush:
     341           0 :   if (b0)
     342             :     {
     343           0 :       s->set_id_length = ipfix_set_id_length (fr->template_id,
     344           0 :                                               next_offset -
     345             :                                               (sizeof (*ip) + sizeof (*udp) +
     346             :                                                sizeof (*h)));
     347           0 :       h->version_length = version_length (next_offset -
     348             :                                           (sizeof (*ip) + sizeof (*udp)));
     349           0 :       b0->current_length = next_offset;
     350           0 :       b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
     351             : 
     352           0 :       tp = vlib_buffer_get_current (b0);
     353           0 :       ip = (ip4_header_t *) & tp->ip4;
     354           0 :       udp = (udp_header_t *) (ip + 1);
     355             : 
     356           0 :       sum0 = ip->checksum;
     357           0 :       old_l0 = ip->length;
     358           0 :       new_l0 = clib_host_to_net_u16 ((u16) next_offset);
     359             : 
     360           0 :       sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t,
     361             :                              length /* changed member */ );
     362             : 
     363           0 :       ip->checksum = ip_csum_fold (sum0);
     364           0 :       ip->length = new_l0;
     365           0 :       udp->length = clib_host_to_net_u16 (b0->current_length - sizeof (*ip));
     366             : 
     367           0 :       if (exp->udp_checksum)
     368             :         {
     369             :           /* RFC 7011 section 10.3.2. */
     370           0 :           udp->checksum = ip4_tcp_udp_compute_checksum (vm, b0, ip);
     371           0 :           if (udp->checksum == 0)
     372           0 :             udp->checksum = 0xffff;
     373             :         }
     374             : 
     375           0 :       ASSERT (ip4_header_checksum_is_valid (ip));
     376             : 
     377           0 :       to_next[0] = bi0;
     378           0 :       f->n_vectors++;
     379             : 
     380           0 :       b0 = 0;
     381           0 :       bi0 = ~0;
     382             :     }
     383             : 
     384           0 :   clib_spinlock_unlock (&t->writer_lock);
     385           0 :   return f;
     386             : }
     387             : 
     388             : static clib_error_t *
     389           0 : ipfix_classify_table_add_del_command_fn (vlib_main_t * vm,
     390             :                                          unformat_input_t * input,
     391             :                                          vlib_cli_command_t * cmd)
     392             : {
     393           0 :   flow_report_classify_main_t *fcm = &flow_report_classify_main;
     394           0 :   ipfix_exporter_t *exp = &flow_report_main.exporters[0];
     395             :   vnet_flow_report_add_del_args_t args;
     396             :   ipfix_classify_table_t *table;
     397             :   int rv;
     398           0 :   int is_add = -1;
     399           0 :   u32 classify_table_index = ~0;
     400           0 :   u8 ip_version = 0;
     401           0 :   u8 transport_protocol = 255;
     402           0 :   clib_error_t *error = 0;
     403             : 
     404           0 :   if (fcm->src_port == 0)
     405           0 :     clib_error_return (0, "call 'set ipfix classify stream' first");
     406             : 
     407           0 :   clib_memset (&args, 0, sizeof (args));
     408             : 
     409           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     410             :     {
     411           0 :       if (unformat (input, "add"))
     412           0 :         is_add = 1;
     413           0 :       else if (unformat (input, "del"))
     414           0 :         is_add = 0;
     415           0 :       else if (unformat (input, "%d", &classify_table_index))
     416             :         ;
     417           0 :       else if (unformat (input, "ip4"))
     418           0 :         ip_version = 4;
     419           0 :       else if (unformat (input, "ip6"))
     420           0 :         ip_version = 6;
     421           0 :       else if (unformat (input, "tcp"))
     422           0 :         transport_protocol = 6;
     423           0 :       else if (unformat (input, "udp"))
     424           0 :         transport_protocol = 17;
     425             :       else
     426           0 :         return clib_error_return (0, "unknown input `%U'",
     427             :                                   format_unformat_error, input);
     428             :     }
     429             : 
     430           0 :   if (is_add == -1)
     431           0 :     return clib_error_return (0, "expecting: add|del");
     432           0 :   if (classify_table_index == ~0)
     433           0 :     return clib_error_return (0, "classifier table not specified");
     434           0 :   if (ip_version == 0)
     435           0 :     return clib_error_return (0, "IP version not specified");
     436             : 
     437           0 :   table = 0;
     438             :   int i;
     439           0 :   for (i = 0; i < vec_len (fcm->tables); i++)
     440           0 :     if (ipfix_classify_table_index_valid (i))
     441           0 :       if (fcm->tables[i].classify_table_index == classify_table_index)
     442             :         {
     443           0 :           table = &fcm->tables[i];
     444           0 :           break;
     445             :         }
     446             : 
     447           0 :   if (is_add)
     448             :     {
     449           0 :       if (table)
     450           0 :         return clib_error_return (0,
     451             :                                   "Specified classifier table already used");
     452           0 :       table = ipfix_classify_add_table ();
     453           0 :       table->classify_table_index = classify_table_index;
     454             :     }
     455             :   else
     456             :     {
     457           0 :       if (!table)
     458           0 :         return clib_error_return (0,
     459             :                                   "Specified classifier table not registered");
     460             :     }
     461             : 
     462           0 :   table->ip_version = ip_version;
     463           0 :   table->transport_protocol = transport_protocol;
     464             : 
     465           0 :   args.opaque.as_uword = table - fcm->tables;
     466           0 :   args.rewrite_callback = ipfix_classify_template_rewrite;
     467           0 :   args.flow_data_callback = ipfix_classify_send_flows;
     468           0 :   args.is_add = is_add;
     469           0 :   args.domain_id = fcm->domain_id;
     470           0 :   args.src_port = fcm->src_port;
     471             : 
     472           0 :   rv = vnet_flow_report_add_del (exp, &args, NULL);
     473             : 
     474           0 :   error = flow_report_add_del_error_to_clib_error (rv);
     475             : 
     476             :   /* If deleting, or add failed */
     477           0 :   if (is_add == 0 || (rv && is_add))
     478           0 :     ipfix_classify_delete_table (table - fcm->tables);
     479             : 
     480           0 :   return error;
     481             : }
     482             : 
     483             : /* *INDENT-OFF* */
     484      285289 : VLIB_CLI_COMMAND (ipfix_classify_table_add_del_command, static) = {
     485             :   .path = "ipfix classify table",
     486             :   .short_help = "ipfix classify table add|del <table-index>",
     487             :   .function = ipfix_classify_table_add_del_command_fn,
     488             : };
     489             : /* *INDENT-ON* */
     490             : 
     491             : static clib_error_t *
     492           0 : set_ipfix_classify_stream_command_fn (vlib_main_t * vm,
     493             :                                       unformat_input_t * input,
     494             :                                       vlib_cli_command_t * cmd)
     495             : {
     496           0 :   flow_report_classify_main_t *fcm = &flow_report_classify_main;
     497           0 :   ipfix_exporter_t *exp = &flow_report_main.exporters[0];
     498           0 :   u32 domain_id = 1;
     499           0 :   u32 src_port = UDP_DST_PORT_ipfix;
     500             : 
     501           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     502             :     {
     503           0 :       if (unformat (input, "domain %d", &domain_id))
     504             :         ;
     505           0 :       else if (unformat (input, "src-port %d", &src_port))
     506             :         ;
     507             :       else
     508           0 :         return clib_error_return (0, "unknown input `%U'",
     509             :                                   format_unformat_error, input);
     510             :     }
     511             : 
     512           0 :   if (fcm->src_port != 0 &&
     513           0 :       (fcm->domain_id != domain_id || fcm->src_port != (u16) src_port))
     514             :     {
     515           0 :       int rv = vnet_stream_change (exp, fcm->domain_id, fcm->src_port,
     516           0 :                                    domain_id, (u16) src_port);
     517           0 :       ASSERT (rv == 0);
     518             :     }
     519             : 
     520           0 :   fcm->domain_id = domain_id;
     521           0 :   fcm->src_port = (u16) src_port;
     522             : 
     523           0 :   return 0;
     524             : }
     525             : 
     526             : /* *INDENT-OFF* */
     527      285289 : VLIB_CLI_COMMAND (set_ipfix_classify_stream_command, static) = {
     528             :   .path = "set ipfix classify stream",
     529             :   .short_help = "set ipfix classify stream"
     530             :                 "[domain <domain-id>] [src-port <src-port>]",
     531             :   .function = set_ipfix_classify_stream_command_fn,
     532             : };
     533             : /* *INDENT-ON* */
     534             : 
     535             : static clib_error_t *
     536         575 : flow_report_classify_init (vlib_main_t * vm)
     537             : {
     538             :   clib_error_t *error;
     539             : 
     540         575 :   if ((error = vlib_call_init_function (vm, flow_report_init)))
     541           0 :     return error;
     542             : 
     543         575 :   return 0;
     544             : }
     545             : 
     546       72575 : VLIB_INIT_FUNCTION (flow_report_classify_init);
     547             : 
     548             : /*
     549             :  * fd.io coding-style-patch-verification: ON
     550             :  *
     551             :  * Local Variables:
     552             :  * eval: (c-set-style "gnu")
     553             :  * End:
     554             :  */

Generated by: LCOV version 1.14