FD.io VPP  v17.07.01-10-g3be13f0
Vector Packet Processing
classify_api.c
Go to the documentation of this file.
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 
30 
31 #include <vnet/vnet_msg_enum.h>
32 
33 #define vl_typedefs /* define message structures */
34 #include <vnet/vnet_all_api_h.h>
35 #undef vl_typedefs
36 
37 #define vl_endianfun /* define message structures */
38 #include <vnet/vnet_all_api_h.h>
39 #undef vl_endianfun
40 
41 /* instantiate all the print functions we know about */
42 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
43 #define vl_printfun
44 #include <vnet/vnet_all_api_h.h>
45 #undef vl_printfun
46 
48 
49 #define foreach_vpe_api_msg \
50 _(CLASSIFY_ADD_DEL_TABLE, classify_add_del_table) \
51 _(CLASSIFY_ADD_DEL_SESSION, classify_add_del_session) \
52 _(CLASSIFY_TABLE_IDS,classify_table_ids) \
53 _(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface) \
54 _(CLASSIFY_TABLE_INFO,classify_table_info) \
55 _(CLASSIFY_SESSION_DUMP,classify_session_dump) \
56 _(POLICER_CLASSIFY_SET_INTERFACE, policer_classify_set_interface) \
57 _(POLICER_CLASSIFY_DUMP, policer_classify_dump) \
58 _(FLOW_CLASSIFY_SET_INTERFACE, flow_classify_set_interface) \
59 _(FLOW_CLASSIFY_DUMP, flow_classify_dump)
60 
61 #define foreach_classify_add_del_table_field \
62 _(table_index) \
63 _(nbuckets) \
64 _(memory_size) \
65 _(skip_n_vectors) \
66 _(match_n_vectors) \
67 _(next_table_index) \
68 _(miss_next_index) \
69 _(current_data_flag) \
70 _(current_data_offset)
71 
74 {
78  int rv;
79 
80 #define _(a) u32 a;
82 #undef _
83 
84 #define _(a) a = ntohl(mp->a);
86 #undef _
87 
88  /* The underlying API fails silently, on purpose, so check here */
89  if (mp->is_add == 0) /* delete */
90  {
91  if (pool_is_free_index (cm->tables, table_index))
92  {
93  rv = VNET_API_ERROR_NO_SUCH_TABLE;
94  goto out;
95  }
96  }
97  else /* add or update */
98  {
99  if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
100  table_index = ~0;
101  }
102 
104  (cm, mp->mask, nbuckets, memory_size,
105  skip_n_vectors, match_n_vectors,
106  next_table_index, miss_next_index, &table_index,
107  current_data_flag, current_data_offset, mp->is_add, mp->del_chain);
108 
109 out:
110  /* *INDENT-OFF* */
111  REPLY_MACRO2(VL_API_CLASSIFY_ADD_DEL_TABLE_REPLY,
112  ({
113  if (rv == 0 && mp->is_add)
114  {
115  t = pool_elt_at_index (cm->tables, table_index);
116  rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
117  rmp->match_n_vectors = ntohl(t->match_n_vectors);
118  rmp->new_table_index = ntohl(table_index);
119  }
120  else
121  {
122  rmp->skip_n_vectors = ~0;
123  rmp->match_n_vectors = ~0;
124  rmp->new_table_index = ~0;
125  }
126  }));
127  /* *INDENT-ON* */
128 }
129 
132 {
134  vl_api_classify_add_del_session_reply_t *rmp;
135  int rv;
136  u32 table_index, hit_next_index, opaque_index, metadata;
137  i32 advance;
138  u8 action;
139 
140  table_index = ntohl (mp->table_index);
141  hit_next_index = ntohl (mp->hit_next_index);
142  opaque_index = ntohl (mp->opaque_index);
143  advance = ntohl (mp->advance);
144  action = mp->action;
145  metadata = ntohl (mp->metadata);
146 
148  (cm, table_index, mp->match, hit_next_index, opaque_index,
149  advance, action, metadata, mp->is_add);
150 
151  REPLY_MACRO (VL_API_CLASSIFY_ADD_DEL_SESSION_REPLY);
152 }
153 
154 static void
157 {
158  vlib_main_t *vm = vlib_get_main ();
159  vl_api_policer_classify_set_interface_reply_t *rmp;
160  int rv;
161  u32 sw_if_index, ip4_table_index, ip6_table_index, l2_table_index;
162 
163  ip4_table_index = ntohl (mp->ip4_table_index);
164  ip6_table_index = ntohl (mp->ip6_table_index);
165  l2_table_index = ntohl (mp->l2_table_index);
166  sw_if_index = ntohl (mp->sw_if_index);
167 
169 
170  rv = vnet_set_policer_classify_intfc (vm, sw_if_index, ip4_table_index,
171  ip6_table_index, l2_table_index,
172  mp->is_add);
173 
175 
176  REPLY_MACRO (VL_API_POLICER_CLASSIFY_SET_INTERFACE_REPLY);
177 }
178 
179 static void
181  u32 table_index,
182  unix_shared_memory_queue_t * q, u32 context)
183 {
185 
186  mp = vl_msg_api_alloc (sizeof (*mp));
187  memset (mp, 0, sizeof (*mp));
188  mp->_vl_msg_id = ntohs (VL_API_POLICER_CLASSIFY_DETAILS);
189  mp->context = context;
190  mp->sw_if_index = htonl (sw_if_index);
191  mp->table_index = htonl (table_index);
192 
193  vl_msg_api_send_shmem (q, (u8 *) & mp);
194 }
195 
196 static void
198 {
201  u32 *vec_tbl;
202  int i;
203 
205  if (q == 0)
206  return;
207 
208  vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
209 
210  if (vec_len (vec_tbl))
211  {
212  for (i = 0; i < vec_len (vec_tbl); i++)
213  {
214  if (vec_elt (vec_tbl, i) == ~0)
215  continue;
216 
217  send_policer_classify_details (i, vec_elt (vec_tbl, i), q,
218  mp->context);
219  }
220  }
221 }
222 
223 static void
225 {
227 
229  if (q == 0)
230  return;
231 
234  u32 *table_ids = 0;
235  u32 count;
236 
237  /* *INDENT-OFF* */
238  pool_foreach (t, cm->tables,
239  ({
240  vec_add1 (table_ids, ntohl(t - cm->tables));
241  }));
242  /* *INDENT-ON* */
243  count = vec_len (table_ids);
244 
246  rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp) + count * sizeof (u32));
247  rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_IDS_REPLY);
248  rmp->context = mp->context;
249  rmp->count = ntohl (count);
250  clib_memcpy (rmp->ids, table_ids, count * sizeof (u32));
251  rmp->retval = 0;
252 
253  vl_msg_api_send_shmem (q, (u8 *) & rmp);
254 
255  vec_free (table_ids);
256 }
257 
258 static void
261 {
263  int rv = 0;
264 
265  u32 sw_if_index = ntohl (mp->sw_if_index);
266  u32 *acl = 0;
267 
268  vec_validate (acl, INPUT_ACL_N_TABLES - 1);
269  vec_set (acl, ~0);
270 
272 
274 
275  int if_idx;
276  u32 type;
277 
278  for (type = 0; type < INPUT_ACL_N_TABLES; type++)
279  {
280  u32 *vec_tbl = am->classify_table_index_by_sw_if_index[type];
281  if (vec_len (vec_tbl))
282  {
283  for (if_idx = 0; if_idx < vec_len (vec_tbl); if_idx++)
284  {
285  if (vec_elt (vec_tbl, if_idx) == ~0 || sw_if_index != if_idx)
286  {
287  continue;
288  }
289  acl[type] = vec_elt (vec_tbl, if_idx);
290  }
291  }
292  }
293 
295 
296  /* *INDENT-OFF* */
297  REPLY_MACRO2(VL_API_CLASSIFY_TABLE_BY_INTERFACE_REPLY,
298  ({
299  rmp->sw_if_index = ntohl(sw_if_index);
300  rmp->l2_table_id = ntohl(acl[INPUT_ACL_TABLE_L2]);
301  rmp->ip4_table_id = ntohl(acl[INPUT_ACL_TABLE_IP4]);
302  rmp->ip6_table_id = ntohl(acl[INPUT_ACL_TABLE_IP6]);
303  }));
304  /* *INDENT-ON* */
305  vec_free (acl);
306 }
307 
308 static void
310 {
312 
314  if (q == 0)
315  return;
316 
318 
320  u32 table_id = ntohl (mp->table_id);
322 
323  /* *INDENT-OFF* */
324  pool_foreach (t, cm->tables,
325  ({
326  if (table_id == t - cm->tables)
327  {
328  rmp = vl_msg_api_alloc_as_if_client
329  (sizeof (*rmp) + t->match_n_vectors * sizeof (u32x4));
330  rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_INFO_REPLY);
331  rmp->context = mp->context;
332  rmp->table_id = ntohl(table_id);
333  rmp->nbuckets = ntohl(t->nbuckets);
334  rmp->match_n_vectors = ntohl(t->match_n_vectors);
335  rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
336  rmp->active_sessions = ntohl(t->active_elements);
337  rmp->next_table_index = ntohl(t->next_table_index);
338  rmp->miss_next_index = ntohl(t->miss_next_index);
339  rmp->mask_length = ntohl(t->match_n_vectors * sizeof (u32x4));
340  clib_memcpy(rmp->mask, t->mask, t->match_n_vectors * sizeof(u32x4));
341  rmp->retval = 0;
342  break;
343  }
344  }));
345  /* *INDENT-ON* */
346 
347  if (rmp == 0)
348  {
349  rmp = vl_msg_api_alloc (sizeof (*rmp));
350  rmp->_vl_msg_id = ntohs ((VL_API_CLASSIFY_TABLE_INFO_REPLY));
351  rmp->context = mp->context;
352  rmp->retval = ntohl (VNET_API_ERROR_CLASSIFY_TABLE_NOT_FOUND);
353  }
354 
355  vl_msg_api_send_shmem (q, (u8 *) & rmp);
356 }
357 
358 static void
360  u32 table_id,
361  u32 match_length,
362  vnet_classify_entry_t * e, u32 context)
363 {
365 
366  rmp = vl_msg_api_alloc (sizeof (*rmp));
367  memset (rmp, 0, sizeof (*rmp));
368  rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_SESSION_DETAILS);
369  rmp->context = context;
370  rmp->table_id = ntohl (table_id);
371  rmp->hit_next_index = ntohl (e->next_index);
372  rmp->advance = ntohl (e->advance);
373  rmp->opaque_index = ntohl (e->opaque_index);
374  rmp->match_length = ntohl (match_length);
375  clib_memcpy (rmp->match, e->key, match_length);
376 
377  vl_msg_api_send_shmem (q, (u8 *) & rmp);
378 }
379 
380 static void
382 {
385 
386  u32 table_id = ntohl (mp->table_id);
388 
390  if (!q)
391  return;
392 
393  /* *INDENT-OFF* */
394  pool_foreach (t, cm->tables,
395  ({
396  if (table_id == t - cm->tables)
397  {
398  vnet_classify_bucket_t * b;
399  vnet_classify_entry_t * v, * save_v;
400  int i, j, k;
401 
402  for (i = 0; i < t->nbuckets; i++)
403  {
404  b = &t->buckets [i];
405  if (b->offset == 0)
406  continue;
407 
408  save_v = vnet_classify_get_entry (t, b->offset);
409  for (j = 0; j < (1<<b->log2_pages); j++)
410  {
411  for (k = 0; k < t->entries_per_page; k++)
412  {
413  v = vnet_classify_entry_at_index
414  (t, save_v, j*t->entries_per_page + k);
415  if (vnet_classify_entry_is_free (v))
416  continue;
417 
418  send_classify_session_details
419  (q, table_id, t->match_n_vectors * sizeof (u32x4),
420  v, mp->context);
421  }
422  }
423  }
424  break;
425  }
426  }));
427  /* *INDENT-ON* */
428 }
429 
430 static void
433 {
434  vlib_main_t *vm = vlib_get_main ();
435  vl_api_flow_classify_set_interface_reply_t *rmp;
436  int rv;
437  u32 sw_if_index, ip4_table_index, ip6_table_index;
438 
439  ip4_table_index = ntohl (mp->ip4_table_index);
440  ip6_table_index = ntohl (mp->ip6_table_index);
441  sw_if_index = ntohl (mp->sw_if_index);
442 
444 
445  rv = vnet_set_flow_classify_intfc (vm, sw_if_index, ip4_table_index,
446  ip6_table_index, mp->is_add);
447 
449 
450  REPLY_MACRO (VL_API_FLOW_CLASSIFY_SET_INTERFACE_REPLY);
451 }
452 
453 static void
455  u32 table_index,
456  unix_shared_memory_queue_t * q, u32 context)
457 {
459 
460  mp = vl_msg_api_alloc (sizeof (*mp));
461  memset (mp, 0, sizeof (*mp));
462  mp->_vl_msg_id = ntohs (VL_API_FLOW_CLASSIFY_DETAILS);
463  mp->context = context;
464  mp->sw_if_index = htonl (sw_if_index);
465  mp->table_index = htonl (table_index);
466 
467  vl_msg_api_send_shmem (q, (u8 *) & mp);
468 }
469 
470 static void
472 {
475  u32 *vec_tbl;
476  int i;
477 
479  if (q == 0)
480  return;
481 
482  vec_tbl = pcm->classify_table_index_by_sw_if_index[mp->type];
483 
484  if (vec_len (vec_tbl))
485  {
486  for (i = 0; i < vec_len (vec_tbl); i++)
487  {
488  if (vec_elt (vec_tbl, i) == ~0)
489  continue;
490 
491  send_flow_classify_details (i, vec_elt (vec_tbl, i), q,
492  mp->context);
493  }
494  }
495 }
496 
497 /*
498  * classify_api_hookup
499  * Add vpe's API message handlers to the table.
500  * vlib has alread mapped shared memory and
501  * added the client registration handlers.
502  * See .../vlib-api/vlibmemory/memclnt_vlib.c:memclnt_process()
503  */
504 #define vl_msg_name_crc_list
505 #include <vnet/vnet_all_api_h.h>
506 #undef vl_msg_name_crc_list
507 
508 static void
510 {
511 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
512  foreach_vl_msg_name_crc_classify;
513 #undef _
514 }
515 
516 static clib_error_t *
518 {
519  api_main_t *am = &api_main;
520 
521 #define _(N,n) \
522  vl_msg_api_set_handlers(VL_API_##N, #n, \
523  vl_api_##n##_t_handler, \
524  vl_noop_handler, \
525  vl_api_##n##_t_endian, \
526  vl_api_##n##_t_print, \
527  sizeof(vl_api_##n##_t), 1);
529 #undef _
530 
531  /*
532  * Set up the (msg_name, crc, message-id) table
533  */
535 
536  return 0;
537 }
538 
540 
541 /*
542  * fd.io coding-style-patch-verification: ON
543  *
544  * Local Variables:
545  * eval: (c-set-style "gnu")
546  * End:
547  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:436
Reply for classify table session dump request.
Definition: classify.api:268
static void vl_api_classify_table_info_t_handler(vl_api_classify_table_info_t *mp)
Definition: classify_api.c:309
void * vl_msg_api_alloc_as_if_client(int nbytes)
Classify get table IDs request.
Definition: classify.api:159
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
#define foreach_vpe_api_msg
Definition: classify_api.c:49
static void vl_api_classify_add_del_table_t_handler(vl_api_classify_add_del_table_t *mp)
Definition: classify_api.c:73
Set/unset policer classify interface.
Definition: classify.api:120
u32 * classify_table_index_by_sw_if_index[INPUT_ACL_N_TABLES]
Definition: input_acl.h:38
#define REPLY_MACRO2(t, body)
Classify add / del session request.
Definition: classify.api:95
Add/Delete classification table request.
Definition: classify.api:40
Reply for classify get table IDs request.
Definition: classify.api:170
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
Classify sessions dump request.
Definition: classify.api:252
u32 * classify_table_index_by_sw_if_index[FLOW_CLASSIFY_N_TABLES]
Definition: flow_classify.h:36
int i32
Definition: types.h:81
static void send_classify_session_details(unix_shared_memory_queue_t *q, u32 table_id, u32 match_length, vnet_classify_entry_t *e, u32 context)
Definition: classify_api.c:359
static void setup_message_id_table(api_main_t *am)
Definition: classify_api.c:509
Reply for classify table id by interface index request.
Definition: classify.api:198
u32 * classify_table_index_by_sw_if_index[POLICER_CLASSIFY_N_TABLES]
void * vl_msg_api_alloc(int nbytes)
flow_classify_main_t flow_classify_main
Definition: flow_classify.h:45
int vnet_classify_add_del_session(vnet_classify_main_t *cm, u32 table_index, u8 *match, u32 hit_next_index, u32 opaque_index, i32 advance, u8 action, u32 metadata, int is_add)
Flow classify operational state response.
Definition: classify.api:316
#define foreach_classify_add_del_table_field
Definition: classify_api.c:61
Add/Delete classification table response.
Definition: classify.api:65
#define REPLY_MACRO(t)
static clib_error_t * classify_api_hookup(vlib_main_t *vm)
Definition: classify_api.c:517
Get list of flow classify interfaces and tables.
Definition: classify.api:305
static void vl_api_flow_classify_set_interface_t_handler(vl_api_flow_classify_set_interface_t *mp)
Definition: classify_api.c:432
Classify table info.
Definition: classify.api:213
#define BAD_SW_IF_INDEX_LABEL
api_main_t api_main
Definition: api_shared.c:35
int vnet_set_flow_classify_intfc(vlib_main_t *vm, u32 sw_if_index, u32 ip4_table_index, u32 ip6_table_index, u32 is_add)
Definition: flow_classify.c:44
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
u64 memory_size
Definition: vhost-user.h:76
#define clib_memcpy(a, b, c)
Definition: string.h:69
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
Set/unset flow classify interface.
Definition: classify.api:291
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:238
static void vl_api_classify_session_dump_t_handler(vl_api_classify_session_dump_t *mp)
Definition: classify_api.c:381
static void send_policer_classify_details(u32 sw_if_index, u32 table_index, unix_shared_memory_queue_t *q, u32 context)
Definition: classify_api.c:180
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:72
input_acl_main_t input_acl_main
Definition: input_acl.c:19
Policer iclassify operational state response.
Definition: classify.api:148
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
unsigned int u32
Definition: types.h:88
Get list of policer classify interfaces and tables.
Definition: classify.api:136
static void vl_api_flow_classify_dump_t_handler(vl_api_flow_classify_dump_t *mp)
Definition: classify_api.c:471
static void vl_api_policer_classify_dump_t_handler(vl_api_policer_classify_dump_t *mp)
Definition: classify_api.c:197
vnet_classify_main_t vnet_classify_main
Definition: vnet_classify.c:22
#define vec_set(v, val)
Set all vector elements to given value.
Definition: vec.h:892
Classify table ids by interface index request.
Definition: classify.api:183
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static void vl_api_policer_classify_set_interface_t_handler(vl_api_policer_classify_set_interface_t *mp)
Definition: classify_api.c:156
int vnet_classify_add_del_table(vnet_classify_main_t *cm, u8 *mask, u32 nbuckets, u32 memory_size, u32 skip, u32 match, u32 next_table_index, u32 miss_next_index, u32 *table_index, u8 current_data_flag, i16 current_data_offset, int is_add, int del_chain)
#define vec_elt(v, i)
Get vector value at index i.
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
static void vl_api_classify_table_by_interface_t_handler(vl_api_classify_table_by_interface_t *mp)
Definition: classify_api.c:260
policer_classify_main_t policer_classify_main
static void vl_api_classify_table_ids_t_handler(vl_api_classify_table_ids_t *mp)
Definition: classify_api.c:224
int vnet_set_policer_classify_intfc(vlib_main_t *vm, u32 sw_if_index, u32 ip4_table_index, u32 ip6_table_index, u32 l2_table_index, u32 is_add)
static void vl_api_classify_add_del_session_t_handler(vl_api_classify_add_del_session_t *mp)
Definition: classify_api.c:131
Reply for classify table info request.
Definition: classify.api:232
VLIB_API_INIT_FUNCTION(classify_api_hookup)
static void send_flow_classify_details(u32 sw_if_index, u32 table_index, unix_shared_memory_queue_t *q, u32 context)
Definition: classify_api.c:454
#define VALIDATE_SW_IF_INDEX(mp)
struct _unix_shared_memory_queue unix_shared_memory_queue_t