LCOV - code coverage report
Current view: top level - vnet/classify - classify_api.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 99 449 22.0 %
Date: 2023-07-05 22:20:52 Functions: 10 28 35.7 %

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * classify_api.c - classify api
       4             :  *
       5             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       6             :  * Licensed under the Apache License, Version 2.0 (the "License");
       7             :  * you may not use this file except in compliance with the License.
       8             :  * You may obtain a copy of the License at:
       9             :  *
      10             :  *     http://www.apache.org/licenses/LICENSE-2.0
      11             :  *
      12             :  * Unless required by applicable law or agreed to in writing, software
      13             :  * distributed under the License is distributed on an "AS IS" BASIS,
      14             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15             :  * See the License for the specific language governing permissions and
      16             :  * limitations under the License.
      17             :  *------------------------------------------------------------------
      18             :  */
      19             : 
      20             : #include <vnet/vnet.h>
      21             : #include <vlibmemory/api.h>
      22             : 
      23             : #include <vnet/interface.h>
      24             : #include <vnet/api_errno.h>
      25             : 
      26             : #include <vnet/classify/vnet_classify.h>
      27             : #include <vnet/classify/in_out_acl.h>
      28             : #include <vnet/classify/policer_classify.h>
      29             : #include <vnet/classify/flow_classify.h>
      30             : #include <vnet/l2/l2_classify.h>
      31             : #include <vnet/ip/ip6.h>
      32             : #include <vnet/ip/ip4.h>
      33             : 
      34             : #include <classify/classify.api_enum.h>
      35             : #include <classify/classify.api_types.h>
      36             : 
      37             : #define REPLY_MSG_ID_BASE msg_id_base
      38             : #include <vlibapi/api_helper_macros.h>
      39             : 
      40             : static u16 msg_id_base;
      41             : 
      42             : #define foreach_classify_add_del_table_field    \
      43             : _(table_index)                                  \
      44             : _(nbuckets)                                     \
      45             : _(memory_size)                                  \
      46             : _(skip_n_vectors)                               \
      47             : _(match_n_vectors)                              \
      48             : _(next_table_index)                             \
      49             : _(miss_next_index)                              \
      50             : _(mask_len)
      51             : 
      52             : 
      53           0 : static void vl_api_classify_pcap_lookup_table_t_handler
      54             :   (vl_api_classify_pcap_lookup_table_t * mp)
      55             : {
      56           0 :   vnet_classify_main_t *cm = &vnet_classify_main;
      57             :   vl_api_registration_t *reg;
      58             :   vl_api_classify_pcap_lookup_table_reply_t *rmp;
      59           0 :   int rv = 0;
      60           0 :   u32 table_index = ~0;
      61             : 
      62           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
      63           0 :   if (!reg)
      64           0 :     return;
      65             : 
      66           0 :   u32 n_skip = ntohl (mp->skip_n_vectors);
      67           0 :   u32 n_match = ntohl (mp->match_n_vectors);
      68           0 :   u32 mask_len = ntohl (mp->mask_len);
      69           0 :   u32 sw_if_index = ntohl (mp->sw_if_index);
      70             : 
      71           0 :   if (n_skip > 5 || n_match == 0 || n_match > 5 ||
      72           0 :       mask_len != n_match * sizeof (u32x4) || sw_if_index == ~0 ||
      73           0 :       sw_if_index >= vec_len (cm->classify_table_index_by_sw_if_index))
      74             :     {
      75           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
      76           0 :       goto out;
      77             :     }
      78             : 
      79             :   u32 table_chain;
      80           0 :   table_chain = classify_get_pcap_chain (cm, sw_if_index);
      81             : 
      82           0 :   u8 *mask_vec = 0;
      83           0 :   vec_validate (mask_vec, mask_len - 1);
      84           0 :   clib_memcpy (mask_vec, mp->mask, mask_len);
      85             : 
      86           0 :   if (table_chain != ~0)
      87           0 :     table_index = classify_lookup_chain (table_chain,
      88             :                                          mask_vec, n_skip, n_match);
      89             : 
      90           0 :   vec_free (mask_vec);
      91             : 
      92           0 : out:
      93           0 :   rmp = vl_msg_api_alloc (sizeof (*rmp));
      94           0 :   rmp->_vl_msg_id =
      95           0 :     ntohs (REPLY_MSG_ID_BASE + VL_API_CLASSIFY_PCAP_LOOKUP_TABLE_REPLY);
      96           0 :   rmp->context = mp->context;
      97           0 :   rmp->retval = ntohl (rv);
      98           0 :   rmp->table_index = htonl (table_index);
      99             : 
     100           0 :   vl_api_send_msg (reg, (u8 *) rmp);
     101             : }
     102             : 
     103           0 : static void vl_api_classify_pcap_set_table_t_handler
     104             :   (vl_api_classify_pcap_set_table_t * mp)
     105             : {
     106           0 :   vnet_classify_main_t *cm = &vnet_classify_main;
     107             :   vl_api_classify_pcap_set_table_reply_t *rmp;
     108             :   vl_api_registration_t *reg;
     109           0 :   int rv = 0;
     110             : 
     111           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
     112           0 :   if (!reg)
     113           0 :     return;
     114             : 
     115           0 :   u32 table_index = ntohl (mp->table_index);
     116           0 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     117             : 
     118           0 :   if (sw_if_index == ~0 ||
     119           0 :       (table_index != ~0 && pool_is_free_index (cm->tables, table_index)))
     120             :     {
     121           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
     122           0 :       goto out;
     123             :     }
     124             : 
     125             :   /*
     126             :    * Maybe reorder tables such that masks are most-specify to least-specific.
     127             :    */
     128           0 :   if (table_index != ~0 && mp->sort_masks)
     129           0 :     table_index = classify_sort_table_chain (cm, table_index);
     130             : 
     131           0 :   classify_set_pcap_chain (cm, sw_if_index, table_index);
     132             : 
     133           0 : out:
     134           0 :   rmp = vl_msg_api_alloc (sizeof (*rmp));
     135           0 :   rmp->_vl_msg_id =
     136           0 :     ntohs (REPLY_MSG_ID_BASE + VL_API_CLASSIFY_PCAP_SET_TABLE_REPLY);
     137           0 :   rmp->context = mp->context;
     138           0 :   rmp->retval = ntohl (rv);
     139           0 :   rmp->table_index = htonl (table_index);
     140             : 
     141           0 :   vl_api_send_msg (reg, (u8 *) rmp);
     142             : }
     143             : 
     144           0 : static void vl_api_classify_pcap_get_tables_t_handler
     145             :   (vl_api_classify_pcap_get_tables_t * mp)
     146             : {
     147           0 :   vnet_classify_main_t *cm = &vnet_classify_main;
     148             :   vl_api_classify_pcap_get_tables_reply_t *rmp;
     149             :   vl_api_registration_t *reg;
     150           0 :   int rv = 0;
     151           0 :   u32 *tables = 0;
     152             :   u32 count;
     153             : 
     154           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
     155           0 :   if (!reg)
     156           0 :     return;
     157             : 
     158           0 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     159           0 :   if (sw_if_index == ~0
     160           0 :       || sw_if_index >= vec_len (cm->classify_table_index_by_sw_if_index))
     161             :     {
     162           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
     163           0 :       goto out;
     164             :     }
     165             : 
     166           0 :   u32 table_index = classify_get_pcap_chain (cm, sw_if_index);
     167           0 :   if (table_index == ~0)
     168           0 :     goto out;
     169             : 
     170             :   /*
     171             :    * Form a vector of all classifier tables in this chain.
     172             :    */
     173             :   vnet_classify_table_t *t;
     174             :   u32 i;
     175             : 
     176           0 :   for (i = table_index; i != ~0; i = t->next_table_index)
     177             :     {
     178           0 :       vec_add1 (tables, i);
     179           0 :       t = pool_elt_at_index (cm->tables, i);
     180             :     }
     181             : 
     182           0 : out:
     183           0 :   count = vec_len (tables);
     184           0 :   rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32));
     185           0 :   rmp->_vl_msg_id =
     186           0 :     ntohs (REPLY_MSG_ID_BASE + VL_API_CLASSIFY_PCAP_GET_TABLES_REPLY);
     187           0 :   rmp->context = mp->context;
     188           0 :   rmp->retval = ntohl (rv);
     189           0 :   rmp->count = htonl (count);
     190             : 
     191           0 :   for (i = 0; i < count; ++i)
     192             :     {
     193           0 :       rmp->indices[i] = htonl (tables[i]);
     194             :     }
     195             : 
     196           0 :   vec_free (tables);
     197             : 
     198           0 :   vl_api_send_msg (reg, (u8 *) rmp);
     199             : }
     200             : 
     201             : 
     202           0 : static void vl_api_classify_trace_lookup_table_t_handler
     203             :   (vl_api_classify_trace_lookup_table_t * mp)
     204             : {
     205             :   vl_api_classify_trace_lookup_table_reply_t *rmp;
     206             :   vl_api_registration_t *reg;
     207           0 :   int rv = 0;
     208           0 :   u32 table_index = ~0;
     209             : 
     210           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
     211           0 :   if (!reg)
     212           0 :     return;
     213             : 
     214           0 :   u32 n_skip = ntohl (mp->skip_n_vectors);
     215           0 :   u32 n_match = ntohl (mp->match_n_vectors);
     216           0 :   u32 mask_len = ntohl (mp->mask_len);
     217           0 :   if (n_skip > 5
     218           0 :       || n_match == 0 || n_match > 5 || mask_len != n_match * sizeof (u32x4))
     219             :     {
     220           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
     221           0 :       goto out;
     222             :     }
     223             : 
     224             :   u32 table_chain;
     225           0 :   table_chain = classify_get_trace_chain ();
     226             : 
     227           0 :   u8 *mask_vec = 0;
     228           0 :   vec_validate (mask_vec, mask_len - 1);
     229           0 :   clib_memcpy (mask_vec, mp->mask, mask_len);
     230             : 
     231           0 :   if (table_chain != ~0)
     232           0 :     table_index = classify_lookup_chain (table_chain,
     233             :                                          mask_vec, n_skip, n_match);
     234           0 :   vec_free (mask_vec);
     235             : 
     236           0 : out:
     237           0 :   rmp = vl_msg_api_alloc (sizeof (*rmp));
     238           0 :   rmp->_vl_msg_id =
     239           0 :     ntohs ((REPLY_MSG_ID_BASE + VL_API_CLASSIFY_TRACE_LOOKUP_TABLE_REPLY));
     240           0 :   rmp->context = mp->context;
     241           0 :   rmp->retval = ntohl (rv);
     242           0 :   rmp->table_index = htonl (table_index);
     243             : 
     244           0 :   vl_api_send_msg (reg, (u8 *) rmp);
     245             : }
     246             : 
     247           0 : static void vl_api_classify_trace_set_table_t_handler
     248             :   (vl_api_classify_trace_set_table_t * mp)
     249             : {
     250           0 :   vnet_classify_main_t *cm = &vnet_classify_main;
     251             :   vl_api_classify_trace_set_table_reply_t *rmp;
     252             :   vl_api_registration_t *reg;
     253           0 :   int rv = 0;
     254             : 
     255           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
     256           0 :   if (!reg)
     257           0 :     return;
     258             : 
     259           0 :   u32 table_index = ntohl (mp->table_index);
     260           0 :   if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
     261             :     {
     262           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
     263           0 :       goto out;
     264             :     }
     265             : 
     266             :   /*
     267             :    * Maybe reorder tables such that masks are most-specific to least-specific.
     268             :    */
     269           0 :   if (table_index != ~0 && mp->sort_masks)
     270           0 :     table_index = classify_sort_table_chain (cm, table_index);
     271             : 
     272           0 :   classify_set_trace_chain (cm, table_index);
     273             : 
     274           0 : out:
     275           0 :   rmp = vl_msg_api_alloc (sizeof (*rmp));
     276           0 :   rmp->_vl_msg_id =
     277           0 :     ntohs ((REPLY_MSG_ID_BASE + VL_API_CLASSIFY_TRACE_SET_TABLE_REPLY));
     278           0 :   rmp->context = mp->context;
     279           0 :   rmp->retval = ntohl (rv);
     280           0 :   rmp->table_index = htonl (table_index);
     281             : 
     282           0 :   vl_api_send_msg (reg, (u8 *) rmp);
     283             : }
     284             : 
     285           0 : static void vl_api_classify_trace_get_tables_t_handler
     286             :   (vl_api_classify_trace_get_tables_t * mp)
     287             : {
     288           0 :   vnet_classify_main_t *cm = &vnet_classify_main;
     289             :   vl_api_classify_trace_get_tables_reply_t *rmp;
     290             :   vl_api_registration_t *reg;
     291           0 :   int rv = 0;
     292           0 :   u32 *tables = 0;
     293             :   u32 count;
     294             : 
     295           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
     296           0 :   if (!reg)
     297           0 :     return;
     298             : 
     299           0 :   u32 table_index = classify_get_trace_chain ();
     300           0 :   if (table_index == ~0)
     301           0 :     goto out;
     302             : 
     303             :   /*
     304             :    * Form a vector of all classifier tables in this chain.
     305             :    */
     306             :   vnet_classify_table_t *t;
     307             :   u32 i;
     308             : 
     309           0 :   for (i = table_index; i != ~0; i = t->next_table_index)
     310             :     {
     311           0 :       vec_add1 (tables, i);
     312           0 :       t = pool_elt_at_index (cm->tables, i);
     313             :     }
     314             : 
     315           0 : out:
     316           0 :   count = vec_len (tables);
     317           0 :   rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32));
     318           0 :   rmp->_vl_msg_id =
     319           0 :     ntohs (REPLY_MSG_ID_BASE + VL_API_CLASSIFY_TRACE_GET_TABLES_REPLY);
     320           0 :   rmp->context = mp->context;
     321           0 :   rmp->retval = ntohl (rv);
     322           0 :   rmp->count = htonl (count);
     323             : 
     324           0 :   for (i = 0; i < count; ++i)
     325             :     {
     326           0 :       rmp->indices[i] = htonl (tables[i]);
     327             :     }
     328             : 
     329           0 :   vec_free (tables);
     330             : 
     331           0 :   vl_api_send_msg (reg, (u8 *) rmp);
     332             : }
     333             : 
     334             : 
     335          46 : static void vl_api_classify_add_del_table_t_handler
     336             :   (vl_api_classify_add_del_table_t * mp)
     337             : {
     338             :   vl_api_classify_add_del_table_reply_t *rmp;
     339          46 :   vnet_classify_main_t *cm = &vnet_classify_main;
     340             :   vnet_classify_table_t *t;
     341             :   int rv;
     342             : 
     343             : #define _(a) u32 a;
     344             :   foreach_classify_add_del_table_field;
     345             : #undef _
     346             : 
     347             : #define _(a) a = ntohl(mp->a);
     348          46 :   foreach_classify_add_del_table_field;
     349             : #undef _
     350             : 
     351          46 :   if (mask_len != match_n_vectors * sizeof (u32x4))
     352             :     {
     353           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
     354           0 :       goto out;
     355             :     }
     356             : 
     357             :   /* The underlying API fails silently, on purpose, so check here */
     358          46 :   if (mp->is_add == 0)               /* delete */
     359             :     {
     360           0 :       if (pool_is_free_index (cm->tables, table_index))
     361             :         {
     362           0 :           rv = VNET_API_ERROR_NO_SUCH_TABLE;
     363           0 :           goto out;
     364             :         }
     365             :     }
     366             :   else                          /* add or update */
     367             :     {
     368          46 :       if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
     369           0 :         table_index = ~0;
     370             :     }
     371             : 
     372          46 :   u8 current_data_flag = mp->current_data_flag;
     373          46 :   i16 current_data_offset = clib_net_to_host_i16 (mp->current_data_offset);
     374             : 
     375          46 :   rv = vnet_classify_add_del_table
     376          46 :     (cm, mp->mask, nbuckets, memory_size,
     377             :      skip_n_vectors, match_n_vectors,
     378             :      next_table_index, miss_next_index, &table_index,
     379          46 :      current_data_flag, current_data_offset, mp->is_add, mp->del_chain);
     380             : 
     381          46 : out:
     382             :   /* *INDENT-OFF* */
     383          46 :   REPLY_MACRO2(VL_API_CLASSIFY_ADD_DEL_TABLE_REPLY,
     384             :   ({
     385             :     if (rv == 0 && mp->is_add)
     386             :       {
     387             :         t = pool_elt_at_index (cm->tables, table_index);
     388             :         rmp->skip_n_vectors = htonl(t->skip_n_vectors);
     389             :         rmp->match_n_vectors = htonl(t->match_n_vectors);
     390             :         rmp->new_table_index = htonl(table_index);
     391             :       }
     392             :     else
     393             :       {
     394             :         rmp->skip_n_vectors = ~0;
     395             :         rmp->match_n_vectors = ~0;
     396             :         rmp->new_table_index = ~0;
     397             :       }
     398             :   }));
     399             :   /* *INDENT-ON* */
     400             : }
     401             : 
     402          42 : static void vl_api_classify_add_del_session_t_handler
     403             :   (vl_api_classify_add_del_session_t * mp)
     404             : {
     405          42 :   vnet_classify_main_t *cm = &vnet_classify_main;
     406             :   vl_api_classify_add_del_session_reply_t *rmp;
     407             :   int rv;
     408             :   u32 table_index, hit_next_index, opaque_index, metadata, match_len;
     409             :   i32 advance;
     410             :   u8 action;
     411             :   vnet_classify_table_t *t;
     412             : 
     413          42 :   table_index = ntohl (mp->table_index);
     414          42 :   hit_next_index = ntohl (mp->hit_next_index);
     415          42 :   opaque_index = ntohl (mp->opaque_index);
     416          42 :   advance = ntohl (mp->advance);
     417          42 :   action = mp->action;
     418          42 :   metadata = ntohl (mp->metadata);
     419          42 :   match_len = ntohl (mp->match_len);
     420             : 
     421          42 :   if (pool_is_free_index (cm->tables, table_index))
     422             :     {
     423           0 :       rv = VNET_API_ERROR_NO_SUCH_TABLE;
     424           0 :       goto out;
     425             :     }
     426             : 
     427          42 :   t = pool_elt_at_index (cm->tables, table_index);
     428             : 
     429          42 :   if (match_len != (t->skip_n_vectors + t->match_n_vectors) * sizeof (u32x4))
     430             :     {
     431           0 :       rv = VNET_API_ERROR_INVALID_VALUE;
     432           0 :       goto out;
     433             :     }
     434             : 
     435          42 :   rv = vnet_classify_add_del_session
     436          42 :     (cm, table_index, mp->match, hit_next_index, opaque_index,
     437          42 :      advance, action, metadata, mp->is_add);
     438             : 
     439          42 : out:
     440          42 :   REPLY_MACRO (VL_API_CLASSIFY_ADD_DEL_SESSION_REPLY);
     441             : }
     442             : 
     443             : static void
     444           0 :   vl_api_policer_classify_set_interface_t_handler
     445             :   (vl_api_policer_classify_set_interface_t * mp)
     446             : {
     447           0 :   vlib_main_t *vm = vlib_get_main ();
     448             :   vl_api_policer_classify_set_interface_reply_t *rmp;
     449             :   int rv;
     450             :   u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
     451             : 
     452           0 :   ip4_table_index = ntohl (mp->ip4_table_index);
     453           0 :   ip6_table_index = ntohl (mp->ip6_table_index);
     454           0 :   l2_table_index = ntohl (mp->l2_table_index);
     455           0 :   sw_if_index = ntohl (mp->sw_if_index);
     456             : 
     457           0 :   VALIDATE_SW_IF_INDEX (mp);
     458             : 
     459           0 :   rv = vnet_set_policer_classify_intfc (vm, sw_if_index, ip4_table_index,
     460             :                                         ip6_table_index, l2_table_index,
     461           0 :                                         mp->is_add);
     462             : 
     463           0 :   BAD_SW_IF_INDEX_LABEL;
     464             : 
     465           0 :   REPLY_MACRO (VL_API_POLICER_CLASSIFY_SET_INTERFACE_REPLY);
     466             : }
     467             : 
     468             : static void
     469           0 : send_policer_classify_details (u32 sw_if_index,
     470             :                                u32 table_index, vl_api_registration_t * reg,
     471             :                                u32 context)
     472             : {
     473             :   vl_api_policer_classify_details_t *mp;
     474             : 
     475           0 :   mp = vl_msg_api_alloc (sizeof (*mp));
     476           0 :   clib_memset (mp, 0, sizeof (*mp));
     477           0 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_POLICER_CLASSIFY_DETAILS);
     478           0 :   mp->context = context;
     479           0 :   mp->sw_if_index = htonl (sw_if_index);
     480           0 :   mp->table_index = htonl (table_index);
     481             : 
     482           0 :   vl_api_send_msg (reg, (u8 *) mp);
     483           0 : }
     484             : 
     485             : static void
     486           0 : vl_api_policer_classify_dump_t_handler (vl_api_policer_classify_dump_t * mp)
     487             : {
     488             :   vl_api_registration_t *reg;
     489           0 :   policer_classify_main_t *pcm = &policer_classify_main;
     490             :   u32 *vec_tbl;
     491             :   int i;
     492             :   u32 filter_sw_if_index;
     493             : 
     494           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
     495           0 :   if (!reg)
     496           0 :     return;
     497             : 
     498           0 :   filter_sw_if_index = ntohl (mp->sw_if_index);
     499           0 :   if (filter_sw_if_index
     500           0 :       >= vec_len (pcm->classify_table_index_by_sw_if_index[mp->type]))
     501           0 :     return;
     502             : 
     503           0 :   if (filter_sw_if_index != ~0)
     504           0 :     vec_tbl =
     505           0 :       &pcm->classify_table_index_by_sw_if_index[mp->type][filter_sw_if_index];
     506             :   else
     507           0 :     vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
     508             : 
     509           0 :   if (vec_len (vec_tbl))
     510             :     {
     511           0 :       for (i = 0; i < vec_len (vec_tbl); i++)
     512             :         {
     513           0 :           if (vec_elt (vec_tbl, i) == ~0)
     514           0 :             continue;
     515             : 
     516           0 :           send_policer_classify_details (i, vec_elt (vec_tbl, i), reg,
     517             :                                          mp->context);
     518             :         }
     519             :     }
     520             : }
     521             : 
     522             : static void
     523           0 : vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t * mp)
     524             : {
     525             :   vl_api_registration_t *reg;
     526             : 
     527           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
     528           0 :   if (!reg)
     529           0 :     return;
     530             : 
     531           0 :   vnet_classify_main_t *cm = &vnet_classify_main;
     532             :   vnet_classify_table_t *t;
     533           0 :   u32 *table_ids = 0;
     534             :   u32 count;
     535             : 
     536             :    /* *INDENT-OFF* */
     537           0 :    pool_foreach (t, cm->tables)
     538             :     {
     539           0 :      vec_add1 (table_ids, ntohl(t - cm->tables));
     540             :    }
     541             :    /* *INDENT-ON* */
     542           0 :   count = vec_len (table_ids);
     543             : 
     544             :   vl_api_classify_table_ids_reply_t *rmp;
     545           0 :   rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32));
     546           0 :   rmp->_vl_msg_id =
     547           0 :     ntohs (REPLY_MSG_ID_BASE + VL_API_CLASSIFY_TABLE_IDS_REPLY);
     548           0 :   rmp->context = mp->context;
     549           0 :   rmp->count = ntohl (count);
     550           0 :   clib_memcpy (rmp->ids, table_ids, count * sizeof (u32));
     551           0 :   rmp->retval = 0;
     552             : 
     553           0 :   vl_api_send_msg (reg, (u8 *) rmp);
     554             : 
     555           0 :   vec_free (table_ids);
     556             : }
     557             : 
     558             : static void
     559           0 :   vl_api_classify_table_by_interface_t_handler
     560             :   (vl_api_classify_table_by_interface_t * mp)
     561             : {
     562             :   vl_api_classify_table_by_interface_reply_t *rmp;
     563           0 :   int rv = 0;
     564             : 
     565           0 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     566           0 :   u32 *acl = 0;
     567             : 
     568           0 :   vec_validate (acl, IN_OUT_ACL_N_TABLES - 1);
     569           0 :   vec_set (acl, ~0);
     570             : 
     571           0 :   VALIDATE_SW_IF_INDEX (mp);
     572             : 
     573           0 :   in_out_acl_main_t *am = &in_out_acl_main;
     574             : 
     575             :   int if_idx;
     576             :   u32 type;
     577             : 
     578           0 :   for (type = 0; type < IN_OUT_ACL_N_TABLES; type++)
     579             :     {
     580           0 :       u32 *vec_tbl =
     581             :         am->classify_table_index_by_sw_if_index[IN_OUT_ACL_INPUT_TABLE_GROUP]
     582             :         [type];
     583           0 :       if (vec_len (vec_tbl))
     584             :         {
     585           0 :           for (if_idx = 0; if_idx < vec_len (vec_tbl); if_idx++)
     586             :             {
     587           0 :               if (vec_elt (vec_tbl, if_idx) == ~0 || sw_if_index != if_idx)
     588             :                 {
     589           0 :                   continue;
     590             :                 }
     591           0 :               acl[type] = vec_elt (vec_tbl, if_idx);
     592             :             }
     593             :         }
     594             :     }
     595             : 
     596           0 :   BAD_SW_IF_INDEX_LABEL;
     597             : 
     598             :    /* *INDENT-OFF* */
     599           0 :    REPLY_MACRO2(VL_API_CLASSIFY_TABLE_BY_INTERFACE_REPLY,
     600             :    ({
     601             :      rmp->sw_if_index = ntohl(sw_if_index);
     602             :      rmp->l2_table_id = ntohl(acl[IN_OUT_ACL_TABLE_L2]);
     603             :      rmp->ip4_table_id = ntohl(acl[IN_OUT_ACL_TABLE_IP4]);
     604             :      rmp->ip6_table_id = ntohl(acl[IN_OUT_ACL_TABLE_IP6]);
     605             :    }));
     606             :    /* *INDENT-ON* */
     607           0 :   vec_free (acl);
     608             : }
     609             : 
     610             : static void
     611           8 : vl_api_classify_table_info_t_handler (vl_api_classify_table_info_t * mp)
     612             : {
     613             :   vl_api_registration_t *reg;
     614             : 
     615           8 :   reg = vl_api_client_index_to_registration (mp->client_index);
     616           8 :   if (!reg)
     617           0 :     return;
     618             : 
     619           8 :   vl_api_classify_table_info_reply_t *rmp = 0;
     620             : 
     621           8 :   vnet_classify_main_t *cm = &vnet_classify_main;
     622           8 :   u32 table_id = ntohl (mp->table_id);
     623             :   vnet_classify_table_t *t;
     624             : 
     625          20 :   pool_foreach (t, cm->tables)
     626             :     {
     627          20 :       if (table_id == t - cm->tables)
     628             :         {
     629           8 :           rmp = vl_msg_api_alloc_as_if_client (
     630           8 :             sizeof (*rmp) + t->match_n_vectors * sizeof (u32x4));
     631           8 :           rmp->_vl_msg_id =
     632           8 :             ntohs (REPLY_MSG_ID_BASE + VL_API_CLASSIFY_TABLE_INFO_REPLY);
     633           8 :           rmp->context = mp->context;
     634           8 :           rmp->table_id = ntohl (table_id);
     635           8 :           rmp->nbuckets = ntohl (t->nbuckets);
     636           8 :           rmp->match_n_vectors = ntohl (t->match_n_vectors);
     637           8 :           rmp->skip_n_vectors = ntohl (t->skip_n_vectors);
     638           8 :           rmp->active_sessions = ntohl (t->active_elements);
     639           8 :           rmp->next_table_index = ntohl (t->next_table_index);
     640           8 :           rmp->miss_next_index = ntohl (t->miss_next_index);
     641           8 :           rmp->mask_length = ntohl (t->match_n_vectors * sizeof (u32x4));
     642           8 :           clib_memcpy (rmp->mask, t->mask,
     643             :                        t->match_n_vectors * sizeof (u32x4));
     644           8 :           rmp->retval = 0;
     645           8 :           break;
     646             :         }
     647             :     }
     648             : 
     649           8 :   if (rmp == 0)
     650             :     {
     651           0 :       rmp = vl_msg_api_alloc (sizeof (*rmp));
     652           0 :       rmp->_vl_msg_id =
     653           0 :         ntohs (REPLY_MSG_ID_BASE + VL_API_CLASSIFY_TABLE_INFO_REPLY);
     654           0 :       rmp->context = mp->context;
     655           0 :       rmp->retval = ntohl (VNET_API_ERROR_CLASSIFY_TABLE_NOT_FOUND);
     656             :     }
     657             : 
     658           8 :   vl_api_send_msg (reg, (u8 *) rmp);
     659             : }
     660             : 
     661             : static void
     662           0 : send_classify_session_details (vl_api_registration_t * reg,
     663             :                                u32 table_id,
     664             :                                u32 match_length,
     665             :                                vnet_classify_entry_t * e, u32 context)
     666             : {
     667             :   vl_api_classify_session_details_t *rmp;
     668             : 
     669           0 :   rmp = vl_msg_api_alloc (sizeof (*rmp) + match_length);
     670           0 :   clib_memset (rmp, 0, sizeof (*rmp));
     671           0 :   rmp->_vl_msg_id =
     672           0 :     ntohs (REPLY_MSG_ID_BASE + VL_API_CLASSIFY_SESSION_DETAILS);
     673           0 :   rmp->context = context;
     674           0 :   rmp->table_id = ntohl (table_id);
     675           0 :   rmp->hit_next_index = ntohl (e->next_index);
     676           0 :   rmp->advance = ntohl (e->advance);
     677           0 :   rmp->opaque_index = ntohl (e->opaque_index);
     678           0 :   rmp->match_length = ntohl (match_length);
     679           0 :   clib_memcpy (rmp->match, e->key, match_length);
     680             : 
     681           0 :   vl_api_send_msg (reg, (u8 *) rmp);
     682           0 : }
     683             : 
     684             : static void
     685           0 : vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t * mp)
     686             : {
     687           0 :   vnet_classify_main_t *cm = &vnet_classify_main;
     688             :   vl_api_registration_t *reg;
     689             : 
     690           0 :   u32 table_id = ntohl (mp->table_id);
     691             :   vnet_classify_table_t *t;
     692             : 
     693           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
     694           0 :   if (!reg)
     695           0 :     return;
     696             : 
     697             :   /* *INDENT-OFF* */
     698           0 :   pool_foreach (t, cm->tables)
     699             :    {
     700           0 :     if (table_id == t - cm->tables)
     701             :       {
     702             :         vnet_classify_bucket_t * b;
     703             :         vnet_classify_entry_t * v, * save_v;
     704             :         int i, j, k;
     705             : 
     706           0 :         for (i = 0; i < t->nbuckets; i++)
     707             :           {
     708           0 :             b = &t->buckets [i];
     709           0 :             if (b->offset == 0)
     710           0 :               continue;
     711             : 
     712           0 :             save_v = vnet_classify_get_entry (t, b->offset);
     713           0 :             for (j = 0; j < (1<<b->log2_pages); j++)
     714             :               {
     715           0 :                 for (k = 0; k < t->entries_per_page; k++)
     716             :                   {
     717           0 :                     v = vnet_classify_entry_at_index
     718           0 :                       (t, save_v, j*t->entries_per_page + k);
     719           0 :                     if (vnet_classify_entry_is_free (v))
     720           0 :                       continue;
     721             : 
     722           0 :                     send_classify_session_details
     723           0 :                       (reg, table_id, t->match_n_vectors * sizeof (u32x4),
     724             :                        v, mp->context);
     725             :                   }
     726             :               }
     727             :           }
     728           0 :         break;
     729             :       }
     730             :   }
     731             :   /* *INDENT-ON* */
     732             : }
     733             : 
     734             : static void
     735           0 :   vl_api_flow_classify_set_interface_t_handler
     736             :   (vl_api_flow_classify_set_interface_t * mp)
     737             : {
     738           0 :   vlib_main_t *vm = vlib_get_main ();
     739             :   vl_api_flow_classify_set_interface_reply_t *rmp;
     740             :   int rv;
     741             :   u32 sw_if_index, ip4_table_index, ip6_table_index;
     742             : 
     743           0 :   ip4_table_index = ntohl (mp->ip4_table_index);
     744           0 :   ip6_table_index = ntohl (mp->ip6_table_index);
     745           0 :   sw_if_index = ntohl (mp->sw_if_index);
     746             : 
     747           0 :   VALIDATE_SW_IF_INDEX (mp);
     748             : 
     749           0 :   rv = vnet_set_flow_classify_intfc (vm, sw_if_index, ip4_table_index,
     750           0 :                                      ip6_table_index, mp->is_add);
     751             : 
     752           0 :   BAD_SW_IF_INDEX_LABEL;
     753             : 
     754           0 :   REPLY_MACRO (VL_API_FLOW_CLASSIFY_SET_INTERFACE_REPLY);
     755             : }
     756             : 
     757             : static void
     758           0 : send_flow_classify_details (u32 sw_if_index,
     759             :                             u32 table_index, vl_api_registration_t * reg,
     760             :                             u32 context)
     761             : {
     762             :   vl_api_flow_classify_details_t *mp;
     763             : 
     764           0 :   mp = vl_msg_api_alloc (sizeof (*mp));
     765           0 :   clib_memset (mp, 0, sizeof (*mp));
     766           0 :   mp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_FLOW_CLASSIFY_DETAILS);
     767           0 :   mp->context = context;
     768           0 :   mp->sw_if_index = htonl (sw_if_index);
     769           0 :   mp->table_index = htonl (table_index);
     770             : 
     771           0 :   vl_api_send_msg (reg, (u8 *) mp);
     772           0 : }
     773             : 
     774             : static void
     775           0 : vl_api_flow_classify_dump_t_handler (vl_api_flow_classify_dump_t * mp)
     776             : {
     777             :   vl_api_registration_t *reg;
     778           0 :   flow_classify_main_t *pcm = &flow_classify_main;
     779             :   u32 *vec_tbl;
     780             :   int i;
     781             :   u32 filter_sw_if_index;
     782             : 
     783           0 :   reg = vl_api_client_index_to_registration (mp->client_index);
     784           0 :   if (!reg)
     785           0 :     return;
     786             : 
     787           0 :   filter_sw_if_index = ntohl (mp->sw_if_index);
     788           0 :   if (filter_sw_if_index
     789           0 :       >= vec_len (pcm->classify_table_index_by_sw_if_index[mp->type]))
     790           0 :     return;
     791             : 
     792           0 :   if (filter_sw_if_index != ~0)
     793           0 :     vec_tbl =
     794           0 :       &pcm->classify_table_index_by_sw_if_index[mp->type][filter_sw_if_index];
     795             :   else
     796           0 :     vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
     797             : 
     798           0 :   if (vec_len (vec_tbl))
     799             :     {
     800           0 :       for (i = 0; i < vec_len (vec_tbl); i++)
     801             :         {
     802           0 :           if (vec_elt (vec_tbl, i) == ~0)
     803           0 :             continue;
     804             : 
     805           0 :           send_flow_classify_details (i, vec_elt (vec_tbl, i), reg,
     806             :                                       mp->context);
     807             :         }
     808             :     }
     809             : }
     810             : 
     811           0 : static void vl_api_classify_set_interface_ip_table_t_handler
     812             :   (vl_api_classify_set_interface_ip_table_t * mp)
     813             : {
     814           0 :   vlib_main_t *vm = vlib_get_main ();
     815             :   vl_api_classify_set_interface_ip_table_reply_t *rmp;
     816             :   int rv;
     817             : 
     818           0 :   VALIDATE_SW_IF_INDEX (mp);
     819             : 
     820           0 :   u32 table_index = ntohl (mp->table_index);
     821           0 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     822             : 
     823           0 :   if (mp->is_ipv6)
     824           0 :     rv = vnet_set_ip6_classify_intfc (vm, sw_if_index, table_index);
     825             :   else
     826           0 :     rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
     827             : 
     828           0 :   BAD_SW_IF_INDEX_LABEL;
     829             : 
     830           0 :   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY);
     831             : }
     832             : 
     833           0 : static void vl_api_classify_set_interface_l2_tables_t_handler
     834             :   (vl_api_classify_set_interface_l2_tables_t * mp)
     835             : {
     836             :   vl_api_classify_set_interface_l2_tables_reply_t *rmp;
     837             :   int rv;
     838             :   u32 sw_if_index, ip4_table_index, ip6_table_index, other_table_index;
     839             :   int enable;
     840             : 
     841           0 :   ip4_table_index = ntohl (mp->ip4_table_index);
     842           0 :   ip6_table_index = ntohl (mp->ip6_table_index);
     843           0 :   other_table_index = ntohl (mp->other_table_index);
     844           0 :   sw_if_index = ntohl (mp->sw_if_index);
     845             : 
     846           0 :   VALIDATE_SW_IF_INDEX (mp);
     847             : 
     848           0 :   if (mp->is_input)
     849           0 :     rv = vnet_l2_input_classify_set_tables (sw_if_index, ip4_table_index,
     850             :                                             ip6_table_index,
     851             :                                             other_table_index);
     852             :   else
     853           0 :     rv = vnet_l2_output_classify_set_tables (sw_if_index, ip4_table_index,
     854             :                                              ip6_table_index,
     855             :                                              other_table_index);
     856             : 
     857           0 :   if (rv == 0)
     858             :     {
     859           0 :       if (ip4_table_index != ~0 || ip6_table_index != ~0
     860           0 :           || other_table_index != ~0)
     861           0 :         enable = 1;
     862             :       else
     863           0 :         enable = 0;
     864             : 
     865           0 :       if (mp->is_input)
     866           0 :         vnet_l2_input_classify_enable_disable (sw_if_index, enable);
     867             :       else
     868           0 :         vnet_l2_output_classify_enable_disable (sw_if_index, enable);
     869             :     }
     870             : 
     871           0 :   BAD_SW_IF_INDEX_LABEL;
     872             : 
     873           0 :   REPLY_MACRO (VL_API_CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY);
     874             : }
     875             : 
     876          70 : static void vl_api_input_acl_set_interface_t_handler
     877             :   (vl_api_input_acl_set_interface_t * mp)
     878             : {
     879          70 :   vlib_main_t *vm = vlib_get_main ();
     880             :   vl_api_input_acl_set_interface_reply_t *rmp;
     881             :   int rv;
     882             : 
     883          70 :   VALIDATE_SW_IF_INDEX (mp);
     884             : 
     885          70 :   u32 ip4_table_index = ntohl (mp->ip4_table_index);
     886          70 :   u32 ip6_table_index = ntohl (mp->ip6_table_index);
     887          70 :   u32 l2_table_index = ntohl (mp->l2_table_index);
     888          70 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     889             : 
     890          70 :   rv = vnet_set_input_acl_intfc (vm, sw_if_index, ip4_table_index,
     891          70 :                                  ip6_table_index, l2_table_index, mp->is_add);
     892             : 
     893          70 :   BAD_SW_IF_INDEX_LABEL;
     894             : 
     895          70 :   REPLY_MACRO (VL_API_INPUT_ACL_SET_INTERFACE_REPLY);
     896             : }
     897             : 
     898             : static void
     899           6 : vl_api_punt_acl_add_del_t_handler (vl_api_punt_acl_add_del_t *mp)
     900             : {
     901           6 :   vlib_main_t *vm = vlib_get_main ();
     902             :   vl_api_punt_acl_add_del_reply_t *rmp;
     903             :   int rv;
     904             : 
     905           6 :   rv = vnet_set_in_out_acl_intfc (
     906             :     vm, 0 /* sw_if_index */, ~0 /* ip4_table_index */,
     907             :     ~0 /* ip6_table_index */, ~0 /* l2_table_index */,
     908           6 :     ntohl (mp->ip4_table_index), ntohl (mp->ip6_table_index), mp->is_add,
     909             :     0 /* is_output */);
     910             : 
     911           6 :   REPLY_MACRO (VL_API_PUNT_ACL_ADD_DEL_REPLY);
     912             : }
     913             : 
     914             : static void
     915           2 : vl_api_punt_acl_get_t_handler (vl_api_punt_acl_get_t *mp)
     916             : {
     917             :   vl_api_punt_acl_get_reply_t *rmp;
     918           2 :   int rv = 0;
     919             : 
     920           2 :   const in_out_acl_main_t *am = &in_out_acl_main;
     921             : 
     922           2 :   u32 *const *tables =
     923             :     am->classify_table_index_by_sw_if_index[IN_OUT_ACL_INPUT_TABLE_GROUP];
     924           2 :   const u32 *ip4_table = tables[IN_OUT_ACL_TABLE_IP4_PUNT];
     925           2 :   const u32 *ip6_table = tables[IN_OUT_ACL_TABLE_IP6_PUNT];
     926           2 :   const u32 ip4_table_index = vec_len (ip4_table) ? ip4_table[0] : ~0;
     927           2 :   const u32 ip6_table_index = vec_len (ip6_table) ? ip6_table[0] : ~0;
     928             : 
     929           2 :   REPLY_MACRO2 (VL_API_PUNT_ACL_GET_REPLY, ({
     930             :                   rmp->ip4_table_index = ntohl (ip4_table_index);
     931             :                   rmp->ip6_table_index = ntohl (ip6_table_index);
     932             :                 }));
     933             : }
     934             : 
     935          14 : static void vl_api_output_acl_set_interface_t_handler
     936             :   (vl_api_output_acl_set_interface_t * mp)
     937             : {
     938          14 :   vlib_main_t *vm = vlib_get_main ();
     939             :   vl_api_output_acl_set_interface_reply_t *rmp;
     940             :   int rv;
     941             : 
     942          14 :   VALIDATE_SW_IF_INDEX (mp);
     943             : 
     944          14 :   u32 ip4_table_index = ntohl (mp->ip4_table_index);
     945          14 :   u32 ip6_table_index = ntohl (mp->ip6_table_index);
     946          14 :   u32 l2_table_index = ntohl (mp->l2_table_index);
     947          14 :   u32 sw_if_index = ntohl (mp->sw_if_index);
     948             : 
     949          14 :   rv = vnet_set_output_acl_intfc (vm, sw_if_index, ip4_table_index,
     950             :                                   ip6_table_index, l2_table_index,
     951          14 :                                   mp->is_add);
     952             : 
     953          14 :   BAD_SW_IF_INDEX_LABEL;
     954             : 
     955          14 :   REPLY_MACRO (VL_API_OUTPUT_ACL_SET_INTERFACE_REPLY);
     956             : }
     957             : 
     958             : #include <classify/classify.api.c>
     959             : 
     960             : static clib_error_t *
     961         559 : classify_api_hookup (vlib_main_t * vm)
     962             : {
     963         559 :   api_main_t *am = vlibapi_get_main ();
     964             : 
     965             :   /*
     966             :    * Trace space for classifier mask+match
     967             :    */
     968         559 :   vl_api_increase_msg_trace_size (am, VL_API_CLASSIFY_ADD_DEL_TABLE,
     969             :                                   5 * sizeof (u32x4));
     970         559 :   vl_api_increase_msg_trace_size (am, VL_API_CLASSIFY_ADD_DEL_SESSION,
     971             :                                   5 * sizeof (u32x4));
     972             : 
     973             :   /*
     974             :    * Set up the (msg_name, crc, message-id) table
     975             :    */
     976         559 :   msg_id_base = setup_message_id_table ();
     977             : 
     978         559 :   return 0;
     979             : }
     980             : 
     981        4479 : VLIB_API_INIT_FUNCTION (classify_api_hookup);
     982             : 
     983             : /*
     984             :  * fd.io coding-style-patch-verification: ON
     985             :  *
     986             :  * Local Variables:
     987             :  * eval: (c-set-style "gnu")
     988             :  * End:
     989             :  */

Generated by: LCOV version 1.14